[ostree/wip/packfile-rebase2: 6/11] core: Expose API to query all object status at once
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/packfile-rebase2: 6/11] core: Expose API to query all object status at once
- Date: Thu, 22 Mar 2012 03:14:25 +0000 (UTC)
commit 63f3a7afe0c7f7de202dddda82f374a0e1965824
Author: Colin Walters <walters verbum org>
Date: Mon Mar 19 19:04:53 2012 -0400
core: Expose API to query all object status at once
This is more efficient in the end than an iteration API, and helps us
allow differentiatiation between packed/loose objects.
src/libostree/ostree-core.c | 17 ++++
src/libostree/ostree-core.h | 7 ++
src/libostree/ostree-repo.c | 156 +++++++++++++++++++++++++----------
src/libostree/ostree-repo.h | 32 +++++---
src/ostree/ot-builtin-fsck.c | 64 ++++++++++-----
src/ostree/ot-builtin-local-clone.c | 71 +++++++++++-----
src/ostree/ot-builtin-prune.c | 60 +++++++++++---
src/ostree/ot-builtin-repack.c | 154 +++++++++++++++++-----------------
8 files changed, 376 insertions(+), 185 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 263988c..852adcb 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -584,6 +584,23 @@ ostree_object_from_string (const char *str,
*out_objtype = ostree_object_type_from_string (dot + 1);
}
+GVariant *
+ostree_object_name_serialize (const char *checksum,
+ OstreeObjectType objtype)
+{
+ return g_variant_new ("(su)", checksum, (guint32)objtype);
+}
+
+void
+ostree_object_name_deserialize (GVariant *variant,
+ const char **out_checksum,
+ OstreeObjectType *out_objtype)
+{
+ guint32 objtype_u32;
+ g_variant_get (variant, "(&su)", out_checksum, &objtype_u32);
+ *out_objtype = (OstreeObjectType)objtype_u32;
+}
+
char *
ostree_get_relative_object_path (const char *checksum,
OstreeObjectType type)
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index db4b6cd..398c4aa 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -144,6 +144,13 @@ const char * ostree_object_type_to_string (OstreeObjectType objtype);
OstreeObjectType ostree_object_type_from_string (const char *str);
+GVariant *ostree_object_name_serialize (const char *checksum,
+ OstreeObjectType objtype);
+
+void ostree_object_name_deserialize (GVariant *variant,
+ const char **out_checksum,
+ OstreeObjectType *out_objtype);
+
char * ostree_object_to_string (const char *checksum,
OstreeObjectType objtype);
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 4c99d88..83489e7 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -2294,43 +2294,54 @@ ostree_repo_commit_modifier_unref (OstreeRepoCommitModifier *modifier)
return;
}
+static guint
+hash_list_object_key (gconstpointer a)
+{
+ GVariant *variant = (gpointer)a;
+ const char *checksum;
+ OstreeObjectType objtype;
+ gint objtype_int;
+
+ ostree_object_name_deserialize (variant, &checksum, &objtype);
+ objtype_int = (gint) objtype;
+ return g_str_hash (checksum) + g_int_hash (&objtype_int);
+}
static gboolean
-iter_object_dir (OstreeRepo *self,
- GFile *dir,
- OstreeRepoObjectIter callback,
- gpointer user_data,
- GError **error)
+list_loose_object_dir (OstreeRepo *self,
+ GFile *dir,
+ GHashTable *inout_objects,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
GError *temp_error = NULL;
GFileEnumerator *enumerator = NULL;
GFileInfo *file_info = NULL;
const char *dirname = NULL;
+ char *dot = NULL;
+ GString *checksum = NULL;
dirname = ot_gfile_get_basename_cached (dir);
enumerator = g_file_enumerate_children (dir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL,
+ cancellable,
error);
if (!enumerator)
goto out;
- while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL)
+ while ((file_info = g_file_enumerator_next_file (enumerator, cancellable, &temp_error)) != NULL)
{
const char *name;
guint32 type;
- char *dot = NULL;
- GFile *child = NULL;
- GString *checksum = NULL;
OstreeObjectType objtype;
name = g_file_info_get_attribute_byte_string (file_info, "standard::name");
type = g_file_info_get_attribute_uint32 (file_info, "standard::type");
if (type == G_FILE_TYPE_DIRECTORY)
- goto loop_out;
+ goto loop_next;
if (g_str_has_suffix (name, ".file"))
objtype = OSTREE_OBJECT_TYPE_RAW_FILE;
@@ -2345,25 +2356,33 @@ iter_object_dir (OstreeRepo *self,
else if (g_str_has_suffix (name, ".commit"))
objtype = OSTREE_OBJECT_TYPE_COMMIT;
else
- goto loop_out;
+ goto loop_next;
dot = strrchr (name, '.');
g_assert (dot);
- if ((dot - name) != 62)
- goto loop_out;
-
- checksum = g_string_new (dirname);
- g_string_append_len (checksum, name, 62);
-
- child = g_file_get_child (dir, name);
- callback (self, checksum->str, objtype, child, file_info, user_data);
-
- loop_out:
- if (checksum)
- g_string_free (checksum, TRUE);
+ if ((dot - name) == 62)
+ {
+ GVariant *key, *value;
+
+ if (checksum)
+ g_string_free (checksum, TRUE);
+ checksum = g_string_new (dirname);
+ g_string_append_len (checksum, name, 62);
+
+ key = ostree_object_name_serialize (checksum->str, objtype);
+ value = g_variant_new ("(b astt)",
+ TRUE, g_variant_new_strv (NULL, 0),
+ g_file_info_get_attribute_uint64 (file_info,
+ G_FILE_ATTRIBUTE_TIME_CHANGED),
+ g_file_info_get_attribute_uint64 (file_info,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE));
+ /* transfer ownership */
+ g_hash_table_replace (inout_objects, g_variant_ref_sink (key),
+ g_variant_ref_sink (value));
+ }
+ loop_next:
g_clear_object (&file_info);
- g_clear_object (&child);
}
if (temp_error != NULL)
{
@@ -2376,32 +2395,33 @@ iter_object_dir (OstreeRepo *self,
ret = TRUE;
out:
g_clear_object (&file_info);
+ g_clear_object (&enumerator);
+ if (checksum)
+ g_string_free (checksum, TRUE);
return ret;
}
-gboolean
-ostree_repo_iter_objects (OstreeRepo *self,
- OstreeRepoObjectIter callback,
- gpointer user_data,
- GError **error)
+static gboolean
+list_loose_objects (OstreeRepo *self,
+ GHashTable *inout_objects,
+ GCancellable *cancellable,
+ GError **error)
{
+ gboolean ret = FALSE;
OstreeRepoPrivate *priv = GET_PRIVATE (self);
GFileEnumerator *enumerator = NULL;
- gboolean ret = FALSE;
GFileInfo *file_info = NULL;
GError *temp_error = NULL;
-
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- g_return_val_if_fail (priv->inited, FALSE);
+ GFile *objdir = NULL;
enumerator = g_file_enumerate_children (priv->objects_dir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL,
+ cancellable,
error);
if (!enumerator)
goto out;
- while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL)
+ while ((file_info = g_file_enumerator_next_file (enumerator, cancellable, &temp_error)) != NULL)
{
const char *name;
guint32 type;
@@ -2411,31 +2431,77 @@ ostree_repo_iter_objects (OstreeRepo *self,
if (strlen (name) == 2 && type == G_FILE_TYPE_DIRECTORY)
{
- GFile *objdir = g_file_get_child (priv->objects_dir, name);
- if (!iter_object_dir (self, objdir, callback, user_data, error))
- {
- g_object_unref (objdir);
- goto out;
- }
- g_object_unref (objdir);
+ g_clear_object (&objdir);
+ objdir = g_file_get_child (priv->objects_dir, name);
+ if (!list_loose_object_dir (self, objdir, inout_objects, cancellable, error))
+ goto out;
}
- g_object_unref (file_info);
+ g_clear_object (&file_info);
}
if (file_info == NULL && temp_error != NULL)
{
g_propagate_error (error, temp_error);
goto out;
}
- if (!g_file_enumerator_close (enumerator, NULL, error))
+ if (!g_file_enumerator_close (enumerator, cancellable, error))
goto out;
ret = TRUE;
out:
+ g_clear_object (&objdir);
g_clear_object (&file_info);
g_clear_object (&enumerator);
return ret;
}
+/**
+ * ostree_repo_list_objects:
+ * @self:
+ * @flags:
+ * @out_objects: (out): Map of serialized object name to variant data
+ * @cancellable:
+ * @error:
+ *
+ * This function synchronously enumerates all objects in the
+ * repository, returning data in @out_objects. @out_objects
+ * maps from keys returned by ostree_object_name_serialize()
+ * to #GVariant values of type %OSTREE_REPO_LIST_OBJECTS_VARIANT_TYPE.
+ *
+ * Returns: %TRUE on success, %FALSE on error, and @error will be set
+ */
+gboolean
+ostree_repo_list_objects (OstreeRepo *self,
+ OstreeRepoListObjectsFlags flags,
+ GHashTable **out_objects,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ OstreeRepoPrivate *priv = GET_PRIVATE (self);
+ GHashTable *ret_objects = NULL;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (priv->inited, FALSE);
+
+ ret_objects = g_hash_table_new_full (hash_list_object_key, g_variant_equal, (GDestroyNotify) g_variant_unref, (GDestroyNotify) g_variant_unref);
+
+ if (flags & OSTREE_REPO_LIST_OBJECTS_ALL)
+ flags |= (OSTREE_REPO_LIST_OBJECTS_LOOSE | OSTREE_REPO_LIST_OBJECTS_PACKED);
+
+ if (flags & OSTREE_REPO_LIST_OBJECTS_LOOSE)
+ {
+ if (!list_loose_objects (self, ret_objects, cancellable, error))
+ goto out;
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_objects, &ret_objects);
+ out:
+ if (ret_objects)
+ g_hash_table_unref (ret_objects);
+ return ret;
+}
+
static gboolean
checkout_file_from_input (GFile *file,
OstreeRepoCheckoutMode mode,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 25ef09e..0d3ae1b 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -226,17 +226,27 @@ gboolean ostree_repo_read_commit (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
-typedef void (*OstreeRepoObjectIter) (OstreeRepo *self,
- const char *checksum,
- OstreeObjectType type,
- GFile *path,
- GFileInfo *fileinfo,
- gpointer user_data);
-
-gboolean ostree_repo_iter_objects (OstreeRepo *self,
- OstreeRepoObjectIter callback,
- gpointer user_data,
- GError **error);
+typedef enum {
+ OSTREE_REPO_LIST_OBJECTS_LOOSE = (1 << 0),
+ OSTREE_REPO_LIST_OBJECTS_PACKED = (1 << 1),
+ OSTREE_REPO_LIST_OBJECTS_ALL = (1 << 2)
+} OstreeRepoListObjectsFlags;
+
+/**
+ * OSTREE_REPO_LIST_OBJECTS_VARIANT_TYPE:
+ *
+ * b - %TRUE if object is available "loose"
+ * as - List of pack file checksums in which this object appears
+ * t - For loose objects, Unix ctime (seconds)
+ * t - object size
+ */
+#define OSTREE_REPO_LIST_OBJECTS_VARIANT_TYPE (G_VARIANT_TYPE ("(bastt)")
+
+gboolean ostree_repo_list_objects (OstreeRepo *self,
+ OstreeRepoListObjectsFlags flags,
+ GHashTable **out_objects,
+ GCancellable *cancellable,
+ GError **error);
G_END_DECLS
diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c
index 9671ffa..6e5de25 100644
--- a/src/ostree/ot-builtin-fsck.c
+++ b/src/ostree/ot-builtin-fsck.c
@@ -123,39 +123,36 @@ checksum_archived_file (OtFsckData *data,
return ret;
}
-static void
-object_iter_callback (OstreeRepo *repo,
- const char *exp_checksum,
- OstreeObjectType objtype,
- GFile *objf,
- GFileInfo *file_info,
- gpointer user_data)
+static gboolean
+fsck_loose_object (OtFsckData *data,
+ const char *exp_checksum,
+ OstreeObjectType objtype,
+ GCancellable *cancellable,
+ GError **error)
{
- OtFsckData *data = user_data;
+ gboolean ret = FALSE;
+ GFile *objf = NULL;
GChecksum *real_checksum = NULL;
- GError *error = NULL;
- /* nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
- if (nlinks < 2 && !quiet)
- g_printerr ("note: floating object: %s\n", path); */
+ objf = ostree_repo_get_object_path (data->repo, exp_checksum, objtype);
if (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META)
{
if (!g_str_has_suffix (ot_gfile_get_path_cached (objf), ".archive-meta"))
{
- g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid archive filename '%s'",
ot_gfile_get_path_cached (objf));
goto out;
}
- if (!checksum_archived_file (data, exp_checksum, objf, &real_checksum, &error))
+ if (!checksum_archived_file (data, exp_checksum, objf, &real_checksum, error))
goto out;
}
else if (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
; /* Handled above */
else
{
- if (!ostree_checksum_file (objf, objtype, &real_checksum, NULL, &error))
+ if (!ostree_checksum_file (objf, objtype, &real_checksum, NULL, error))
goto out;
}
@@ -170,13 +167,10 @@ object_iter_callback (OstreeRepo *repo,
data->n_objects++;
+ ret = TRUE;
out:
ot_clear_checksum (&real_checksum);
- if (error != NULL)
- {
- g_printerr ("%s\n", error->message);
- g_clear_error (&error);
- }
+ return ret;
}
gboolean
@@ -186,6 +180,10 @@ ostree_builtin_fsck (int argc, char **argv, GFile *repo_path, GError **error)
OtFsckData data;
gboolean ret = FALSE;
OstreeRepo *repo = NULL;
+ GHashTable *objects = NULL;
+ GCancellable *cancellable = NULL;
+ GHashTableIter hash_iter;
+ gpointer key, value;
context = g_option_context_new ("- Check the repository for consistency");
g_option_context_add_main_entries (context, options, NULL);
@@ -201,8 +199,30 @@ ostree_builtin_fsck (int argc, char **argv, GFile *repo_path, GError **error)
data.n_objects = 0;
data.had_error = FALSE;
- if (!ostree_repo_iter_objects (repo, object_iter_callback, &data, error))
+ 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;
+ GVariant *objdata = value;
+ const char *checksum;
+ OstreeObjectType objtype;
+ gboolean is_loose;
+
+ ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+ g_variant_get_child (objdata, 0, "b", &is_loose);
+
+ if (is_loose)
+ {
+ if (!fsck_loose_object (&data, checksum, objtype, cancellable, error))
+ goto out;
+ }
+ }
if (data.had_error)
{
@@ -218,5 +238,7 @@ ostree_builtin_fsck (int argc, char **argv, GFile *repo_path, GError **error)
if (context)
g_option_context_free (context);
g_clear_object (&repo);
+ if (objects)
+ g_hash_table_unref (objects);
return ret;
}
diff --git a/src/ostree/ot-builtin-local-clone.c b/src/ostree/ot-builtin-local-clone.c
index 87b0151..840bf9d 100644
--- a/src/ostree/ot-builtin-local-clone.c
+++ b/src/ostree/ot-builtin-local-clone.c
@@ -97,23 +97,29 @@ copy_dir_contents_recurse (GFile *src,
return ret;
}
-static void
-object_iter_callback (OstreeRepo *repo,
- const char *checksum,
- OstreeObjectType objtype,
- GFile *objfile,
- GFileInfo *file_info,
- gpointer user_data)
+static gboolean
+import_loose_object (OtLocalCloneData *data,
+ const char *checksum,
+ OstreeObjectType objtype,
+ GCancellable *cancellable,
+ GError **error)
{
- OtLocalCloneData *data = user_data;
- GError *real_error = NULL;
- GError **error = &real_error;
+ gboolean ret = FALSE;
+ GFile *objfile = NULL;
+ GFileInfo *file_info = NULL;
GFile *content_path = NULL;
GFileInfo *archive_info = NULL;
GVariant *archive_metadata = NULL;
GVariant *xattrs = NULL;
GInputStream *input = NULL;
+ objfile = ostree_repo_get_object_path (data->src_repo, checksum, objtype);
+ file_info = g_file_query_info (objfile, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error);
+
+ if (file_info == NULL)
+ goto out;
+
if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE)
xattrs = ostree_get_xattrs_for_file (objfile, error);
@@ -121,13 +127,13 @@ object_iter_callback (OstreeRepo *repo,
;
else if (objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META)
{
- if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, checksum, &archive_metadata, error))
+ if (!ostree_repo_load_variant (data->src_repo, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, checksum, &archive_metadata, error))
goto out;
if (!ostree_parse_archived_file_meta (archive_metadata, &archive_info, &xattrs, error))
goto out;
- content_path = ostree_repo_get_object_path (repo, checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
+ content_path = ostree_repo_get_object_path (data->src_repo, checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
if (g_file_info_get_file_type (archive_info) == G_FILE_TYPE_REGULAR)
{
@@ -156,18 +162,16 @@ object_iter_callback (OstreeRepo *repo,
goto out;
}
+ ret = TRUE;
out:
ot_clear_gvariant (&archive_metadata);
ot_clear_gvariant (&xattrs);
g_clear_object (&archive_info);
g_clear_object (&input);
g_clear_object (&content_path);
- if (real_error != NULL)
- {
- g_printerr ("%s\n", real_error->message);
- g_clear_error (error);
- exit (1);
- }
+ g_clear_object (&file_info);
+ g_clear_object (&objfile);
+ return ret;
}
static gboolean
@@ -209,6 +213,7 @@ ostree_builtin_local_clone (int argc, char **argv, GFile *repo_path, GError **er
{
gboolean ret = FALSE;
GCancellable *cancellable = NULL;
+ GHashTable *objects = NULL;
GOptionContext *context;
const char *destination;
GFile *dest_f = NULL;
@@ -220,6 +225,8 @@ ostree_builtin_local_clone (int argc, char **argv, GFile *repo_path, GError **er
GFile *src_dir = NULL;
GFile *dest_dir = NULL;
int i;
+ GHashTableIter hash_iter;
+ gpointer key, value;
context = g_option_context_new ("DEST ... - Create new repository DEST");
g_option_context_add_main_entries (context, options, NULL);
@@ -266,11 +273,33 @@ ostree_builtin_local_clone (int argc, char **argv, GFile *repo_path, GError **er
data.uids_differ = g_file_info_get_attribute_uint32 (src_info, "unix::uid") != g_file_info_get_attribute_uint32 (dest_info, "unix::uid");
- if (!ostree_repo_prepare_transaction (data.dest_repo, NULL, error))
+ if (!ostree_repo_list_objects (data.src_repo, OSTREE_REPO_LIST_OBJECTS_ALL,
+ &objects, cancellable, error))
goto out;
- if (!ostree_repo_iter_objects (data.src_repo, object_iter_callback, &data, error))
+ if (!ostree_repo_prepare_transaction (data.dest_repo, NULL, 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;
+ GVariant *objdata = value;
+ const char *checksum;
+ OstreeObjectType objtype;
+ gboolean is_loose;
+
+ ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+ g_variant_get_child (objdata, 0, "b", &is_loose);
+
+ if (is_loose)
+ {
+ if (!import_loose_object (&data, checksum, objtype, cancellable, error))
+ goto out;
+ }
+ }
if (!ostree_repo_commit_transaction (data.dest_repo, NULL, error))
goto out;
@@ -311,5 +340,7 @@ ostree_builtin_local_clone (int argc, char **argv, GFile *repo_path, GError **er
g_clear_object (&dest_dir);
g_clear_object (&data.src_repo);
g_clear_object (&data.dest_repo);
+ if (objects)
+ g_hash_table_unref (objects);
return ret;
}
diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c
index 5090036..2c50f51 100644
--- a/src/ostree/ot-builtin-prune.c
+++ b/src/ostree/ot-builtin-prune.c
@@ -187,24 +187,27 @@ compute_reachable_objects_from_commit (OstreeRepo *repo,
return ret;
}
-static void
-object_iter_callback (OstreeRepo *repo,
- const char *checksum,
- OstreeObjectType objtype,
- GFile *objf,
- GFileInfo *file_info,
- gpointer user_data)
+static gboolean
+prune_loose_object (OtPruneData *data,
+ const char *checksum,
+ OstreeObjectType objtype,
+ GCancellable *cancellable,
+ GError **error)
{
- OtPruneData *data = user_data;
+ gboolean ret = FALSE;
char *key;
+ GFile *objf = NULL;
key = ostree_object_to_string (checksum, objtype);
+ objf = ostree_repo_get_object_path (data->repo, checksum, objtype);
+
if (!g_hash_table_lookup_extended (data->reachable, key, NULL, NULL))
{
if (delete)
{
- (void) unlink (ot_gfile_get_path_cached (objf));
+ if (!g_file_delete (objf, cancellable, error))
+ goto out;
g_print ("Deleted: %s\n", key);
}
else
@@ -216,16 +219,21 @@ object_iter_callback (OstreeRepo *repo,
else
data->n_reachable++;
+ ret = TRUE;
+ out:
+ g_clear_object (&objf);
g_free (key);
+ return ret;
}
gboolean
ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
{
+ gboolean ret = FALSE;
GOptionContext *context;
OtPruneData data;
- gboolean ret = FALSE;
+ GHashTable *objects = NULL;
OstreeRepo *repo = NULL;
GHashTable *all_refs = NULL;
GHashTableIter hash_iter;
@@ -266,10 +274,36 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
goto out;
}
- g_hash_table_iter_init (&hash_iter, data.reachable);
+ if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error))
+ goto out;
+
+ g_hash_table_iter_init (&hash_iter, objects);
+
- if (!ostree_repo_iter_objects (repo, object_iter_callback, &data, error))
+ 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;
+ GVariant *objdata = value;
+ const char *checksum;
+ OstreeObjectType objtype;
+ gboolean is_loose;
+
+ ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+ g_variant_get_child (objdata, 0, "b", &is_loose);
+
+ if (is_loose)
+ {
+ if (!prune_loose_object (&data, checksum, objtype, cancellable, error))
+ goto out;
+ }
+ }
if (data.had_error)
goto out;
@@ -286,5 +320,7 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
if (context)
g_option_context_free (context);
g_clear_object (&repo);
+ if (objects)
+ g_hash_table_unref (objects);
return ret;
}
diff --git a/src/ostree/ot-builtin-repack.c b/src/ostree/ot-builtin-repack.c
index 4bee9f3..cbf92ff 100644
--- a/src/ostree/ot-builtin-repack.c
+++ b/src/ostree/ot-builtin-repack.c
@@ -64,7 +64,6 @@ typedef struct {
guint n_dirmeta;
guint n_dirtree;
guint n_files;
- GPtrArray *objects;
gboolean had_error;
GError **error;
} OtRepackData;
@@ -133,56 +132,6 @@ create_compressor_subprocess (OtBuildRepackFile *self,
return ret;
}
-static void
-object_iter_callback (OstreeRepo *repo,
- const char *checksum,
- OstreeObjectType objtype,
- GFile *objf,
- GFileInfo *file_info,
- gpointer user_data)
-{
- gboolean ret = FALSE;
- OtRepackData *data = user_data;
- guint64 objsize;
- GVariant *objdata = NULL;
-
- switch (objtype)
- {
- case OSTREE_OBJECT_TYPE_COMMIT:
- data->n_commits++;
- break;
- case OSTREE_OBJECT_TYPE_DIR_TREE:
- data->n_dirtree++;
- break;
- case OSTREE_OBJECT_TYPE_DIR_META:
- data->n_dirmeta++;
- break;
- case OSTREE_OBJECT_TYPE_RAW_FILE:
- case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT:
- data->n_files++;
- break;
- case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META:
- /* Counted under files */
- break;
- }
-
- /* For archived content, only count regular files */
- if (!(objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT
- && g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR))
- {
- objsize = g_file_info_get_size (file_info);
-
- objdata = g_variant_new ("(tsu)", objsize, checksum, (guint32)objtype);
- g_ptr_array_add (data->objects, g_variant_ref_sink (objdata));
- objdata = NULL; /* Transfer ownership */
- }
-
- ret = TRUE;
- /* out: */
- ot_clear_gvariant (&objdata);
- data->had_error = !ret;
-}
-
static gint
compare_object_data_by_size (gconstpointer ap,
gconstpointer bp)
@@ -192,8 +141,8 @@ compare_object_data_by_size (gconstpointer ap,
guint64 a_size;
guint64 b_size;
- g_variant_get_child (a, 0, "t", &a_size);
- g_variant_get_child (b, 0, "t", &b_size);
+ g_variant_get_child (a, 2, "t", &a_size);
+ g_variant_get_child (b, 2, "t", &b_size);
if (a == b)
return 0;
else if (a > b)
@@ -315,7 +264,7 @@ create_pack_file (OtRepackData *data,
GOutputStream *write_pack_out;
guchar entry_flags;
- g_variant_get (object_data, "(t&su)", &objsize, &checksum, &objtype_u32);
+ g_variant_get (object_data, "(&sut)", &checksum, &objtype_u32, &objsize);
objtype = (OstreeObjectType) objtype_u32;
@@ -489,26 +438,49 @@ create_pack_file (OtRepackData *data,
* Returns: [Array of [Array of object data]]. Free with g_ptr_array_unref().
*/
static GPtrArray *
-cluster_objects_stupidly (OtRepackData *data)
+cluster_objects_stupidly (OtRepackData *data,
+ GHashTable *objects)
{
GPtrArray *ret = NULL;
- GPtrArray *objects = data->objects;
+ GPtrArray *object_list = NULL;
guint i;
guint64 current_size;
guint current_offset;
+ GHashTableIter hash_iter;
+ gpointer key, value;
+
+ object_list = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
- g_ptr_array_sort (data->objects, compare_object_data_by_size);
+ g_hash_table_iter_init (&hash_iter, objects);
+
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ {
+ GVariant *serialized_key = key;
+ GVariant *objdata = value;
+ const char *checksum;
+ OstreeObjectType objtype;
+ guint64 size;
+
+ ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+ g_variant_get_child (objdata, 3, "t", &size);
+
+ g_ptr_array_add (object_list,
+ g_variant_new ("(sut)", checksum, objtype, size));
+ }
+
+ g_ptr_array_sort (object_list, compare_object_data_by_size);
ret = g_ptr_array_new ();
current_size = 0;
current_offset = 0;
- for (i = 0; i < objects->len; i++)
+ for (i = 0; i < object_list->len; i++)
{
- GVariant *objdata = objects->pdata[i];
+ GVariant *objdata = object_list->pdata[i];
guint64 objsize;
- g_variant_get_child (objdata, 0, "t", &objsize);
+ g_variant_get_child (objdata, 2, "t", &objsize);
if (current_size + objsize > data->pack_size)
{
@@ -516,7 +488,7 @@ cluster_objects_stupidly (OtRepackData *data)
GPtrArray *current = g_ptr_array_new ();
for (j = current_offset; j < i; j++)
{
- g_ptr_array_add (current, objects->pdata[j]);
+ g_ptr_array_add (current, object_list->pdata[j]);
}
g_ptr_array_add (ret, current);
current_size = objsize;
@@ -532,6 +504,8 @@ cluster_objects_stupidly (OtRepackData *data)
}
}
+ if (object_list)
+ g_ptr_array_unref (object_list);
return ret;
}
@@ -622,14 +596,17 @@ parse_compression_string (const char *compstr,
gboolean
ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
{
+ gboolean ret = FALSE;
GOptionContext *context;
OtRepackData data;
- gboolean ret = FALSE;
OstreeRepo *repo = NULL;
+ GHashTable *objects = NULL;
GCancellable *cancellable = NULL;
guint i;
guint64 total_size;
GPtrArray *clusters = NULL;
+ GHashTableIter hash_iter;
+ gpointer key, value;
memset (&data, 0, sizeof (data));
@@ -645,7 +622,6 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
data.repo = repo;
data.error = error;
- data.objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
if (!parse_size_spec_with_suffix (opt_pack_size, OT_DEFAULT_PACK_SIZE_BYTES, &data.pack_size, error))
goto out;
@@ -655,33 +631,57 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
if (!parse_compression_string (opt_ext_compression, &data.ext_compression, error))
goto out;
- if (!ostree_repo_iter_objects (repo, object_iter_callback, &data, error))
+ if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_LOOSE, &objects, cancellable, error))
goto out;
- if (data.had_error)
- goto out;
-
- g_print ("Commits: %u\n", data.n_commits);
- g_print ("Tree contents: %u\n", data.n_dirtree);
- g_print ("Tree meta: %u\n", data.n_dirmeta);
- g_print ("Files: %u\n", data.n_files);
+ g_hash_table_iter_init (&hash_iter, objects);
total_size = 0;
- for (i = 0; i < data.objects->len; i++)
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
- GVariant *objdata = data.objects->pdata[i];
+ GVariant *serialized_key = key;
+ GVariant *objdata = value;
+ const char *checksum;
+ OstreeObjectType objtype;
guint64 size;
-
- g_variant_get_child (objdata, 0, "t", &size);
+
+ ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
+
+ switch (objtype)
+ {
+ case OSTREE_OBJECT_TYPE_COMMIT:
+ data.n_commits++;
+ break;
+ case OSTREE_OBJECT_TYPE_DIR_TREE:
+ data.n_dirtree++;
+ break;
+ case OSTREE_OBJECT_TYPE_DIR_META:
+ data.n_dirmeta++;
+ break;
+ case OSTREE_OBJECT_TYPE_RAW_FILE:
+ case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT:
+ data.n_files++;
+ break;
+ case OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META:
+ /* Counted under files */
+ break;
+ }
+
+ g_variant_get_child (objdata, 3, "t", &size);
total_size += size;
}
+
+ g_print ("Commits: %u\n", data.n_commits);
+ g_print ("Tree contents: %u\n", data.n_dirtree);
+ g_print ("Tree meta: %u\n", data.n_dirmeta);
+ g_print ("Files: %u\n", data.n_files);
g_print ("Total size: %" G_GUINT64_FORMAT "\n", total_size);
g_print ("\n");
g_print ("Using pack size: %" G_GUINT64_FORMAT "\n", data.pack_size);
- clusters = cluster_objects_stupidly (&data);
+ clusters = cluster_objects_stupidly (&data, objects);
g_print ("Going to create %u packfiles\n", clusters->len);
@@ -705,5 +705,7 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
g_clear_object (&repo);
if (clusters)
g_ptr_array_unref (clusters);
+ if (objects)
+ g_hash_table_unref (objects);
return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]