From dc0f3c3dcbdd63d6a41ebc172b38c65576db9cd3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 1 Jul 2013 10:18:26 -0400 Subject: [PATCH] Add support for deleting refs The internal API will be used by admin, and "ostree refs --delete" is handy for interactive management. --- src/libostree/ostree-repo.c | 119 +++++++++++++++++++++++++---------- src/ostree/ot-builtin-refs.c | 27 ++++++-- tests/libtest.sh | 6 ++ tests/t0000-basic.sh | 12 +++- 4 files changed, 124 insertions(+), 40 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 5ef94bfd..d53e4c64 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1757,6 +1757,42 @@ create_empty_gvariant_dict (void) return g_variant_builder_end (&builder); } +static gboolean +add_ref_to_set (const char *remote, + GFile *base, + GFile *child, + GHashTable *refs, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + char *contents; + char *relpath; + gsize len; + GString *refname; + + if (!g_file_load_contents (child, cancellable, &contents, &len, NULL, error)) + goto out; + + g_strchomp (contents); + + refname = g_string_new (""); + if (remote) + { + g_string_append (refname, remote); + g_string_append_c (refname, ':'); + } + relpath = g_file_get_relative_path (base, child); + g_string_append (refname, relpath); + g_free (relpath); + + g_hash_table_insert (refs, g_string_free (refname, FALSE), contents); + + ret = TRUE; + out: + return ret; +} + static gboolean enumerate_refs_recurse (OstreeRepo *repo, const char *remote, @@ -1793,27 +1829,9 @@ enumerate_refs_recurse (OstreeRepo *repo, } else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { - char *contents; - char *relpath; - gsize len; - GString *refname; - - if (!g_file_load_contents (child, cancellable, &contents, &len, NULL, error)) + if (!add_ref_to_set (remote, base, child, refs, + cancellable, error)) goto out; - - g_strchomp (contents); - - refname = g_string_new (""); - if (remote) - { - g_string_append (refname, remote); - g_string_append_c (refname, ':'); - } - relpath = g_file_get_relative_path (base, child); - g_string_append (refname, relpath); - g_free (relpath); - - g_hash_table_insert (refs, g_string_free (refname, FALSE), contents); } } @@ -1840,6 +1858,7 @@ ostree_repo_list_refs (OstreeRepo *repo, { gs_unref_object GFile *dir = NULL; gs_unref_object GFile *child = NULL; + gs_unref_object GFileInfo *info = NULL; if (!ostree_parse_refspec (refspec_prefix, &remote, &ref_prefix, error)) goto out; @@ -1850,11 +1869,26 @@ ostree_repo_list_refs (OstreeRepo *repo, dir = g_object_ref (repo->local_heads_dir); child = g_file_resolve_relative_path (dir, ref_prefix); - - if (!enumerate_refs_recurse (repo, remote, child, child, - ret_all_refs, - cancellable, error)) + if (!ot_gfile_query_info_allow_noent (child, OSTREE_GIO_FAST_QUERYINFO, 0, + &info, cancellable, error)) goto out; + + if (info) + { + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + if (!enumerate_refs_recurse (repo, remote, child, child, + ret_all_refs, + cancellable, error)) + goto out; + } + else + { + if (!add_ref_to_set (remote, dir, child, ret_all_refs, + cancellable, error)) + goto out; + } + } } else { @@ -1954,19 +1988,38 @@ ostree_repo_write_ref (OstreeRepo *self, else { dir = g_file_get_child (self->remote_heads_dir, remote); - - if (!gs_file_ensure_directory (dir, FALSE, NULL, error)) - goto out; + + if (rev != NULL) + { + if (!gs_file_ensure_directory (dir, FALSE, NULL, error)) + goto out; + } } - if (!write_checksum_file (dir, name, rev, error)) - goto out; - - if (self->mode == OSTREE_REPO_MODE_ARCHIVE - || self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (rev == NULL) { - if (!write_ref_summary (self, NULL, error)) + gs_unref_object GFile *child = g_file_resolve_relative_path (dir, name); + + if (g_file_query_exists (child, NULL)) + { + if (!gs_file_unlink (child, NULL, error)) + goto out; + } + } + else + { + if (!write_checksum_file (dir, name, rev, error)) goto out; + + if (rev != NULL) + { + if (self->mode == OSTREE_REPO_MODE_ARCHIVE + || self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + { + if (!write_ref_summary (self, NULL, error)) + goto out; + } + } } ret = TRUE; diff --git a/src/ostree/ot-builtin-refs.c b/src/ostree/ot-builtin-refs.c index 541d959b..3164604d 100644 --- a/src/ostree/ot-builtin-refs.c +++ b/src/ostree/ot-builtin-refs.c @@ -26,7 +26,10 @@ #include "ostree.h" #include "ostree-repo-file.h" +static gboolean opt_delete; + static GOptionEntry options[] = { + { "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Delete refs which match PREFIX, rather than listing them", "PREFIX" }, { NULL } }; @@ -41,9 +44,8 @@ ostree_builtin_refs (int argc, char **argv, GFile *repo_path, GError **error) gs_unref_hashtable GHashTable *refs = NULL; GHashTableIter hashiter; gpointer hashkey, hashvalue; - guint i; - context = g_option_context_new ("[PREFIX...] - List refs"); + context = g_option_context_new ("[PREFIX] - List refs"); g_option_context_add_main_entries (context, options, NULL); if (!g_option_context_parse (context, &argc, &argv, error)) @@ -60,11 +62,24 @@ ostree_builtin_refs (int argc, char **argv, GFile *repo_path, GError **error) cancellable, error)) goto out; - g_hash_table_iter_init (&hashiter, refs); - while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)) + if (!opt_delete) { - const char *ref = hashkey; - g_print ("%s\n", ref); + g_hash_table_iter_init (&hashiter, refs); + while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)) + { + const char *ref = hashkey; + g_print ("%s\n", ref); + } + } + else + { + g_hash_table_iter_init (&hashiter, refs); + while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)) + { + const char *refspec = hashkey; + if (!ostree_repo_write_refspec (repo, refspec, NULL, error)) + goto out; + } } ret = TRUE; diff --git a/tests/libtest.sh b/tests/libtest.sh index e4518f1f..12ddd646 100644 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -44,6 +44,12 @@ assert_not_has_file () { fi } +assert_not_file_has_content () { + if grep -q -e "$2" "$1"; then + echo 1>&2 "File '$1' incorrectly matches regexp '$2'"; exit 1 + fi +} + assert_file_has_content () { if ! grep -q -e "$2" "$1"; then echo 1>&2 "File '$1' doesn't match regexp '$2'"; exit 1 diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh index 97bd7ed3..a58a1fd7 100755 --- a/tests/t0000-basic.sh +++ b/tests/t0000-basic.sh @@ -19,7 +19,7 @@ set -e -echo "1..33" +echo "1..34" . $(dirname $0)/libtest.sh @@ -244,3 +244,13 @@ fi rm repo3 objlist-before-prune objlist-after-prune -rf echo "ok prune" +cd ${test_tmpdir} +$OSTREE commit -b test3 -s "Another commit" --tree=ref=test2 +ostree --repo=repo refs > reflist +assert_file_has_content reflist '^test3$' +ostree --repo=repo refs --delete test3 +ostree --repo=repo refs > reflist +assert_not_file_has_content reflist '^test3$' +echo "ok reflist --delete" + +