prune: Add option to traverse refs only

The previous code (unintentionally) only traversed from refs; so data
only reachable from previous commits would be deleted.  That shouldn't
be the default, but we do want to offer it as an option.

So add a --refs-only option.
This commit is contained in:
Colin Walters 2012-11-16 12:26:29 -05:00
parent 51b1dd7cbd
commit 7861b98673
1 changed files with 65 additions and 33 deletions

View File

@ -29,27 +29,31 @@
#include <glib/gprintf.h> #include <glib/gprintf.h>
static gboolean opt_no_prune; static gboolean opt_no_prune;
static int opt_depth = -1; static gint opt_depth = -1;
static gboolean opt_refs_only;
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Only traverse commit objects by this count", NULL },
{ "no-prune", 0, 0, G_OPTION_ARG_NONE, &opt_no_prune, "Only display unreachable objects; don't delete", NULL }, { "no-prune", 0, 0, G_OPTION_ARG_NONE, &opt_no_prune, "Only display unreachable objects; don't delete", NULL },
{ "refs-only", 0, 0, G_OPTION_ARG_NONE, &opt_refs_only, "Only compute reachability via refs", NULL },
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Only traverse DEPTH parents for each commit (default: -1=infinite)", "DEPTH" },
{ NULL } { NULL }
}; };
typedef struct { typedef struct {
OstreeRepo *repo; OstreeRepo *repo;
GHashTable *reachable; GHashTable *reachable;
guint n_reachable; guint n_reachable_meta;
guint n_unreachable; guint n_reachable_content;
guint n_unreachable_meta;
guint n_unreachable_content;
} OtPruneData; } OtPruneData;
static gboolean static gboolean
prune_loose_object (OtPruneData *data, maybe_prune_loose_object (OtPruneData *data,
const char *checksum, const char *checksum,
OstreeObjectType objtype, OstreeObjectType objtype,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
ot_lvariant GVariant *key = NULL; ot_lvariant GVariant *key = NULL;
@ -66,10 +70,18 @@ prune_loose_object (OtPruneData *data,
if (!ot_gfile_unlink (objf, cancellable, error)) if (!ot_gfile_unlink (objf, cancellable, error))
goto out; goto out;
} }
data->n_unreachable++; if (OSTREE_OBJECT_TYPE_IS_META (objtype))
data->n_unreachable_meta++;
else
data->n_unreachable_content++;
} }
else else
data->n_reachable++; {
if (OSTREE_OBJECT_TYPE_IS_META (objtype))
data->n_reachable_meta++;
else
data->n_reachable_content++;
}
ret = TRUE; ret = TRUE;
out: out:
@ -103,28 +115,47 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
data.repo = repo; data.repo = repo;
data.reachable = ostree_traverse_new_reachable (); data.reachable = ostree_traverse_new_reachable ();
data.n_reachable = 0;
data.n_unreachable = 0;
if (!ostree_repo_list_all_refs (repo, &all_refs, cancellable, error)) if (opt_refs_only)
goto out;
g_hash_table_iter_init (&hash_iter, all_refs);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{ {
const char *checksum = value; if (!ostree_repo_list_all_refs (repo, &all_refs, cancellable, error))
// g_print ("Computing reachable, currently %u total, from %s: %s\n", g_hash_table_size (data.reachable), name, checksum);
if (!ostree_traverse_commit (repo, checksum, opt_depth, data.reachable, cancellable, error))
goto out; goto out;
g_hash_table_iter_init (&hash_iter, all_refs);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *checksum = value;
// g_print ("Computing reachable, currently %u total, from %s: %s\n", g_hash_table_size (data.reachable), name, checksum);
if (!ostree_traverse_commit (repo, checksum, opt_depth, data.reachable, cancellable, error))
goto out;
}
} }
if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error)) if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error))
goto out; goto out;
g_hash_table_iter_init (&hash_iter, objects); if (!opt_refs_only)
{
g_hash_table_iter_init (&hash_iter, objects);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
GVariant *serialized_key = key;
const char *checksum;
OstreeObjectType objtype;
ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
if (objtype != OSTREE_OBJECT_TYPE_COMMIT)
continue;
if (!ostree_traverse_commit (repo, checksum, opt_depth, data.reachable, cancellable, error))
goto out;
}
}
g_hash_table_iter_init (&hash_iter, objects);
while (g_hash_table_iter_next (&hash_iter, &key, &value)) while (g_hash_table_iter_next (&hash_iter, &key, &value))
{ {
GVariant *serialized_key = key; GVariant *serialized_key = key;
@ -132,20 +163,21 @@ ostree_builtin_prune (int argc, char **argv, GFile *repo_path, GError **error)
const char *checksum; const char *checksum;
OstreeObjectType objtype; OstreeObjectType objtype;
gboolean is_loose; gboolean is_loose;
ostree_object_name_deserialize (serialized_key, &checksum, &objtype); ostree_object_name_deserialize (serialized_key, &checksum, &objtype);
g_variant_get_child (objdata, 0, "b", &is_loose); g_variant_get_child (objdata, 0, "b", &is_loose);
if (is_loose) if (!is_loose)
{ continue;
if (!prune_loose_object (&data, checksum, objtype, cancellable, error))
goto out; if (!maybe_prune_loose_object (&data, checksum, objtype, cancellable, error))
} goto out;
} }
g_print ("Total reachable: %u\n", data.n_reachable); g_print ("Total reachable: %u meta, %u content\n",
g_print ("Total unreachable: %u\n", data.n_unreachable); data.n_reachable_meta, data.n_reachable_content);
g_print ("Total unreachable: %u meta, %u content\n",
data.n_unreachable_meta, data.n_unreachable_content);
ret = TRUE; ret = TRUE;
out: out: