[ostree] core: Make commit always operate on directory contents, not file list



commit 7e32bc6cd7ef7cde8fe570cb0e8d4b3ea237dad5
Author: Colin Walters <walters verbum org>
Date:   Sun Nov 27 18:03:05 2011 -0500

    core: Make commit always operate on directory contents, not file list
    
    This simplifies things significantly, at some cost in flexibility.
    We'll later add the ability to e.g. filter out files by regular
    expression.

 src/libostree/ostree-repo.c    |  663 +++++++++++++---------------------------
 src/libostree/ostree-repo.h    |   21 +-
 src/ostree/ot-builtin-commit.c |  214 +------------
 tests/t0000-basic.sh           |    4 +-
 tests/t0004-compose.sh         |    6 +-
 5 files changed, 238 insertions(+), 670 deletions(-)
---
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 545591d..337b61c 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -698,7 +698,7 @@ ostree_repo_load_variant_checked (OstreeRepo  *self,
 
 static gboolean
 import_directory_meta (OstreeRepo  *self,
-                       const char *path,
+                       GFile       *f,
                        GVariant  **out_variant,
                        GChecksum **out_checksum,
                        GError    **error)
@@ -706,11 +706,8 @@ import_directory_meta (OstreeRepo  *self,
   gboolean ret = FALSE;
   GChecksum *ret_checksum = NULL;
   GVariant *dirmeta = NULL;
-  GFile *f = NULL;
   GFileInfo *f_info = NULL;
 
-  f = ot_gfile_new_for_path (path);
-
   f_info = g_file_query_info (f, OSTREE_GIO_FAST_QUERYINFO,
                               G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                               NULL, error);
@@ -725,12 +722,17 @@ import_directory_meta (OstreeRepo  *self,
     goto out;
 
   ret = TRUE;
-  *out_variant = dirmeta;
-  dirmeta = NULL;
-  *out_checksum = ret_checksum;
-  ret_checksum = NULL;
+  if (out_variant)
+    {
+      *out_variant = dirmeta;
+      dirmeta = NULL;
+    }
+  if (out_checksum)
+    {
+      *out_checksum = ret_checksum;
+      ret_checksum = NULL;
+    }
  out:
-  g_clear_object (&f);
   g_clear_object (&f_info);
   if (ret_checksum)
     g_checksum_free (ret_checksum);
@@ -951,85 +953,194 @@ ostree_repo_store_packfile (OstreeRepo       *self,
   return ret;
 }
 
-typedef struct _ParsedTreeData ParsedTreeData;
-typedef struct _ParsedDirectoryData ParsedDirectoryData;
+static GVariant *
+create_empty_gvariant_dict (void)
+{
+  GVariantBuilder builder;
+  g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
+  return g_variant_builder_end (&builder);
+}
 
-static void parsed_tree_data_free (ParsedTreeData *pdata);
+gboolean      
+ostree_repo_write_ref (OstreeRepo  *self,
+                       const char  *remote,
+                       const char  *name,
+                       const char  *rev,
+                       GError     **error)
+{
+  gboolean ret = FALSE;
+  OstreeRepoPrivate *priv = GET_PRIVATE (self);
+  GFile *dir = NULL;
 
-struct _ParsedDirectoryData {
-  ParsedTreeData *tree_data;
-  char *metadata_sha256;
-  GVariant *meta_data;
-};
+  if (remote == NULL)
+    dir = g_object_ref (priv->local_heads_dir);
+  else
+    {
+      dir = g_file_get_child (priv->remote_heads_dir, remote);
 
-static void
-parsed_directory_data_free (ParsedDirectoryData *pdata)
-{
-  if (pdata == NULL)
-    return;
-  parsed_tree_data_free (pdata->tree_data);
-  g_free (pdata->metadata_sha256);
-  ot_clear_gvariant (&pdata->meta_data);
-  g_free (pdata);
-}
+      if (!ot_gfile_ensure_directory (dir, FALSE, error))
+        goto out;
+    }
 
-struct _ParsedTreeData {
-  GHashTable *files;  /* char* filename -> char* checksum */
-  GHashTable *directories;  /* char* dirname -> ParsedDirectoryData* */
-};
+  if (!write_checksum_file (dir, name, rev, error))
+    goto out;
 
-static ParsedTreeData *
-parsed_tree_data_new (void)
-{
-  ParsedTreeData *ret = g_new0 (ParsedTreeData, 1);
-  ret->files = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                      (GDestroyNotify)g_free, 
-                                      (GDestroyNotify)g_free);
-  ret->directories = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                            (GDestroyNotify)g_free, 
-                                            (GDestroyNotify)parsed_directory_data_free);
+  ret = TRUE;
+ out:
+  g_clear_object (&dir);
   return ret;
 }
 
-static void
-parsed_tree_data_free (ParsedTreeData *pdata)
+static gboolean
+import_commit (OstreeRepo *self,
+               const char   *branch,
+               const char   *parent,
+               const char   *subject,
+               const char   *body,
+               GVariant     *metadata,
+               GChecksum    *root_contents_checksum,
+               GChecksum    *root_metadata_checksum,
+               GChecksum   **out_commit,
+               GError      **error)
 {
-  if (pdata == NULL)
-    return;
-  g_hash_table_destroy (pdata->files);
-  g_hash_table_destroy (pdata->directories);
-  g_free (pdata);
-}
+  gboolean ret = FALSE;
+  GChecksum *ret_commit = NULL;
+  GVariant *commit = NULL;
+  GDateTime *now = NULL;
 
-static GVariant *
-create_empty_gvariant_dict (void)
-{
-  GVariantBuilder builder;
-  g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
-  return g_variant_builder_end (&builder);
+  g_assert (branch != NULL);
+  g_assert (subject != NULL);
+
+  now = g_date_time_new_now_utc ();
+  commit = g_variant_new ("(u a{sv}ssstss)",
+                          GUINT32_TO_BE (OSTREE_COMMIT_VERSION),
+                          metadata ? metadata : create_empty_gvariant_dict (),
+                          parent ? parent : "",
+                          subject, body ? body : "",
+                          GUINT64_TO_BE (g_date_time_to_unix (now)),
+                          g_checksum_get_string (root_contents_checksum),
+                          g_checksum_get_string (root_metadata_checksum));
+  g_variant_ref_sink (commit);
+  if (!import_gvariant_object (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
+                               commit, &ret_commit, error))
+    goto out;
+
+  if (!ostree_repo_write_ref (self, NULL, branch, g_checksum_get_string (ret_commit), error))
+    goto out;
+
+  ret = TRUE;
+  if (out_commit)
+    {
+      *out_commit = ret_commit;
+      ret_commit = NULL;
+    }
+ out:
+  if (ret_commit)
+    g_checksum_free (ret_commit);
+  ot_clear_gvariant (&commit);
+  if (now)
+    g_date_time_unref (now);
+  return ret;
 }
 
 static gboolean
-import_parsed_tree (OstreeRepo    *self,
-                    ParsedTreeData  *tree,
-                    GChecksum      **out_checksum,
-                    GError         **error)
+import_directory_recurse (OstreeRepo           *self,
+                          GFile                *base,
+                          GFile                *dir,
+                          GChecksum           **out_contents_checksum,
+                          GChecksum           **out_metadata_checksum,
+                          GCancellable         *cancellable,
+                          GError              **error)
 {
   gboolean ret = FALSE;
-  GVariant *serialized_tree = NULL;
+  GError *temp_error = NULL;
+  GChecksum *ret_metadata_checksum = NULL;
+  GChecksum *ret_contents_checksum = NULL;
+  GFileEnumerator *dir_enum = NULL;
+  GFileInfo *child_info = NULL;
+  GFile *child = NULL;
+  GHashTable *file_checksums = NULL;
+  GHashTable *dir_metadata_checksums = NULL;
+  GHashTable *dir_contents_checksums = NULL;
+  GChecksum *child_file_checksum = NULL;
+  gboolean did_exist;
   gboolean builders_initialized = FALSE;
   GVariantBuilder files_builder;
   GVariantBuilder dirs_builder;
   GHashTableIter hash_iter;
   GSList *sorted_filenames = NULL;
   GSList *iter;
+  GVariant *serialized_tree = NULL;
   gpointer key, value;
 
+  if (!import_directory_meta (self, dir, NULL, &ret_metadata_checksum, error))
+    goto out;
+
+  dir_enum = g_file_enumerate_children ((GFile*)dir, OSTREE_GIO_FAST_QUERYINFO, 
+                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                        cancellable, 
+                                        error);
+  if (!dir_enum)
+    goto out;
+  
+  file_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                          (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+  dir_metadata_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                  (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+  dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                  (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+
+  while ((child_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL)
+    {
+      const char *name = g_file_info_get_name (child_info);
+
+      g_clear_object (&child);
+      child = g_file_get_child (dir, name);
+
+      if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY)
+        {
+          GChecksum *child_dir_metadata_checksum;
+          GChecksum *child_dir_contents_checksum;
+
+          if (!import_directory_recurse (self, base, child, &child_dir_contents_checksum,
+                                         &child_dir_metadata_checksum, cancellable, error))
+            goto out;
+
+          g_hash_table_replace (dir_contents_checksums, g_strdup (name),
+                                g_strdup (g_checksum_get_string (child_dir_contents_checksum)));
+          g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
+                                g_strdup (g_checksum_get_string (child_dir_metadata_checksum)));
+          g_checksum_free (child_dir_contents_checksum);
+          g_checksum_free (child_dir_metadata_checksum);
+        }
+      else
+        {
+          if (child_file_checksum)
+            g_checksum_free (child_file_checksum);
+          if (!ostree_checksum_file (child, OSTREE_OBJECT_TYPE_FILE, &child_file_checksum, cancellable, error))
+            goto out;
+          
+          if (!ostree_repo_store_object_trusted (self, child, g_checksum_get_string (child_file_checksum),
+                                                 OSTREE_OBJECT_TYPE_FILE, FALSE, &did_exist, error))
+            goto out;
+
+          g_hash_table_replace (file_checksums, g_strdup (name),
+                                g_strdup (g_checksum_get_string (child_file_checksum)));
+        }
+
+      g_clear_object (&child_info);
+    }
+  if (temp_error != NULL)
+    {
+      g_propagate_error (error, temp_error);
+      goto out;
+    }
+
   g_variant_builder_init (&files_builder, G_VARIANT_TYPE ("a(ss)"));
   g_variant_builder_init (&dirs_builder, G_VARIANT_TYPE ("a(sss)"));
   builders_initialized = TRUE;
 
-  g_hash_table_iter_init (&hash_iter, tree->files);
+  g_hash_table_iter_init (&hash_iter, file_checksums);
   while (g_hash_table_iter_next (&hash_iter, &key, &value))
     {
       const char *name = key;
@@ -1043,14 +1154,14 @@ import_parsed_tree (OstreeRepo    *self,
       const char *name = iter->data;
       const char *value;
 
-      value = g_hash_table_lookup (tree->files, name);
+      value = g_hash_table_lookup (file_checksums, name);
       g_variant_builder_add (&files_builder, "(ss)", name, value);
     }
-
+  
   g_slist_free (sorted_filenames);
   sorted_filenames = NULL;
 
-  g_hash_table_iter_init (&hash_iter, tree->directories);
+  g_hash_table_iter_init (&hash_iter, dir_metadata_checksums);
   while (g_hash_table_iter_next (&hash_iter, &key, &value))
     {
       const char *name = key;
@@ -1062,17 +1173,11 @@ import_parsed_tree (OstreeRepo    *self,
   for (iter = sorted_filenames; iter; iter = iter->next)
     {
       const char *name = iter->data;
-      GChecksum *dir_checksum = NULL;
-      ParsedDirectoryData *dir;
-
-      dir = g_hash_table_lookup (tree->directories, name);
-
-      if (!import_parsed_tree (self, dir->tree_data, &dir_checksum, error))
-        goto out;
 
       g_variant_builder_add (&dirs_builder, "(sss)",
-                             name, g_checksum_get_string (dir_checksum), dir->metadata_sha256);
-      g_checksum_free (dir_checksum);
+                             name,
+                             g_hash_table_lookup (dir_contents_checksums, name),
+                             g_hash_table_lookup (dir_metadata_checksums, name));
     }
 
   g_slist_free (sorted_filenames);
@@ -1085,11 +1190,28 @@ import_parsed_tree (OstreeRepo    *self,
                                    g_variant_builder_end (&dirs_builder));
   builders_initialized = FALSE;
   g_variant_ref_sink (serialized_tree);
-  if (!import_gvariant_object (self, OSTREE_SERIALIZED_TREE_VARIANT, serialized_tree, out_checksum, error))
+
+  if (!import_gvariant_object (self, OSTREE_SERIALIZED_TREE_VARIANT, serialized_tree, &ret_contents_checksum, error))
     goto out;
-  
+
+  *out_metadata_checksum = ret_metadata_checksum;
+  ret_metadata_checksum = NULL;
+  *out_contents_checksum = ret_contents_checksum;
+  ret_contents_checksum = NULL;
   ret = TRUE;
  out:
+  g_clear_object (&dir_enum);
+  g_clear_object (&child);
+  g_clear_object (&child_info);
+  g_hash_table_destroy (file_checksums);
+  g_hash_table_destroy (dir_metadata_checksums);
+  g_hash_table_destroy (dir_contents_checksums);
+  if (ret_metadata_checksum)
+    g_checksum_free (ret_metadata_checksum);
+  if (ret_contents_checksum)
+    g_checksum_free (ret_contents_checksum);
+  if (child_file_checksum)
+    g_checksum_free (child_file_checksum);
   g_slist_free (sorted_filenames);
   if (builders_initialized)
     {
@@ -1100,360 +1222,23 @@ import_parsed_tree (OstreeRepo    *self,
   return ret;
 }
 
-static gboolean
-check_path (const char *filename,
-            GError    **error)
-{
-  gboolean ret = FALSE;
-
-  if (!*filename)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Invalid empty filename");
-      goto out;
-    }
-
-  if (strcmp (filename, ".") == 0)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Self-reference '.' in filename '%s' not allowed (yet)", filename);
-      goto out;
-    }
-  
-  if (ot_util_filename_has_dotdot (filename))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Path uplink '..' in filename '%s' not allowed (yet)", filename);
-      goto out;
-    }
-  
-  if (g_path_is_absolute (filename))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Absolute filename '%s' not allowed (yet)", filename);
-      goto out;
-    }
-
-  ret = TRUE;
- out:
-  return ret;
-}
-
-static gboolean
-add_one_directory_to_tree_and_import (OstreeRepo   *self,
-                                      const char     *basename,
-                                      const char     *abspath,
-                                      ParsedTreeData *tree,
-                                      ParsedDirectoryData **dir, /*inout*/
-                                      GError        **error)
-{
-  gboolean ret = FALSE;
-  GVariant *dirmeta = NULL;
-  GChecksum *dir_meta_checksum = NULL;
-  ParsedDirectoryData *dir_value = *dir;
-  
-  g_assert (tree != NULL);
-
-  if (!import_directory_meta (self, abspath, &dirmeta, &dir_meta_checksum, error))
-    goto out;
-
-  if (dir_value)
-    {
-      ot_clear_gvariant (&dir_value->meta_data);
-      dir_value->meta_data = dirmeta;
-    }
-  else
-    {
-      dir_value = g_new0 (ParsedDirectoryData, 1);
-      dir_value->tree_data = parsed_tree_data_new ();
-      dir_value->metadata_sha256 = g_strdup (g_checksum_get_string (dir_meta_checksum));
-      dir_value->meta_data = dirmeta;
-      g_hash_table_insert (tree->directories, g_strdup (basename), dir_value);
-    }
-
-  ret = TRUE;
-  *dir = dir_value;
- out:
-  if (dir_meta_checksum)
-    g_checksum_free (dir_meta_checksum);
-  return ret;
-}
-
-static gboolean
-add_one_file_to_tree_and_import (OstreeRepo   *self,
-                                 const char     *basename,
-                                 const char     *abspath,
-                                 ParsedTreeData *tree,
-                                 GError        **error)
-{
-  gboolean ret = FALSE;
-  GChecksum *checksum = NULL;
-  gboolean did_exist;
-  GFile *f = NULL;
-  
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-  g_assert (tree != NULL);
-
-  f = ot_gfile_new_for_path (abspath);
-
-  if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_FILE, &checksum, NULL, error))
-    goto out;
-
-  if (!ostree_repo_store_object_trusted (self, f, g_checksum_get_string (checksum),
-                                         OSTREE_OBJECT_TYPE_FILE, FALSE, &did_exist, error))
-    goto out;
-
-  g_hash_table_replace (tree->files, g_strdup (basename),
-                        g_strdup (g_checksum_get_string (checksum)));
-
-  ret = TRUE;
- out:
-  g_clear_object (&f);
-  if (checksum)
-    g_checksum_free (checksum);
-  return ret;
-}
-
-static gboolean
-add_one_path_to_tree_and_import (OstreeRepo     *self,
-                                 const char     *base,
-                                 const char     *filename,
-                                 ParsedTreeData *tree,
-                                 GError        **error)
-{
-  gboolean ret = FALSE;
-  GPtrArray *components = NULL;
-  struct stat stbuf;
-  char *component_abspath = NULL;
-  ParsedTreeData *current_tree = tree;
-  const char *component = NULL;
-  const char *file_sha1;
-  char *abspath = NULL;
-  ParsedDirectoryData *dir;
-  int i;
-  gboolean is_directory;
-
-  if (!check_path (filename, error))
-    goto out;
-
-  abspath = g_build_filename (base, filename, NULL);
-
-  if (lstat (abspath, &stbuf) < 0)
-    {
-      ot_util_set_error_from_errno (error, errno);
-      goto out;
-    }
-  is_directory = S_ISDIR(stbuf.st_mode);
-       
-  if (components)
-    g_ptr_array_free (components, TRUE);
-  components = ot_util_path_split (filename);
-  g_assert (components->len > 0);
-
-  current_tree = tree;
-  for (i = 0; i < components->len; i++)
-    {
-      component = components->pdata[i];
-      g_free (component_abspath);
-      component_abspath = ot_util_path_join_n (base, components, i);
-      file_sha1 = g_hash_table_lookup (current_tree->files, component);
-      dir = g_hash_table_lookup (current_tree->directories, component);
-
-      g_assert_cmpstr (component, !=, ".");
-
-      if (i < components->len - 1)
-        {
-          if (file_sha1 != NULL)
-            {
-              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                           "Encountered non-directory '%s' in '%s'",
-                           component,
-                           filename);
-              goto out;
-            }
-          /* Implicitly add intermediate directories */
-          if (!add_one_directory_to_tree_and_import (self, component,
-                                                     component_abspath, current_tree, &dir,
-                                                     error))
-            goto out;
-          g_assert (dir != NULL);
-          current_tree = dir->tree_data;
-        }
-      else if (is_directory)
-        {
-          if (file_sha1 != NULL)
-            {
-              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                           "File '%s' can't be overwritten by directory",
-                           filename);
-              goto out;
-            }
-          if (!add_one_directory_to_tree_and_import (self, component,
-                                                     abspath, current_tree, &dir,
-                                                     error))
-            goto out;
-        }
-      else 
-        {
-          g_assert (!is_directory);
-          if (dir != NULL)
-            {
-              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                           "File '%s' can't be overwritten by directory",
-                           filename);
-              goto out;
-            }
-          if (!add_one_file_to_tree_and_import (self, component, abspath,
-                                                current_tree, error))
-            goto out;
-        }
-    }
-
-  ret = TRUE;
- out:
-  if (components)
-    g_ptr_array_unref (components);
-  g_free (component_abspath);
-  g_free (abspath);
-  return ret;
-}
-
 gboolean      
-ostree_repo_write_ref (OstreeRepo  *self,
-                       const char  *remote,
-                       const char  *name,
-                       const char  *rev,
-                       GError     **error)
-{
-  gboolean ret = FALSE;
-  OstreeRepoPrivate *priv = GET_PRIVATE (self);
-  GFile *dir = NULL;
-
-  if (remote == NULL)
-    dir = g_object_ref (priv->local_heads_dir);
-  else
-    {
-      dir = g_file_get_child (priv->remote_heads_dir, remote);
-
-      if (!ot_gfile_ensure_directory (dir, FALSE, error))
-        goto out;
-    }
-
-  if (!write_checksum_file (dir, name, rev, error))
-    goto out;
-
-  ret = TRUE;
- out:
-  g_clear_object (&dir);
-  return ret;
-}
-
-static gboolean
-commit_parsed_tree (OstreeRepo *self,
+ostree_repo_commit (OstreeRepo *self,
                     const char   *branch,
                     const char   *parent,
                     const char   *subject,
                     const char   *body,
                     GVariant     *metadata,
-                    ParsedDirectoryData *root,
+                    GFile        *dir,
                     GChecksum   **out_commit,
+                    GCancellable *cancellable,
                     GError      **error)
 {
-  gboolean ret = FALSE;
-  GChecksum *root_checksum = NULL;
-  GChecksum *ret_commit = NULL;
-  GVariant *commit = NULL;
-  GDateTime *now = NULL;
-
-  g_assert (branch != NULL);
-  g_assert (subject != NULL);
-
-  if (!import_parsed_tree (self, root->tree_data, &root_checksum, error))
-    goto out;
-
-  now = g_date_time_new_now_utc ();
-  commit = g_variant_new ("(u a{sv}ssstss)",
-                          GUINT32_TO_BE (OSTREE_COMMIT_VERSION),
-                          metadata ? metadata : create_empty_gvariant_dict (),
-                          parent ? parent : "",
-                          subject, body ? body : "",
-                          GUINT64_TO_BE (g_date_time_to_unix (now)),
-                          g_checksum_get_string (root_checksum),
-                          root->metadata_sha256);
-  g_variant_ref_sink (commit);
-  if (!import_gvariant_object (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
-                               commit, &ret_commit, error))
-    goto out;
-
-  if (!ostree_repo_write_ref (self, NULL, branch, g_checksum_get_string (ret_commit), error))
-    goto out;
-
-  ret = TRUE;
-  *out_commit = ret_commit;
- out:
-  if (root_checksum)
-    g_checksum_free (root_checksum);
-  ot_clear_gvariant (&commit);
-  if (now)
-    g_date_time_unref (now);
-  return ret;
-}
-
-static gboolean
-import_root (OstreeRepo           *self,
-             const char           *base,
-             ParsedDirectoryData **out_root,
-             GError              **error)
-{
-  gboolean ret = FALSE;
-  ParsedDirectoryData *ret_root = NULL;
-  GVariant *root_metadata = NULL;
-  GChecksum *root_meta_checksum = NULL;
-
-  if (!import_directory_meta (self, base, &root_metadata, &root_meta_checksum, error))
-    goto out;
-
-  ret_root = g_new0 (ParsedDirectoryData, 1);
-  ret_root->tree_data = parsed_tree_data_new ();
-  ret_root->meta_data = root_metadata;
-  root_metadata = NULL;
-  ret_root->metadata_sha256 = g_strdup (g_checksum_get_string (root_meta_checksum));
-
-  ret = TRUE;
-  *out_root = ret_root;
-  ret_root = NULL;
- out:
-  ot_clear_gvariant (&root_metadata);
-  if (root_meta_checksum)
-    g_checksum_free (root_meta_checksum);
-  parsed_directory_data_free (ret_root);
-  return ret;
-}
-
-gboolean      
-ostree_repo_commit_from_filelist_fd (OstreeRepo *self,
-                                     const char   *branch,
-                                     const char   *parent,
-                                     const char   *subject,
-                                     const char   *body,
-                                     GVariant     *metadata,
-                                     const char   *base,
-                                     int           fd,
-                                     char          separator,
-                                     GChecksum   **out_commit,
-                                     GError      **error)
-{
   OstreeRepoPrivate *priv = GET_PRIVATE (self);
   gboolean ret = FALSE;
-  ParsedDirectoryData *root = NULL;
   GChecksum *ret_commit_checksum = NULL;
-  GUnixInputStream *in = NULL;
-  GDataInputStream *datain = NULL;
-  char *filename = NULL;
-  gsize filename_len;
-  GError *temp_error = NULL;
-  GVariant *root_metadata = NULL;
-  GChecksum *root_meta_checksum = NULL;
+  GChecksum *root_metadata_checksum = NULL;
+  GChecksum *root_contents_checksum = NULL;
   char *current_head = NULL;
 
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -1465,39 +1250,14 @@ ostree_repo_commit_from_filelist_fd (OstreeRepo *self,
   if (parent == NULL)
     parent = branch;
 
-  /* We're overwriting the tree */
-  if (!import_root (self, base, &root, error))
-    goto out;
-
   if (!ostree_repo_resolve_rev (self, parent, TRUE, &current_head, error))
     goto out;
 
-  in = (GUnixInputStream*)g_unix_input_stream_new (fd, FALSE);
-  datain = g_data_input_stream_new ((GInputStream*)in);
+  if (!import_directory_recurse (self, dir, dir, &root_contents_checksum, &root_metadata_checksum, cancellable, error))
+    goto out;
 
-  while ((filename = g_data_input_stream_read_upto (datain, &separator, 1,
-                                                    &filename_len, NULL, &temp_error)) != NULL)
-    {
-      if (!g_data_input_stream_read_byte (datain, NULL, &temp_error))
-        {
-          if (temp_error != NULL)
-            {
-              g_propagate_prefixed_error (error, temp_error, "%s", "While reading filelist: ");
-              goto out;
-            }
-        }
-      if (!add_one_path_to_tree_and_import (self, base, filename, root->tree_data, error))
-        goto out;
-      g_free (filename);
-      filename = NULL;
-    }
-  if (filename == NULL && temp_error != NULL)
-    {
-      g_propagate_prefixed_error (error, temp_error, "%s", "While reading filelist: ");
-      goto out;
-    }
-  if (!commit_parsed_tree (self, branch, current_head, subject, body, metadata,
-                           root, &ret_commit_checksum, error))
+  if (!import_commit (self, branch, current_head, subject, body, metadata,
+                      root_contents_checksum, root_metadata_checksum, &ret_commit_checksum, error))
     goto out;
   
   ret = TRUE;
@@ -1507,13 +1267,10 @@ ostree_repo_commit_from_filelist_fd (OstreeRepo *self,
   if (ret_commit_checksum)
     g_checksum_free (ret_commit_checksum);
   g_free (current_head);
-  ot_clear_gvariant (&root_metadata);
-  if (root_meta_checksum)
-    g_checksum_free (root_meta_checksum);
-  g_clear_object (&datain);
-  g_clear_object (&in);
-  g_free (filename);
-  parsed_directory_data_free (root);
+  if (root_metadata_checksum)
+    g_checksum_free (root_metadata_checksum);
+  if (root_contents_checksum)
+    g_checksum_free (root_contents_checksum);
   return ret;
   
 }
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 36a8f56..f8b064a 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -110,17 +110,16 @@ gboolean      ostree_repo_load_variant_checked (OstreeRepo  *self,
                                                 GVariant     **out_variant,
                                                 GError       **error);
 
-gboolean      ostree_repo_commit_from_filelist_fd (OstreeRepo   *self,
-                                                   const char   *branch,
-                                                   const char   *parent,
-                                                   const char   *subject,
-                                                   const char   *body,
-                                                   GVariant     *metadata,
-                                                   const char   *base,
-                                                   int           fd,
-                                                   char          separator,
-                                                   GChecksum   **out_commit,
-                                                   GError      **error);
+gboolean      ostree_repo_commit (OstreeRepo   *self,
+                                  const char   *branch,
+                                  const char   *parent,
+                                  const char   *subject,
+                                  const char   *body,
+                                  GVariant     *metadata,
+                                  GFile        *base,
+                                  GChecksum   **out_commit,
+                                  GCancellable *cancellable,
+                                  GError      **error);
 
 gboolean      ostree_repo_checkout (OstreeRepo *self,
                                     const char   *ref,
diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c
index 275e16d..f3955f1 100644
--- a/src/ostree/ot-builtin-commit.c
+++ b/src/ostree/ot-builtin-commit.c
@@ -29,10 +29,6 @@
 
 #include <glib/gi18n.h>
 
-static gboolean separator_null;
-static int from_fd = -1;
-static gboolean from_stdin;
-static char *from_file;
 static char *metadata_text_path;
 static char *metadata_bin_path;
 static char *subject;
@@ -47,159 +43,22 @@ static GOptionEntry options[] = {
   { "metadata-variant", 0, 0, G_OPTION_ARG_FILENAME, &metadata_bin_path, "File containing serialized variant, in host endianness", "path" },
   { "branch", 'b', 0, G_OPTION_ARG_STRING, &branch, "Branch", "branch" },
   { "parent", 'p', 0, G_OPTION_ARG_STRING, &parent, "Parent commit", "commit" },
-  { "from-fd", 0, 0, G_OPTION_ARG_INT, &from_fd, "Read new tree files from fd", "file descriptor" },
-  { "from-stdin", 0, 0, G_OPTION_ARG_NONE, &from_stdin, "Read new tree files from stdin", "file descriptor" },
-  { "from-file", 0, 0, G_OPTION_ARG_FILENAME, &from_file, "Read new tree files from another file", "path" },
-  { "separator-null", 0, 0, G_OPTION_ARG_NONE, &separator_null, "", "Use '\\0' as filename separator, as with find -print0" },
   { NULL }
 };
 
-typedef struct {
-  GFile *dir;
-  char separator;
-  GOutputStream *out;
-  GCancellable *cancellable;
-} FindThreadData;
-
-static gboolean
-find (const char *basepath,
-      GFile *dir,
-      char separator,
-      GOutputStream *out,
-      GCancellable *cancellable,
-      GError  **error);
-
-static gboolean
-find_write_child (const char *basepath,
-                  GFile      *dir,
-                  char        separator,
-                  GOutputStream *out,
-                  GFileInfo  *finfo,
-                  GCancellable *cancellable,
-                  GError    **error)
-{
-  gboolean ret = FALSE;
-  guint32 type;
-  const char *name;
-  char buf[1];
-  const char *child_path = NULL;
-  GString *child_trimmed_path = NULL;
-  GFile *child = NULL;
-  gsize bytes_written;
-
-  type = g_file_info_get_attribute_uint32 (finfo, "standard::type");
-  name = g_file_info_get_attribute_byte_string (finfo, "standard::name");
-
-  child = g_file_get_child (dir, name);
-
-  if (type == G_FILE_TYPE_DIRECTORY)
-    {
-      if (!find (basepath, child, separator, out, cancellable, error))
-        goto out;
-    }
-
-  child_path = ot_gfile_get_path_cached (child);
-  child_trimmed_path = g_string_new (child_path + strlen (basepath));
-  if (!*(child_trimmed_path->str))
-    {
-      /* do nothing - we implicitly add the root . */
-    }
-  else
-    {
-      g_assert (*(child_trimmed_path->str) == '/');
-      g_string_insert_c (child_trimmed_path, 0, '.');
-
-      if (!g_output_stream_write_all (out, child_trimmed_path->str, child_trimmed_path->len,
-                                      &bytes_written, cancellable, error))
-        goto out;
-      buf[0] = separator;
-      if (!g_output_stream_write_all (out, buf, 1, &bytes_written,
-                                      cancellable, error))
-        goto out;
-    }
-      
-  ret = TRUE;
- out:
-  g_string_free (child_trimmed_path, TRUE);
-  child_trimmed_path = NULL;
-  child_path = NULL;
-  g_clear_object (&child);
-  return ret;
-}
-
-static gboolean
-find (const char *basepath,
-      GFile *dir,
-      char separator,
-      GOutputStream *out,
-      GCancellable *cancellable,
-      GError  **error)
-{
-  gboolean ret = FALSE;
-  GError *temp_error = NULL;
-  GFileEnumerator *enumerator = NULL;
-  GFileInfo *finfo = NULL;
-
-  enumerator = g_file_enumerate_children (dir, "standard::type,standard::name", 
-                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                          cancellable, error);
-  if (!enumerator)
-    goto out;
-
-  while ((finfo = g_file_enumerator_next_file (enumerator, cancellable, error)) != NULL)
-    {
-      if (!find_write_child (basepath, dir, separator, out, finfo, cancellable, error))
-        goto out;
-      g_clear_object (&finfo);
-    }
-  if (temp_error)
-    {
-      g_propagate_error (error, temp_error);
-      goto out;
-    }
-
-  ret = TRUE;
- out:
-  g_clear_object (&finfo);
-  g_clear_object (&enumerator);
-  return ret;
-}
-
-static gpointer
-find_thread (gpointer data)
-{
-  FindThreadData *tdata = data;
-  GError *error = NULL;
-  const char *path;
-  
-  path = ot_gfile_get_path_cached (tdata->dir);
-  if (!find (path, tdata->dir, tdata->separator, tdata->out,
-             tdata->cancellable, &error))
-    {
-      g_printerr ("%s", error->message);
-      g_clear_error (&error);
-    }
-  g_clear_object (&(tdata->dir));
-  g_clear_object (&(tdata->out));
-  return NULL;
-}
-
 gboolean
 ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **error)
 {
   GOptionContext *context;
   gboolean ret = FALSE;
   OstreeRepo *repo = NULL;
-  char *dir = NULL;
+  char *dirpath = NULL;
+  GFile *dir = NULL;
   GChecksum *commit_checksum = NULL;
   char separator;
   GVariant *metadata = NULL;
   GMappedFile *metadata_mappedf = NULL;
   GFile *metadata_f = NULL;
-  gboolean temp_fd = -1;
-  int pipefd[2] = { -1, -1 };
-  GOutputStream *out = NULL;
-  FindThreadData fdata;
 
   context = g_option_context_new ("[DIR] - Commit a new revision");
   g_option_context_add_main_entries (context, options, NULL);
@@ -208,22 +67,22 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
     goto out;
 
   if (argc > 1)
-    dir = g_strdup (argv[1]);
+    dirpath = g_strdup (argv[1]);
   else
-    dir = g_get_current_dir ();
+    dirpath = g_get_current_dir ();
 
-  if (g_str_has_suffix (dir, "/"))
-    dir[strlen (dir) - 1] = '\0';
+  if (g_str_has_suffix (dirpath, "/"))
+    dirpath[strlen (dirpath) - 1] = '\0';
 
-  separator = separator_null ? '\0' : '\n';
-
-  if (!*dir)
+  if (!*dirpath)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                    "Invalid empty directory");
       goto out;
     }
 
+  dir = ot_gfile_new_for_path (dirpath);
+
   if (metadata_text_path || metadata_bin_path)
     {
       metadata_mappedf = g_mapped_file_new (metadata_text_path ? metadata_text_path : metadata_bin_path, FALSE, error);
@@ -266,62 +125,15 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
       goto out;
     }
 
-  if (!(from_file || from_fd >= 0 || from_stdin))
-    {
-      /* We're using the current directory */
-
-    }
-
-  if (from_stdin)
-    from_fd = 0;
-  else if (from_file)
-    {
-      temp_fd = ot_util_open_file_read (from_file, error);
-      if (temp_fd < 0)
-        {
-          g_prefix_error (error, "Failed to open '%s': ", from_file);
-          goto out;
-        }
-      from_fd = temp_fd;
-    }
-  else
-    {
-      if (pipe (pipefd) < 0)
-        {
-          ot_util_set_error_from_errno (error, errno);
-          goto out;
-        }
-
-      out = (GOutputStream*)g_unix_output_stream_new (pipefd[1], TRUE);
-      from_fd = pipefd[0];
-
-      fdata.dir = ot_gfile_new_for_path (dir);
-      fdata.separator = separator;
-      fdata.out = out;
-      fdata.cancellable = NULL;
-
-      if (g_thread_create_full (find_thread, &fdata, 0, FALSE, FALSE, G_THREAD_PRIORITY_NORMAL, error) == NULL)
-        goto out;
-
-      out = NULL;
-    }
-
-  if (!ostree_repo_commit_from_filelist_fd (repo, branch, parent, subject, body, metadata,
-                                            dir, from_fd, separator,
-                                            &commit_checksum, error))
+  if (!ostree_repo_commit (repo, branch, parent, subject, body, metadata,
+                           dir, &commit_checksum, NULL, error))
     goto out;
 
   ret = TRUE;
   g_print ("%s\n", g_checksum_get_string (commit_checksum));
  out:
-  g_clear_object (&out);
-  if (temp_fd >= 0)
-    (void)close (temp_fd);
-  if (pipefd[0] > 0)
-    (void) close (pipefd[0]);
-  if (pipefd[1] > 0)
-    (void) close (pipefd[1]);
-  g_free (dir);
+  g_free (dirpath);
+  g_clear_object (&dir);
   if (metadata_mappedf)
     g_mapped_file_unref (metadata_mappedf);
   if (context)
diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh
index 0db1527..02a060a 100755
--- a/tests/t0000-basic.sh
+++ b/tests/t0000-basic.sh
@@ -71,8 +71,8 @@ mkdir -p another/nested/tree
 echo anotherone > another/nested/tree/1
 echo whee2 > another/whee
 # FIXME - remove grep for .
-find | grep -v '^\.$' | $OSTREE commit -b test2 -s "From find" --from-stdin
-echo "ok stdin commit"
+$OSTREE commit -b test2 -s "Another commit"
+echo "ok commit"
 
 cd ${test_tmpdir}
 $OSTREE checkout test2 $test_tmpdir/checkout-test2-3
diff --git a/tests/t0004-compose.sh b/tests/t0004-compose.sh
index 1a747dc..51d2f8d 100755
--- a/tests/t0004-compose.sh
+++ b/tests/t0004-compose.sh
@@ -35,7 +35,7 @@ echo 'an ELF file' > usr/lib/libfoo.so
 mkdir -p usr/share
 echo 'some data' > usr/share/foo.data
 
-find | grep -v '^\.$' | $OSTREE commit -b artifact-libfoo-runtime -s 'Build 12345 of libfoo' --from-stdin
+$OSTREE commit -b artifact-libfoo-runtime -s 'Build 12345 of libfoo'
 
 cd "${test_tmpdir}"
 mkdir artifact-libfoo-devel
@@ -45,7 +45,7 @@ echo 'a header' > usr/include/foo.h
 mkdir -p usr/share/doc
 echo 'some documentation' > usr/share/doc/foo.txt
 
-find | grep -v '^\.$' | $OSTREE commit -b artifact-libfoo-devel -s 'Build 12345 of libfoo' --from-stdin
+$OSTREE commit -b artifact-libfoo-devel -s 'Build 12345 of libfoo'
 
 cd "${test_tmpdir}"
 mkdir artifact-barapp
@@ -53,7 +53,7 @@ cd artifact-barapp
 mkdir -p usr/bin
 echo 'another ELF file' > usr/bin/bar
 
-find | grep -v '^\.$' | $OSTREE commit -b artifact-barapp -s 'Build 42 of barapp' --from-stdin
+$OSTREE commit -b artifact-barapp -s 'Build 42 of barapp'
 
 echo 'ok artifacts committed'
 



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