[ostree] core: Move commit/dirtree traversal into library



commit d8173a5125a28507aa5df57c351d310ad11db8a9
Author: Colin Walters <walters verbum org>
Date:   Mon Apr 2 15:51:23 2012 -0400

    core: Move commit/dirtree traversal into library
    
    So it can more easily be reused by other builtins.

 Makefile-libostree.am           |    2 +
 src/libostree/ostree-traverse.c |  164 +++++++++++++++++++++++++++++++++++++++
 src/libostree/ostree-traverse.h |   48 +++++++++++
 src/libostree/ostree.h          |    1 +
 src/ostree/ot-builtin-prune.c   |  154 +++----------------------------------
 5 files changed, 226 insertions(+), 143 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index f2b688f..99e85c2 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -31,6 +31,8 @@ libostree_la_SOURCES = src/libostree/ostree.h \
 	src/libostree/ostree-repo-file-enumerator.c \
 	src/libostree/ostree-repo-file-enumerator.h \
 	src/libostree/ostree-types.h \
+	src/libostree/ostree-traverse.c \
+	src/libostree/ostree-traverse.h \
 	$(NULL)
 if USE_LIBARCHIVE
 libostree_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \
diff --git a/src/libostree/ostree-traverse.c b/src/libostree/ostree-traverse.c
new file mode 100644
index 0000000..a207fad
--- /dev/null
+++ b/src/libostree/ostree-traverse.c
@@ -0,0 +1,164 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include "ostree.h"
+#include "otutil.h"
+
+GHashTable *
+ostree_traverse_new_reachable (void)
+{
+  return g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
+                                (GDestroyNotify)g_variant_unref, NULL);
+}
+
+gboolean
+ostree_traverse_dirtree (OstreeRepo      *repo,
+                         const char      *dirtree_checksum,
+                         GHashTable      *inout_reachable,
+                         GCancellable    *cancellable,
+                         GError         **error)
+{
+  gboolean ret = FALSE;
+  GVariant *tree = NULL;
+  GVariant *files_variant = NULL;
+  GVariant *dirs_variant = NULL;
+  int n, i;
+  GVariant *key;
+
+  if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_DIR_TREE, dirtree_checksum, &tree, error))
+    goto out;
+
+  key = ostree_object_name_serialize (dirtree_checksum, OSTREE_OBJECT_TYPE_DIR_TREE);
+  if (!g_hash_table_lookup (inout_reachable, key))
+    { 
+      g_hash_table_insert (inout_reachable, key, key);
+      key = NULL;
+
+      /* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
+      files_variant = g_variant_get_child_value (tree, 2);
+      n = g_variant_n_children (files_variant);
+      for (i = 0; i < n; i++)
+        {
+          const char *filename;
+          const char *checksum;
+      
+          g_variant_get_child (files_variant, i, "(&s&s)", &filename, &checksum);
+          if (ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_BARE)
+            {
+              key = ostree_object_name_serialize (checksum, OSTREE_OBJECT_TYPE_RAW_FILE);
+              g_hash_table_replace (inout_reachable, key, key);
+              key = NULL;
+            }
+          else
+            {
+              key = ostree_object_name_serialize (checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META);
+              g_hash_table_replace (inout_reachable, key, key);
+              key = ostree_object_name_serialize (checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
+              g_hash_table_replace (inout_reachable, key, key);
+              key = NULL;
+            }
+        }
+
+      dirs_variant = g_variant_get_child_value (tree, 3);
+      n = g_variant_n_children (dirs_variant);
+      for (i = 0; i < n; i++)
+        {
+          const char *dirname;
+          const char *tree_checksum;
+          const char *meta_checksum;
+      
+          g_variant_get_child (dirs_variant, i, "(&s&s&s)",
+                               &dirname, &tree_checksum, &meta_checksum);
+      
+          if (!ostree_traverse_dirtree (repo, tree_checksum, inout_reachable,
+                                        cancellable, error))
+            goto out;
+
+          key = ostree_object_name_serialize (meta_checksum, OSTREE_OBJECT_TYPE_DIR_META);
+          g_hash_table_replace (inout_reachable, key, key);
+          key = NULL;
+        }
+    }
+
+  ret = TRUE;
+ out:
+  ot_clear_gvariant (&key);
+  ot_clear_gvariant (&tree);
+  ot_clear_gvariant (&files_variant);
+  ot_clear_gvariant (&dirs_variant);
+  return ret;
+}
+
+gboolean
+ostree_traverse_commit (OstreeRepo      *repo,
+                        const char      *commit_checksum,
+                        int              maxdepth,
+                        GHashTable      *inout_reachable,
+                        GCancellable    *cancellable,
+                        GError         **error)
+{
+  gboolean ret = FALSE;
+  GVariant *commit = NULL;
+  const char *contents_checksum;
+  const char *meta_checksum;
+  GVariant *key;
+
+  /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
+  if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, commit_checksum, &commit, error))
+    goto out;
+  
+  key = ostree_object_name_serialize (commit_checksum, OSTREE_OBJECT_TYPE_COMMIT);
+  g_hash_table_replace (inout_reachable, key, key);
+
+  g_variant_get_child (commit, 7, "&s", &meta_checksum);
+  key = ostree_object_name_serialize (meta_checksum, OSTREE_OBJECT_TYPE_DIR_META);
+  g_hash_table_replace (inout_reachable, key, key);
+
+  g_variant_get_child (commit, 6, "&s", &contents_checksum);
+  if (!ostree_traverse_dirtree (repo, contents_checksum, inout_reachable, cancellable, error))
+    goto out;
+
+  if (maxdepth == -1 || maxdepth > 0)
+    {
+      const char *parent_checksum;
+
+      g_variant_get_child (commit, 2, "&s", &parent_checksum);
+
+      if (parent_checksum[0])
+        {
+          if (!ostree_traverse_commit (repo, parent_checksum,
+                                       maxdepth > 0 ? maxdepth - 1 : -1,
+                                       inout_reachable, cancellable, error))
+            goto out;
+        }
+    }
+
+  ret = TRUE;
+ out:
+  ot_clear_gvariant (&commit);
+  return ret;
+}
+
diff --git a/src/libostree/ostree-traverse.h b/src/libostree/ostree-traverse.h
new file mode 100644
index 0000000..9d5cb7f
--- /dev/null
+++ b/src/libostree/ostree-traverse.h
@@ -0,0 +1,48 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#ifndef _OSTREE_TRAVERSE
+#define _OSTREE_TRAVERSE
+
+#include "ostree-core.h"
+#include "ostree-types.h"
+
+G_BEGIN_DECLS
+
+GHashTable *ostree_traverse_new_reachable (void);
+
+gboolean ostree_traverse_dirtree (OstreeRepo         *repo,
+                                  const char         *commit_checksum,
+                                  GHashTable         *inout_reachable,
+                                  GCancellable       *cancellable,
+                                  GError            **error);
+
+gboolean ostree_traverse_commit (OstreeRepo         *repo,
+                                 const char         *commit_checksum,
+                                 int                 maxdepth,
+                                 GHashTable         *inout_reachable,
+                                 GCancellable       *cancellable,
+                                 GError            **error);
+
+G_END_DECLS
+
+#endif /* _OSTREE_REPO */
diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h
index bf4153a..ecd8477 100644
--- a/src/libostree/ostree.h
+++ b/src/libostree/ostree.h
@@ -26,5 +26,6 @@
 #include <ostree-repo.h>
 #include <ostree-mutable-tree.h>
 #include <ostree-repo-file.h>
+#include <ostree-traverse.h>
 
 #endif
diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c
index 2c50f51..65a5f3e 100644
--- a/src/ostree/ot-builtin-prune.c
+++ b/src/ostree/ot-builtin-prune.c
@@ -30,7 +30,7 @@
 
 static gboolean verbose;
 static gboolean delete;
-static int depth = 0;
+static int depth = -1;
 
 static GOptionEntry options[] = {
   { "verbose", 0, 0, G_OPTION_ARG_NONE, &verbose, "Display progress", NULL },
@@ -63,129 +63,10 @@ log_verbose (const char  *fmt,
 typedef struct {
   OstreeRepo *repo;
   GHashTable *reachable;
-  gboolean had_error;
-  GError **error;
   guint n_reachable;
   guint n_unreachable;
 } OtPruneData;
 
-static gboolean
-compute_reachable_objects_from_dir_contents (OstreeRepo      *repo,
-                                             const char      *sha256,
-                                             GHashTable      *inout_reachable,
-                                             GCancellable    *cancellable,
-                                             GError         **error)
-{
-  gboolean ret = FALSE;
-  GVariant *tree = NULL;
-  GVariant *files_variant = NULL;
-  GVariant *dirs_variant = NULL;
-  int n, i;
-  char *key;
-
-  if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_DIR_TREE, sha256, &tree, error))
-    goto out;
-
-  key = ostree_object_to_string (sha256, OSTREE_OBJECT_TYPE_DIR_TREE);
-  g_hash_table_replace (inout_reachable, key, key);
-
-  /* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
-  files_variant = g_variant_get_child_value (tree, 2);
-  n = g_variant_n_children (files_variant);
-  for (i = 0; i < n; i++)
-    {
-      const char *filename;
-      const char *checksum;
-      
-      g_variant_get_child (files_variant, i, "(&s&s)", &filename, &checksum);
-      if (ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_BARE)
-        {
-          key = ostree_object_to_string (checksum, OSTREE_OBJECT_TYPE_RAW_FILE);
-          g_hash_table_replace (inout_reachable, key, key);
-        }
-      else
-        {
-          key = ostree_object_to_string (checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META);
-          g_hash_table_replace (inout_reachable, key, key);
-          key = ostree_object_to_string (checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
-          g_hash_table_replace (inout_reachable, key, key);
-        }
-    }
-
-  dirs_variant = g_variant_get_child_value (tree, 3);
-  n = g_variant_n_children (dirs_variant);
-  for (i = 0; i < n; i++)
-    {
-      const char *dirname;
-      const char *tree_checksum;
-      const char *meta_checksum;
-      
-      g_variant_get_child (dirs_variant, i, "(&s&s&s)",
-                           &dirname, &tree_checksum, &meta_checksum);
-      
-      if (!compute_reachable_objects_from_dir_contents (repo, tree_checksum, inout_reachable,
-                                                        cancellable, error))
-        goto out;
-
-      key = ostree_object_to_string (meta_checksum, OSTREE_OBJECT_TYPE_DIR_META);
-      g_hash_table_replace (inout_reachable, key, key);
-    }
-
-  ret = TRUE;
- out:
-  ot_clear_gvariant (&tree);
-  ot_clear_gvariant (&files_variant);
-  ot_clear_gvariant (&dirs_variant);
-  return ret;
-}
-
-static gboolean
-compute_reachable_objects_from_commit (OstreeRepo      *repo,
-                                       const char      *sha256,
-                                       int              traverse_depth,
-                                       GHashTable      *inout_reachable,
-                                       GCancellable    *cancellable,
-                                       GError         **error)
-{
-  gboolean ret = FALSE;
-  GVariant *commit = NULL;
-  const char *parent_checksum;
-  const char *contents_checksum;
-  const char *meta_checksum;
-  char *key;
-
-  if (depth == 0 || traverse_depth < depth)
-    {
-      if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, sha256, &commit, error))
-        goto out;
-
-      key = ostree_object_to_string (sha256, OSTREE_OBJECT_TYPE_COMMIT);
-      g_hash_table_replace (inout_reachable, key, key);
-
-      /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
-      g_variant_get_child (commit, 2, "&s", &parent_checksum);
-
-      if (strlen (parent_checksum) > 0)
-        {
-          if (!compute_reachable_objects_from_commit (repo, parent_checksum, traverse_depth + 1, inout_reachable, cancellable, error))
-            goto out;
-        }
-
-      g_variant_get_child (commit, 6, "&s", &contents_checksum);
-
-      if (!compute_reachable_objects_from_dir_contents (repo, contents_checksum, inout_reachable, cancellable, error))
-        goto out;
-
-      g_variant_get_child (commit, 7, "&s", &meta_checksum);
-      key = ostree_object_to_string (meta_checksum, OSTREE_OBJECT_TYPE_DIR_META);
-      g_hash_table_replace (inout_reachable, key, key);
-    }
-
-  ret = TRUE;
- out:
-  ot_clear_gvariant (&commit);
-  return ret;
-}
 
 static gboolean
 prune_loose_object (OtPruneData    *data,
@@ -195,10 +76,10 @@ prune_loose_object (OtPruneData    *data,
                     GError         **error)
 {
   gboolean ret = FALSE;
-  char *key;
+  GVariant *key = NULL;
   GFile *objf = NULL;
 
-  key = ostree_object_to_string (checksum, objtype);
+  key = ostree_object_name_serialize (checksum, objtype);
 
   objf = ostree_repo_get_object_path (data->repo, checksum, objtype);
 
@@ -206,13 +87,13 @@ prune_loose_object (OtPruneData    *data,
     {
       if (delete)
         {
-          if (!g_file_delete (objf, cancellable, error))
+          if (!ot_gfile_unlink (objf, cancellable, error))
             goto out;
-          g_print ("Deleted: %s\n", key);
+          g_print ("Deleted: %s.%s\n", checksum, ostree_object_type_to_string (objtype));
         }
       else
         {
-          g_print ("Unreachable: %s\n", key);
+          g_print ("Unreachable: %s.%s\n", checksum, ostree_object_type_to_string (objtype));
         }
       data->n_unreachable++;
     }
@@ -222,11 +103,10 @@ prune_loose_object (OtPruneData    *data,
   ret = TRUE;
  out:
   g_clear_object (&objf);
-  g_free (key);
+  ot_clear_gvariant (&key);
   return ret;
 }
 
-
 gboolean
 ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
 {
@@ -253,9 +133,7 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
     goto out;
 
   data.repo = repo;
-  data.reachable = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-  data.had_error = FALSE;
-  data.error = error;
+  data.reachable = ostree_traverse_new_reachable ();
   data.n_reachable = 0;
   data.n_unreachable = 0;
 
@@ -267,10 +145,10 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
   while (g_hash_table_iter_next (&hash_iter, &key, &value))
     {
       const char *name = key;
-      const char *sha256 = value;
+      const char *checksum = value;
 
-      log_verbose ("Computing reachable, currently %u total, from %s: %s", g_hash_table_size (data.reachable), name, sha256);
-      if (!compute_reachable_objects_from_commit (repo, sha256, 0, data.reachable, cancellable, error))
+      log_verbose ("Computing reachable, currently %u total, from %s: %s", g_hash_table_size (data.reachable), name, checksum);
+      if (!ostree_traverse_commit (repo, checksum, depth, data.reachable, cancellable, error))
         goto out;
     }
 
@@ -279,13 +157,6 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
 
   g_hash_table_iter_init (&hash_iter, objects);
 
-
-  if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL,
-                                 &objects, cancellable, error))
-    goto out;
-  
-  g_hash_table_iter_init (&hash_iter, objects);
-
   while (g_hash_table_iter_next (&hash_iter, &key, &value))
     {
       GVariant *serialized_key = key;
@@ -305,9 +176,6 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
         }
     }
 
-  if (data.had_error)
-    goto out;
-
   g_print ("Total reachable: %u\n", data.n_reachable);
   g_print ("Total unreachable: %u\n", data.n_unreachable);
 



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