diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2015-11-06 09:50:17 +0100 |
---|---|---|
committer | Giuseppe Scrivano <gscrivan@redhat.com> | 2015-11-16 11:07:38 +0100 |
commit | f56688da71273b32a4458d294bd7ccacb0e54c66 (patch) | |
tree | 78455128b022c11be42fb4a9c25e996442ef7a85 /src/ostree/ot-builtin-prune.c | |
parent | daa6f150c43f09d057fbadbdba44366c7dd0cf41 (diff) | |
download | ostree-f56688da71273b32a4458d294bd7ccacb0e54c66.tar.gz |
prune: add --keep-younger-than=DATE
The format used for DATE is "%Y-%m-%d %H:%M:%S %z"
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Diffstat (limited to 'src/ostree/ot-builtin-prune.c')
-rw-r--r-- | src/ostree/ot-builtin-prune.c | 125 |
1 files changed, 103 insertions, 22 deletions
diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c index 44868a14..104736ec 100644 --- a/src/ostree/ot-builtin-prune.c +++ b/src/ostree/ot-builtin-prune.c @@ -26,20 +26,115 @@ #include "ot-builtins.h" #include "ostree.h" #include "otutil.h" +#include "parse-datetime.h" static gboolean opt_no_prune; static gint opt_depth = -1; static gboolean opt_refs_only; static char *opt_delete_commit; +static char *opt_keep_younger_than; static GOptionEntry options[] = { { "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" }, { "delete-commit", 0, 0, G_OPTION_ARG_STRING, &opt_delete_commit, "Specify a commit to delete", "COMMIT" }, + { "keep-younger-than", 0, 0, G_OPTION_ARG_STRING, &opt_keep_younger_than, "Prune all commits older than the specified date", "DATE" }, { NULL } }; +static gboolean +delete_commit (OstreeRepo *repo, const char *commit_to_delete, GCancellable *cancellable, GError **error) +{ + g_autoptr(GHashTable) refs = NULL; + GHashTableIter hashiter; + gpointer hashkey, hashvalue; + gboolean ret = FALSE; + + if (!ostree_repo_list_refs (repo, NULL, &refs, cancellable, error)) + goto out; + + g_hash_table_iter_init (&hashiter, refs); + while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)) + { + const char *ref = hashkey; + const char *commit = hashvalue; + if (g_strcmp0 (commit_to_delete, commit) == 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Commit '%s' is referenced by '%s'", commit_to_delete, ref); + goto out; + } + } + + if (!ot_enable_tombstone_commits (repo, error)) + goto out; + + if (!ostree_repo_delete_object (repo, OSTREE_OBJECT_TYPE_COMMIT, commit_to_delete, cancellable, error)) + goto out; + + ret = TRUE; + + out: + return ret; +} + +static gboolean +prune_commits_keep_younger_than_date (OstreeRepo *repo, const char *date, GCancellable *cancellable, GError **error) +{ + g_autoptr(GHashTable) objects = NULL; + GHashTableIter hash_iter; + gpointer key, value; + struct timespec ts; + gboolean ret = FALSE; + + if (!parse_datetime (&ts, date, NULL)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Could not parse '%s'", date); + goto out; + } + + if (!ot_enable_tombstone_commits (repo, error)) + goto out; + + 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; + const char *checksum; + OstreeObjectType objtype; + guint64 commit_timestamp; + g_autoptr(GVariant) commit = NULL; + + ostree_object_name_deserialize (serialized_key, &checksum, &objtype); + + if (objtype != OSTREE_OBJECT_TYPE_COMMIT) + continue; + + if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, + &commit, error)) + goto out; + + commit_timestamp = ostree_commit_get_timestamp (commit); + if (commit_timestamp < ts.tv_sec) + { + if (!ostree_repo_delete_object (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, cancellable, error)) + goto out; + } + } + + ret = TRUE; + + out: + return ret; +} + gboolean ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError **error) { @@ -62,36 +157,22 @@ ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError * if (opt_delete_commit) { - g_autoptr(GHashTable) refs = NULL; - GHashTableIter hashiter; - gpointer hashkey, hashvalue; - if (opt_no_prune) { ot_util_usage_error (context, "Cannot specify both --delete-commit and --no-prune", error); goto out; } - - if (!ostree_repo_list_refs (repo, NULL, &refs, cancellable, error)) + if (!delete_commit (repo, opt_delete_commit, cancellable, error)) goto out; - - g_hash_table_iter_init (&hashiter, refs); - while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)) + } + if (opt_keep_younger_than) + { + if (opt_no_prune) { - const char *ref = hashkey; - const char *commit = hashvalue; - if (g_strcmp0 (commit, opt_delete_commit) == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Commit '%s' is referenced by '%s'", opt_delete_commit, ref); - goto out; - } + ot_util_usage_error (context, "Cannot specify both --keep-younger-than and --no-prune", error); + goto out; } - - if (!ot_enable_tombstone_commits (repo, error)) - goto out; - - if (!ostree_repo_delete_object (repo, OSTREE_OBJECT_TYPE_COMMIT, opt_delete_commit, cancellable, error)) + if (!prune_commits_keep_younger_than_date (repo, opt_keep_younger_than, cancellable, error)) goto out; } |