lib: Move bareuseronly verification into commit/core
authorColin Walters <walters@verbum.org>
Mon, 18 Sep 2017 19:46:03 +0000 (15:46 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Thu, 21 Sep 2017 19:14:59 +0000 (19:14 +0000)
Conceptually `ostree-repo-pull.c` should be be written using
just public APIs; we theoretically support building without HTTP
for people who just want to use the object store portion and
do their own fetching.

We have some nontrivial behaviors in the pull layer though; one
of those is the "bareuseronly" verification.  Make a new internal
API that accepts flags, move it into `commit.c`.  This
is prep for further work in changing object import to support
reflinks.

Closes: #1193
Approved by: jlebon

src/libostree/ostree-core-private.h
src/libostree/ostree-core.c
src/libostree/ostree-repo-commit.c
src/libostree/ostree-repo-private.h
src/libostree/ostree-repo-pull.c
src/libostree/ostree-repo.c
tests/basic-test.sh
tests/pull-test.sh
tests/test-basic-user-only.sh

index 5a2835d5ced3607835f3d1d3bc4fb808a4898daf..e81537a6e3961520206d170535cb2c1a86ced963 100644 (file)
@@ -134,6 +134,19 @@ static inline char * _ostree_get_commitpartial_path (const char *checksum)
   return g_strconcat ("state/", checksum, ".commitpartial", NULL);
 }
 
+gboolean
+_ostree_validate_bareuseronly_mode (guint32     mode,
+                                    const char *checksum,
+                                    GError    **error);
+static inline gboolean
+_ostree_validate_bareuseronly_mode_finfo (GFileInfo  *finfo,
+                                          const char *checksum,
+                                          GError    **error)
+{
+  const guint32 content_mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode");
+  return _ostree_validate_bareuseronly_mode (content_mode, checksum, error);
+}
+
 gboolean
 _ostree_parse_delta_name (const char  *delta_name,
                           char        **out_from,
index 7d34278a967de0b22faed5a1e0bbcaf701e6007b..e64cee4cad66449cf0c3c84c6e9a2a21cc544f40 100644 (file)
@@ -1998,6 +1998,29 @@ ostree_validate_structureof_dirtree (GVariant      *dirtree,
   return TRUE;
 }
 
+/* This bit mirrors similar code in commit_loose_regfile_object() for the
+ * bare-user-only mode. It's opt-in though for all pulls.
+ */
+gboolean
+_ostree_validate_bareuseronly_mode (guint32     content_mode,
+                                    const char *checksum,
+                                    GError    **error)
+{
+  if (S_ISREG (content_mode))
+    {
+      const guint32 invalid_modebits = ((content_mode & ~S_IFMT) & ~0775);
+      if (invalid_modebits > 0)
+        return glnx_throw (error, "Content object %s: invalid mode 0%04o with bits 0%04o",
+                           checksum, content_mode, invalid_modebits);
+    }
+  else if (S_ISLNK (content_mode))
+    ; /* Nothing */
+  else
+    g_assert_not_reached ();
+
+  return TRUE;
+}
+
 static gboolean
 validate_stat_mode_perms (guint32        mode,
                           GError       **error)
index 04349ed01e3be72e39ef094d3fb66ce5090c9d26..6d770dea3d0cf5c97cecdf9b82218c39d559ab28 100644 (file)
@@ -262,10 +262,8 @@ commit_loose_regfile_object (OstreeRepo        *self,
     }
   else if (self->mode == OSTREE_REPO_MODE_BARE_USER_ONLY)
     {
-      guint32 invalid_modebits = (mode & ~S_IFMT) & ~0775;
-      if (invalid_modebits > 0)
-        return glnx_throw (error, "Invalid mode 0%04o with bits 0%04o in bare-user-only repository",
-                           mode, invalid_modebits);
+      if (!_ostree_validate_bareuseronly_mode (mode, checksum, error))
+        return FALSE;
 
       if (!glnx_fchmod (tmpf->fd, mode, error))
         return FALSE;
@@ -3171,6 +3169,249 @@ G_DEFINE_BOXED_TYPE(OstreeRepoCommitModifier, ostree_repo_commit_modifier,
                     ostree_repo_commit_modifier_ref,
                     ostree_repo_commit_modifier_unref);
 
+/* Special case between bare-user and bare-user-only,
+ * mostly for https://github.com/flatpak/flatpak/issues/845
+ * see below for any more comments.
+ */
+static gboolean
+import_is_bareuser_only_conversion (OstreeRepo *src_repo,
+                                    OstreeRepo *dest_repo,
+                                    OstreeObjectType objtype)
+{
+  return src_repo->mode == OSTREE_REPO_MODE_BARE_USER
+    && dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY
+    && objtype == OSTREE_OBJECT_TYPE_FILE;
+}
+
+/* Returns TRUE if we can potentially just call link() to copy an object. */
+static gboolean
+import_via_hardlink_is_possible (OstreeRepo *src_repo,
+                                 OstreeRepo *dest_repo,
+                                 OstreeObjectType objtype)
+{
+  /* We need the ability to make hardlinks */
+  if (src_repo->owner_uid != dest_repo->owner_uid)
+    return FALSE;
+  /* Equal modes are always compatible */
+  if (src_repo->mode == dest_repo->mode)
+    return TRUE;
+  /* Metadata is identical between all modes */
+  if (OSTREE_OBJECT_TYPE_IS_META (objtype))
+    return TRUE;
+  /* And now a special case between bare-user and bare-user-only,
+   * mostly for https://github.com/flatpak/flatpak/issues/845
+   */
+  if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype))
+    return TRUE;
+  return FALSE;
+}
+
+/* Copy the detached metadata for commit @checksum from @source repo
+ * to @self.
+ */
+static gboolean
+copy_detached_metadata (OstreeRepo    *self,
+                        OstreeRepo    *source,
+                        const char   *checksum,
+                        GCancellable  *cancellable,
+                        GError        **error)
+{
+  g_autoptr(GVariant) detached_meta = NULL;
+  if (!ostree_repo_read_commit_detached_metadata (source,
+                                                  checksum, &detached_meta,
+                                                  cancellable, error))
+    return FALSE;
+
+  if (detached_meta)
+    {
+      if (!ostree_repo_write_commit_detached_metadata (self,
+                                                       checksum, detached_meta,
+                                                       cancellable, error))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Try to import an object by just calling linkat(); returns
+ * a value in @out_was_supported if we were able to do it or not.
+ */
+static gboolean
+import_one_object_link (OstreeRepo    *self,
+                        OstreeRepo    *source,
+                        const char   *checksum,
+                        OstreeObjectType objtype,
+                        gboolean       *out_was_supported,
+                        GCancellable  *cancellable,
+                        GError        **error)
+{
+  const char *errprefix = glnx_strjoina ("Importing ", checksum, ".",
+                                         ostree_object_type_to_string (objtype));
+  GLNX_AUTO_PREFIX_ERROR (errprefix, error);
+  char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
+  _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode);
+
+  /* Hardlinking between bare-user → bare-user-only is only possible for regular
+   * files, *not* symlinks, which in bare-user are stored as regular files.  At
+   * this point we need to parse the file to see the difference.
+   */
+  if (import_is_bareuser_only_conversion (source, self, objtype))
+    {
+      struct stat stbuf;
+
+      if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf,
+                                        NULL, NULL, cancellable, error))
+        return FALSE;
+
+      if (S_ISREG (stbuf.st_mode))
+        {
+          /* This is OK, we'll drop through and try a hardlink */
+        }
+      else if (S_ISLNK (stbuf.st_mode))
+        {
+          /* NOTE early return */
+          *out_was_supported = FALSE;
+          return TRUE;
+        }
+      else
+        g_assert_not_reached ();
+    }
+
+  if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error))
+    return FALSE;
+
+  *out_was_supported = TRUE;
+  if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0)
+    {
+      if (errno == EEXIST)
+        return TRUE;
+      else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
+        {
+          /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the
+           * optimization of hardlinking instead of copying.
+           */
+          *out_was_supported = FALSE;
+          return TRUE;
+        }
+      else
+        return glnx_throw_errno_prefix (error, "linkat");
+    }
+
+  if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
+    {
+      if (!copy_detached_metadata (self, source, checksum, cancellable, error))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* A version of ostree_repo_import_object_from_with_trust()
+ * with flags; may make this public API later.
+ */
+gboolean
+_ostree_repo_import_object (OstreeRepo           *self,
+                            OstreeRepo           *source,
+                            OstreeObjectType      objtype,
+                            const char           *checksum,
+                            OstreeRepoImportFlags flags,
+                            GCancellable         *cancellable,
+                            GError              **error)
+{
+  const gboolean trusted = (flags & _OSTREE_REPO_IMPORT_FLAGS_TRUSTED) > 0;
+  /* Implements OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES which was designed for flatpak */
+  const gboolean verify_bareuseronly = (flags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0;
+
+  /* If we need to do bareuseronly verification, let's dispense with that
+   * first so we don't complicate the rest of the code below.
+   */
+  if (verify_bareuseronly && !OSTREE_OBJECT_TYPE_IS_META (objtype))
+    {
+      g_autoptr(GFileInfo) src_finfo = NULL;
+      if (!ostree_repo_load_file (source, checksum,
+                                  NULL, &src_finfo, NULL,
+                                  cancellable, error))
+        return FALSE;
+
+      if (!_ostree_validate_bareuseronly_mode_finfo (src_finfo, checksum, error))
+        return FALSE;
+    }
+
+   /* We try to import via hardlink. If the remote is explicitly not trusted
+   * (i.e.) their checksums may be incorrect, we skip that. Also, we require the
+   * repository modes to match, as well as the owner uid (since we need to be
+   * able to make hardlinks).
+   */
+  if (trusted && import_via_hardlink_is_possible (source, self, objtype))
+    {
+      gboolean hardlink_was_supported = FALSE;
+
+      if (!import_one_object_link (self, source, checksum, objtype,
+                                   &hardlink_was_supported,
+                                   cancellable, error))
+        return FALSE;
+
+      /* If we hardlinked, we're done! */
+      if (hardlink_was_supported)
+        return TRUE;
+    }
+
+  /* The copy path */
+
+  /* First, do we have the object already? */
+  gboolean has_object;
+  if (!ostree_repo_has_object (self, objtype, checksum, &has_object,
+                               cancellable, error))
+    return FALSE;
+  /* If we have it, we're done */
+  if (has_object)
+    return TRUE;
+
+  if (OSTREE_OBJECT_TYPE_IS_META (objtype))
+    {
+      /* Metadata object */
+      g_autoptr(GVariant) variant = NULL;
+
+      if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
+        {
+          /* FIXME - cleanup detached metadata if copy below fails */
+          if (!copy_detached_metadata (self, source, checksum, cancellable, error))
+            return FALSE;
+        }
+
+      if (!ostree_repo_load_variant (source, objtype, checksum,
+                                     &variant, error))
+        return FALSE;
+
+      g_autofree guchar *real_csum = NULL;
+      if (!ostree_repo_write_metadata (self, objtype,
+                                       checksum, variant,
+                                       trusted ? NULL : &real_csum,
+                                       cancellable, error))
+        return FALSE;
+    }
+  else
+    {
+      /* Content object */
+      guint64 length;
+      g_autoptr(GInputStream) object_stream = NULL;
+
+      if (!ostree_repo_load_object_stream (source, objtype, checksum,
+                                           &object_stream, &length,
+                                           cancellable, error))
+        return FALSE;
+
+      g_autofree guchar *real_csum = NULL;
+      if (!ostree_repo_write_content (self, checksum,
+                                      object_stream, length,
+                                      trusted ? NULL : &real_csum,
+                                      cancellable, error))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
 static OstreeRepoTransactionStats *
 ostree_repo_transaction_stats_copy (OstreeRepoTransactionStats *stats)
 {
index dc78569058908c78e3078429cff6fdd9c20346ea..f5eb140e2924e859b75b7a1a6c251a1f8e6df40c 100644 (file)
@@ -343,6 +343,21 @@ _ostree_repo_verify_commit_internal (OstreeRepo    *self,
                                      GCancellable  *cancellable,
                                      GError       **error);
 
+typedef enum {
+  _OSTREE_REPO_IMPORT_FLAGS_NONE,
+  _OSTREE_REPO_IMPORT_FLAGS_TRUSTED,
+  _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY,
+} OstreeRepoImportFlags;
+
+gboolean
+_ostree_repo_import_object (OstreeRepo           *self,
+                            OstreeRepo           *source,
+                            OstreeObjectType      objtype,
+                            const char           *checksum,
+                            OstreeRepoImportFlags flags,
+                            GCancellable         *cancellable,
+                            GError              **error);
+
 gboolean
 _ostree_repo_commit_tmpf_final (OstreeRepo        *self,
                                 const char        *checksum,
index 5c36e081c2faa3ac5fe750c98af686baa4f6ac54..d8d2e34bbe08eb035a139193ca229ee22e243621 100644 (file)
@@ -623,33 +623,6 @@ pull_matches_subdir (OtPullData *pull_data,
   return FALSE;
 }
 
-/* This bit mirrors similar code in commit_loose_content_object() for the
- * bare-user-only mode. It's opt-in though for all pulls.
- */
-static gboolean
-validate_bareuseronly_mode (OtPullData *pull_data,
-                            const char *checksum,
-                            guint32     content_mode,
-                            GError    **error)
-{
-  if (!pull_data->is_bareuseronly_files)
-    return TRUE;
-
-  if (S_ISREG (content_mode))
-    {
-      const guint32 invalid_modebits = ((content_mode & ~S_IFMT) & ~0775);
-      if (invalid_modebits > 0)
-        return glnx_throw (error, "object %s.file: invalid mode 0%04o with bits 0%04o",
-                           checksum, content_mode, invalid_modebits);
-    }
-  else if (S_ISLNK (content_mode))
-    ; /* Nothing */
-  else
-    g_assert_not_reached ();
-
-  return TRUE;
-}
-
 /* Synchronously import a single content object; this is used async for content,
  * or synchronously for metadata. @src_repo is either
  * pull_data->remote_repo_local or one of pull_data->localcache_repos.
@@ -664,51 +637,14 @@ import_one_local_content_object_sync (OtPullData *pull_data,
                                       GCancellable *cancellable,
                                       GError    **error)
 {
-  const gboolean trusted = !pull_data->is_untrusted;
-  if (trusted && !pull_data->is_bareuseronly_files)
-    {
-      if (!ostree_repo_import_object_from_with_trust (pull_data->repo, src_repo,
-                                                      OSTREE_OBJECT_TYPE_FILE, checksum,
-                                                      trusted,
-                                                      cancellable, error))
-        return FALSE;
-    }
-  else
-    {
-      /* In this case we either need to validate the checksum
-       * or the file mode.
-       */
-      g_autoptr(GInputStream) content_input = NULL;
-      g_autoptr(GFileInfo) content_finfo = NULL;
-      g_autoptr(GVariant) content_xattrs = NULL;
-
-      if (!ostree_repo_load_file (src_repo, checksum,
-                                  &content_input, &content_finfo, &content_xattrs,
-                                  cancellable, error))
-        return FALSE;
-
-      if (!validate_bareuseronly_mode (pull_data, checksum,
-                                       g_file_info_get_attribute_uint32 (content_finfo, "unix::mode"),
-                                       error))
-        return FALSE;
-
-      /* Now that we've potentially validated it, convert to object stream */
-      guint64 length;
-      g_autoptr(GInputStream) object_stream = NULL;
-      if (!ostree_raw_file_to_content_stream (content_input, content_finfo,
-                                              content_xattrs, &object_stream,
-                                              &length, cancellable, error))
-        return FALSE;
-
-      g_autofree guchar *real_csum = NULL;
-      if (!ostree_repo_write_content (pull_data->repo, checksum,
-                                      object_stream, length,
-                                      &real_csum,
-                                      cancellable, error))
-        return FALSE;
-    }
-
-  return TRUE;
+  OstreeRepoImportFlags flags = _OSTREE_REPO_IMPORT_FLAGS_NONE;
+  if (!pull_data->is_untrusted)
+    flags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED;
+  if (pull_data->is_bareuseronly_files)
+    flags |= _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY;
+  return _ostree_repo_import_object (pull_data->repo, src_repo,
+                                     OSTREE_OBJECT_TYPE_FILE, checksum,
+                                     flags, cancellable, error);
 }
 
 typedef struct {
@@ -1129,11 +1065,11 @@ content_fetch_on_complete (GObject        *object,
        */
       ot_cleanup_unlinkat (&tmp_unlinker);
 
-      if (!validate_bareuseronly_mode (pull_data,
-                                       checksum,
-                                       g_file_info_get_attribute_uint32 (file_info, "unix::mode"),
-                                       error))
-        goto out;
+      if (pull_data->is_bareuseronly_files)
+        {
+          if (!_ostree_validate_bareuseronly_mode_finfo (file_info, checksum, error))
+            goto out;
+        }
 
       if (!ostree_raw_file_to_content_stream (file_in, file_info, xattrs,
                                               &object_input, &length,
index e04a1b6aa11b14bdc8a980c1f5d97981ca3d3c16..5c3c298753f1f3046ccf44283b669d6f59b6c63b 100644 (file)
@@ -3367,114 +3367,6 @@ ostree_repo_delete_object (OstreeRepo           *self,
   return TRUE;
 }
 
-static gboolean
-copy_detached_metadata (OstreeRepo    *self,
-                        OstreeRepo    *source,
-                        const char   *checksum,
-                        GCancellable  *cancellable,
-                        GError        **error)
-{
-  g_autoptr(GVariant) detached_meta = NULL;
-  if (!ostree_repo_read_commit_detached_metadata (source,
-                                                  checksum, &detached_meta,
-                                                  cancellable, error))
-    return FALSE;
-
-  if (detached_meta)
-    {
-      if (!ostree_repo_write_commit_detached_metadata (self,
-                                                       checksum, detached_meta,
-                                                       cancellable, error))
-        return FALSE;
-    }
-
-  return TRUE;
-}
-
-/* Special case between bare-user and bare-user-only,
- * mostly for https://github.com/flatpak/flatpak/issues/845
- * see below for any more comments.
- */
-static gboolean
-import_is_bareuser_only_conversion (OstreeRepo *src_repo,
-                                    OstreeRepo *dest_repo,
-                                    OstreeObjectType objtype)
-{
-  return src_repo->mode == OSTREE_REPO_MODE_BARE_USER
-    && dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY
-    && objtype == OSTREE_OBJECT_TYPE_FILE;
-}
-
-static gboolean
-import_one_object_link (OstreeRepo    *self,
-                        OstreeRepo    *source,
-                        const char   *checksum,
-                        OstreeObjectType objtype,
-                        gboolean       *out_was_supported,
-                        GCancellable  *cancellable,
-                        GError        **error)
-{
-  const char *errprefix = glnx_strjoina ("Importing ", checksum, ".",
-                                         ostree_object_type_to_string (objtype));
-  GLNX_AUTO_PREFIX_ERROR (errprefix, error);
-  char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
-  _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode);
-
-  /* Hardlinking between bare-user → bare-user-only is only possible for regular
-   * files, *not* symlinks, which in bare-user are stored as regular files.  At
-   * this point we need to parse the file to see the difference.
-   */
-  if (import_is_bareuser_only_conversion (source, self, objtype))
-    {
-      struct stat stbuf;
-
-      if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf,
-                                        NULL, NULL, cancellable, error))
-        return FALSE;
-
-      if (S_ISREG (stbuf.st_mode))
-        {
-          /* This is OK, we'll drop through and try a hardlink */
-        }
-      else if (S_ISLNK (stbuf.st_mode))
-        {
-          /* NOTE early return */
-          *out_was_supported = FALSE;
-          return TRUE;
-        }
-      else
-        g_assert_not_reached ();
-    }
-
-  if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error))
-    return FALSE;
-
-  *out_was_supported = TRUE;
-  if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0)
-    {
-      if (errno == EEXIST)
-        return TRUE;
-      else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
-        {
-          /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the
-           * optimization of hardlinking instead of copying.
-           */
-          *out_was_supported = FALSE;
-          return TRUE;
-        }
-      else
-        return glnx_throw_errno_prefix (error, "linkat");
-    }
-
-  if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
-    {
-      if (!copy_detached_metadata (self, source, checksum, cancellable, error))
-        return FALSE;
-    }
-
-  return TRUE;
-}
-
 /**
  * ostree_repo_import_object_from:
  * @self: Destination repo
@@ -3504,28 +3396,6 @@ ostree_repo_import_object_from (OstreeRepo           *self,
                                                checksum, TRUE, cancellable, error);
 }
 
-static gboolean
-import_via_hardlink_is_possible (OstreeRepo *src_repo,
-                                 OstreeRepo *dest_repo,
-                                 OstreeObjectType objtype)
-{
-  /* We need the ability to make hardlinks */
-  if (src_repo->owner_uid != dest_repo->owner_uid)
-    return FALSE;
-  /* Equal modes are always compatible */
-  if (src_repo->mode == dest_repo->mode)
-    return TRUE;
-  /* Metadata is identical between all modes */
-  if (OSTREE_OBJECT_TYPE_IS_META (objtype))
-    return TRUE;
-  /* And now a special case between bare-user and bare-user-only,
-   * mostly for https://github.com/flatpak/flatpak/issues/845
-   */
-  if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype))
-    return TRUE;
-  return FALSE;
-}
-
 /**
  * ostree_repo_import_object_from_with_trust:
  * @self: Destination repo
@@ -3552,82 +3422,12 @@ ostree_repo_import_object_from_with_trust (OstreeRepo           *self,
                                            GCancellable         *cancellable,
                                            GError              **error)
 {
-  /* We try to import via hardlink. If the remote is explicitly not trusted
-   * (i.e.) their checksums may be incorrect, we skip that. Also, we require the
-   * repository modes to match, as well as the owner uid (since we need to be
-   * able to make hardlinks).
-   */
-  if (trusted && import_via_hardlink_is_possible (source, self, objtype))
-    {
-      gboolean hardlink_was_supported = FALSE;
-
-      if (!import_one_object_link (self, source, checksum, objtype,
-                                   &hardlink_was_supported,
-                                   cancellable, error))
-        return FALSE;
-
-      /* If we hardlinked, we're done! */
-      if (hardlink_was_supported)
-        return TRUE;
-    }
-
-  /* The copy path */
-
-  /* First, do we have the object already? */
-  gboolean has_object;
-  if (!ostree_repo_has_object (self, objtype, checksum, &has_object,
-                               cancellable, error))
-    return FALSE;
-  /* If we have it, we're done */
-  if (has_object)
-    return TRUE;
-
-  if (OSTREE_OBJECT_TYPE_IS_META (objtype))
-    {
-      /* Metadata object */
-      g_autoptr(GVariant) variant = NULL;
-
-      if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
-        {
-          /* FIXME - cleanup detached metadata if copy below fails */
-          if (!copy_detached_metadata (self, source, checksum, cancellable, error))
-            return FALSE;
-        }
-
-      if (!ostree_repo_load_variant (source, objtype, checksum,
-                                     &variant, error))
-        return FALSE;
-
-      g_autofree guchar *real_csum = NULL;
-      if (!ostree_repo_write_metadata (self, objtype,
-                                       checksum, variant,
-                                       trusted ? NULL : &real_csum,
-                                       cancellable, error))
-        return FALSE;
-    }
-  else
-    {
-      /* Content object */
-      guint64 length;
-      g_autoptr(GInputStream) object_stream = NULL;
-
-      if (!ostree_repo_load_object_stream (source, objtype, checksum,
-                                           &object_stream, &length,
-                                           cancellable, error))
-        return FALSE;
-
-      g_autofree guchar *real_csum = NULL;
-      if (!ostree_repo_write_content (self, checksum,
-                                      object_stream, length,
-                                      trusted ? NULL : &real_csum,
-                                      cancellable, error))
-        return FALSE;
-    }
-
-  return TRUE;
+  /* This just wraps a currently internal API, may make it public later */
+  OstreeRepoImportFlags flags = trusted ? _OSTREE_REPO_IMPORT_FLAGS_TRUSTED : 0;
+  return _ostree_repo_import_object (self, source, objtype, checksum,
+                                     flags, cancellable, error);
 }
 
-
 /**
  * ostree_repo_query_object_storage_size:
  * @self: Repo
index 218bc31c38e3563b72c3f448d1ca162feaaa6e2f..742b1adaaabfd561f9d7569e7a997c734f37c189 100644 (file)
@@ -314,7 +314,7 @@ $CMD_PREFIX ostree --repo=repo-input commit -b content-with-suid --statoverride=
 if $CMD_PREFIX ostree pull-local --repo=repo --bareuseronly-files repo-input content-with-suid 2>err.txt; then
     assert_not_reached "copying suid file with --bareuseronly-files worked?"
 fi
-assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*'
+assert_file_has_content err.txt 'Content object.*: invalid mode.*with bits 040.*'
 echo "ok pull-local (bareuseronly files)"
 
 if ! skip_one_without_user_xattrs; then
index f44c2cedd9427ad144f04f9cf343355dece1f5f2..3780d1ad57a92adc02fc49b84ff6c10be3539d24 100644 (file)
@@ -127,7 +127,7 @@ for flag in "" "--mirror"; do
     if ${CMD_PREFIX} ostree --repo=mirrorrepo pull ${flag} --bareuseronly-files origin content-with-suid 2>err.txt; then
         assert_not_reached "pulled unsafe bareuseronly"
     fi
-    assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*'
+    assert_file_has_content err.txt 'Content object.*: invalid mode.*with bits 040.*'
 done
 echo "ok pull (bareuseronly, unsafe)"
 
index ce69e49e8e7e2c53e9a0c2e205cd226d5d489aa8..19262b7b6ed7655c2e3145341d2172df1b8e379a 100755 (executable)
@@ -45,7 +45,7 @@ $CMD_PREFIX ostree --repo=repo-input commit -b content-with-suid --statoverride=
 if $CMD_PREFIX ostree pull-local --repo=repo repo-input 2>err.txt; then
     assert_not_reached "copying suid file into bare-user worked?"
 fi
-assert_file_has_content err.txt "Invalid mode.*with bits 040.*in bare-user-only"
+assert_file_has_content err.txt "Content object.*invalid mode.*with bits 040.*"
 echo "ok failed to commit suid"
 
 cd ${test_tmpdir}