static gboolean
dispatch_open (OstreeRepo                 *repo,
               StaticDeltaExecutionState  *state,
               GCancellable               *cancellable,  
               GError                    **error)
{
  gboolean ret = FALSE;

  g_assert (state->output_target == NULL);
  /* FIXME - lift this restriction */
  g_assert (repo->mode == OSTREE_REPO_MODE_BARE ||
            repo->mode == OSTREE_REPO_MODE_BARE_USER);
  
  if (!open_output_target (state, cancellable, error))
    goto out;

  if (!do_content_open_generic (repo, state, cancellable, error))
    goto out;

  if (!read_varuint64 (state, &state->content_size, error))
    goto out;

  if (state->trusted)
    {
      if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
                                                   state->content_size,
                                                   &state->barecommitstate,
                                                   &state->content_out,
                                                   &state->have_obj,
                                                   cancellable, error))
        goto out;
    }
  else
    {
      if (!_ostree_repo_open_untrusted_content_bare (repo, state->checksum,
                                                     state->content_size,
                                                     &state->barecommitstate,
                                                     &state->content_out,
                                                     &state->have_obj,
                                                     cancellable, error))
        goto out;
    }

  ret = TRUE;
 out:
  if (!ret)
    g_prefix_error (error, "opcode open: ");
  return ret;
}
static gboolean
dispatch_open_splice_and_close (OstreeRepo                 *repo,
                                StaticDeltaExecutionState  *state,
                                GCancellable               *cancellable,  
                                GError                    **error)
{
  gboolean ret = FALSE;

  if (!open_output_target (state, cancellable, error))
    goto out;

  if (OSTREE_OBJECT_TYPE_IS_META (state->output_objtype))
    {
      g_autoptr(GVariant) metadata = NULL;
      guint64 offset;
      guint64 length;

      if (!read_varuint64 (state, &length, error))
        goto out;
      if (!read_varuint64 (state, &offset, error))
        goto out;
      if (!validate_ofs (state, offset, length, error))
        goto out;
      
      metadata = g_variant_new_from_data (ostree_metadata_variant_type (state->output_objtype),
                                          state->payload_data + offset, length, TRUE, NULL, NULL);

      if (state->trusted)
        {
          if (!ostree_repo_write_metadata_trusted (state->repo, state->output_objtype,
                                                   state->checksum,
                                                   metadata,
                                                   cancellable,
                                                   error))
            goto out;
        }
      else
        {
          g_autofree guchar *actual_csum = NULL;

          if (!ostree_repo_write_metadata (state->repo, state->output_objtype,
                                           state->checksum,
                                           metadata, &actual_csum,
                                           cancellable,
                                           error))
            goto out;
        }
    }
  else
    {
      guint64 content_offset;
      guint64 objlen;
      gsize bytes_written;
      g_autoptr(GInputStream) object_input = NULL;
      g_autoptr(GInputStream) memin = NULL;
      
      if (!do_content_open_generic (repo, state, cancellable, error))
        goto out;

      if (!read_varuint64 (state, &state->content_size, error))
        goto out;
      if (!read_varuint64 (state, &content_offset, error))
        goto out;
      if (!validate_ofs (state, content_offset, state->content_size, error))
        goto out;
      
      /* Fast path for regular files to bare repositories */
      if (S_ISREG (state->mode) && 
          (repo->mode == OSTREE_REPO_MODE_BARE ||
           repo->mode == OSTREE_REPO_MODE_BARE_USER))
        {
          if (state->trusted)
            {
              if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
                                                           state->content_size,
                                                           &state->barecommitstate,
                                                           &state->content_out,
                                                           &state->have_obj,
                                                           cancellable, error))
                goto out;
            }
          else
            {
              if (!_ostree_repo_open_untrusted_content_bare (repo, state->checksum,
                                                             state->content_size,
                                                             &state->barecommitstate,
                                                             &state->content_out,
                                                             &state->have_obj,
                                                             cancellable, error))
                goto out;
            }

          if (!state->have_obj)
            {
              if (!g_output_stream_write_all (state->content_out,
                                              state->payload_data + content_offset,
                                              state->content_size,
                                              &bytes_written,
                                              cancellable, error))
                goto out;
            }
        }
      else
        {
          /* Slower path, for symlinks and unpacking deltas into archive-z2 */
          g_autoptr(GFileInfo) finfo = NULL;
      
          finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid);

          if (S_ISLNK (state->mode))
            {
              g_autofree char *nulterminated_target =
                g_strndup ((char*)state->payload_data + content_offset, state->content_size);
              g_file_info_set_symlink_target (finfo, nulterminated_target);
            }
          else
            {
              g_assert (S_ISREG (state->mode));
              g_file_info_set_size (finfo, state->content_size);
              memin = g_memory_input_stream_new_from_data (state->payload_data + content_offset, state->content_size, NULL);
            }

          if (!ostree_raw_file_to_content_stream (memin, finfo, state->xattrs,
                                                  &object_input, &objlen,
                                                  cancellable, error))
            goto out;
          
          if (state->trusted)
            {
              if (!ostree_repo_write_content_trusted (state->repo,
                                                      state->checksum,
                                                      object_input,
                                                      objlen,
                                                      cancellable,
                                                      error))
                goto out;
            }
          else
            {
              g_autofree guchar *actual_csum = NULL;
              if (!ostree_repo_write_content (state->repo,
                                              state->checksum,
                                              object_input,
                                              objlen,
                                              &actual_csum,
                                              cancellable,
                                              error))
                goto out;
            }
        }
    }

  if (!dispatch_close (repo, state, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (!ret)
    g_prefix_error (error, "opcode open-splice-and-close: ");
  return ret;
}