[ostree] ostree_repo_checkout_tree_at: New API for checkouts



commit c2aabcac3b69aa64ac6eb9c9b09c237e24634a65
Author: Colin Walters <walters verbum org>
Date:   Mon Apr 6 18:29:01 2015 -0400

    ostree_repo_checkout_tree_at: New API for checkouts
    
    rpm-ostree currently uses ostree_repo_checkout_tree(), which as a side
    effect will use the uncompressed objects cache by default.  This is
    rather annoying if you're using rpm-ostree on a server-side
    repository, because if you then rsync the repo, you'll be syncing out
    the uncompressed objects unless you exclude them.
    
    We added the ability to disable the uncompressed cache in the
    repository config to fix this, but it's better to allow application
    control over this.  The uncompressed cache will in some future version
    become opt in as well.
    
    This new API further:
     - Drops the `GFile` usage in favor of `openat` APIs
     - Improves ergonomics by avoiding callers having to query the source
       `GFileInfo` (and carry around a copy of `OSTREE_GIO_FAST_QUERYINFO`)
     - Has a more extensible options structure
    
    Per the comment, I rather crudely have the `ostree checkout` builtin
    call both APIs to ensure some testing coverage.
    
    However, I'd like to in the future have easier-to-set-up testing code
    that calls `libtest.sh` to set up dummy data.

 doc/ostree-sections.txt              |    1 +
 src/libostree/ostree-repo-checkout.c |  154 ++++++++++++++++++++++++++--------
 src/libostree/ostree-repo.h          |   30 +++++++
 src/ostree/ot-builtin-checkout.c     |  100 ++++++++++++++--------
 tests/basic-test.sh                  |   21 +++++-
 5 files changed, 232 insertions(+), 74 deletions(-)
---
diff --git a/doc/ostree-sections.txt b/doc/ostree-sections.txt
index 3452ce9..f8fca73 100644
--- a/doc/ostree-sections.txt
+++ b/doc/ostree-sections.txt
@@ -277,6 +277,7 @@ ostree_repo_write_commit_detached_metadata
 OstreeRepoCheckoutMode
 OstreeRepoCheckoutOverwriteMode
 ostree_repo_checkout_tree
+ostree_repo_checkout_tree_at
 ostree_repo_checkout_gc
 ostree_repo_read_commit
 OstreeRepoListObjectsFlags
diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c
index 22aaf56..e6c321b 100644
--- a/src/libostree/ostree-repo-checkout.c
+++ b/src/libostree/ostree-repo-checkout.c
@@ -173,7 +173,7 @@ write_regular_file_content (OstreeRepo            *self,
 
 static gboolean
 checkout_file_from_input_at (OstreeRepo     *self,
-                             OstreeRepoCheckoutMode mode,
+                             OstreeRepoCheckoutOptions *options,
                              GFileInfo      *file_info,
                              GVariant       *xattrs,
                              GInputStream   *input,
@@ -197,7 +197,7 @@ checkout_file_from_input_at (OstreeRepo     *self,
           goto out;
         }
 
-      if (mode != OSTREE_REPO_CHECKOUT_MODE_USER)
+      if (options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
         {
           if (G_UNLIKELY (fchownat (destination_dfd, destination_name,
                                     g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
@@ -224,7 +224,7 @@ checkout_file_from_input_at (OstreeRepo     *self,
 
       file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
       /* Don't make setuid files on checkout when we're doing --user */
-      if (mode == OSTREE_REPO_CHECKOUT_MODE_USER)
+      if (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
         file_mode &= ~(S_ISUID|S_ISGID);
 
       do
@@ -238,7 +238,7 @@ checkout_file_from_input_at (OstreeRepo     *self,
       temp_out = g_unix_output_stream_new (fd, TRUE);
       fd = -1; /* Transfer ownership */
 
-      if (!write_regular_file_content (self, mode, temp_out, file_info, xattrs, input,
+      if (!write_regular_file_content (self, options->mode, temp_out, file_info, xattrs, input,
                                        cancellable, error))
         goto out;
     }
@@ -256,7 +256,7 @@ checkout_file_from_input_at (OstreeRepo     *self,
  */
 static gboolean
 checkout_file_unioning_from_input_at (OstreeRepo     *repo,
-                                      OstreeRepoCheckoutMode mode,
+                                      OstreeRepoCheckoutOptions  *options,
                                       GFileInfo      *file_info,
                                       GVariant       *xattrs,
                                       GInputStream   *input,
@@ -290,7 +290,7 @@ checkout_file_unioning_from_input_at (OstreeRepo     *repo,
 
       file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
       /* Don't make setuid files on checkout when we're doing --user */
-      if (mode == OSTREE_REPO_CHECKOUT_MODE_USER)
+      if (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
         file_mode &= ~(S_ISUID|S_ISGID);
 
       if (!gs_file_open_in_tmpdir_at (destination_dfd, file_mode,
@@ -298,7 +298,7 @@ checkout_file_unioning_from_input_at (OstreeRepo     *repo,
                                       cancellable, error))
         goto out;
 
-      if (!write_regular_file_content (repo, mode, temp_out, file_info, xattrs, input,
+      if (!write_regular_file_content (repo, options->mode, temp_out, file_info, xattrs, input,
                                        cancellable, error))
         goto out;
     }
@@ -319,8 +319,7 @@ checkout_file_unioning_from_input_at (OstreeRepo     *repo,
 
 static gboolean
 checkout_file_hardlink (OstreeRepo                          *self,
-                        OstreeRepoCheckoutMode               mode,
-                        OstreeRepoCheckoutOverwriteMode      overwrite_mode,
+                        OstreeRepoCheckoutOptions           *options,
                         const char                          *loose_path,
                         int                                  destination_dfd,
                         const char                          *destination_name,
@@ -348,7 +347,7 @@ checkout_file_hardlink (OstreeRepo                          *self,
     {
       ret_was_supported = FALSE;
     }
-  else if (errno == EEXIST && overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
+  else if (errno == EEXIST && options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
     { 
       /* Idiocy, from man rename(2)
        *
@@ -377,18 +376,18 @@ checkout_file_hardlink (OstreeRepo                          *self,
 
 static gboolean
 checkout_one_file_at (OstreeRepo                        *repo,
+                      OstreeRepoCheckoutOptions         *options,
                       GFile                             *source,
                       GFileInfo                         *source_info,
                       int                                destination_dfd,
                       const char                        *destination_name,
-                      OstreeRepoCheckoutMode             mode,
-                      OstreeRepoCheckoutOverwriteMode    overwrite_mode,
                       GCancellable                      *cancellable,
                       GError                           **error)
 {
   gboolean ret = FALSE;
   const char *checksum;
   gboolean is_symlink;
+  gboolean can_cache;
   gboolean did_hardlink = FALSE;
   char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
   gs_unref_object GInputStream *input = NULL;
@@ -408,12 +407,14 @@ checkout_one_file_at (OstreeRepo                        *repo,
       while (current_repo)
         {
           gboolean is_bare = ((current_repo->mode == OSTREE_REPO_MODE_BARE
-                               && mode == OSTREE_REPO_CHECKOUT_MODE_NONE) ||
+                               && options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) ||
                               (current_repo->mode == OSTREE_REPO_MODE_BARE_USER
-                               && mode == OSTREE_REPO_CHECKOUT_MODE_USER));
+                               && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER));
+          gboolean current_can_cache = (options->enable_uncompressed_cache
+                                        && current_repo->enable_uncompressed_cache);
           gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
-                                               && mode == OSTREE_REPO_CHECKOUT_MODE_USER
-                                               && current_repo->enable_uncompressed_cache);
+                                               && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER
+                                               && current_can_cache);
 
           /* But only under these conditions */
           if (is_bare || is_archive_z2_with_cache)
@@ -422,7 +423,8 @@ checkout_one_file_at (OstreeRepo                        *repo,
                  the cache, which is in "bare" form */
               _ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, OSTREE_REPO_MODE_BARE);
               if (!checkout_file_hardlink (current_repo,
-                                           mode, overwrite_mode, loose_path_buf,
+                                           options,
+                                           loose_path_buf,
                                            destination_dfd, destination_name,
                                            TRUE, &did_hardlink,
                                            cancellable, error))
@@ -434,14 +436,17 @@ checkout_one_file_at (OstreeRepo                        *repo,
         }
     }
 
+  can_cache = (options->enable_uncompressed_cache
+               && repo->enable_uncompressed_cache);
+
   /* Ok, if we're archive-z2 and we didn't find an object, uncompress
    * it now, stick it in the cache, and then hardlink to that.
    */
-  if (!is_symlink
+  if (can_cache
+      && !is_symlink
       && !did_hardlink
       && repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
-      && mode == OSTREE_REPO_CHECKOUT_MODE_USER
-      && repo->enable_uncompressed_cache)
+      && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
     {
       if (!ostree_repo_load_file (repo, checksum, &input, NULL, NULL,
                                   cancellable, error))
@@ -485,7 +490,7 @@ checkout_one_file_at (OstreeRepo                        *repo,
       }
       g_mutex_unlock (&repo->cache_lock);
 
-      if (!checkout_file_hardlink (repo, mode, overwrite_mode, loose_path_buf,
+      if (!checkout_file_hardlink (repo, options, loose_path_buf,
                                    destination_dfd, destination_name,
                                    FALSE, &did_hardlink,
                                    cancellable, error))
@@ -502,9 +507,9 @@ checkout_one_file_at (OstreeRepo                        *repo,
                                   cancellable, error))
         goto out;
 
-      if (overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
+      if (options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
         {
-          if (!checkout_file_unioning_from_input_at (repo, mode, source_info, xattrs, input,
+          if (!checkout_file_unioning_from_input_at (repo, options, source_info, xattrs, input,
                                                      destination_dfd,
                                                      destination_name,
                                                      cancellable, error)) 
@@ -515,7 +520,7 @@ checkout_one_file_at (OstreeRepo                        *repo,
         }
       else
         {
-          if (!checkout_file_from_input_at (repo, mode, source_info, xattrs, input,
+          if (!checkout_file_from_input_at (repo, options, source_info, xattrs, input,
                                             destination_dfd,
                                             destination_name,
                                             cancellable, error))
@@ -554,8 +559,7 @@ checkout_one_file_at (OstreeRepo                        *repo,
  */
 static gboolean
 checkout_tree_at (OstreeRepo                        *self,
-                  OstreeRepoCheckoutMode             mode,
-                  OstreeRepoCheckoutOverwriteMode    overwrite_mode,
+                  OstreeRepoCheckoutOptions         *options,
                   int                                destination_parent_fd,
                   const char                        *destination_name,
                   OstreeRepoFile                    *source,
@@ -579,7 +583,7 @@ checkout_tree_at (OstreeRepo                        *self,
   while (G_UNLIKELY (res == -1 && errno == EINTR));
   if (res == -1)
     {
-      if (errno == EEXIST && overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
+      if (errno == EEXIST && options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
         did_exist = TRUE;
       else
         {
@@ -594,7 +598,7 @@ checkout_tree_at (OstreeRepo                        *self,
     goto out;
 
   /* Set the xattrs now, so any derived labeling works */
-  if (!did_exist && mode != OSTREE_REPO_CHECKOUT_MODE_USER)
+  if (!did_exist && options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
     {
       if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
         goto out;
@@ -608,11 +612,11 @@ checkout_tree_at (OstreeRepo                        *self,
 
   if (g_file_info_get_file_type (source_info) != G_FILE_TYPE_DIRECTORY)
     {
-      ret = checkout_one_file_at (self, (GFile *) source,
+      ret = checkout_one_file_at (self, options,
+                                  (GFile *) source,
                                   source_info,
                                   destination_dfd,
                                   g_file_info_get_name (source_info),
-                                  mode, TRUE,
                                   cancellable, error);
       goto out;
     }
@@ -640,7 +644,7 @@ checkout_tree_at (OstreeRepo                        *self,
 
       if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
         {
-          if (!checkout_tree_at (self, mode, overwrite_mode,
+          if (!checkout_tree_at (self, options,
                                  destination_dfd, name,
                                  (OstreeRepoFile*)src_child, file_info,
                                  cancellable, error))
@@ -648,9 +652,9 @@ checkout_tree_at (OstreeRepo                        *self,
         }
       else
         {
-          if (!checkout_one_file_at (self, src_child, file_info,
+          if (!checkout_one_file_at (self, options,
+                                     src_child, file_info,
                                      destination_dfd, name,
-                                     mode, overwrite_mode,
                                      cancellable, error))
             goto out;
         }
@@ -672,7 +676,7 @@ checkout_tree_at (OstreeRepo                        *self,
         }
     }
 
-  if (!did_exist && mode != OSTREE_REPO_CHECKOUT_MODE_USER)
+  if (!did_exist && options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
     {
       do
         res = fchown (destination_dfd,
@@ -748,14 +752,90 @@ ostree_repo_checkout_tree (OstreeRepo               *self,
                            GCancellable             *cancellable,
                            GError                  **error)
 {
-  return checkout_tree_at (self, mode, overwrite_mode,
-                           AT_FDCWD,
-                           gs_file_get_path_cached (destination),
+  OstreeRepoCheckoutOptions options = { 0, };
+
+  options.mode = mode;
+  options.overwrite_mode = overwrite_mode;
+  /* Backwards compatibility */
+  options.enable_uncompressed_cache = TRUE;
+
+  return checkout_tree_at (self, &options,
+                           AT_FDCWD, gs_file_get_path_cached (destination),
                            source, source_info,
                            cancellable, error);
 }
 
 /**
+ * ostree_repo_checkout_tree_at:
+ * @self: Repo
+ * @options: (allow-none): Options
+ * @destination_dfd: Directory FD for destination
+ * @destination_path: Directory for destination
+ * @commit: Checksum for commit
+ * @subpath: (allow-none): Subdirectory path
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Similar to ostree_repo_checkout_tree(), but uses directory-relative
+ * paths for the destination, uses a new `OstreeRepoCheckoutOptions`,
+ * and takes a commit checksum and optional subpath pair, rather than
+ * requiring use of `GFile` APIs for the caller.
+ *
+ * Note in addition that unlike ostree_repo_checkout_tree(), the
+ * default is not to use the repository-internal uncompressed objects
+ * cache.
+ */
+gboolean
+ostree_repo_checkout_tree_at (OstreeRepo                         *self,
+                              OstreeRepoCheckoutOptions         *options,
+                              int                                destination_dfd,
+                              const char                        *destination_path,
+                              const char                        *commit,
+                              GCancellable                      *cancellable,
+                              GError                           **error)
+{
+  gboolean ret = FALSE;
+  gs_unref_object GFile* commit_root = NULL;
+  gs_unref_object GFile* target_dir = NULL;
+  gs_unref_object GFileInfo* target_info = NULL;
+  OstreeRepoCheckoutOptions default_options = { 0, };
+
+  if (!options)
+    {
+      default_options.subpath = NULL;
+      options = &default_options;
+    }
+
+  commit_root = (GFile*) _ostree_repo_file_new_for_commit (self, commit, error);
+  if (!commit_root)
+    goto out;
+
+  if (!ostree_repo_file_ensure_resolved ((OstreeRepoFile*)commit_root, error))
+    goto out;
+
+  if (options->subpath && strcmp (options->subpath, "/") != 0)
+    target_dir = g_file_get_child (commit_root, options->subpath);
+  else
+    target_dir = g_object_ref (commit_root);
+  target_info = g_file_query_info (target_dir, OSTREE_GIO_FAST_QUERYINFO,
+                                   G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                   cancellable, error);
+  if (!target_info)
+    goto out;
+
+  if (!checkout_tree_at (self, options,
+                         destination_dfd,
+                         destination_path,
+                         (OstreeRepoFile*)target_dir, target_info,
+                         cancellable, error))
+    goto out;
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+/**
  * ostree_repo_checkout_gc:
  * @self: Repo
  * @cancellable: Cancellable
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index e775b54..7f0c85d 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -449,6 +449,36 @@ ostree_repo_checkout_tree (OstreeRepo               *self,
                            GCancellable             *cancellable,
                            GError                  **error);
 
+/**
+ * OstreeRepoCheckoutOptions:
+ *
+ * An extensible options structure controlling checkout.  Ensure that
+ * you have entirely zeroed the structure, then set just the desired
+ * options.  This is used by ostree_repo_checkout_tree_at() which
+ * supercedes previous separate enumeration usage in
+ * ostree_repo_checkout_tree().
+ */
+typedef struct {
+  OstreeRepoCheckoutMode mode;
+  OstreeRepoCheckoutOverwriteMode overwrite_mode;
+  
+  guint enable_uncompressed_cache : 1;
+  guint unused : 31;
+
+  const char *subpath;
+
+  guint unused_uints[6];
+  gpointer unused_ptrs[8];
+} OstreeRepoCheckoutOptions;
+
+gboolean ostree_repo_checkout_tree_at (OstreeRepo                         *self,
+                                       OstreeRepoCheckoutOptions          *options,
+                                       int                                 destination_dfd,
+                                       const char                         *destination_path,
+                                       const char                         *commit,
+                                       GCancellable                       *cancellable,
+                                       GError                            **error);
+
 gboolean       ostree_repo_checkout_gc (OstreeRepo        *self,
                                         GCancellable      *cancellable,
                                         GError           **error);
diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c
index 39d9afc..8a3e1c6 100644
--- a/src/ostree/ot-builtin-checkout.c
+++ b/src/ostree/ot-builtin-checkout.c
@@ -33,6 +33,7 @@
 
 static gboolean opt_user_mode;
 static gboolean opt_allow_noent;
+static gboolean opt_disable_cache;
 static char *opt_subpath;
 static gboolean opt_union;
 static gboolean opt_from_stdin;
@@ -57,6 +58,7 @@ parse_fsync_cb (const char  *option_name,
 
 static GOptionEntry options[] = {
   { "user-mode", 'U', 0, G_OPTION_ARG_NONE, &opt_user_mode, "Do not change file ownership or initialize 
extended attributes", NULL },
+  { "disable-cache", 0, 0, G_OPTION_ARG_NONE, &opt_disable_cache, "Do not update or use the internal 
repository uncompressed object cache", NULL },
   { "subpath", 0, 0, G_OPTION_ARG_STRING, &opt_subpath, "Checkout sub-directory PATH", "PATH" },
   { "union", 0, 0, G_OPTION_ARG_NONE, &opt_union, "Keep existing directories, overwrite existing files", 
NULL },
   { "allow-noent", 0, 0, G_OPTION_ARG_NONE, &opt_allow_noent, "Do nothing if specified path does not exist", 
NULL },
@@ -70,46 +72,76 @@ static gboolean
 process_one_checkout (OstreeRepo           *repo,
                       const char           *resolved_commit,
                       const char           *subpath,
-                      GFile                *target,
+                      const char           *destination,
                       GCancellable         *cancellable,
                       GError              **error)
 {
   gboolean ret = FALSE;
-  GError *tmp_error = NULL;
-  gs_unref_object GFile *root = NULL;
-  gs_unref_object GFile *subtree = NULL;
-  gs_unref_object GFileInfo *file_info = NULL;
 
-  if (!ostree_repo_read_commit (repo, resolved_commit, &root, NULL, cancellable, error))
-    goto out;
-
-  if (subpath)
-    subtree = g_file_resolve_relative_path (root, subpath);
+  /* This strange code structure is to preserve testing
+   * coverage of both `ostree_repo_checkout_tree` and
+   * `ostree_repo_checkout_tree_at` until such time as we have a more
+   * convenient infrastructure for testing C APIs with data.
+   */
+  if (opt_disable_cache)
+    {
+      OstreeRepoCheckoutOptions options = { 0, };
+      
+      if (opt_user_mode)
+        options.mode = OSTREE_REPO_CHECKOUT_MODE_USER;
+      if (opt_union)
+        options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES;
+      if (subpath)
+        options.subpath = subpath;
+
+
+      if (!ostree_repo_checkout_tree_at (repo, &options,
+                                         AT_FDCWD, destination,
+                                         resolved_commit,
+                                         cancellable, error))
+        goto out;
+    }
   else
-    subtree = g_object_ref (root);
-
-  file_info = g_file_query_info (subtree, OSTREE_GIO_FAST_QUERYINFO,
-                                 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                 cancellable, &tmp_error);
-  if (!file_info)
     {
-      if (opt_allow_noent
-          && g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
-        {
-          g_clear_error (&tmp_error);
-          ret = TRUE;
-        }
+      GError *tmp_error = NULL;
+      gs_unref_object GFile *root = NULL;
+      gs_unref_object GFile *subtree = NULL;
+      gs_unref_object GFileInfo *file_info = NULL;
+      gs_unref_object GFile *destination_file = g_file_new_for_path (destination);
+
+      if (!ostree_repo_read_commit (repo, resolved_commit, &root, NULL, cancellable, error))
+        goto out;
+
+      if (subpath)
+        subtree = g_file_resolve_relative_path (root, subpath);
       else
+        subtree = g_object_ref (root);
+
+      file_info = g_file_query_info (subtree, OSTREE_GIO_FAST_QUERYINFO,
+                                     G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                     cancellable, &tmp_error);
+      if (!file_info)
         {
-          g_propagate_error (error, tmp_error);
+          if (opt_allow_noent
+              && g_error_matches (tmp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+            {
+              g_clear_error (&tmp_error);
+              ret = TRUE;
+            }
+          else
+            {
+              g_propagate_error (error, tmp_error);
+            }
+          goto out;
         }
-      goto out;
-    }
 
-  if (!ostree_repo_checkout_tree (repo, opt_user_mode ? OSTREE_REPO_CHECKOUT_MODE_USER : 0,
-                                  opt_union ? OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES : 0,
-                                  target, OSTREE_REPO_FILE (subtree), file_info, cancellable, error))
-    goto out;
+      if (!ostree_repo_checkout_tree (repo, opt_user_mode ? OSTREE_REPO_CHECKOUT_MODE_USER : 0,
+                                      opt_union ? OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES : 0,
+                                      destination_file,
+                                      OSTREE_REPO_FILE (subtree), file_info,
+                                      cancellable, error))
+        goto out;
+    }
                       
   ret = TRUE;
  out:
@@ -118,7 +150,7 @@ process_one_checkout (OstreeRepo           *repo,
 
 static gboolean
 process_many_checkouts (OstreeRepo         *repo,
-                        GFile              *target,
+                        const char         *target,
                         GCancellable       *cancellable,
                         GError            **error)
 {
@@ -198,7 +230,6 @@ ostree_builtin_checkout (int argc, char **argv, GCancellable *cancellable, GErro
   const char *commit;
   const char *destination;
   gs_free char *resolved_commit = NULL;
-  gs_unref_object GFile *checkout_target = NULL;
 
   context = g_option_context_new ("COMMIT [DESTINATION] - Check out a commit into a filesystem tree");
 
@@ -221,9 +252,8 @@ ostree_builtin_checkout (int argc, char **argv, GCancellable *cancellable, GErro
   if (opt_from_stdin || opt_from_file)
     {
       destination = argv[1];
-      checkout_target = g_file_new_for_path (destination);
 
-      if (!process_many_checkouts (repo, checkout_target, cancellable, error))
+      if (!process_many_checkouts (repo, destination, cancellable, error))
         goto out;
     }
   else
@@ -237,10 +267,8 @@ ostree_builtin_checkout (int argc, char **argv, GCancellable *cancellable, GErro
       if (!ostree_repo_resolve_rev (repo, commit, FALSE, &resolved_commit, error))
         goto out;
 
-      checkout_target = g_file_new_for_path (destination);
-
       if (!process_one_checkout (repo, resolved_commit, opt_subpath,
-                                 checkout_target,
+                                 destination,
                                  cancellable, error))
         goto out;
     }
diff --git a/tests/basic-test.sh b/tests/basic-test.sh
index 65e2229..753f500 100755
--- a/tests/basic-test.sh
+++ b/tests/basic-test.sh
@@ -19,7 +19,7 @@
 
 set -e
 
-echo "1..47"
+echo "1..48"
 
 $OSTREE checkout test2 checkout-test2
 echo "ok checkout"
@@ -363,6 +363,25 @@ fi
 echo "ok commit of fifo was rejected"
 
 cd ${test_tmpdir}
+rm repo2 -rf
+mkdir repo2
+${CMD_PREFIX} ostree --repo=repo2 init --mode=archive-z2
+${CMD_PREFIX} ostree --repo=repo2 pull-local repo
+rm -rf test2-checkout
+${CMD_PREFIX} ostree --repo=repo2 checkout -U --disable-cache test2 test2-checkout
+if test -d repo2/uncompressed-objects-cache; then
+    ls repo2/uncompressed-objects-cache > ls.txt
+    if test -s ls.txt; then
+       assert_not_reached "repo has uncompressed objects"
+    fi
+fi
+rm test2-checkout -rf
+${CMD_PREFIX} ostree --repo=repo2 checkout -U test2 test2-checkout
+assert_file_has_content test2-checkout/baz/cow moo
+assert_has_dir repo2/uncompressed-objects-cache
+echo "ok disable cache checkout"
+
+cd ${test_tmpdir}
 rm -rf test2-checkout
 mkdir -p test2-checkout
 cd test2-checkout


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]