[ostree] pull: Add ability to fetch refs/summary if no ref specified
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] pull: Add ability to fetch refs/summary if no ref specified
- Date: Mon, 27 Feb 2012 13:39:20 +0000 (UTC)
commit 24403389687b1d6aed475711d22c092a39736a83
Author: Colin Walters <walters verbum org>
Date: Mon Feb 27 08:37:51 2012 -0500
pull: Add ability to fetch refs/summary if no ref specified
This allows us to fetch all refs, which is useful for ostbuild where
we do want the buildroot/ refs.
src/ostree/ostree-pull.c | 336 ++++++++++++++++++++++++++++++++++++----------
1 files changed, 265 insertions(+), 71 deletions(-)
---
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
index ec0adda..ad108eb 100644
--- a/src/ostree/ostree-pull.c
+++ b/src/ostree/ostree-pull.c
@@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
- * Copyright (C) 2011 Colin Walters <walters verbum org>
+ * Copyright (C) 2011,2012 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
@@ -83,6 +83,7 @@ fetch_uri (OstreeRepo *repo,
SoupURI *uri,
const char *tmp_prefix,
GFile **out_temp_filename,
+ GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
@@ -137,12 +138,50 @@ fetch_uri (OstreeRepo *repo,
}
static gboolean
+fetch_uri_contents_utf8 (OstreeRepo *repo,
+ SoupSession *soup,
+ SoupURI *uri,
+ char **out_contents,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GFile *tmpf = NULL;
+ char *ret_contents = NULL;
+ gsize len;
+
+ if (!fetch_uri (repo, soup, uri, "tmp-", &tmpf, cancellable, error))
+ goto out;
+
+ if (!g_file_load_contents (tmpf, cancellable, &ret_contents, &len, NULL, error))
+ goto out;
+
+ if (!g_utf8_validate (ret_contents, -1, NULL))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid UTF-8");
+ goto out;
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_contents, &ret_contents);
+ out:
+ if (tmpf)
+ (void) unlink (ot_gfile_get_path_cached (tmpf));
+ g_clear_object (&tmpf);
+ g_free (ret_contents);
+ return ret;
+}
+
+
+static gboolean
fetch_object (OstreeRepo *repo,
SoupSession *soup,
SoupURI *baseuri,
const char *checksum,
OstreeObjectType objtype,
GFile **out_temp_path,
+ GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
@@ -156,7 +195,8 @@ fetch_object (OstreeRepo *repo,
relpath = g_build_filename (soup_uri_get_path (obj_uri), objpath, NULL);
soup_uri_set_path (obj_uri, relpath);
- if (!fetch_uri (repo, soup, obj_uri, ostree_object_type_to_string (objtype), &ret_temp_path, error))
+ if (!fetch_uri (repo, soup, obj_uri, ostree_object_type_to_string (objtype), &ret_temp_path,
+ cancellable, error))
goto out;
ret = TRUE;
@@ -178,6 +218,7 @@ fetch_and_store_object (OstreeRepo *repo,
OstreeObjectType objtype,
gboolean *out_is_pending,
GVariant **out_metadata,
+ GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
@@ -197,25 +238,25 @@ fetch_and_store_object (OstreeRepo *repo,
if (!(stored_path || pending_path))
{
- if (!fetch_object (repo, soup, baseuri, checksum, objtype, &temp_path, error))
+ if (!fetch_object (repo, soup, baseuri, checksum, objtype, &temp_path, cancellable, error))
goto out;
}
if (temp_path)
{
file_info = g_file_query_info (temp_path, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, error);
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error);
if (!file_info)
goto out;
- input = (GInputStream*)g_file_read (temp_path, NULL, error);
+ input = (GInputStream*)g_file_read (temp_path, cancellable, error);
if (!input)
goto out;
}
if (pending_path || temp_path)
{
- if (!ostree_repo_stage_object (repo, objtype, checksum, file_info, NULL, input, NULL, error))
+ if (!ostree_repo_stage_object (repo, objtype, checksum, file_info, NULL, input, cancellable, error))
goto out;
log_verbose ("Staged object: %s.%s", checksum, ostree_object_type_to_string (objtype));
@@ -253,6 +294,7 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
SoupSession *soup,
SoupURI *base_uri,
const char *rev,
+ GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
@@ -270,7 +312,8 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
GFile *pending_path = NULL;
GInputStream *input = NULL;
- if (!fetch_and_store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_DIR_TREE, &is_pending, &tree, error))
+ if (!fetch_and_store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_DIR_TREE,
+ &is_pending, &tree, cancellable, error))
goto out;
if (!is_pending)
@@ -302,13 +345,13 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
if (ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_BARE)
{
if (!ostree_repo_find_object (repo, OSTREE_OBJECT_TYPE_RAW_FILE, checksum,
- &stored_path, &pending_path, NULL, error))
+ &stored_path, &pending_path, cancellable, error))
goto out;
}
else
{
if (!ostree_repo_find_object (repo, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT, checksum,
- &stored_path, &pending_path, NULL, error))
+ &stored_path, &pending_path, cancellable, error))
goto out;
}
@@ -321,6 +364,7 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
if (!fetch_object (repo, soup, base_uri, checksum,
OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META,
&meta_temp_path,
+ cancellable,
error))
goto out;
@@ -337,10 +381,11 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
if (!fetch_object (repo, soup, base_uri, checksum,
OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT,
&content_temp_path,
+ cancellable,
error))
goto out;
- input = (GInputStream*)g_file_read (content_temp_path, NULL, error);
+ input = (GInputStream*)g_file_read (content_temp_path, cancellable, error);
if (!input)
goto out;
}
@@ -353,7 +398,7 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
if (!ostree_repo_stage_object (repo, OSTREE_OBJECT_TYPE_RAW_FILE,
checksum,
archive_file_info, archive_xattrs, input,
- NULL, error))
+ cancellable, error))
goto out;
}
@@ -386,10 +431,11 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
if (!ostree_validate_checksum_string (meta_checksum, error))
goto out;
- if (!fetch_and_store_object (repo, soup, base_uri, meta_checksum, OSTREE_OBJECT_TYPE_DIR_META, NULL, NULL, error))
+ if (!fetch_and_store_object (repo, soup, base_uri, meta_checksum, OSTREE_OBJECT_TYPE_DIR_META,
+ NULL, NULL, cancellable, error))
goto out;
- if (!fetch_and_store_tree_recurse (repo, soup, base_uri, tree_checksum, error))
+ if (!fetch_and_store_tree_recurse (repo, soup, base_uri, tree_checksum, cancellable, error))
goto out;
}
}
@@ -423,6 +469,7 @@ fetch_and_store_commit_recurse (OstreeRepo *repo,
SoupSession *soup,
SoupURI *base_uri,
const char *rev,
+ GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
@@ -431,7 +478,8 @@ fetch_and_store_commit_recurse (OstreeRepo *repo,
const char *tree_meta_checksum;
gboolean is_pending;
- if (!fetch_and_store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_COMMIT, &is_pending, &commit, error))
+ if (!fetch_and_store_object (repo, soup, base_uri, rev, OSTREE_OBJECT_TYPE_COMMIT,
+ &is_pending, &commit, cancellable, error))
goto out;
if (!is_pending)
@@ -442,10 +490,12 @@ fetch_and_store_commit_recurse (OstreeRepo *repo,
g_variant_get_child (commit, 6, "&s", &tree_contents_checksum);
g_variant_get_child (commit, 7, "&s", &tree_meta_checksum);
- if (!fetch_and_store_object (repo, soup, base_uri, tree_meta_checksum, OSTREE_OBJECT_TYPE_DIR_META, NULL, NULL, error))
+ if (!fetch_and_store_object (repo, soup, base_uri, tree_meta_checksum, OSTREE_OBJECT_TYPE_DIR_META,
+ NULL, NULL, cancellable, error))
goto out;
- if (!fetch_and_store_tree_recurse (repo, soup, base_uri, tree_contents_checksum, error))
+ if (!fetch_and_store_tree_recurse (repo, soup, base_uri, tree_contents_checksum,
+ cancellable, error))
goto out;
}
@@ -454,6 +504,152 @@ fetch_and_store_commit_recurse (OstreeRepo *repo,
ot_clear_gvariant (&commit);
return ret;
}
+
+static gboolean
+fetch_ref_contents (OstreeRepo *repo,
+ SoupSession *soup,
+ SoupURI *base_uri,
+ const char *ref,
+ char **out_contents,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ char *ret_contents = NULL;
+ char *refpath = NULL;
+ SoupURI *target_uri = NULL;
+
+ target_uri = soup_uri_copy (base_uri);
+ refpath = g_build_filename (soup_uri_get_path (target_uri), "refs", "heads", ref, NULL);
+ soup_uri_set_path (target_uri, refpath);
+
+ if (!fetch_uri_contents_utf8 (repo, soup, target_uri, &ret_contents, cancellable, error))
+ goto out;
+
+ g_strchomp (ret_contents);
+
+ if (!ostree_validate_checksum_string (ret_contents, error))
+ goto out;
+
+ ret = TRUE;
+ ot_transfer_out_value (out_contents, &ret_contents);
+ out:
+ g_free (refpath);
+ g_free (ret_contents);
+ if (target_uri)
+ soup_uri_free (target_uri);
+ return ret;
+}
+
+static gboolean
+pull_one_commit (OstreeRepo *repo,
+ const char *remote,
+ const char *branch,
+ const char *rev,
+ SoupSession *soup,
+ SoupURI *base_uri,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ char *key = NULL;
+ char *remote_ref = NULL;
+ char *baseurl = NULL;
+ char *original_rev = NULL;
+
+ remote_ref = g_strdup_printf ("%s/%s", remote, branch);
+
+ if (!ostree_repo_resolve_rev (repo, remote_ref, TRUE, &original_rev, error))
+ goto out;
+
+ if (original_rev && strcmp (rev, original_rev) == 0)
+ {
+ g_print ("No changes in %s\n", remote_ref);
+ }
+ else
+ {
+ if (!ostree_validate_checksum_string (rev, error))
+ goto out;
+
+ if (!ostree_repo_prepare_transaction (repo, NULL, error))
+ goto out;
+
+ if (!fetch_and_store_commit_recurse (repo, soup, base_uri, rev, cancellable, error))
+ goto out;
+
+ if (!ostree_repo_commit_transaction (repo, cancellable, error))
+ goto out;
+
+ if (!ostree_repo_write_ref (repo, remote, branch, rev, error))
+ goto out;
+
+ g_print ("remote %s is now %s\n", remote_ref, rev);
+ }
+
+ ret = TRUE;
+ out:
+ g_free (key);
+ g_free (remote_ref);
+ g_free (baseurl);
+ g_free (original_rev);
+ return ret;
+}
+
+static gboolean
+parse_ref_summary (const char *contents,
+ GHashTable **out_refs,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GHashTable *ret_refs = NULL;
+ char **lines = NULL;
+ char **iter = NULL;
+ char *ref = NULL;
+ char *sha256 = NULL;
+
+ ret_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ lines = g_strsplit_set (contents, "\n", -1);
+ for (iter = lines; *iter; iter++)
+ {
+ const char *line = *iter;
+ const char *spc;
+
+ if (!*line)
+ continue;
+
+ spc = strchr (line, ' ');
+ if (!spc)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid ref summary file; missing ' ' in line");
+ goto out;
+ }
+
+ g_free (ref);
+ ref = g_strdup (spc + 1);
+ if (!ostree_validate_rev (ref, error))
+ goto out;
+
+ g_free (sha256);
+ sha256 = g_strndup (line, spc - line);
+ if (!ostree_validate_checksum_string (sha256, error))
+ goto out;
+
+ g_hash_table_replace (ret_refs, ref, sha256);
+ /* Transfer ownership */
+ ref = NULL;
+ sha256 = NULL;
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_refs, &ret_refs);
+ out:
+ if (ret_refs)
+ g_hash_table_unref (ret_refs);
+ g_strfreev (lines);
+ return ret;
+}
static gboolean
ostree_builtin_pull (int argc, char **argv, GFile *repo_path, GError **error)
@@ -463,19 +659,20 @@ ostree_builtin_pull (int argc, char **argv, GFile *repo_path, GError **error)
OstreeRepo *repo = NULL;
const char *remote;
const char *branch;
- char *key = NULL;
+ SoupSession *soup = NULL;
+ char *path = NULL;
char *baseurl = NULL;
- char *refpath = NULL;
- GFile *tempf = NULL;
- char *remote_ref = NULL;
- char *original_rev = NULL;
- GKeyFile *config = NULL;
+ char *summary_data = NULL;
SoupURI *base_uri = NULL;
- SoupURI *target_uri = NULL;
- SoupSession *soup = NULL;
- char *rev = NULL;
+ SoupURI *summary_uri = NULL;
+ GKeyFile *config = NULL;
+ GCancellable *cancellable = NULL;
+ GHashTable *refs_to_fetch = NULL;
+ GHashTableIter hash_iter;
+ gpointer key, value;
+ char *branch_rev = NULL;
- context = g_option_context_new ("REMOTE BRANCH - Download data from remote repository");
+ context = g_option_context_new ("REMOTE [BRANCH] - Download data from remote repository");
g_option_context_add_main_entries (context, options, NULL);
if (!g_option_context_parse (context, &argc, &argv, error))
@@ -485,19 +682,21 @@ ostree_builtin_pull (int argc, char **argv, GFile *repo_path, GError **error)
if (!ostree_repo_check (repo, error))
goto out;
- if (argc < 3)
+ if (argc < 2)
{
- ot_util_usage_error (context, "REMOTE and BRANCH must be specified", error);
+ ot_util_usage_error (context, "REMOTE must be specified", error);
goto out;
}
remote = argv[1];
- branch = argv[2];
-
- remote_ref = g_strdup_printf ("%s/%s", remote, branch);
+ if (argc == 2)
+ branch = NULL;
+ else
+ branch = argv[2];
- if (!ostree_repo_resolve_rev (repo, remote_ref, TRUE, &original_rev, error))
- goto out;
+ soup = soup_session_sync_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
+ SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
+ NULL);
config = ostree_repo_get_config (repo);
@@ -506,69 +705,64 @@ ostree_builtin_pull (int argc, char **argv, GFile *repo_path, GError **error)
if (!baseurl)
goto out;
base_uri = soup_uri_new (baseurl);
+
if (!base_uri)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to parse url '%s'", baseurl);
goto out;
}
- target_uri = soup_uri_copy (base_uri);
- g_free (refpath);
- refpath = g_build_filename (soup_uri_get_path (target_uri), "refs", "heads", branch, NULL);
- soup_uri_set_path (target_uri, refpath);
-
- soup = soup_session_sync_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
- NULL);
- if (!fetch_uri (repo, soup, target_uri, "ref-", &tempf, error))
- goto out;
- if (!ot_gfile_load_contents_utf8 (tempf, &rev, NULL, NULL, error))
- goto out;
- g_strchomp (rev);
-
- if (original_rev && strcmp (rev, original_rev) == 0)
+ if (branch != NULL)
{
- g_print ("No changes in %s\n", remote_ref);
+ char *contents;
+
+ if (!fetch_ref_contents (repo, soup, base_uri, branch, &contents, cancellable, error))
+ goto out;
+
+ /* Transfer ownership of contents */
+ refs_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_insert (refs_to_fetch, g_strdup (branch), contents);
}
else
{
- if (!ostree_validate_checksum_string (rev, error))
- goto out;
+ summary_uri = soup_uri_copy (base_uri);
+ path = g_build_filename (soup_uri_get_path (summary_uri), "refs", "summary", NULL);
+ soup_uri_set_path (summary_uri, path);
- if (!ostree_repo_prepare_transaction (repo, NULL, error))
- goto out;
-
- if (!fetch_and_store_commit_recurse (repo, soup, base_uri, rev, error))
+ if (!fetch_uri_contents_utf8 (repo, soup, summary_uri, &summary_data, cancellable, error))
goto out;
- if (!ostree_repo_commit_transaction (repo, NULL, error))
+ if (!parse_ref_summary (summary_data, &refs_to_fetch, error))
goto out;
+ }
+
+ g_hash_table_iter_init (&hash_iter, refs_to_fetch);
+
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ {
+ const char *ref = key;
+ const char *sha256 = value;
- if (!ostree_repo_write_ref (repo, remote, branch, rev, error))
+ if (!pull_one_commit (repo, remote, ref, sha256, soup, base_uri, cancellable, error))
goto out;
-
- g_print ("remote %s is now %s\n", remote_ref, rev);
}
-
+
ret = TRUE;
out:
+ if (refs_to_fetch)
+ g_hash_table_unref (refs_to_fetch);
+ g_free (path);
+ g_free (baseurl);
+ g_free (summary_data);
+ g_free (branch_rev);
if (context)
g_option_context_free (context);
- if (tempf)
- (void) unlink (ot_gfile_get_path_cached (tempf));
- g_clear_object (&tempf);
- g_free (key);
- g_free (rev);
- g_free (remote_ref);
- g_free (original_rev);
- g_free (baseurl);
- g_free (refpath);
g_clear_object (&soup);
if (base_uri)
soup_uri_free (base_uri);
- if (target_uri)
- soup_uri_free (target_uri);
+ if (summary_uri)
+ soup_uri_free (summary_uri);
g_clear_object (&repo);
g_clear_object (&soup);
return ret;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]