diff --git a/app/flatpak-builtins-build-bundle.c b/app/flatpak-builtins-build-bundle.c index e812da0a..6c42c9b2 100644 --- a/app/flatpak-builtins-build-bundle.c +++ b/app/flatpak-builtins-build-bundle.c @@ -126,6 +126,7 @@ build_bundle (OstreeRepo *repo, GFile *file, g_autoptr(GBytes) gpg_data = NULL; g_autoptr(GVariant) params = NULL; g_autoptr(GVariant) metadata = NULL; + const char *collection_id; if (!ostree_repo_resolve_rev (repo, full_branch, FALSE, &commit_checksum, error)) return FALSE; @@ -231,6 +232,14 @@ build_bundle (OstreeRepo *repo, GFile *file, if (opt_runtime_repo) g_variant_builder_add (&metadata_builder, "{sv}", "runtime-repo", g_variant_new_string (opt_runtime_repo)); +#ifdef FLATPAK_ENABLE_P2P + collection_id = ostree_repo_get_collection_id (repo); +#else /* if !FLATPAK_ENABLE_P2P */ + collection_id = NULL; +#endif /* !FLATPAK_ENABLE_P2P */ + g_variant_builder_add (&metadata_builder, "{sv}", "collection-id", + g_variant_new_string (collection_id ? collection_id : "")); + if (opt_gpg_file != NULL) { gpg_data = read_gpg_data (cancellable, error); diff --git a/app/flatpak-builtins-build-import-bundle.c b/app/flatpak-builtins-build-import-bundle.c index e12c0882..047d6d4e 100644 --- a/app/flatpak-builtins-build-import-bundle.c +++ b/app/flatpak-builtins-build-import-bundle.c @@ -134,10 +134,12 @@ import_bundle (OstreeRepo *repo, GFile *file, g_autofree char *to_checksum = NULL; const char *ref; + /* Don’t need to check the collection ID of the bundle here; + * flatpak_pull_from_bundle() does that. */ metadata = flatpak_bundle_load (file, &to_checksum, &bundle_ref, NULL, NULL, NULL, - NULL, NULL, error); + NULL, NULL, NULL, error); if (metadata == NULL) return NULL; diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c index 955de209..e4ca2b99 100644 --- a/app/flatpak-builtins-install.c +++ b/app/flatpak-builtins-install.c @@ -124,6 +124,7 @@ handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error) g_autoptr(GKeyFile) config = NULL; g_autoptr(GBytes) gpg_key = NULL; g_autofree char *group = NULL; + g_autofree char *runtime_collection_id = NULL; char *t; int i; @@ -170,8 +171,11 @@ handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error) group = g_strdup_printf ("remote \"%s\"", new_remote); runtime_url = g_key_file_get_string (config, group, "url", NULL); g_assert (runtime_url != NULL); +#ifdef FLATPAK_ENABLE_P2P + runtime_collection_id = g_key_file_get_string (config, group, "collection-id", NULL); +#endif /* FLATPAK_ENABLE_P2P */ - old_remote = flatpak_dir_find_remote_by_uri (dir, runtime_url); + old_remote = flatpak_dir_find_remote_by_uri (dir, runtime_url, runtime_collection_id); if (old_remote == NULL && flatpak_dir_is_user (dir)) { g_autoptr(GPtrArray) system_dirs = NULL; @@ -184,7 +188,7 @@ handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error) for (i = 0; i < system_dirs->len; i++) { FlatpakDir *system_dir = g_ptr_array_index (system_dirs, i); - old_remote = flatpak_dir_find_remote_by_uri (system_dir, runtime_url); + old_remote = flatpak_dir_find_remote_by_uri (system_dir, runtime_url, runtime_collection_id); if (old_remote != NULL) break; } @@ -225,6 +229,7 @@ handle_runtime_repo_deps_from_bundle (FlatpakDir *dir, GFile *file, GError **err NULL, NULL, NULL, + NULL, NULL); if (metadata == NULL || dep_url == NULL) return TRUE; diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 6a8b110b..f3058348 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -5498,6 +5498,7 @@ flatpak_dir_ensure_bundle_remote (FlatpakDir *self, GBytes *gpg_data = NULL; g_autofree char *to_checksum = NULL; g_autofree char *remote = NULL; + g_autofree char *collection_id = NULL; if (!flatpak_dir_ensure_repo (self, cancellable, error)) return NULL; @@ -5507,6 +5508,7 @@ flatpak_dir_ensure_bundle_remote (FlatpakDir *self, &origin, NULL, &fp_metadata, NULL, &included_gpg_data, + &collection_id, error); if (metadata == NULL) return NULL; @@ -5544,6 +5546,7 @@ flatpak_dir_ensure_bundle_remote (FlatpakDir *self, basename, ref, gpg_data, + collection_id, cancellable, error); if (remote == NULL) @@ -5613,7 +5616,7 @@ flatpak_dir_install_bundle (FlatpakDir *self, &ref, &origin, NULL, NULL, - NULL, NULL, + NULL, NULL, NULL, error); if (metadata == NULL) return FALSE; @@ -7733,6 +7736,7 @@ create_origin_remote_config (OstreeRepo *repo, const char *title, const char *main_ref, gboolean gpg_verify, + const char *collection_id, GKeyFile *new_config) { g_autofree char *remote = NULL; @@ -7776,6 +7780,11 @@ create_origin_remote_config (OstreeRepo *repo, if (main_ref) g_key_file_set_string (new_config, group, "xa.main-ref", main_ref); +#ifdef FLATPAK_ENABLE_P2P + if (collection_id) + g_key_file_set_string (new_config, group, "collection-id", collection_id); +#endif /* FLATPAK_ENABLE_P2P */ + return g_steal_pointer (&remote); } @@ -7786,13 +7795,14 @@ flatpak_dir_create_origin_remote (FlatpakDir *self, const char *title, const char *main_ref, GBytes *gpg_data, + const char *collection_id, GCancellable *cancellable, GError **error) { g_autoptr(GKeyFile) new_config = g_key_file_new (); g_autofree char *remote = NULL; - remote = create_origin_remote_config (self->repo, url, id, title, main_ref, gpg_data != NULL, new_config); + remote = create_origin_remote_config (self->repo, url, id, title, main_ref, gpg_data != NULL, collection_id, new_config); if (!flatpak_dir_modify_remote (self, remote, new_config, gpg_data, cancellable, error)) @@ -7815,6 +7825,7 @@ flatpak_dir_parse_repofile (FlatpakDir *self, g_autofree char *uri = NULL; g_autofree char *title = NULL; g_autofree char *gpg_key = NULL; + g_autofree char *collection_id = NULL; g_autofree char *default_branch = NULL; gboolean nodeps; GKeyFile *config = g_key_file_new (); @@ -7880,6 +7891,23 @@ flatpak_dir_parse_repofile (FlatpakDir *self, g_key_file_set_boolean (config, group, "gpg-verify-summary", TRUE); } +#ifdef FLATPAK_ENABLE_P2P + collection_id = g_key_file_get_string (keyfile, FLATPAK_REPO_GROUP, + FLATPAK_REPO_COLLECTION_ID_KEY, NULL); +#else /* if !FLATPAK_ENABLE_P2P */ + collection_id = NULL; +#endif /* !FLATPAK_ENABLE_P2P */ + if (collection_id != NULL) + { + if (gpg_key == NULL) + { + flatpak_fail (error, "Collection ID requires GPG key to be provided"); + return NULL; + } + + g_key_file_set_string (config, group, "collection-id", collection_id); + } + *gpg_data_out = g_steal_pointer (&gpg_data); return g_steal_pointer (&config); @@ -7893,6 +7921,7 @@ parse_ref_file (GBytes *data, char **title_out, GBytes **gpg_data_out, gboolean *is_runtime_out, + char **collection_id_out, GError **error) { g_autoptr(GKeyFile) keyfile = g_key_file_new (); @@ -7903,6 +7932,7 @@ parse_ref_file (GBytes *data, g_autofree char *version = NULL; g_autoptr(GBytes) gpg_data = NULL; gboolean is_runtime = FALSE; + g_autofree char *collection_id = NULL; char *str; *name_out = NULL; @@ -7960,12 +7990,22 @@ parse_ref_file (GBytes *data, gpg_data = g_bytes_new_take (decoded, decoded_len); } +#ifdef FLATPAK_ENABLE_P2P + collection_id = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP, + FLATPAK_REF_COLLECTION_ID_KEY, NULL); +#else /* if !FLATPAK_ENABLE_P2P */ + collection_id = NULL; +#endif /* !FLATPAK_ENABLE_P2P */ + if (collection_id != NULL && gpg_data == NULL) + return flatpak_fail (error, "Collection ID requires GPG key to be provided"); + *name_out = g_steal_pointer (&name); *branch_out = g_steal_pointer (&branch); *url_out = g_steal_pointer (&url); *title_out = g_steal_pointer (&title); *gpg_data_out = g_steal_pointer (&gpg_data); *is_runtime_out = is_runtime; + *collection_id_out = g_steal_pointer (&collection_id); return TRUE; } @@ -7986,9 +8026,10 @@ flatpak_dir_create_remote_for_ref_file (FlatpakDir *self, g_autofree char *ref = NULL; g_autofree char *remote = NULL; gboolean is_runtime = FALSE; + g_autofree char *collection_id = NULL; g_autoptr(GFile) deploy_dir = NULL; - if (!parse_ref_file (data, &name, &branch, &url, &title, &gpg_data, &is_runtime, error)) + if (!parse_ref_file (data, &name, &branch, &url, &title, &gpg_data, &is_runtime, &collection_id, error)) return FALSE; ref = flatpak_compose_ref (!is_runtime, name, branch, default_arch, error); @@ -8006,12 +8047,12 @@ flatpak_dir_create_remote_for_ref_file (FlatpakDir *self, } /* First try to reuse existing remote */ - remote = flatpak_dir_find_remote_by_uri (self, url); + remote = flatpak_dir_find_remote_by_uri (self, url, collection_id); if (remote == NULL) { remote = flatpak_dir_create_origin_remote (self, url, name, title, ref, - gpg_data, NULL, error); + gpg_data, collection_id, NULL, error); if (remote == NULL) return FALSE; } @@ -8023,13 +8064,20 @@ flatpak_dir_create_remote_for_ref_file (FlatpakDir *self, char * flatpak_dir_find_remote_by_uri (FlatpakDir *self, - const char *uri) + const char *uri, + const char *collection_id) { g_auto(GStrv) remotes = NULL; if (!flatpak_dir_ensure_repo (self, NULL, NULL)) return NULL; +#ifndef FLATPAK_ENABLE_P2P + /* If we don’t have P2P support enabled, we always want to ignore collection IDs + * in comparisons. */ + collection_id = NULL; +#endif /* !FLATPAK_ENABLE_P2P */ + remotes = flatpak_dir_list_enumerated_remotes (self, NULL, NULL); if (remotes) { @@ -8039,14 +8087,21 @@ flatpak_dir_find_remote_by_uri (FlatpakDir *self, { const char *remote = remotes[i]; g_autofree char *remote_uri = NULL; + g_autofree char *remote_collection_id = NULL; if (!ostree_repo_remote_get_url (self->repo, remote, &remote_uri, NULL)) continue; +#ifdef FLATPAK_ENABLE_P2P + if (!ostree_repo_get_remote_option (self->repo, remote, "collection-id", + NULL, &remote_collection_id, NULL)) + continue; +#endif /* FLATPAK_ENABLE_P2P */ - if (strcmp (uri, remote_uri) == 0) + if (strcmp (uri, remote_uri) == 0 && + g_strcmp0 (collection_id, remote_collection_id) == 0) return g_strdup (remote); } } diff --git a/common/flatpak-dir.h b/common/flatpak-dir.h index 2a695124..932127ec 100644 --- a/common/flatpak-dir.h +++ b/common/flatpak-dir.h @@ -47,6 +47,10 @@ GType flatpak_deploy_get_type (void); #define FLATPAK_REF_NAME_KEY "Name" #define FLATPAK_REF_BRANCH_KEY "Branch" +#ifdef FLATPAK_ENABLE_P2P +#define FLATPAK_REF_COLLECTION_ID_KEY "CollectionID" +#endif /* FLATPAK_ENABLE_P2P */ + #define FLATPAK_REPO_GROUP "Flatpak Repo" #define FLATPAK_REPO_VERSION_KEY "Version" #define FLATPAK_REPO_URL_KEY "Url" @@ -55,6 +59,10 @@ GType flatpak_deploy_get_type (void); #define FLATPAK_REPO_GPGKEY_KEY "GPGKey" #define FLATPAK_REPO_NODEPS_KEY "NoDeps" +#ifdef FLATPAK_ENABLE_P2P +#define FLATPAK_REPO_COLLECTION_ID_KEY "CollectionID" +#endif /* FLATPAK_ENABLE_P2P */ + #define FLATPAK_DEFAULT_UPDATE_FREQUENCY 100 #define FLATPAK_CLI_UPDATE_FREQUENCY 300 @@ -486,6 +494,7 @@ char *flatpak_dir_create_origin_remote (FlatpakDir *self, const char *title, const char *main_ref, GBytes *gpg_data, + const char *collection_id, GCancellable *cancellable, GError **error); gboolean flatpak_dir_create_remote_for_ref_file (FlatpakDir *self, @@ -502,7 +511,8 @@ GKeyFile * flatpak_dir_parse_repofile (FlatpakDir *self, GError **error); char *flatpak_dir_find_remote_by_uri (FlatpakDir *self, - const char *uri); + const char *uri, + const char *collection_id); char **flatpak_dir_list_remotes (FlatpakDir *self, GCancellable *cancellable, GError **error); diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c index 57630292..2769e680 100644 --- a/common/flatpak-utils.c +++ b/common/flatpak-utils.c @@ -4370,6 +4370,7 @@ flatpak_bundle_load (GFile *file, char **app_metadata, guint64 *installed_size, GBytes **gpg_keys, + char **collection_id, GError **error) { g_autoptr(GVariant) delta = NULL; @@ -4443,6 +4444,16 @@ flatpak_bundle_load (GFile *file, *runtime_repo = NULL; } + if (collection_id != NULL) + { +#ifdef FLATPAK_ENABLE_P2P + if (!g_variant_lookup (metadata, "collection-id", "s", collection_id)) + *collection_id = NULL; +#else /* if !FLATPAK_ENABLE_P2P */ + *collection_id = NULL; +#endif /* !FLATPAK_ENABLE_P2P */ + } + if (app_metadata != NULL) { if (!g_variant_lookup (metadata, "metadata", "s", app_metadata)) @@ -4492,14 +4503,28 @@ flatpak_pull_from_bundle (OstreeRepo *repo, g_autoptr(GError) my_error = NULL; g_autoptr(GVariant) metadata = NULL; gboolean metadata_valid; + g_autofree char *remote_collection_id = NULL; + g_autofree char *collection_id = NULL; - metadata = flatpak_bundle_load (file, &to_checksum, NULL, NULL, NULL, &metadata_contents, NULL, NULL, error); + metadata = flatpak_bundle_load (file, &to_checksum, NULL, NULL, NULL, &metadata_contents, NULL, NULL, &collection_id, error); if (metadata == NULL) return FALSE; +#ifdef FLATPAK_ENABLE_P2P + if (!ostree_repo_get_remote_option (repo, remote, "collection-id", NULL, + &remote_collection_id, NULL)) + remote_collection_id = NULL; +#endif /* FLATPAK_ENABLE_P2P */ + + if (remote_collection_id != NULL && collection_id != NULL && + strcmp (remote_collection_id, collection_id) != 0) + return flatpak_fail (error, "Collection ‘%s’ of bundle doesn’t match collection ‘%s’ of remote", + collection_id, remote_collection_id); + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) return FALSE; + /* Don’t need to set the collection ID here, since the remote binds this ref to the collection. */ ostree_repo_transaction_set_ref (repo, remote, ref, to_checksum); if (!ostree_repo_static_delta_execute_offline (repo, diff --git a/common/flatpak-utils.h b/common/flatpak-utils.h index 53757f90..2851913e 100644 --- a/common/flatpak-utils.h +++ b/common/flatpak-utils.h @@ -341,6 +341,7 @@ GVariant * flatpak_bundle_load (GFile *file, char **app_metadata, guint64 *installed_size, GBytes **gpg_keys, + char **collection_id, GError **error); gboolean flatpak_pull_from_bundle (OstreeRepo *repo, diff --git a/doc/flatpak-build-bundle.xml b/doc/flatpak-build-bundle.xml index 80d07e0b..adc568ce 100644 --- a/doc/flatpak-build-bundle.xml +++ b/doc/flatpak-build-bundle.xml @@ -48,6 +48,11 @@ in the repository at LOCATION. If a BRANCH is specified, this branch of the application is used. + The format of the bundle file is that of an ostree static delta diff --git a/doc/flatpak-flatpakref.xml b/doc/flatpak-flatpakref.xml index 2256aea6..a8d2854e 100644 --- a/doc/flatpak-flatpakref.xml +++ b/doc/flatpak-flatpakref.xml @@ -107,6 +107,13 @@ (string) The url of a webpage describing the application or runtime. + (boolean) diff --git a/doc/flatpak-flatpakrepo.xml b/doc/flatpak-flatpakrepo.xml index edecaca6..675c0b5e 100644 --- a/doc/flatpak-flatpakrepo.xml +++ b/doc/flatpak-flatpakrepo.xml @@ -103,6 +103,13 @@ (string) The url of a webpage describing the remote. + @@ -114,6 +121,10 @@ Title=GEdit Url=http://sdk.gnome.org/repo-apps/ GPGKey=mQENBFUUCGcBCAC/K9WeV4xCaKr3NKRqPXeY5mpaXAJyasLqCtrDx92WUgbu0voWrhohNAKpqizod2dvzc/XTxm3rHyIxmNfdhz1gaGhynU75Qw4aJVcly2eghTIl++gfDtOvrOZo/VuAq30f32dMIgHQdRwEpgCwz7WyjpqZYltPAEcCNL4MTChAfiHJeeiQ5ibystNBW8W6Ymf7sO4m4g5+/aOxI54oCOzD9TwBAe+yXcJJWtc2rAhMCjtyPJzxd0ZVXqIzCe1xRvJ6Rq7YCiMbiM2DQFWXKnmYQbj4TGNMnwNdAajCdrcBWEMSbzq7EzuThIJRd8Ky4BkEe1St6tuqwFaMZz+F9eXABEBAAG0KEdub21lIFNESyAzLjE2IDxnbm9tZS1vcy1saXN0QGdub21lLm9yZz6JATgEEwECACIFAlUUCGcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEArkz6VV0VKBa5cH/0vXa31YgEjNk78gGFXqnQxdD1WYA87OYxDi189l4lA802EFTF4wCBuZyDOqdd5BhS3Ab0cR778DmZXRUP2gwe+1zTJypU2JMnDpkwJ4NK1VP6/tE4SAPrznBtmb76BKaWBqUfZ9Wq1zg3ugvqkZB/Exq+usypIOwQVp1KL58TrjBRda0HvRctzkNhr0qYAtkfLFe0GvksBp4vBm8uGwAx7fw/HbhIjQ9pekTwvB+5GwDPO/tSip/1bQfCS+XJB8Ffa04HYPLGedalnWBrwhYY+G/kn5Zh9L/AC8xeLwTJTHM212rBjPa9CWs9C6a57MSaeGIEHLC1hEyiJJ15w8jmY= + diff --git a/lib/flatpak-bundle-ref.c b/lib/flatpak-bundle-ref.c index 2e72c369..5d0c1088 100644 --- a/lib/flatpak-bundle-ref.c +++ b/lib/flatpak-bundle-ref.c @@ -286,9 +286,10 @@ flatpak_bundle_ref_new (GFile *file, g_autoptr(GVariant) icon_64 = NULL; g_autoptr(GVariant) icon_128 = NULL; guint64 installed_size; + g_autofree char *collection_id = NULL; metadata = flatpak_bundle_load (file, &commit, &full_ref, &origin, &runtime_repo, &metadata_contents, &installed_size, - NULL, error); + NULL, &collection_id, error); if (metadata == NULL) return NULL; @@ -306,6 +307,9 @@ flatpak_bundle_ref_new (GFile *file, "branch", parts[3], "commit", commit, "file", file, +#ifdef FLATPAK_ENABLE_P2P + "collection-id", collection_id, +#endif /* FLATPAK_ENABLE_P2P */ NULL); priv = flatpak_bundle_ref_get_instance_private (ref);