gboolean
_ostree_static_delta_part_execute (OstreeRepo      *repo,
                                   GVariant        *objects,
                                   GVariant        *part,
                                   gboolean         stats_only,
                                   OstreeDeltaExecuteStats *stats,
                                   GCancellable    *cancellable,
                                   GError         **error)
{
  gboolean ret = FALSE;
  guint8 *checksums_data;
  g_autoptr(GVariant) mode_dict = NULL;
  g_autoptr(GVariant) xattr_dict = NULL;
  g_autoptr(GVariant) payload = NULL;
  g_autoptr(GVariant) ops = NULL;
  StaticDeltaExecutionState statedata = { 0, };
  StaticDeltaExecutionState *state = &statedata;
  guint n_executed = 0;

  static_delta_execution_state_init (&statedata);

  state->repo = repo;
  state->async_error = error;
  state->stats_only = stats_only;

  if (!_ostree_static_delta_parse_checksum_array (objects,
                                                  &checksums_data,
                                                  &state->n_checksums,
                                                  error))
    goto out;

  /* Skip processing for empty delta part */
  if (state->n_checksums == 0)
    {
      ret = TRUE;
      goto out;
    }

  state->checksums = checksums_data;

  g_variant_get (part, "(@a(uuu)@aa(ayay)@ay@ay)",
                 &mode_dict,
                 &xattr_dict,
                 &payload, &ops);

  state->mode_dict = mode_dict;
  state->xattr_dict = xattr_dict;

  state->payload_data = g_variant_get_data (payload);
  state->payload_size = g_variant_get_size (payload);

  state->oplen = g_variant_n_children (ops);
  state->opdata = g_variant_get_data (ops);

  while (state->oplen > 0)
    {
      guint8 opcode;

      opcode = state->opdata[0];
      state->oplen--;
      state->opdata++;

      switch (opcode)
        {
        case OSTREE_STATIC_DELTA_OP_OPEN_SPLICE_AND_CLOSE:
          if (!dispatch_open_splice_and_close (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_OPEN:
          if (!dispatch_open (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_WRITE:
          if (!dispatch_write (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_SET_READ_SOURCE:
          if (!dispatch_set_read_source (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_UNSET_READ_SOURCE:
          if (!dispatch_unset_read_source (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_CLOSE:
          if (!dispatch_close (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_BSPATCH:
          if (!dispatch_bspatch (repo, state, cancellable, error))
            goto out;
          break;
        default:
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
                       "Unknown opcode %u at offset %u", opcode, n_executed);
          goto out;
        }

      n_executed++;
      if (stats)
        stats->n_ops_executed[delta_opcode_index(opcode)]++;
    }

  if (state->caught_error)
    goto out;

  ret = TRUE;
 out:
  g_clear_pointer (&state->content_checksum, g_checksum_free);
  return ret;
}
gboolean
_ostree_static_delta_part_execute_raw (OstreeRepo      *repo,
                                       GVariant        *objects,
                                       GVariant        *part,
                                       GCancellable    *cancellable,
                                       GError         **error)
{
  gboolean ret = FALSE;
  guint8 *checksums_data;
  gs_unref_variant GVariant *checksums = NULL;
  gs_unref_variant GVariant *mode_dict = NULL;
  gs_unref_variant GVariant *xattr_dict = NULL;
  gs_unref_variant GVariant *payload = NULL;
  gs_unref_variant GVariant *ops = NULL;
  StaticDeltaExecutionState statedata = { 0, };
  StaticDeltaExecutionState *state = &statedata;
  guint n_executed = 0;

  state->repo = repo;
  state->async_error = error;

  if (!_ostree_static_delta_parse_checksum_array (objects,
                                                  &checksums_data,
                                                  &state->n_checksums,
                                                  error))
    goto out;

  state->checksums = checksums_data;
  g_assert (state->n_checksums > 0);

  g_variant_get (part, "(@a(uuu)@aa(ayay)@ay@ay)",
                 &mode_dict,
                 &xattr_dict,
                 &payload, &ops);

  state->mode_dict = mode_dict;
  state->xattr_dict = xattr_dict;

  state->payload_data = g_variant_get_data (payload);
  state->payload_size = g_variant_get_size (payload);

  state->oplen = g_variant_n_children (ops);
  state->opdata = g_variant_get_data (ops);

  while (state->oplen > 0)
    {
      guint8 opcode;

      opcode = state->opdata[0];
      state->oplen--;
      state->opdata++;

      switch (opcode)
        {
        case OSTREE_STATIC_DELTA_OP_OPEN_SPLICE_AND_CLOSE:
          if (!dispatch_open_splice_and_close (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_OPEN:
          if (!dispatch_open (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_WRITE:
          if (!dispatch_write (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_SET_READ_SOURCE:
          if (!dispatch_set_read_source (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_UNSET_READ_SOURCE:
          if (!dispatch_unset_read_source (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_CLOSE:
          if (!dispatch_close (repo, state, cancellable, error))
            goto out;
          break;
        case OSTREE_STATIC_DELTA_OP_BSPATCH:
          if (!dispatch_bspatch (repo, state, cancellable, error))
            goto out;
          break;
        default:
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
                       "Unknown opcode %u at offset %u", opcode, n_executed);
          goto out;
        }

      n_executed++;
    }

  if (state->caught_error)
    goto out;

  ret = TRUE;
 out:
  return ret;
}