[ostree] core: Allow / in ref names like git does
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] core: Allow / in ref names like git does
- Date: Thu, 22 Dec 2011 21:06:06 +0000 (UTC)
commit 3292dcb6d62afc8c7546fa712f0e16b2e0b23c25
Author: Colin Walters <walters verbum org>
Date: Thu Dec 22 15:59:47 2011 -0500
core: Allow / in ref names like git does
Using / is nice basically.
src/libostree/ostree-core.c | 19 +++++++-
src/libostree/ostree-repo.c | 114 +++++++++++++++++++++++++------------------
tests/t0000-basic.sh | 6 ++-
3 files changed, 90 insertions(+), 49 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index fcda638..90cf6ce 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -32,12 +32,29 @@ gboolean
ostree_validate_checksum_string (const char *sha256,
GError **error)
{
- if (strlen (sha256) != 64)
+ int i = 0;
+ size_t len = strlen (sha256);
+
+ if (len != 64)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid rev '%s'", sha256);
return FALSE;
}
+
+ for (i = 0; i < len; i++)
+ {
+ guint8 c = ((guint8*) sha256)[i];
+
+ if (!((c >= 48 && c <= 57)
+ || (c >= 97 && c <= 102)))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid character '%d' in rev '%s'",
+ c, sha256);
+ return FALSE;
+ }
+ }
return TRUE;
}
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index c26fa50..220994d 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -273,25 +273,26 @@ ostree_repo_resolve_rev (OstreeRepo *self,
char *ret_rev = NULL;
GFile *child = NULL;
GFile *origindir = NULL;
- const char *child_path = NULL;
GError *temp_error = NULL;
GVariant *commit = NULL;
-
+ GPtrArray *components = NULL;
+
g_return_val_if_fail (rev != NULL, FALSE);
- if (strlen (rev) == 0)
+ /* This checks for .. and such, but we don't actually walk
+ * the parsed bits below.
+ */
+ if (!ot_util_path_split_validate (rev, &components, error))
+ goto out;
+
+ if (components->len == 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid empty rev");
goto out;
}
- else if (strstr (rev, "..") != NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid rev %s", rev);
- goto out;
- }
- else if (strlen (rev) == 64)
+ /* We intentionally don't allow a ref that looks like a checksum */
+ else if (ostree_validate_checksum_string (rev, NULL))
{
ret_rev = g_strdup (rev);
}
@@ -317,52 +318,35 @@ ostree_repo_resolve_rev (OstreeRepo *self,
}
else
{
- const char *slash = strchr (rev, '/');
- if (slash != NULL && (slash == rev || !*(slash+1)))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid rev %s", rev);
- goto out;
- }
- else if (slash == NULL)
- {
- child = g_file_get_child (priv->local_heads_dir, rev);
- child_path = ot_gfile_get_path_cached (child);
- }
- else
- {
- const char *rest = slash + 1;
+ child = g_file_resolve_relative_path (priv->local_heads_dir, rev);
- if (strchr (rest, '/'))
+ if (!g_file_query_exists (child, NULL))
+ {
+ g_clear_object (&child);
+ child = g_file_get_child (priv->remote_heads_dir, rev);
+ if (!g_file_query_exists (child, NULL))
{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid rev %s", rev);
- goto out;
+ 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);
}
-
- child = g_file_get_child (priv->remote_heads_dir, rev);
- child_path = ot_gfile_get_path_cached (child);
-
}
- if (!ot_gfile_load_contents_utf8 (child, &ret_rev, NULL, NULL, &temp_error))
+
+ if (child)
{
- if (allow_noent && g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- g_clear_error (&temp_error);
- g_free (ret_rev);
- ret_rev = NULL;
- }
- else
+ if (!ot_gfile_load_contents_utf8 (child, &ret_rev, NULL, NULL, &temp_error))
{
g_propagate_error (error, temp_error);
- g_prefix_error (error, "Couldn't open ref '%s': ", child_path);
+ g_prefix_error (error, "Couldn't open ref '%s': ", ot_gfile_get_path_cached (child));
goto out;
}
- }
- else
- {
+
g_strchomp (ret_rev);
-
if (!ostree_validate_checksum_string (ret_rev, error))
goto out;
}
@@ -387,12 +371,47 @@ write_checksum_file (GFile *parentdir,
GError **error)
{
gboolean ret = FALSE;
+ GFile *parent = NULL;
GFile *child = NULL;
GOutputStream *out = NULL;
gsize bytes_written;
+ GPtrArray *components = NULL;
+ int i;
+
+ if (!ostree_validate_checksum_string (sha256, error))
+ goto out;
+
+ if (ostree_validate_checksum_string (name, NULL))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Rev name '%s' looks like a checksum", name);
+ goto out;
+ }
+
+ if (!ot_util_path_split_validate (name, &components, error))
+ goto out;
+
+ if (components->len == 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid empty ref name");
+ goto out;
+ }
+
+ parent = g_object_ref (parentdir);
+ for (i = 0; i+1 < components->len; i++)
+ {
+ child = g_file_get_child (parent, (char*)components->pdata[i]);
- child = g_file_get_child (parentdir, name);
+ if (!ot_gfile_ensure_directory (child, FALSE, error))
+ goto out;
+ g_clear_object (&parent);
+ parent = child;
+ child = NULL;
+ }
+
+ child = g_file_get_child (parent, components->pdata[components->len - 1]);
if ((out = (GOutputStream*)g_file_replace (child, NULL, FALSE, 0, NULL, error)) == NULL)
goto out;
if (!g_output_stream_write_all (out, sha256, strlen (sha256), &bytes_written, NULL, error))
@@ -404,6 +423,7 @@ write_checksum_file (GFile *parentdir,
ret = TRUE;
out:
+ g_clear_object (&parent);
g_clear_object (&child);
g_clear_object (&out);
return ret;
diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh
index 3ef89d2..62e15b1 100755
--- a/tests/t0000-basic.sh
+++ b/tests/t0000-basic.sh
@@ -19,7 +19,7 @@
set -e
-echo "1..19"
+echo "1..20"
. libtest.sh
@@ -154,3 +154,7 @@ echo "ok user checkout"
$OSTREE commit -b test2 -s "Another commit" --tree=ref=test2
echo "ok commit from ref"
+
+$OSTREE commit -b trees/test2 -s 'ref with / in it' --tree=ref=test2
+echo "ok commit ref with /"
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]