common: Support collection IDs in flatpak{ref,repo} and bundle files

These are loaded from the ref/repo/bundle metadata and added to the new
remote configuration.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
tingping/wmclass
Philip Withnall 2017-06-30 15:18:50 +01:00 committed by Alexander Larsson
parent 4c395cec13
commit ae7d960372
11 changed files with 147 additions and 13 deletions

View File

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

View File

@ -134,10 +134,12 @@ import_bundle (OstreeRepo *repo, GFile *file,
g_autofree char *to_checksum = NULL;
const char *ref;
/* Dont 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;

View File

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

View File

@ -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 dont 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);
}
}

View File

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

View File

@ -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 doesnt match collection %s of remote",
collection_id, remote_collection_id);
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
return FALSE;
/* Dont 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,

View File

@ -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,

View File

@ -48,6 +48,11 @@
in the repository at <arg choice="plain">LOCATION</arg>. If
a <arg choice="plain">BRANCH</arg> is specified, this branch of
the application is used.
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
The collection ID set on the repository at
<arg choice="plain">LOCATION</arg> (if set) will be used for the
bundle.
-->
</para>
<para>
The format of the bundle file is that of an ostree static delta

View File

@ -107,6 +107,13 @@
<term><option>Homepage</option> (string)</term>
<listitem><para>The url of a webpage describing the application or runtime.</para></listitem>
</varlistentry>
<!--
FIXME: Uncomment this when P2P support is made unconditional on enable-p2p.
<varlistentry>
<term><option>CollectionID</option> (string)</term>
<listitem><para>The collection ID of the remote, if it has one. This uniquely identifies the collection of apps in the remote, to allow peer to peer redistribution.</para></listitem>
</varlistentry>
-->
<varlistentry>
<term><option>IsRuntime</option> (boolean)</term>

View File

@ -103,6 +103,13 @@
<term><option>Homepage</option> (string)</term>
<listitem><para>The url of a webpage describing the remote.</para></listitem>
</varlistentry>
<!--
FIXME: Uncomment this when P2P support is made unconditional on enable-p2p.
<varlistentry>
<term><option>CollectionID</option> (string)</term>
<listitem><para>The collection ID of the remote, if it has one. This uniquely identifies the collection of apps in the remote, to allow peer to peer redistribution.</para></listitem>
</varlistentry>
-->
</variablelist>
</refsect2>
</refsect1>
@ -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=
<!--
FIXME: Uncomment this when P2P support is made unconditional on enable-p2p.
CollectionID=org.gnome.Apps
-->
</programlisting>
</refsect1>

View File

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