[ostree] core: Add --tar-autocreate-parents option for commit



commit 3e59cc1305dce5e3d603c78d12f89df571ca1084
Author: Colin Walters <walters verbum org>
Date:   Fri Dec 23 06:49:04 2011 -0500

    core: Add --tar-autocreate-parents option for commit
    
    The tar files we're making of artifacts don't include parent
    directories.  Now we could change the builder to make them, but we can
    also just autocreate them on import.  Mode 0755 with no xattrs seems
    OK here.

 src/libostree/ostree-mutable-tree.c |   49 ++++++++++++++++++++++++++++
 src/libostree/ostree-mutable-tree.h |    7 ++++
 src/libostree/ostree-repo.c         |   61 ++++++++++++++++++++++++++++-------
 src/libostree/ostree-repo.h         |    1 +
 src/ostree/ot-builtin-commit.c      |    3 ++
 tests/t0006-libarchive.sh           |   10 ++++++
 6 files changed, 119 insertions(+), 12 deletions(-)
---
diff --git a/src/libostree/ostree-mutable-tree.c b/src/libostree/ostree-mutable-tree.c
index ca8be1e..5f63f11 100644
--- a/src/libostree/ostree-mutable-tree.c
+++ b/src/libostree/ostree-mutable-tree.c
@@ -222,6 +222,55 @@ ostree_mutable_tree_lookup (OstreeMutableTree   *self,
 }
 
 gboolean
+ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree  *self,
+                                        GPtrArray          *split_path,
+                                        const char         *metadata_checksum,
+                                        OstreeMutableTree **out_parent,
+                                        GError            **error)
+{
+  gboolean ret = FALSE;
+  int i;
+  OstreeMutableTree *ret_parent = NULL;
+  OstreeMutableTree *subdir = self;
+
+  g_assert (metadata_checksum != NULL);
+
+  if (!self->metadata_checksum)
+    ostree_mutable_tree_set_metadata_checksum (self, metadata_checksum);
+
+  for (i = 0; i+1 < split_path->len; i++)
+    {
+      OstreeMutableTree *next;
+      const char *name = split_path->pdata[i];
+
+      if (g_hash_table_lookup (subdir->files, name))
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Can't replace file with directory: %s", name);
+          goto out;
+        }
+
+      next = g_hash_table_lookup (subdir->subdirs, name);
+      if (!next) 
+        {
+          next = ostree_mutable_tree_new ();
+          ostree_mutable_tree_set_metadata_checksum (next, metadata_checksum);
+          g_hash_table_insert (subdir->subdirs, g_strdup (name), next);
+        }
+      
+      subdir = next;
+    }
+
+  ret_parent = g_object_ref (subdir);
+
+  ret = TRUE;
+  ot_transfer_out_value (out_parent, &ret_parent);
+ out:
+  g_clear_object (&ret_parent);
+  return ret;
+}
+
+gboolean
 ostree_mutable_tree_walk (OstreeMutableTree     *self,
                           GPtrArray             *split_path,
                           guint                  start,
diff --git a/src/libostree/ostree-mutable-tree.h b/src/libostree/ostree-mutable-tree.h
index 413da02..e47964d 100644
--- a/src/libostree/ostree-mutable-tree.h
+++ b/src/libostree/ostree-mutable-tree.h
@@ -77,6 +77,13 @@ gboolean ostree_mutable_tree_lookup (OstreeMutableTree   *self,
                                      OstreeMutableTree  **out_subdir,
                                      GError             **error);
 
+gboolean
+ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree  *self,
+                                        GPtrArray          *split_path,
+                                        const char         *metadata_checksum,
+                                        OstreeMutableTree **out_parent,
+                                        GError            **error);
+
 gboolean ostree_mutable_tree_walk (OstreeMutableTree   *self,
                                    GPtrArray           *split_path,
                                    guint                start,
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 80b8181..71bf055 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -1585,6 +1585,7 @@ ostree_repo_stage_mtree (OstreeRepo           *self,
       while (g_hash_table_iter_next (&hash_iter, &key, &value))
         {
           const char *name = key;
+          const char *metadata_checksum;
           OstreeMutableTree *child_dir = value;
           char *child_dir_contents_checksum;
 
@@ -1592,10 +1593,13 @@ ostree_repo_stage_mtree (OstreeRepo           *self,
                                         cancellable, error))
             goto out;
       
+          g_assert (child_dir_contents_checksum);
           g_hash_table_replace (dir_contents_checksums, g_strdup (name),
                                 child_dir_contents_checksum); /* Transfer ownership */
+          metadata_checksum = ostree_mutable_tree_get_metadata_checksum (child_dir);
+          g_assert (metadata_checksum);
           g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
-                                g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
+                                g_strdup (metadata_checksum));
         }
     
       serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
@@ -1709,6 +1713,7 @@ stage_libarchive_entry_to_mtree (OstreeRepo           *self,
                                  struct archive       *a,
                                  struct archive_entry *entry,
                                  OstreeRepoCommitModifier *modifier,
+                                 const char               *tmp_dir_checksum,
                                  GCancellable         *cancellable,
                                  GError              **error)
 {
@@ -1738,8 +1743,19 @@ stage_libarchive_entry_to_mtree (OstreeRepo           *self,
     }
   else
     {
-      if (!ostree_mutable_tree_walk (root, split_path, 0, &parent, error))
-        goto out;
+      if (tmp_dir_checksum)
+        {
+          if (!ostree_mutable_tree_ensure_parent_dirs (root, split_path,
+                                                       tmp_dir_checksum,
+                                                       &parent,
+                                                       error))
+            goto out;
+        }
+      else
+        {
+          if (!ostree_mutable_tree_walk (root, split_path, 0, &parent, error))
+            goto out;
+        }
       basename = (char*)split_path->pdata[split_path->len-1];
     }
 
@@ -1854,18 +1870,21 @@ stage_libarchive_entry_to_mtree (OstreeRepo           *self,
 #endif
                           
 gboolean
-ostree_repo_stage_archive_to_mtree (OstreeRepo           *self,
-                                    GFile                *archive_f,
-                                    OstreeMutableTree    *root,
-                                    OstreeRepoCommitModifier *modifier,
-                                    GCancellable         *cancellable,
-                                    GError              **error)
+ostree_repo_stage_archive_to_mtree (OstreeRepo                *self,
+                                    GFile                     *archive_f,
+                                    OstreeMutableTree         *root,
+                                    OstreeRepoCommitModifier  *modifier,
+                                    gboolean                   autocreate_parents,
+                                    GCancellable             *cancellable,
+                                    GError                  **error)
 {
 #ifdef HAVE_LIBARCHIVE
   gboolean ret = FALSE;
-  struct archive *a;
+  struct archive *a = NULL;
   struct archive_entry *entry;
   int r;
+  GFileInfo *tmp_dir_info = NULL;
+  GChecksum *tmp_dir_checksum = NULL;
 
   a = archive_read_new ();
   archive_read_support_compression_all (a);
@@ -1887,7 +1906,22 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo           *self,
           goto out;
         }
 
-      if (!stage_libarchive_entry_to_mtree (self, root, a, entry, modifier, cancellable, error))
+      if (autocreate_parents && !tmp_dir_checksum)
+        {
+          tmp_dir_info = g_file_info_new ();
+          
+          g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::uid", archive_entry_uid (entry));
+          g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::gid", archive_entry_gid (entry));
+          g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::mode", 0755 | S_IFDIR);
+          
+          if (!stage_directory_meta (self, tmp_dir_info, NULL, &tmp_dir_checksum, cancellable, error))
+            goto out;
+        }
+
+      if (!stage_libarchive_entry_to_mtree (self, root, a,
+                                            entry, modifier,
+                                            autocreate_parents ? g_checksum_get_string (tmp_dir_checksum) : NULL,
+                                            cancellable, error))
         goto out;
     }
   if (archive_read_close (a) != ARCHIVE_OK)
@@ -1898,7 +1932,10 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo           *self,
 
   ret = TRUE;
  out:
-  (void)archive_read_close (a);
+  g_clear_object (&tmp_dir_info);
+  ot_clear_checksum (&tmp_dir_checksum);
+  if (a)
+    (void)archive_read_close (a);
   return ret;
 #else
   g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 08ebd58..3777d84 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -158,6 +158,7 @@ gboolean      ostree_repo_stage_archive_to_mtree (OstreeRepo         *self,
                                                   GFile              *archive,
                                                   OstreeMutableTree  *tree,
                                                   OstreeRepoCommitModifier *modifier,
+                                                  gboolean            autocreate_parents,
                                                   GCancellable *cancellable,
                                                   GError      **error);
 
diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c
index 5fcc037..8e525ef 100644
--- a/src/ostree/ot-builtin-commit.c
+++ b/src/ostree/ot-builtin-commit.c
@@ -36,6 +36,7 @@ static char *body;
 static char *parent;
 static char *branch;
 static gboolean skip_if_unchanged;
+static gboolean tar_autocreate_parents;
 static char **trees;
 static gint owner_uid = -1;
 static gint owner_gid = -1;
@@ -50,6 +51,7 @@ static GOptionEntry options[] = {
   { "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &trees, "Overlay the given argument as a tree", "NAME" },
   { "owner-uid", 0, 0, G_OPTION_ARG_INT, &owner_uid, "Set file ownership user id", "UID" },
   { "owner-gid", 0, 0, G_OPTION_ARG_INT, &owner_gid, "Set file ownership group id", "GID" },
+  { "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
   { "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
   { NULL }
 };
@@ -187,6 +189,7 @@ ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error)
             {
               arg = ot_gfile_new_for_path (tree);
               if (!ostree_repo_stage_archive_to_mtree (repo, arg, mtree, modifier,
+                                                       tar_autocreate_parents,
                                                        cancellable, error))
                 goto out;
             }
diff --git a/tests/t0006-libarchive.sh b/tests/t0006-libarchive.sh
index 4173c97..06a0bf9 100755
--- a/tests/t0006-libarchive.sh
+++ b/tests/t0006-libarchive.sh
@@ -100,3 +100,13 @@ assert_file_has_content otherfile "not overwritten"
 assert_file_has_content subdir/original "original"
 assert_file_has_content subdir/new "new"
 echo "ok tar multicommit contents"
+
+cd ${test_tmpdir}/multicommit-files
+tar -c -C files1 -z -f partial.tar.gz subdir/original
+$OSTREE commit -s 'partial' -b partial --tar-autocreate-parents --tree=tar=partial.tar.gz
+echo "ok tar partial commit"
+
+cd ${test_tmpdir}
+$OSTREE checkout partial partial-checkout
+cd partial-checkout
+assert_file_has_content subdir/original "original"



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