[ostree/wip/bootloader: 1/4] core: Add "refspec" which is remote:refname
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/bootloader: 1/4] core: Add "refspec" which is remote:refname
- Date: Sat, 29 Jun 2013 16:04:55 +0000 (UTC)
commit 0a01454b6ef753b6af797f43a89641bccdec8000
Author: Colin Walters <walters verbum org>
Date: Sat Jun 29 11:42:33 2013 -0400
core: Add "refspec" which is remote:refname
This allows an unambiguous reference; otherwise, it was too easy to
have confusion between local heads and remotes.
src/libostree/ostree-core.c | 70 +++++++++++++-
src/libostree/ostree-core.h | 5 +
src/libostree/ostree-repo.c | 223 +++++++++++++++++++++++++++++++------------
src/libostree/ostree-repo.h | 7 +-
4 files changed, 237 insertions(+), 68 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 9a90da5..642154b 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -61,25 +61,85 @@ ostree_validate_checksum_string (const char *sha256,
return ostree_validate_structureof_checksum_string (sha256, error);
}
+#define OSTREE_REF_FRAGMENT_REGEXP "[-_\\w\\d]+"
+#define OSTREE_REF_REGEXP "(?:" OSTREE_REF_FRAGMENT_REGEXP "/)*" OSTREE_REF_FRAGMENT_REGEXP
+
+gboolean
+ostree_parse_refspec (const char *refspec,
+ char **out_remote,
+ char **out_ref,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GMatchInfo *match = NULL;
+ char *remote;
+
+ static gsize regex_initialized;
+ static GRegex *regex;
+
+ if (g_once_init_enter (®ex_initialized))
+ {
+ regex = g_regex_new ("^(" OSTREE_REF_FRAGMENT_REGEXP ":)?(" OSTREE_REF_REGEXP ")$", 0, 0, NULL);
+ g_assert (regex);
+ g_once_init_leave (®ex_initialized, 1);
+ }
+
+ if (!g_regex_match (regex, refspec, 0, &match))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid refspec %s", refspec);
+ goto out;
+ }
+
+ remote = g_match_info_fetch (match, 1);
+ if (*remote == '\0')
+ {
+ g_clear_pointer (&remote, g_free);
+ }
+ else
+ {
+ /* Trim the : */
+ remote[strlen(remote)-1] = '\0';
+ }
+
+ ret = TRUE;
+ *out_remote = remote;
+ *out_ref = g_match_info_fetch (match, 2);
+ out:
+ if (match)
+ g_match_info_unref (match);
+ return ret;
+}
+
gboolean
ostree_validate_rev (const char *rev,
GError **error)
{
gboolean ret = FALSE;
- ot_lptrarray GPtrArray *components = NULL;
+ gs_unref_ptrarray GPtrArray *components = NULL;
+ GMatchInfo *match = NULL;
- if (!ot_util_path_split_validate (rev, &components, error))
- goto out;
+ static gsize regex_initialized;
+ static GRegex *regex;
+
+ if (g_once_init_enter (®ex_initialized))
+ {
+ regex = g_regex_new ("^" OSTREE_REF_REGEXP "$", 0, 0, NULL);
+ g_assert (regex);
+ g_once_init_leave (®ex_initialized, 1);
+ }
- if (components->len == 0)
+ if (!g_regex_match (regex, rev, 0, &match))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid empty rev");
+ "Invalid ref name %s", rev);
goto out;
}
ret = TRUE;
out:
+ if (match)
+ g_match_info_unref (match);
return ret;
}
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index b3f761e..93ec5ec 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -122,6 +122,11 @@ int ostree_cmp_checksum_bytes (const guchar *a, const guchar *b);
gboolean ostree_validate_rev (const char *rev, GError **error);
+gboolean ostree_parse_refspec (const char *refspec,
+ char **out_remote,
+ char **out_ref,
+ GError **error);
+
void ostree_checksum_update_meta (GChecksum *checksum, GFileInfo *file_info, GVariant *xattrs);
const char * ostree_object_type_to_string (OstreeObjectType objtype);
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 13b95e1..31d25fb 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -284,7 +284,7 @@ parse_rev_file (OstreeRepo *self,
}
static gboolean
-find_rev_in_remotes (OstreeRepo *self,
+find_ref_in_remotes (OstreeRepo *self,
const char *rev,
GFile **out_file,
GError **error)
@@ -325,112 +325,190 @@ find_rev_in_remotes (OstreeRepo *self,
return ret;
}
-gboolean
-ostree_repo_resolve_rev (OstreeRepo *self,
- const char *rev,
- gboolean allow_noent,
- char **sha256,
- GError **error)
+static gboolean
+resolve_refspec (OstreeRepo *self,
+ const char *remote,
+ const char *ref,
+ gboolean allow_noent,
+ char **out_rev,
+ GError **error);
+
+static gboolean
+resolve_refspec_fallback (OstreeRepo *self,
+ const char *remote,
+ const char *ref,
+ gboolean allow_noent,
+ char **out_rev,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_free char *ret_rev = NULL;
+
+ if (self->parent_repo)
+ {
+ if (!resolve_refspec (self->parent_repo, remote, ref,
+ allow_noent, &ret_rev, error))
+ goto out;
+ }
+ else if (!allow_noent)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Refspec '%s%s%s' not found",
+ remote ? remote : "",
+ remote ? ":" : "",
+ ref);
+ goto out;
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_rev, &ret_rev);
+ out:
+ return ret;
+}
+
+static gboolean
+resolve_refspec (OstreeRepo *self,
+ const char *remote,
+ const char *ref,
+ gboolean allow_noent,
+ char **out_rev,
+ GError **error)
{
gboolean ret = FALSE;
+ __attribute__((unused)) GCancellable *cancellable = NULL;
GError *temp_error = NULL;
ot_lfree char *tmp = NULL;
ot_lfree char *tmp2 = NULL;
ot_lfree char *ret_rev = NULL;
ot_lobj GFile *child = NULL;
ot_lobj GFile *origindir = NULL;
- ot_lvariant GVariant *commit = NULL;
- ot_lvariant GVariant *parent_csum_v = NULL;
- g_return_val_if_fail (rev != NULL, FALSE);
-
- if (!ostree_validate_rev (rev, error))
- goto out;
+ g_return_val_if_fail (ref != NULL, FALSE);
/* We intentionally don't allow a ref that looks like a checksum */
- if (ostree_validate_checksum_string (rev, NULL))
+ if (ostree_validate_checksum_string (ref, NULL))
{
- ret_rev = g_strdup (rev);
+ ret_rev = g_strdup (ref);
}
- else if (g_str_has_suffix (rev, "^"))
+ else if (remote != NULL)
{
- tmp = g_strdup (rev);
- tmp[strlen(tmp) - 1] = '\0';
-
- if (!ostree_repo_resolve_rev (self, tmp, allow_noent, &tmp2, error))
- goto out;
-
- if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, tmp2, &commit, error))
- goto out;
-
- g_variant_get_child (commit, 1, "@ay", &parent_csum_v);
- if (g_variant_n_children (parent_csum_v) == 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Commit %s has no parent", tmp2);
- goto out;
- }
- ret_rev = ostree_checksum_from_bytes_v (parent_csum_v);
+ child = ot_gfile_resolve_path_printf (self->remote_heads_dir, "%s/%s",
+ remote, ref);
+ if (!g_file_query_exists (child, NULL))
+ g_clear_object (&child);
}
else
{
- child = g_file_resolve_relative_path (self->local_heads_dir, rev);
+ child = g_file_resolve_relative_path (self->local_heads_dir, ref);
if (!g_file_query_exists (child, NULL))
{
g_clear_object (&child);
- child = g_file_resolve_relative_path (self->remote_heads_dir, rev);
+ child = g_file_resolve_relative_path (self->remote_heads_dir, ref);
if (!g_file_query_exists (child, NULL))
{
g_clear_object (&child);
- if (!find_rev_in_remotes (self, rev, &child, error))
+ if (!find_ref_in_remotes (self, ref, &child, error))
goto out;
-
- if (child == NULL)
- {
- if (self->parent_repo)
- {
- if (!ostree_repo_resolve_rev (self->parent_repo, rev,
- allow_noent, &ret_rev,
- error))
- goto out;
- }
- else if (!allow_noent)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Rev '%s' not found", rev);
- goto out;
- }
- else
- g_clear_object (&child);
- }
}
}
+ }
- if (child)
+ if (child)
+ {
+ if ((ret_rev = gs_file_load_contents_utf8 (child, NULL, &temp_error)) == NULL)
{
- if ((ret_rev = gs_file_load_contents_utf8 (child, NULL, &temp_error)) == NULL)
+ g_propagate_error (error, temp_error);
+ g_prefix_error (error, "Couldn't open ref '%s': ", gs_file_get_path_cached (child));
+ goto out;
+ }
+
+ g_strchomp (ret_rev);
+ if (!ostree_validate_checksum_string (ret_rev, error))
+ goto out;
+ }
+ else
+ {
+ if (!resolve_refspec_fallback (self, remote, ref, allow_noent,
+ &ret_rev, cancellable, error))
+ goto out;
+ }
+
+ ot_transfer_out_value (out_rev, &ret_rev);
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+ostree_repo_resolve_rev (OstreeRepo *self,
+ const char *refspec,
+ gboolean allow_noent,
+ char **out_rev,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_free char *ret_rev = NULL;
+
+ g_return_val_if_fail (refspec != NULL, FALSE);
+
+ if (ostree_validate_checksum_string (refspec, NULL))
+ {
+ ret_rev = g_strdup (refspec);
+ }
+ else
+ {
+ if (g_str_has_suffix (refspec, "^"))
+ {
+ gs_free char *parent_refspec = NULL;
+ gs_free char *parent_rev = NULL;
+ gs_unref_variant GVariant *commit = NULL;
+ gs_unref_variant GVariant *parent_csum_v = NULL;
+
+ parent_refspec = g_strdup (refspec);
+ parent_refspec[strlen(parent_refspec) - 1] = '\0';
+
+ if (!ostree_repo_resolve_rev (self, parent_refspec, allow_noent, &parent_rev, error))
+ goto out;
+
+ if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, parent_rev,
+ &commit, error))
+ goto out;
+
+ g_variant_get_child (commit, 1, "@ay", &parent_csum_v);
+ if (g_variant_n_children (parent_csum_v) == 0)
{
- g_propagate_error (error, temp_error);
- g_prefix_error (error, "Couldn't open ref '%s': ", gs_file_get_path_cached (child));
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Commit %s has no parent", parent_rev);
goto out;
}
+ ret_rev = ostree_checksum_from_bytes_v (parent_csum_v);
+ }
+ else
+ {
+ gs_free char *remote = NULL;
+ gs_free char *ref = NULL;
- g_strchomp (ret_rev);
- if (!ostree_validate_checksum_string (ret_rev, error))
+ if (!ostree_parse_refspec (refspec, &remote, &ref, error))
+ goto out;
+
+ if (!resolve_refspec (self, remote, ref, allow_noent,
+ &ret_rev, error))
goto out;
}
}
- ot_transfer_out_value(sha256, &ret_rev);
ret = TRUE;
+ ot_transfer_out_value (out_rev, &ret_rev);
out:
return ret;
}
+
static gboolean
write_checksum_file (GFile *parentdir,
const char *name,
@@ -1838,6 +1916,27 @@ ostree_repo_write_ref (OstreeRepo *self,
}
gboolean
+ostree_repo_write_refspec (OstreeRepo *self,
+ const char *refspec,
+ const char *rev,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_free char *remote = NULL;
+ gs_free char *ref = NULL;
+
+ if (!ostree_parse_refspec (refspec, &remote, &ref, error))
+ goto out;
+
+ if (!ostree_repo_write_ref (self, remote, ref, rev, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
ostree_repo_stage_commit (OstreeRepo *self,
const char *branch,
const char *parent,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 4b11c81..e10c78f 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -153,7 +153,7 @@ gboolean ostree_repo_stage_content_finish (OstreeRepo *self,
GError **error);
gboolean ostree_repo_resolve_rev (OstreeRepo *self,
- const char *rev,
+ const char *refspec,
gboolean allow_noent,
char **out_resolved,
GError **error);
@@ -164,6 +164,11 @@ gboolean ostree_repo_write_ref (OstreeRepo *self,
const char *rev,
GError **error);
+gboolean ostree_repo_write_refspec (OstreeRepo *self,
+ const char *refspec,
+ const char *rev,
+ GError **error);
+
gboolean ostree_repo_list_all_refs (OstreeRepo *repo,
GHashTable **out_all_refs,
GCancellable *cancellable,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]