[ostree] libostree: Split off -refs.c
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] libostree: Split off -refs.c
- Date: Wed, 10 Jul 2013 00:55:27 +0000 (UTC)
commit cb6b69616c7e452599b9e49edf73fcd893fb887e
Author: Colin Walters <walters verbum org>
Date: Tue Jul 9 19:49:00 2013 -0400
libostree: Split off -refs.c
Continuing to break up ostree-repo.c.
Makefile-libostree.am | 1 +
src/libostree/ostree-repo-refs.c | 670 ++++++++++++++++++++++++++++++++++++++
src/libostree/ostree-repo.c | 646 ------------------------------------
3 files changed, 671 insertions(+), 646 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index cbe3bb9..1ad3b63 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -33,6 +33,7 @@ libostree_la_SOURCES = src/libostree/ostree.h \
src/libostree/ostree-repo.c \
src/libostree/ostree-repo-checkout.c \
src/libostree/ostree-repo-libarchive.c \
+ src/libostree/ostree-repo-refs.c \
src/libostree/ostree-repo.h \
src/libostree/ostree-repo-private.h \
src/libostree/ostree-repo-file.c \
diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c
new file mode 100644
index 0000000..fb9f361
--- /dev/null
+++ b/src/libostree/ostree-repo-refs.c
@@ -0,0 +1,670 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#include "config.h"
+
+#include "ostree-repo-private.h"
+
+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
+write_checksum_file (GFile *parentdir,
+ const char *name,
+ const char *sha256,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gsize bytes_written;
+ int i;
+ gs_unref_object GFile *parent = NULL;
+ gs_unref_object GFile *child = NULL;
+ gs_unref_object GOutputStream *out = NULL;
+ gs_unref_ptrarray GPtrArray *components = NULL;
+
+ 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]);
+
+ if (!gs_file_ensure_directory (child, FALSE, NULL, 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))
+ goto out;
+ if (!g_output_stream_write_all (out, "\n", 1, &bytes_written, NULL, error))
+ goto out;
+ if (!g_output_stream_close (out, NULL, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+
+static gboolean
+parse_rev_file (OstreeRepo *self,
+ GFile *f,
+ char **sha256,
+ GError **error) G_GNUC_UNUSED;
+
+static gboolean
+parse_rev_file (OstreeRepo *self,
+ GFile *f,
+ char **sha256,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GError *temp_error = NULL;
+ gs_free char *rev = NULL;
+
+ if ((rev = gs_file_load_contents_utf8 (f, NULL, &temp_error)) == NULL)
+ goto out;
+
+ if (rev == NULL)
+ {
+ if (g_error_matches (temp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ {
+ g_clear_error (&temp_error);
+ }
+ else
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+ }
+ else
+ {
+ g_strchomp (rev);
+ }
+
+ if (g_str_has_prefix (rev, "ref: "))
+ {
+ gs_unref_object GFile *ref = NULL;
+ char *ref_sha256;
+ gboolean subret;
+
+ ref = g_file_resolve_relative_path (self->local_heads_dir, rev + 5);
+ subret = parse_rev_file (self, ref, &ref_sha256, error);
+
+ if (!subret)
+ {
+ g_free (ref_sha256);
+ goto out;
+ }
+
+ g_free (rev);
+ rev = ref_sha256;
+ }
+ else
+ {
+ if (!ostree_validate_checksum_string (rev, error))
+ goto out;
+ }
+
+ ot_transfer_out_value(sha256, &rev);
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static gboolean
+find_ref_in_remotes (OstreeRepo *self,
+ const char *rev,
+ GFile **out_file,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileEnumerator *dir_enum = NULL;
+ gs_unref_object GFile *ret_file = NULL;
+
+ dir_enum = g_file_enumerate_children (self->remote_heads_dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error);
+ if (!dir_enum)
+ goto out;
+
+ while (TRUE)
+ {
+ GFileInfo *file_info;
+ GFile *child;
+ if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
+ NULL, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+ if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
+ continue;
+
+ g_clear_object (&ret_file);
+ ret_file = g_file_resolve_relative_path (child, rev);
+ if (!g_file_query_exists (ret_file, NULL))
+ g_clear_object (&ret_file);
+ else
+ break;
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_file, &ret_file);
+ out:
+ return ret;
+}
+
+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;
+ gs_free char *tmp = NULL;
+ gs_free char *tmp2 = NULL;
+ gs_free char *ret_rev = NULL;
+ gs_unref_object GFile *child = NULL;
+ gs_unref_object GFile *origindir = NULL;
+
+ 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 (ref, NULL))
+ {
+ ret_rev = g_strdup (ref);
+ }
+ else if (remote != NULL)
+ {
+ 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, ref);
+
+ if (!g_file_query_exists (child, NULL))
+ {
+ g_clear_object (&child);
+
+ child = g_file_resolve_relative_path (self->remote_heads_dir, ref);
+
+ if (!g_file_query_exists (child, NULL))
+ {
+ g_clear_object (&child);
+
+ if (!find_ref_in_remotes (self, ref, &child, error))
+ goto out;
+ }
+ }
+ }
+
+ if (child)
+ {
+ 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_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;
+
+ if (!ostree_parse_refspec (refspec, &remote, &ref, error))
+ goto out;
+
+ if (!resolve_refspec (self, remote, ref, allow_noent,
+ &ret_rev, error))
+ goto out;
+ }
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_rev, &ret_rev);
+ out:
+ return ret;
+}
+
+static gboolean
+enumerate_refs_recurse (OstreeRepo *repo,
+ const char *remote,
+ GFile *base,
+ GFile *dir,
+ GHashTable *refs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileEnumerator *enumerator = NULL;
+
+ enumerator = g_file_enumerate_children (dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!enumerator)
+ goto out;
+
+ while (TRUE)
+ {
+ GFileInfo *file_info = NULL;
+ GFile *child = NULL;
+
+ if (!gs_file_enumerator_iterate (enumerator, &file_info, &child,
+ NULL, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+ {
+ if (!enumerate_refs_recurse (repo, remote, base, child, refs, cancellable, error))
+ goto out;
+ }
+ else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ {
+ if (!add_ref_to_set (remote, base, child, refs,
+ cancellable, error))
+ goto out;
+ }
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+ostree_repo_list_refs (OstreeRepo *repo,
+ const char *refspec_prefix,
+ GHashTable **out_all_refs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_hashtable GHashTable *ret_all_refs = NULL;
+ gs_free char *remote = NULL;
+ gs_free char *ref_prefix = NULL;
+
+ ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ if (refspec_prefix)
+ {
+ 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;
+
+ if (remote)
+ dir = g_file_get_child (repo->remote_heads_dir, remote);
+ else
+ dir = g_object_ref (repo->local_heads_dir);
+
+ child = g_file_resolve_relative_path (dir, ref_prefix);
+ 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
+ {
+ gs_unref_object GFileEnumerator *remote_enumerator = NULL;
+
+ if (!enumerate_refs_recurse (repo, NULL, repo->local_heads_dir, repo->local_heads_dir,
+ ret_all_refs,
+ cancellable, error))
+ goto out;
+
+ remote_enumerator = g_file_enumerate_children (repo->remote_heads_dir, OSTREE_GIO_FAST_QUERYINFO,
+ 0,
+ cancellable, error);
+
+ while (TRUE)
+ {
+ GFileInfo *info;
+ GFile *child;
+ const char *name;
+
+ if (!gs_file_enumerator_iterate (remote_enumerator, &info, &child,
+ cancellable, error))
+ goto out;
+ if (!info)
+ break;
+
+ name = g_file_info_get_name (info);
+ if (!enumerate_refs_recurse (repo, name, child, child,
+ ret_all_refs,
+ cancellable, error))
+ goto out;
+ }
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_all_refs, &ret_all_refs);
+ out:
+ return ret;
+}
+
+static gboolean
+write_ref_summary (OstreeRepo *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GHashTableIter hash_iter;
+ gpointer key, value;
+ gsize bytes_written;
+ gs_unref_hashtable GHashTable *all_refs = NULL;
+ gs_unref_object GFile *summary_path = NULL;
+ gs_unref_object GOutputStream *out = NULL;
+ gs_free char *buf = NULL;
+
+ if (!ostree_repo_list_refs (self, NULL, &all_refs, cancellable, error))
+ goto out;
+
+ summary_path = g_file_resolve_relative_path (ostree_repo_get_path (self),
+ "refs/summary");
+
+ out = (GOutputStream*) g_file_replace (summary_path, NULL, FALSE, 0, cancellable, error);
+ if (!out)
+ goto out;
+
+ g_hash_table_iter_init (&hash_iter, all_refs);
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ {
+ const char *name = key;
+ const char *sha256 = value;
+
+ g_free (buf);
+ buf = g_strdup_printf ("%s %s\n", sha256, name);
+ if (!g_output_stream_write_all (out, buf, strlen (buf), &bytes_written, cancellable, error))
+ goto out;
+ }
+
+ if (!g_output_stream_close (out, cancellable, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+ostree_repo_write_ref (OstreeRepo *self,
+ const char *remote,
+ const char *name,
+ const char *rev,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFile *dir = NULL;
+
+ if (remote == NULL)
+ dir = g_object_ref (self->local_heads_dir);
+ else
+ {
+ dir = g_file_get_child (self->remote_heads_dir, remote);
+
+ if (rev != NULL)
+ {
+ if (!gs_file_ensure_directory (dir, FALSE, NULL, error))
+ goto out;
+ }
+ }
+
+ if (rev == NULL)
+ {
+ 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;
+ out:
+ return ret;
+}
+
+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;
+}
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 2b9ba65..a151b71 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -186,361 +186,6 @@ ostree_repo_new (GFile *path)
{
return g_object_new (OSTREE_TYPE_REPO, "path", path, NULL);
}
-
-static gboolean
-parse_rev_file (OstreeRepo *self,
- GFile *f,
- char **sha256,
- GError **error) G_GNUC_UNUSED;
-
-static gboolean
-parse_rev_file (OstreeRepo *self,
- GFile *f,
- char **sha256,
- GError **error)
-{
- gboolean ret = FALSE;
- GError *temp_error = NULL;
- gs_free char *rev = NULL;
-
- if ((rev = gs_file_load_contents_utf8 (f, NULL, &temp_error)) == NULL)
- goto out;
-
- if (rev == NULL)
- {
- if (g_error_matches (temp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
- {
- g_clear_error (&temp_error);
- }
- else
- {
- g_propagate_error (error, temp_error);
- goto out;
- }
- }
- else
- {
- g_strchomp (rev);
- }
-
- if (g_str_has_prefix (rev, "ref: "))
- {
- gs_unref_object GFile *ref = NULL;
- char *ref_sha256;
- gboolean subret;
-
- ref = g_file_resolve_relative_path (self->local_heads_dir, rev + 5);
- subret = parse_rev_file (self, ref, &ref_sha256, error);
-
- if (!subret)
- {
- g_free (ref_sha256);
- goto out;
- }
-
- g_free (rev);
- rev = ref_sha256;
- }
- else
- {
- if (!ostree_validate_checksum_string (rev, error))
- goto out;
- }
-
- ot_transfer_out_value(sha256, &rev);
- ret = TRUE;
- out:
- return ret;
-}
-
-static gboolean
-find_ref_in_remotes (OstreeRepo *self,
- const char *rev,
- GFile **out_file,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFileEnumerator *dir_enum = NULL;
- gs_unref_object GFile *ret_file = NULL;
-
- dir_enum = g_file_enumerate_children (self->remote_heads_dir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, error);
- if (!dir_enum)
- goto out;
-
- while (TRUE)
- {
- GFileInfo *file_info;
- GFile *child;
- if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
- NULL, error))
- goto out;
- if (file_info == NULL)
- break;
- if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
- continue;
-
- g_clear_object (&ret_file);
- ret_file = g_file_resolve_relative_path (child, rev);
- if (!g_file_query_exists (ret_file, NULL))
- g_clear_object (&ret_file);
- else
- break;
- }
-
- ret = TRUE;
- ot_transfer_out_value (out_file, &ret_file);
- out:
- return ret;
-}
-
-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;
- gs_free char *tmp = NULL;
- gs_free char *tmp2 = NULL;
- gs_free char *ret_rev = NULL;
- gs_unref_object GFile *child = NULL;
- gs_unref_object GFile *origindir = NULL;
-
- 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 (ref, NULL))
- {
- ret_rev = g_strdup (ref);
- }
- else if (remote != NULL)
- {
- 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, ref);
-
- if (!g_file_query_exists (child, NULL))
- {
- g_clear_object (&child);
-
- child = g_file_resolve_relative_path (self->remote_heads_dir, ref);
-
- if (!g_file_query_exists (child, NULL))
- {
- g_clear_object (&child);
-
- if (!find_ref_in_remotes (self, ref, &child, error))
- goto out;
- }
- }
- }
-
- if (child)
- {
- 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_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;
-
- if (!ostree_parse_refspec (refspec, &remote, &ref, error))
- goto out;
-
- if (!resolve_refspec (self, remote, ref, allow_noent,
- &ret_rev, error))
- goto out;
- }
- }
-
- ret = TRUE;
- ot_transfer_out_value (out_rev, &ret_rev);
- out:
- return ret;
-}
-
-
-static gboolean
-write_checksum_file (GFile *parentdir,
- const char *name,
- const char *sha256,
- GError **error)
-{
- gboolean ret = FALSE;
- gsize bytes_written;
- int i;
- gs_unref_object GFile *parent = NULL;
- gs_unref_object GFile *child = NULL;
- gs_unref_object GOutputStream *out = NULL;
- gs_unref_ptrarray GPtrArray *components = NULL;
-
- 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]);
-
- if (!gs_file_ensure_directory (child, FALSE, NULL, 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))
- goto out;
- if (!g_output_stream_write_all (out, "\n", 1, &bytes_written, NULL, error))
- goto out;
- if (!g_output_stream_close (out, NULL, error))
- goto out;
-
- ret = TRUE;
- out:
- return ret;
-}
-
/**
* ostree_repo_get_config:
* @self:
@@ -1752,297 +1397,6 @@ 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,
- GFile *base,
- GFile *dir,
- GHashTable *refs,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFileEnumerator *enumerator = NULL;
-
- enumerator = g_file_enumerate_children (dir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!enumerator)
- goto out;
-
- while (TRUE)
- {
- GFileInfo *file_info = NULL;
- GFile *child = NULL;
-
- if (!gs_file_enumerator_iterate (enumerator, &file_info, &child,
- NULL, error))
- goto out;
- if (file_info == NULL)
- break;
-
- if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
- {
- if (!enumerate_refs_recurse (repo, remote, base, child, refs, cancellable, error))
- goto out;
- }
- else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
- {
- if (!add_ref_to_set (remote, base, child, refs,
- cancellable, error))
- goto out;
- }
- }
-
- ret = TRUE;
- out:
- return ret;
-}
-
-gboolean
-ostree_repo_list_refs (OstreeRepo *repo,
- const char *refspec_prefix,
- GHashTable **out_all_refs,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_hashtable GHashTable *ret_all_refs = NULL;
- gs_free char *remote = NULL;
- gs_free char *ref_prefix = NULL;
-
- ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
- if (refspec_prefix)
- {
- 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;
-
- if (remote)
- dir = g_file_get_child (repo->remote_heads_dir, remote);
- else
- dir = g_object_ref (repo->local_heads_dir);
-
- child = g_file_resolve_relative_path (dir, ref_prefix);
- 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
- {
- gs_unref_object GFileEnumerator *remote_enumerator = NULL;
-
- if (!enumerate_refs_recurse (repo, NULL, repo->local_heads_dir, repo->local_heads_dir,
- ret_all_refs,
- cancellable, error))
- goto out;
-
- remote_enumerator = g_file_enumerate_children (repo->remote_heads_dir, OSTREE_GIO_FAST_QUERYINFO,
- 0,
- cancellable, error);
-
- while (TRUE)
- {
- GFileInfo *info;
- GFile *child;
- const char *name;
-
- if (!gs_file_enumerator_iterate (remote_enumerator, &info, &child,
- cancellable, error))
- goto out;
- if (!info)
- break;
-
- name = g_file_info_get_name (info);
- if (!enumerate_refs_recurse (repo, name, child, child,
- ret_all_refs,
- cancellable, error))
- goto out;
- }
- }
-
- ret = TRUE;
- ot_transfer_out_value (out_all_refs, &ret_all_refs);
- out:
- return ret;
-}
-
-static gboolean
-write_ref_summary (OstreeRepo *self,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- GHashTableIter hash_iter;
- gpointer key, value;
- gsize bytes_written;
- gs_unref_hashtable GHashTable *all_refs = NULL;
- gs_unref_object GFile *summary_path = NULL;
- gs_unref_object GOutputStream *out = NULL;
- gs_free char *buf = NULL;
-
- if (!ostree_repo_list_refs (self, NULL, &all_refs, cancellable, error))
- goto out;
-
- summary_path = g_file_resolve_relative_path (ostree_repo_get_path (self),
- "refs/summary");
-
- out = (GOutputStream*) g_file_replace (summary_path, NULL, FALSE, 0, cancellable, error);
- if (!out)
- goto out;
-
- g_hash_table_iter_init (&hash_iter, all_refs);
- while (g_hash_table_iter_next (&hash_iter, &key, &value))
- {
- const char *name = key;
- const char *sha256 = value;
-
- g_free (buf);
- buf = g_strdup_printf ("%s %s\n", sha256, name);
- if (!g_output_stream_write_all (out, buf, strlen (buf), &bytes_written, cancellable, error))
- goto out;
- }
-
- if (!g_output_stream_close (out, cancellable, error))
- goto out;
-
- ret = TRUE;
- out:
- return ret;
-}
-
-gboolean
-ostree_repo_write_ref (OstreeRepo *self,
- const char *remote,
- const char *name,
- const char *rev,
- GError **error)
-{
- gboolean ret = FALSE;
- gs_unref_object GFile *dir = NULL;
-
- if (remote == NULL)
- dir = g_object_ref (self->local_heads_dir);
- else
- {
- dir = g_file_get_child (self->remote_heads_dir, remote);
-
- if (rev != NULL)
- {
- if (!gs_file_ensure_directory (dir, FALSE, NULL, error))
- goto out;
- }
- }
-
- if (rev == NULL)
- {
- 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;
- out:
- return ret;
-}
-
-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,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]