[ostree/wip/packfile-rebase2: 11/11] core: Delete loose objects



commit 999f2eb292e44f191a591d60626e32f5cadd7887
Author: Colin Walters <walters verbum org>
Date:   Wed Mar 21 23:12:38 2012 -0400

    core: Delete loose objects

 src/libostree/ostree-repo.c    |  156 ++++++++++++++++++++++++++++------------
 src/libostree/ostree-repo.h    |    1 +
 src/ostree/ostree-pull.c       |   17 ++++-
 src/ostree/ot-builtin-repack.c |   44 +++++++++++-
 4 files changed, 165 insertions(+), 53 deletions(-)
---
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 7cc8081..c9b6b72 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -781,48 +781,6 @@ get_pending_object_path (OstreeRepo       *self,
   return ret;
 }
 
-gboolean      
-ostree_repo_find_object (OstreeRepo           *self,
-                         OstreeObjectType      objtype,
-                         const char           *checksum,
-                         GFile               **out_stored_path,
-                         GFile               **out_pending_path,
-                         GCancellable         *cancellable,
-                         GError             **error)
-{
-  gboolean ret = FALSE;
-  GFile *object_path = NULL;
-  struct stat stbuf;
-
-  g_return_val_if_fail (out_stored_path, FALSE);
-  g_return_val_if_fail (out_pending_path, FALSE);
-
-  object_path = ostree_repo_get_object_path (self, checksum, objtype);
-  
-  *out_stored_path = NULL;
-  *out_pending_path = NULL;
-  if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
-    {
-      *out_stored_path = object_path;
-      object_path = NULL;
-    }
-  else
-    {
-      g_clear_object (&object_path);
-      object_path = get_pending_object_path (self, checksum, objtype);
-      if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
-        {
-          *out_pending_path = object_path;
-          object_path = NULL;
-        }
-    }
-  
-  ret = TRUE;
-  /* out: */
-  g_clear_object (&object_path);
-  return ret;
-}
-
 static GFileInfo *
 dup_file_info_owned_by_me (GFileInfo  *file_info)
 {
@@ -1008,6 +966,7 @@ stage_object_impl (OstreeRepo         *self,
   GFile *temp_file = NULL;
   GFile *stored_path = NULL;
   GFile *pending_path = NULL;
+  char *pack_checksum = NULL;
   const char *actual_checksum;
 
   g_return_val_if_fail (priv->in_transaction, FALSE);
@@ -1019,7 +978,9 @@ stage_object_impl (OstreeRepo         *self,
 
   if (expected_checksum)
     {
-      if (!ostree_repo_find_object (self, objtype, expected_checksum, &stored_path, &pending_path,
+      if (!ostree_repo_find_object (self, objtype, expected_checksum,
+                                    &stored_path, &pending_path,
+                                    &pack_checksum,
                                     cancellable, error))
         goto out;
     }
@@ -1027,7 +988,7 @@ stage_object_impl (OstreeRepo         *self,
   g_assert (objtype != OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
   g_assert (objtype != OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META);
 
-  if (stored_path == NULL && pending_path == NULL)
+  if (stored_path == NULL && pending_path == NULL && pack_checksum == NULL)
     {
       if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE)
         {
@@ -1088,7 +1049,7 @@ stage_object_impl (OstreeRepo         *self,
     }
   else
     {
-      g_assert (stored_path != NULL);
+      g_assert (stored_path != NULL || pack_checksum != NULL);
       /* Nothing to do */
     }
 
@@ -1101,6 +1062,7 @@ stage_object_impl (OstreeRepo         *self,
   g_clear_object (&temp_info);
   g_clear_object (&stored_path);
   g_clear_object (&pending_path);
+  g_free (pack_checksum);
   ot_clear_checksum (&ret_checksum);
   return ret;
 }
@@ -2827,7 +2789,7 @@ ostree_repo_load_pack_entry (OstreeRepo         *self,
     goto out;
 
   index_contents = g_variant_get_child_value (index, 3);
-
+  
   if (!bsearch_in_pack_index (index_contents, entry_sha256, objtype, &offset))
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -2986,6 +2948,108 @@ ostree_repo_list_pack_indexes (OstreeRepo              *self,
   return ret;
 }
 
+static gboolean
+find_object_in_packs (OstreeRepo        *self,
+                      const char        *checksum,
+                      OstreeObjectType   objtype,
+                      char             **out_pack_checksum,
+                      GCancellable      *cancellable,
+                      GError           **error)
+{
+  gboolean ret = FALSE;
+  GPtrArray *index_checksums = NULL;
+  char *ret_pack_checksum = NULL;
+  GFile *index_path = NULL;
+  GVariant *index_variant = NULL;
+  GVariant *index_contents = NULL;
+  guint i;
+
+  if (!ostree_repo_list_pack_indexes (self, &index_checksums, cancellable, error))
+    goto out;
+
+  for (i = 0; i < index_checksums->len; i++)
+    {
+      const char *pack_checksum = index_checksums->pdata[i];
+      guint64 offset;
+
+      g_clear_object (&index_path);
+      index_path = get_pack_index_path (self, pack_checksum);
+
+      ot_clear_gvariant (&index_variant);
+      if (!ostree_repo_load_pack_index (self, pack_checksum, &index_variant, cancellable, error))
+        goto out;
+
+      ot_clear_gvariant (&index_contents);
+      index_contents = g_variant_get_child_value (index_variant, 3);
+      
+      if (!bsearch_in_pack_index (index_contents, checksum, objtype, &offset))
+        continue;
+
+      ret_pack_checksum = g_strdup (checksum);
+      break;
+    }
+
+  ret = TRUE;
+  ot_transfer_out_value (out_pack_checksum, &ret_pack_checksum);
+ out:
+  g_free (ret_pack_checksum);
+  if (index_checksums)
+    g_ptr_array_unref (index_checksums);
+  g_clear_object (&index_path);
+  ot_clear_gvariant (&index_variant);
+  ot_clear_gvariant (&index_contents);
+  return ret;
+}
+
+gboolean      
+ostree_repo_find_object (OstreeRepo           *self,
+                         OstreeObjectType      objtype,
+                         const char           *checksum,
+                         GFile               **out_stored_path,
+                         GFile               **out_pending_path,
+                         char                **out_pack_checksum,
+                         GCancellable         *cancellable,
+                         GError             **error)
+{
+  gboolean ret = FALSE;
+  GFile *object_path = NULL;
+  char *ret_pack_checksum = NULL;
+  struct stat stbuf;
+
+  g_return_val_if_fail (out_stored_path, FALSE);
+  g_return_val_if_fail (out_pending_path, FALSE);
+
+  object_path = ostree_repo_get_object_path (self, checksum, objtype);
+  
+  *out_stored_path = NULL;
+  *out_pending_path = NULL;
+  if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
+    {
+      *out_stored_path = object_path;
+      object_path = NULL;
+    }
+  else
+    {
+      g_clear_object (&object_path);
+      object_path = get_pending_object_path (self, checksum, objtype);
+      if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
+        {
+          *out_pending_path = object_path;
+          object_path = NULL;
+        }
+      if (!find_object_in_packs (self, checksum, objtype, &ret_pack_checksum,
+                                 cancellable, error))
+        goto out;
+    }
+  
+  ret = TRUE;
+  ot_transfer_out_value (out_pack_checksum, &ret_pack_checksum);
+out:
+  g_clear_object (&object_path);
+  g_free (ret_pack_checksum);
+  return ret;
+}
+
 /**
  * ostree_repo_list_objects:
  * @self:
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 29c6504..2fc4508 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -97,6 +97,7 @@ gboolean      ostree_repo_find_object (OstreeRepo           *self,
                                        const char           *checksum,
                                        GFile               **out_stored_path,
                                        GFile               **out_pending_path,
+                                       char                **out_pack_checksum,
                                        GCancellable         *cancellable,
                                        GError              **error);
 
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
index 40f3d46..619042e 100644
--- a/src/ostree/ostree-pull.c
+++ b/src/ostree/ostree-pull.c
@@ -226,6 +226,7 @@ fetch_and_store_object (OstreeRepo  *repo,
   GInputStream *input = NULL;
   GFile *stored_path = NULL;
   GFile *pending_path = NULL;
+  char *pack_checksum = NULL;
   GFile *temp_path = NULL;
   GVariant *ret_metadata = NULL;
   gboolean ret_is_pending;
@@ -233,10 +234,11 @@ fetch_and_store_object (OstreeRepo  *repo,
   g_assert (objtype != OSTREE_OBJECT_TYPE_RAW_FILE);
 
   if (!ostree_repo_find_object (repo, objtype, checksum,
-                                &stored_path, &pending_path, NULL, error))
+                                &stored_path, &pending_path, &pack_checksum,
+                                cancellable, error))
     goto out;
       
-  if (!(stored_path || pending_path))
+  if (!(stored_path || pending_path || pack_checksum))
     {
       if (!fetch_object (repo, soup, baseuri, checksum, objtype, &temp_path, cancellable, error))
         goto out;
@@ -286,6 +288,7 @@ fetch_and_store_object (OstreeRepo  *repo,
   g_clear_object (&input);
   g_clear_object (&stored_path);
   g_clear_object (&pending_path);
+  g_free (pack_checksum);
   return ret;
 }
 
@@ -310,6 +313,7 @@ fetch_and_store_tree_recurse (OstreeRepo   *repo,
   GFile *content_temp_path = NULL;
   GFile *stored_path = NULL;
   GFile *pending_path = NULL;
+  char *pack_checksum = NULL;
   GInputStream *input = NULL;
 
   if (!fetch_and_store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_DIR_TREE,
@@ -339,19 +343,23 @@ fetch_and_store_tree_recurse (OstreeRepo   *repo,
 
           g_clear_object (&stored_path);
           g_clear_object (&pending_path);
+          g_free (pack_checksum);
+          pack_checksum = NULL;
           /* If we're fetching from an archive into a bare repository, we need
            * to explicitly check for raw file types locally.
            */
           if (ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_BARE)
             {
               if (!ostree_repo_find_object (repo, OSTREE_OBJECT_TYPE_RAW_FILE, checksum,
-                                            &stored_path, &pending_path, cancellable, error))
+                                            &stored_path, &pending_path, &pack_checksum,
+                                            cancellable, error))
                 goto out;
             }
           else
             {
               if (!ostree_repo_find_object (repo, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT, checksum,
-                                            &stored_path, &pending_path, cancellable, error))
+                                            &stored_path, &pending_path, &pack_checksum,
+                                            cancellable, error))
                 goto out;
             }
 
@@ -451,6 +459,7 @@ fetch_and_store_tree_recurse (OstreeRepo   *repo,
   g_clear_object (&input);
   g_clear_object (&stored_path);
   g_clear_object (&pending_path);
+  g_free (pack_checksum);
   if (content_temp_path)
     {
       (void) unlink (ot_gfile_get_path_cached (content_temp_path));
diff --git a/src/ostree/ot-builtin-repack.c b/src/ostree/ot-builtin-repack.c
index afa4864..40c92f9 100644
--- a/src/ostree/ot-builtin-repack.c
+++ b/src/ostree/ot-builtin-repack.c
@@ -35,6 +35,7 @@
 #define OT_GZIP_COMPRESSION_LEVEL (8)
 
 static gboolean opt_analyze_only;
+static gboolean opt_keep_loose;
 static char* opt_pack_size;
 static char* opt_int_compression;
 static char* opt_ext_compression;
@@ -50,6 +51,7 @@ static GOptionEntry options[] = {
   { "internal-compression", 0, 0, G_OPTION_ARG_STRING, &opt_int_compression, "Compress objects using COMPRESSION", "COMPRESSION" },
   { "external-compression", 0, 0, G_OPTION_ARG_STRING, &opt_ext_compression, "Compress entire packfiles using COMPRESSION", "COMPRESSION" },
   { "analyze-only", 0, 0, G_OPTION_ARG_NONE, &opt_analyze_only, "Just analyze current state", NULL },
+  { "keep-loose", 0, 0, G_OPTION_ARG_NONE, &opt_keep_loose, "Don't delete loose objects", NULL },
   { NULL }
 };
 
@@ -660,11 +662,13 @@ static gboolean
 do_stats_gather_loose (OtRepackData  *data,
                        GHashTable    *objects,
                        GHashTable   **out_loose,
+                       GHashTable   **out_loose_and_packed,
                        GCancellable  *cancellable,
                        GError       **error)
 {
   gboolean ret = FALSE;
   GHashTable *ret_loose = NULL;
+  GHashTable *ret_loose_and_packed = NULL;
   guint n_loose = 0;
   guint n_loose_and_packed = 0;
   guint n_packed = 0;
@@ -679,6 +683,9 @@ do_stats_gather_loose (OtRepackData  *data,
   ret_loose = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
                                      (GDestroyNotify) g_variant_unref,
                                      NULL);
+  ret_loose_and_packed = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
+                                                (GDestroyNotify) g_variant_unref,
+                                                NULL);
 
   g_hash_table_iter_init (&hash_iter, objects);
   while (g_hash_table_iter_next (&hash_iter, &key, &value))
@@ -698,14 +705,19 @@ do_stats_gather_loose (OtRepackData  *data,
       is_packed = g_variant_n_children (pack_array) > 0;
       
       if (is_loose && is_packed)
-        n_loose_and_packed++;
+        {
+          GVariant *copy = g_variant_ref (serialized_key);
+          g_hash_table_replace (ret_loose_and_packed, copy, copy);
+          n_loose++;
+          n_loose_and_packed++;
+        }
       else if (is_loose)
         {
           GVariant *copy = g_variant_ref (serialized_key);
           g_hash_table_replace (ret_loose, copy, copy);
           n_loose++;
         }
-      else if (g_variant_n_children (pack_array) > 0)
+      else if (g_variant_n_children (pack_array) > 1)
         n_dup_packed++;
       else
         n_packed++;
@@ -743,9 +755,12 @@ do_stats_gather_loose (OtRepackData  *data,
 
   ret = TRUE;
   ot_transfer_out_value (out_loose, &ret_loose);
+  ot_transfer_out_value (out_loose_and_packed, &ret_loose_and_packed);
  /* out: */
   if (ret_loose)
     g_hash_table_unref (ret_loose);
+  if (ret_loose_and_packed)
+    g_hash_table_unref (ret_loose_and_packed);
   return ret;
 }
 
@@ -761,6 +776,10 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
   guint i;
   GPtrArray *clusters = NULL;
   GHashTable *loose_objects = NULL;
+  GHashTable *loose_and_packed_objects = NULL;
+  GHashTableIter hash_iter;
+  gpointer key, value;
+  GFile *objpath = NULL;
 
   memset (&data, 0, sizeof (data));
 
@@ -788,12 +807,30 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
   if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error))
     goto out;
 
-  if (!do_stats_gather_loose (&data, objects, &loose_objects, cancellable, error))
+  if (!do_stats_gather_loose (&data, objects, &loose_objects, &loose_and_packed_objects, cancellable, error))
     goto out;
 
   g_print ("\n");
   g_print ("Using pack size: %" G_GUINT64_FORMAT "\n", data.pack_size);
 
+  if (!opt_keep_loose)
+    {
+      g_hash_table_iter_init (&hash_iter, loose_and_packed_objects);
+      while (g_hash_table_iter_next (&hash_iter, &key, &value))
+        {
+          GVariant *variant = key;
+          const char *checksum;
+          OstreeObjectType objtype;
+
+          ostree_object_name_deserialize (variant, &checksum, &objtype);
+
+          g_clear_object (&objpath);
+          objpath = ostree_repo_get_object_path (data.repo, checksum, objtype);
+          if (!g_file_delete (objpath, cancellable, error))
+            goto out;
+        }
+    }
+
   if (!cluster_objects_stupidly (&data, loose_objects, &clusters, cancellable, error))
     goto out;
   
@@ -817,6 +854,7 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
 
   ret = TRUE;
  out:
+  g_clear_object (&objpath);
   if (context)
     g_option_context_free (context);
   g_clear_object (&repo);



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