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);