diff --git a/src/libostree/ostree-remote-private.h b/src/libostree/ostree-remote-private.h index b7e9eb3bb8..ff7f885b15 100644 --- a/src/libostree/ostree-remote-private.h +++ b/src/libostree/ostree-remote-private.h @@ -35,17 +35,24 @@ G_BEGIN_DECLS +/* @refspec_name is set if this is a dynamic remote. It’s the name of the static + * remote which this one inherits from, and is what should be used in refspecs + * for pulls from this remote. If it’s %NULL, @name should be used instead. */ struct OstreeRemote { volatile int ref_count; char *name; /* (not nullable) */ + char *refspec_name; /* (nullable) */ char *group; /* group name in options (not nullable) */ - char *keyring; /* keyring name (NAME.trustedkeys.gpg) (not nullable) */ + char *keyring; /* keyring name ($refspec_name.trustedkeys.gpg) (not nullable) */ GFile *file; /* NULL if remote defined in repo/config */ GKeyFile *options; }; G_GNUC_INTERNAL OstreeRemote *ostree_remote_new (const gchar *name); +G_GNUC_INTERNAL +OstreeRemote *ostree_remote_new_dynamic (const gchar *name, + const gchar *refspec_name); G_GNUC_INTERNAL OstreeRemote *ostree_remote_new_from_keyfile (GKeyFile *keyfile, diff --git a/src/libostree/ostree-remote.c b/src/libostree/ostree-remote.c index cac7838c66..605a7eb9b0 100644 --- a/src/libostree/ostree-remote.c +++ b/src/libostree/ostree-remote.c @@ -53,16 +53,25 @@ OstreeRemote * ostree_remote_new (const gchar *name) +{ + return ostree_remote_new_dynamic (name, NULL); +} + +OstreeRemote * +ostree_remote_new_dynamic (const gchar *name, + const gchar *refspec_name) { OstreeRemote *remote; g_return_val_if_fail (name != NULL && *name != '\0', NULL); + g_return_val_if_fail (refspec_name == NULL || *refspec_name != '\0', NULL); remote = g_slice_new0 (OstreeRemote); remote->ref_count = 1; remote->name = g_strdup (name); - remote->group = g_strdup_printf ("remote \"%s\"", name); - remote->keyring = g_strdup_printf ("%s.trustedkeys.gpg", name); + remote->refspec_name = g_strdup (refspec_name); + remote->group = g_strdup_printf ("remote \"%s\"", (refspec_name != NULL) ? refspec_name : name); + remote->keyring = g_strdup_printf ("%s.trustedkeys.gpg", (refspec_name != NULL) ? refspec_name : name); remote->options = g_key_file_new (); return remote; diff --git a/src/libostree/ostree-repo-finder-avahi.c b/src/libostree/ostree-repo-finder-avahi.c index 4de74c6e60..a39d95339b 100644 --- a/src/libostree/ostree-repo-finder-avahi.c +++ b/src/libostree/ostree-repo-finder-avahi.c @@ -165,28 +165,28 @@ ostree_avahi_browser_event_to_string (AvahiBrowserEvent event) typedef struct { gchar *uri; - gchar *keyring; + OstreeRemote *keyring_remote; /* (owned) */ } UriAndKeyring; static void uri_and_keyring_free (UriAndKeyring *data) { g_free (data->uri); - g_free (data->keyring); + ostree_remote_unref (data->keyring_remote); g_free (data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (UriAndKeyring, uri_and_keyring_free) static UriAndKeyring * -uri_and_keyring_new (const gchar *uri, - const gchar *keyring) +uri_and_keyring_new (const gchar *uri, + OstreeRemote *keyring_remote) { g_autoptr(UriAndKeyring) data = NULL; data = g_new0 (UriAndKeyring, 1); data->uri = g_strdup (uri); - data->keyring = g_strdup (keyring); + data->keyring_remote = ostree_remote_ref (keyring_remote); return g_steal_pointer (&data); } @@ -196,7 +196,7 @@ uri_and_keyring_hash (gconstpointer key) { const UriAndKeyring *_key = key; - return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring); + return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring_remote->keyring); } static gboolean @@ -205,7 +205,8 @@ uri_and_keyring_equal (gconstpointer a, { const UriAndKeyring *_a = a, *_b = b; - return g_str_equal (_a->uri, _b->uri) && g_str_equal (_a->keyring, _b->keyring); + return (g_str_equal (_a->uri, _b->uri) && + g_str_equal (_a->keyring_remote->keyring, _b->keyring_remote->keyring)); } /* This must return a valid remote name (suitable for use in a refspec). */ @@ -213,7 +214,7 @@ static gchar * uri_and_keyring_to_name (UriAndKeyring *data) { g_autofree gchar *escaped_uri = g_uri_escape_string (data->uri, NULL, FALSE); - g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring, NULL, FALSE); + g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring_remote->keyring, NULL, FALSE); /* FIXME: Need a better separator than `_`, since it’s not escaped in the input. */ g_autofree gchar *out = g_strdup_printf ("%s_%s", escaped_uri, escaped_keyring); @@ -770,14 +771,15 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService for (i = 0; i < possible_refs->len; i++) { const OstreeCollectionRef *ref = g_ptr_array_index (possible_refs, i); - g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; + g_autoptr(OstreeRemote) keyring_remote = NULL; /* Look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, ref->collection_id, - cancellable, &error); + keyring_remote = ostree_repo_resolve_keyring_for_collection (parent_repo, + ref->collection_id, + cancellable, &error); - if (keyring == NULL) + if (keyring_remote == NULL) { g_debug ("Ignoring ref (%s, %s) on host ‘%s’ due to missing keyring: %s", ref->collection_id, refs[i]->ref_name, service->address, @@ -788,10 +790,11 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService /* Add this repo to the results, keyed by the canonicalised repository URI * to deduplicate the results. */ - g_debug ("Resolved ref (%s, %s) to repo URI ‘%s’ with keyring ‘%s’.", - ref->collection_id, ref->ref_name, uri, keyring); + g_debug ("Resolved ref (%s, %s) to repo URI ‘%s’ with keyring ‘%s’ from remote ‘%s’.", + ref->collection_id, ref->ref_name, uri, keyring_remote->keyring, + keyring_remote->name); - resolved_repo = uri_and_keyring_new (uri, keyring); + resolved_repo = uri_and_keyring_new (uri, keyring_remote); supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); @@ -818,10 +821,10 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService /* Build an #OstreeRemote. Use the escaped URI, since remote->name * is used in file paths, so needs to not contain special characters. */ g_autofree gchar *name = uri_and_keyring_to_name (repo); - remote = ostree_remote_new (name); + remote = ostree_remote_new_dynamic (name, repo->keyring_remote->name); g_clear_pointer (&remote->keyring, g_free); - remote->keyring = g_strdup (repo->keyring); + remote->keyring = g_strdup (repo->keyring_remote->keyring); /* gpg-verify-summary is false since we use the unsigned summary file support. */ g_key_file_set_string (remote->options, remote->group, "url", repo->uri); diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index 5784b9862c..c385e70c8a 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -93,28 +93,28 @@ G_DEFINE_TYPE_WITH_CODE (OstreeRepoFinderMount, ostree_repo_finder_mount, G_TYPE typedef struct { gchar *uri; - gchar *keyring; + OstreeRemote *keyring_remote; /* (owned) */ } UriAndKeyring; static void uri_and_keyring_free (UriAndKeyring *data) { g_free (data->uri); - g_free (data->keyring); + ostree_remote_unref (data->keyring_remote); g_free (data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (UriAndKeyring, uri_and_keyring_free) static UriAndKeyring * -uri_and_keyring_new (const gchar *uri, - const gchar *keyring) +uri_and_keyring_new (const gchar *uri, + OstreeRemote *keyring_remote) { g_autoptr(UriAndKeyring) data = NULL; data = g_new0 (UriAndKeyring, 1); data->uri = g_strdup (uri); - data->keyring = g_strdup (keyring); + data->keyring_remote = ostree_remote_ref (keyring_remote); return g_steal_pointer (&data); } @@ -124,7 +124,7 @@ uri_and_keyring_hash (gconstpointer key) { const UriAndKeyring *_key = key; - return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring); + return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring_remote->keyring); } static gboolean @@ -133,7 +133,8 @@ uri_and_keyring_equal (gconstpointer a, { const UriAndKeyring *_a = a, *_b = b; - return g_str_equal (_a->uri, _b->uri) && g_str_equal (_a->keyring, _b->keyring); + return (g_str_equal (_a->uri, _b->uri) && + g_str_equal (_a->keyring_remote->keyring, _b->keyring_remote->keyring)); } /* This must return a valid remote name (suitable for use in a refspec). */ @@ -141,7 +142,7 @@ static gchar * uri_and_keyring_to_name (UriAndKeyring *data) { g_autofree gchar *escaped_uri = g_uri_escape_string (data->uri, NULL, FALSE); - g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring, NULL, FALSE); + g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring_remote->keyring, NULL, FALSE); /* FIXME: Need a better separator than `_`, since it’s not escaped in the input. */ g_autofree gchar *out = g_strdup_printf ("%s_%s", escaped_uri, escaped_keyring); @@ -439,7 +440,6 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde { const OstreeCollectionRef *ref = refs[i]; g_autofree gchar *resolved_repo_uri = NULL; - g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; for (gsize j = 0; j < repos_refs->len; j++) @@ -448,6 +448,7 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde OstreeRepo *repo = repo_and_refs->repo; GHashTable *repo_refs = repo_and_refs->refs; g_autofree char *repo_path = g_file_get_path (ostree_repo_get_path (repo)); + g_autoptr(OstreeRemote) keyring_remote = NULL; const gchar *checksum = g_hash_table_lookup (repo_refs, ref); @@ -460,10 +461,11 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde } /* Finally, look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, ref->collection_id, - cancellable, &local_error); + keyring_remote = ostree_repo_resolve_keyring_for_collection (parent_repo, + ref->collection_id, + cancellable, &local_error); - if (keyring == NULL) + if (keyring_remote == NULL) { g_debug ("Ignoring repository ‘%s’ when looking for ref (%s, %s) on mount ‘%s’ due to missing keyring: %s", repo_path, ref->collection_id, ref->ref_name, mount_name, local_error->message); @@ -477,10 +479,11 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde * to deduplicate the results. */ g_autofree char *canonical_repo_path = realpath (repo_path, NULL); resolved_repo_uri = g_strconcat ("file://", canonical_repo_path, NULL); - g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’.", - ref->collection_id, ref->ref_name, mount_name, resolved_repo_uri, keyring); + g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’ from remote ‘%s’.", + ref->collection_id, ref->ref_name, mount_name, resolved_repo_uri, + keyring_remote->keyring, keyring_remote->name); - resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring); + resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring_remote); supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); @@ -510,10 +513,10 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde /* Build an #OstreeRemote. Use the escaped URI, since remote->name * is used in file paths, so needs to not contain special characters. */ g_autofree gchar *name = uri_and_keyring_to_name (repo); - remote = ostree_remote_new (name); + remote = ostree_remote_new_dynamic (name, repo->keyring_remote->name); g_clear_pointer (&remote->keyring, g_free); - remote->keyring = g_strdup (repo->keyring); + remote->keyring = g_strdup (repo->keyring_remote->keyring); /* gpg-verify-summary is false since we use the unsigned summary file support. */ g_key_file_set_string (remote->options, remote->group, "url", repo->uri); diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 4aff9e0919..9040fb4467 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -68,7 +68,8 @@ typedef struct { OstreeRepo *repo; int tmpdir_dfd; OstreeRepoPullFlags flags; - char *remote_name; + char *remote_name; + char *remote_refspec_name; OstreeRepoMode remote_mode; OstreeFetcher *fetcher; OstreeFetcherSecurityState fetcher_security_state; @@ -3222,7 +3223,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, flags = flags_i; (void) g_variant_lookup (options, "subdir", "&s", &dir_to_pull); (void) g_variant_lookup (options, "subdirs", "^a&s", &dirs_to_pull); - (void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_name); + (void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_refspec_name); opt_gpg_verify_set = g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify); opt_gpg_verify_summary_set = @@ -3238,6 +3239,9 @@ ostree_repo_pull_with_options (OstreeRepo *self, (void) g_variant_lookup (options, "update-frequency", "u", &update_frequency); (void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos); (void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check); + + if (pull_data->remote_refspec_name != NULL) + pull_data->remote_name = g_strdup (pull_data->remote_refspec_name); } g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); @@ -3356,6 +3360,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, { g_autofree char *unconfigured_state = NULL; + g_free (pull_data->remote_name); pull_data->remote_name = g_strdup (remote_name_or_baseurl); /* Fetch GPG verification settings from remote if it wasn't already @@ -4044,7 +4049,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, ostree_repo_transaction_set_collection_ref (pull_data->repo, ref, checksum); else - ostree_repo_transaction_set_ref (pull_data->repo, pull_data->remote_name, + ostree_repo_transaction_set_ref (pull_data->repo, + (pull_data->remote_refspec_name != NULL) ? pull_data->remote_refspec_name : pull_data->remote_name, ref->ref_name, checksum); } } @@ -5359,6 +5365,8 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self, g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", TRUE); g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE); g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE); + if (result->remote->refspec_name != NULL) + g_variant_dict_insert (&local_options_dict, "override-remote-name", "s", result->remote->refspec_name); copy_option (&options_dict, &local_options_dict, "depth", G_VARIANT_TYPE ("i")); copy_option (&options_dict, &local_options_dict, "disable-static-deltas", G_VARIANT_TYPE ("b")); copy_option (&options_dict, &local_options_dict, "http-headers", G_VARIANT_TYPE ("a(ss)")); @@ -5487,7 +5495,7 @@ check_remote_matches_collection_id (OstreeRepo *repo, * Find the GPG keyring for the given @collection_id, using the local * configuration from the given #OstreeRepo. This will search the configured * remotes for ones whose `collection-id` key matches @collection_id, and will - * return the GPG keyring from the first matching remote. + * return the first matching remote. * * If multiple remotes match and have different keyrings, a debug message will * be emitted, and the first result will be returned. It is expected that the @@ -5495,10 +5503,11 @@ check_remote_matches_collection_id (OstreeRepo *repo, * * If no match can be found, a %G_IO_ERROR_NOT_FOUND error will be returned. * - * Returns: (transfer full): filename of the GPG keyring for @collection_id + * Returns: (transfer full): #OstreeRemote containing the GPG keyring for + * @collection_id * Since: 2017.8 */ -gchar * +OstreeRemote * ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, const gchar *collection_id, GCancellable *cancellable, @@ -5506,7 +5515,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, { gsize i; g_auto(GStrv) remotes = NULL; - const OstreeRemote *keyring_remote = NULL; + OstreeRemote *keyring_remote = NULL; g_return_val_if_fail (OSTREE_IS_REPO (self), NULL); g_return_val_if_fail (ostree_validate_collection_id (collection_id, NULL), NULL); @@ -5556,7 +5565,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, } if (keyring_remote != NULL) - return g_strdup (keyring_remote->keyring); + return ostree_remote_ref (keyring_remote); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index a2986e6ddc..990573e76d 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -1208,10 +1208,10 @@ gboolean ostree_repo_pull_from_remotes_finish (OstreeRepo *self, GError **error); _OSTREE_PUBLIC -gchar *ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, - const gchar *collection_id, - GCancellable *cancellable, - GError **error); +OstreeRemote *ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, + const gchar *collection_id, + GCancellable *cancellable, + GError **error); _OSTREE_PUBLIC gboolean ostree_repo_list_collection_refs (OstreeRepo *self,