refs: Add a --collections argument to the built-in refs command

Rather than change the output format used by the existing refs command
to output collection IDs in addition to ref names, this functionality has
been hidden behind an --collections argument. If it’s not specified `ostree
refs` will output the same content as before for a given repository. If
it is specified, the collection ID for each ref will be included in the
output as (collection ID, ref name).

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #924
Approved by: cgwalters
This commit is contained in:
Philip Withnall authored and Atomic Bot committed 2017-06-26 15:56:07 +00:00
1 parent 205a84b36e
commit b7b79fa78d
2 files changed
+117

No files matched your search

+97
View File
@@ -29,14 +29,106 @@
static gboolean opt_delete;
static gboolean opt_list;
static char *opt_create;
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
static gboolean opt_collections;
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
static GOptionEntry options[] = {
{ "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Delete refs which match PREFIX, rather than listing them", NULL },
{ "list", 0, 0, G_OPTION_ARG_NONE, &opt_list, "Do not remove the prefix from the refs", NULL },
{ "create", 0, 0, G_OPTION_ARG_STRING, &opt_create, "Create a new ref for an existing commit", "NEWREF" },
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
{ "collections", 'c', 0, G_OPTION_ARG_NONE, &opt_collections, "Enable listing collection IDs for refs", NULL },
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
{ NULL }
};
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
static gboolean
do_ref_with_collections (OstreeRepo *repo,
const char *refspec_prefix,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */
GHashTableIter hashiter;
gpointer hashkey, hashvalue;
gboolean ret = FALSE;
if (!ostree_repo_list_collection_refs (repo,
(!opt_create) ? refspec_prefix : NULL,
&refs, cancellable, error))
goto out;
if (!opt_delete && !opt_create)
{
g_hash_table_iter_init (&hashiter, refs);
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
{
const OstreeCollectionRef *ref = hashkey;
g_print ("(%s, %s)\n", ref->collection_id, ref->ref_name);
}
}
else if (opt_create)
{
g_autofree char *checksum = NULL;
g_autofree char *checksum_existing = NULL;
if (!ostree_repo_resolve_rev_ext (repo, opt_create, TRUE, OSTREE_REPO_RESOLVE_REV_EXT_NONE, &checksum_existing, error))
{
if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
{
/* A folder exists with the specified ref name,
* which is handled by _ostree_repo_write_ref */
g_clear_error (error);
}
else goto out;
}
if (checksum_existing != NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"--create specified but ref %s already exists", opt_create);
goto out;
}
if (!ostree_repo_resolve_rev (repo, refspec_prefix, FALSE, &checksum, error))
goto out;
/* This is technically an abuse of the refspec syntax: collection IDs
* should not be treated like remote names. */
g_auto(GStrv) parts = g_strsplit (opt_create, ":", 2);
const char *collection_id = parts[0];
const char *ref_name = parts[1];
if (!ostree_validate_collection_id (collection_id, error))
goto out;
if (!ostree_validate_rev (ref_name, error))
goto out;
const OstreeCollectionRef ref = { (gchar *) collection_id, (gchar *) ref_name };
if (!ostree_repo_set_collection_ref_immediate (repo, &ref, checksum,
cancellable, error))
goto out;
}
else
/* delete */
{
g_hash_table_iter_init (&hashiter, refs);
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
{
const OstreeCollectionRef *ref = hashkey;
if (!ostree_repo_set_collection_ref_immediate (repo, ref, NULL,
cancellable, error))
goto out;
}
}
ret = TRUE;
out:
return ret;
}
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellable *cancellable, GError **error)
{
g_autoptr(GHashTable) refs = NULL;
@@ -44,6 +136,11 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
gpointer hashkey, hashvalue;
gboolean ret = FALSE;
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
if (opt_collections)
return do_ref_with_collections (repo, refspec_prefix, cancellable, error);
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
if (opt_delete || opt_list)
{
if (!ostree_repo_list_refs_ext (repo, refspec_prefix, &refs, OSTREE_REPO_LIST_REFS_EXT_NONE,