diff --git a/app/flatpak-builtins-build-bundle.c b/app/flatpak-builtins-build-bundle.c
index ed2d172f..e393199b 100644
--- a/app/flatpak-builtins-build-bundle.c
+++ b/app/flatpak-builtins-build-bundle.c
@@ -44,6 +44,7 @@
static char *opt_arch;
static char *opt_repo_url;
+static char *opt_runtime_repo;
static gboolean opt_runtime = FALSE;
static char **opt_gpg_file;
static gboolean opt_oci = FALSE;
@@ -52,6 +53,7 @@ static GOptionEntry options[] = {
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Export runtime instead of app"), NULL },
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to bundle for"), N_("ARCH") },
{ "repo-url", 0, 0, G_OPTION_ARG_STRING, &opt_repo_url, N_("Url for repo"), N_("URL") },
+ { "runtime-repo", 0, 0, G_OPTION_ARG_STRING, &opt_runtime_repo, N_("Url for runtime flatpakrepo file"), N_("URL") },
{ "gpg-keys", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, N_("Add GPG key from FILE (- for stdin)"), N_("FILE") },
{ "oci", 0, 0, G_OPTION_ARG_NONE, &opt_oci, N_("Export oci image instead of flatpak bundle"), NULL },
@@ -222,6 +224,9 @@ build_bundle (OstreeRepo *repo, GFile *file,
if (opt_repo_url)
g_variant_builder_add (&metadata_builder, "{sv}", "origin", g_variant_new_string (opt_repo_url));
+ if (opt_runtime_repo)
+ g_variant_builder_add (&metadata_builder, "{sv}", "runtime-repo", g_variant_new_string (opt_runtime_repo));
+
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 5faebb57..0e50e3f0 100644
--- a/app/flatpak-builtins-build-import-bundle.c
+++ b/app/flatpak-builtins-build-import-bundle.c
@@ -108,10 +108,8 @@ import_bundle (OstreeRepo *repo, GFile *file,
metadata = flatpak_bundle_load (file, &to_checksum,
&bundle_ref,
- NULL,
- NULL,
- NULL,
- error);
+ NULL, NULL, NULL,
+ NULL, NULL, error);
if (metadata == NULL)
return NULL;
diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c
index 13a77ba4..ec529fc8 100644
--- a/app/flatpak-builtins-install.c
+++ b/app/flatpak-builtins-install.c
@@ -112,49 +112,8 @@ read_gpg_data (GCancellable *cancellable,
}
static gboolean
-install_bundle (FlatpakDir *dir,
- GOptionContext *context,
- int argc, char **argv,
- GCancellable *cancellable,
- GError **error)
+handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error)
{
- g_autoptr(GFile) file = NULL;
- const char *filename;
- g_autoptr(GBytes) gpg_data = NULL;
-
- if (argc < 2)
- return usage_error (context, _("Bundle filename must be specified"), error);
-
- if (argc > 2)
- return usage_error (context, _("Too many arguments"), error);
-
- filename = argv[1];
-
- file = g_file_new_for_commandline_arg (filename);
-
- if (!g_file_is_native (file))
- return flatpak_fail (error, _("Remote bundles are not supported"));
-
- if (opt_gpg_file != NULL)
- {
- /* Override gpg_data from file */
- gpg_data = read_gpg_data (cancellable, error);
- if (gpg_data == NULL)
- return FALSE;
- }
-
- if (!flatpak_dir_install_bundle (dir, file, gpg_data, NULL,
- cancellable, error))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-handle_runtime_repo_deps (FlatpakDir *dir, GBytes *data, GError **error)
-{
- g_autoptr(GKeyFile) keyfile = g_key_file_new ();
- g_autofree char *dep_url = NULL;
g_autoptr(GBytes) dep_data = NULL;
g_autofree char *runtime_url = NULL;
g_autofree char *old_remote = NULL;
@@ -168,13 +127,7 @@ handle_runtime_repo_deps (FlatpakDir *dir, GBytes *data, GError **error)
char *t;
int i;
- if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
- 0, error))
- return FALSE;
-
- dep_url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
- FLATPAK_REF_RUNTIME_REPO_KEY, NULL);
- if (dep_url == NULL)
+ if (opt_no_deps)
return TRUE;
dep_data = download_uri (dep_url, error);
@@ -256,6 +209,101 @@ handle_runtime_repo_deps (FlatpakDir *dir, GBytes *data, GError **error)
return TRUE;
}
+static gboolean
+handle_runtime_repo_deps_from_bundle (FlatpakDir *dir, GFile *file, GError **error)
+{
+ g_autofree char *dep_url = NULL;
+ g_autoptr(GVariant) metadata = NULL;
+
+ if (opt_no_deps)
+ return TRUE;
+
+ metadata = flatpak_bundle_load (file, NULL,
+ NULL,
+ NULL,
+ &dep_url,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (metadata == NULL || dep_url == NULL)
+ return TRUE;
+
+ return handle_runtime_repo_deps (dir, dep_url, error);
+}
+
+static gboolean
+install_bundle (FlatpakDir *dir,
+ GOptionContext *context,
+ int argc, char **argv,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(GFile) file = NULL;
+ const char *filename;
+ g_autoptr(GBytes) gpg_data = NULL;
+ g_autoptr(FlatpakTransaction) transaction = NULL;
+
+ if (argc < 2)
+ return usage_error (context, _("Bundle filename must be specified"), error);
+
+ if (argc > 2)
+ return usage_error (context, _("Too many arguments"), error);
+
+ filename = argv[1];
+
+ file = g_file_new_for_commandline_arg (filename);
+
+ if (!g_file_is_native (file))
+ return flatpak_fail (error, _("Remote bundles are not supported"));
+
+ if (opt_gpg_file != NULL)
+ {
+ /* Override gpg_data from file */
+ gpg_data = read_gpg_data (cancellable, error);
+ if (gpg_data == NULL)
+ return FALSE;
+ }
+
+ if (!handle_runtime_repo_deps_from_bundle (dir, file, error))
+ return FALSE;
+
+ if (!flatpak_dir_ensure_repo (dir, cancellable, error))
+ return FALSE;
+
+ transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy,
+ !opt_no_deps, !opt_no_related);
+
+ if (!flatpak_transaction_add_install_bundle (transaction, file, gpg_data, error))
+ return FALSE;
+
+ if (!flatpak_transaction_run (transaction, TRUE, cancellable, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+handle_runtime_repo_deps_from_keyfile (FlatpakDir *dir, GBytes *data, GError **error)
+{
+ g_autoptr(GKeyFile) keyfile = g_key_file_new ();
+ g_autofree char *dep_url = NULL;
+
+ if (opt_no_deps)
+ return TRUE;
+
+ if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
+ 0, error))
+ return FALSE;
+
+ dep_url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
+ FLATPAK_REF_RUNTIME_REPO_KEY, NULL);
+ if (dep_url == NULL)
+ return TRUE;
+
+ return handle_runtime_repo_deps (dir, dep_url, error);
+}
+
static gboolean
install_from (FlatpakDir *dir,
GOptionContext *context,
@@ -303,7 +351,7 @@ install_from (FlatpakDir *dir,
file_data = g_bytes_new_take (g_steal_pointer (&data), data_len);
}
- if (!handle_runtime_repo_deps (dir, file_data, error))
+ if (!handle_runtime_repo_deps_from_keyfile (dir, file_data, error))
return FALSE;
if (!flatpak_dir_create_remote_for_ref_file (dir, file_data, &remote, &ref, error))
diff --git a/app/flatpak-transaction.c b/app/flatpak-transaction.c
index aefdb6ad..4b294938 100644
--- a/app/flatpak-transaction.c
+++ b/app/flatpak-transaction.c
@@ -30,13 +30,20 @@
typedef struct FlatpakTransactionOp FlatpakTransactionOp;
+typedef enum {
+ FLATPAK_TRANSACTION_OP_KIND_INSTALL,
+ FLATPAK_TRANSACTION_OP_KIND_UPDATE,
+ FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE,
+ FLATPAK_TRANSACTION_OP_KIND_BUNDLE
+} FlatpakTransactionOpKind;
+
struct FlatpakTransactionOp {
char *remote;
char *ref;
char **subpaths;
char *commit;
- gboolean update;
- gboolean install;
+ GFile *bundle;
+ FlatpakTransactionOpKind kind;
gboolean non_fatal;
};
@@ -117,8 +124,8 @@ flatpak_transaction_operation_new (const char *remote,
const char *ref,
const char **subpaths,
const char *commit,
- gboolean install,
- gboolean update)
+ GFile *bundle,
+ FlatpakTransactionOpKind kind)
{
FlatpakTransactionOp *self = g_new0 (FlatpakTransactionOp, 1);
@@ -126,8 +133,9 @@ flatpak_transaction_operation_new (const char *remote,
self->ref = g_strdup (ref);
self->subpaths = g_strdupv ((char **)subpaths);
self->commit = g_strdup (commit);
- self->update = update;
- self->install = install;
+ if (bundle)
+ self->bundle = g_object_ref (bundle);
+ self->kind = kind;
return self;
}
@@ -139,6 +147,7 @@ flatpak_transaction_operation_free (FlatpakTransactionOp *self)
g_free (self->ref);
g_free (self->commit);
g_strfreev (self->subpaths);
+ g_clear_object (&self->bundle);
g_free (self);
}
@@ -212,31 +221,38 @@ subpaths_to_string (const char **subpaths)
return g_string_free (s, FALSE);
}
+static const char *
+kind_to_str (FlatpakTransactionOpKind kind)
+{
+ switch (kind)
+ {
+ case FLATPAK_TRANSACTION_OP_KIND_INSTALL:
+ return "install";
+ case FLATPAK_TRANSACTION_OP_KIND_UPDATE:
+ return "update";
+ case FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE:
+ return "install/update";
+ case FLATPAK_TRANSACTION_OP_KIND_BUNDLE:
+ return "install bundle";
+ }
+ return "unknown";
+}
+
FlatpakTransactionOp *
flatpak_transaction_add_op (FlatpakTransaction *self,
const char *remote,
const char *ref,
const char **subpaths,
const char *commit,
- gboolean install,
- gboolean update)
+ GFile *bundle,
+ FlatpakTransactionOpKind kind)
{
FlatpakTransactionOp *op;
g_autofree char *subpaths_str = NULL;
- const char *opname;
- if (install)
- {
- if (update)
- opname = "install/update";
- else
- opname = "install";
- }
- else
- opname = "update";
subpaths_str = subpaths_to_string (subpaths);
g_debug ("Transaction: %s %s:%s%s%s%s",
- opname, remote, ref,
+ kind_to_str (kind), remote, ref,
commit != NULL ? "@" : "",
commit != NULL ? commit : "",
subpaths_str);
@@ -255,7 +271,7 @@ flatpak_transaction_add_op (FlatpakTransaction *self,
return op;
}
- op = flatpak_transaction_operation_new (remote, ref, subpaths, commit, install, update);
+ op = flatpak_transaction_operation_new (remote, ref, subpaths, commit, bundle, kind);
g_hash_table_insert (self->refs, g_strdup (ref), op);
self->ops = g_list_prepend (self->ops, op);
@@ -329,7 +345,8 @@ add_related (FlatpakTransaction *self,
op = flatpak_transaction_add_op (self, remote, rel->ref,
(const char **)rel->subpaths,
- NULL, TRUE, TRUE);
+ NULL, NULL,
+ FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE);
op->non_fatal = TRUE;
}
}
@@ -394,14 +411,16 @@ add_deps (FlatpakTransaction *self,
"The Application %s requires the runtime %s which is not installed",
pref, runtime_ref);
- flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, TRUE, TRUE);
+ flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, NULL,
+ FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE);
}
else
{
/* Update if in same dir */
if (dir_ref_is_installed (self->dir, full_runtime_ref, &runtime_remote))
{
- flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, FALSE, TRUE);
+ flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, NULL,
+ FLATPAK_TRANSACTION_OP_KIND_UPDATE);
}
}
}
@@ -419,17 +438,19 @@ flatpak_transaction_add_ref (FlatpakTransaction *self,
const char *ref,
const char **subpaths,
const char *commit,
- gboolean is_update,
+ FlatpakTransactionOpKind kind,
+ GFile *bundle,
+ const char *metadata,
GError **error)
{
g_autofree char *origin = NULL;
const char *pref;
- g_autofree char *metadata = NULL;
+ g_autofree char *remote_metadata = NULL;
g_autoptr(GKeyFile) metakey = NULL;
pref = strchr (ref, '/') + 1;
- if (is_update)
+ if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE)
{
if (!dir_ref_is_installed (self->dir, ref, &origin))
{
@@ -456,7 +477,11 @@ flatpak_transaction_add_ref (FlatpakTransaction *self,
}
}
- if (flatpak_dir_fetch_ref_cache (self->dir, remote, ref, NULL, NULL, &metadata, NULL, NULL))
+ if (metadata == NULL && remote != NULL &&
+ flatpak_dir_fetch_ref_cache (self->dir, remote, ref, NULL, NULL, &remote_metadata, NULL, NULL))
+ metadata = remote_metadata;
+
+ if (metadata)
{
metakey = g_key_file_new ();
if (!g_key_file_load_from_data (metakey, metadata, -1, 0, NULL))
@@ -487,7 +512,7 @@ flatpak_transaction_add_ref (FlatpakTransaction *self,
return FALSE;
}
- flatpak_transaction_add_op (self, remote, ref, subpaths, commit, !is_update, is_update);
+ flatpak_transaction_add_op (self, remote, ref, subpaths, commit, bundle, kind);
if (!add_related (self, remote, ref, error))
return FALSE;
@@ -508,7 +533,30 @@ flatpak_transaction_add_install (FlatpakTransaction *self,
if (subpaths == NULL)
subpaths = all_paths;
- return flatpak_transaction_add_ref (self, remote, ref, subpaths, NULL, FALSE, error);
+ return flatpak_transaction_add_ref (self, remote, ref, subpaths, NULL, FLATPAK_TRANSACTION_OP_KIND_INSTALL, NULL, NULL, error);
+}
+
+gboolean
+flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
+ GFile *file,
+ GBytes *gpg_data,
+ GError **error)
+{
+ g_autofree char *remote = NULL;
+ g_autofree char *ref = NULL;
+ g_autofree char *metadata = NULL;
+ gboolean created_remote;
+
+ remote = flatpak_dir_ensure_bundle_remote (self->dir, file, gpg_data,
+ &ref, &metadata, &created_remote,
+ NULL, error);
+ if (remote == NULL)
+ return FALSE;
+
+ if (!flatpak_dir_recreate_repo (self->dir, NULL, error))
+ return FALSE;
+
+ return flatpak_transaction_add_ref (self, remote, ref, NULL, NULL, FLATPAK_TRANSACTION_OP_KIND_BUNDLE, file, metadata, error);
}
gboolean
@@ -557,7 +605,7 @@ flatpak_transaction_add_install_oci (FlatpakTransaction *self,
id = g_strdup_printf ("oci-%s", parts[1]);
remote = flatpak_dir_create_origin_remote (self->dir, NULL,
- id, title,
+ id, title,
ref, uri, tag, NULL,
NULL, error);
if (remote == NULL)
@@ -568,7 +616,7 @@ flatpak_transaction_add_install_oci (FlatpakTransaction *self,
g_debug ("Added OCI origin remote %s", remote);
- return flatpak_transaction_add_ref (self, remote, ref, all_paths, checksum, FALSE, error);
+ return flatpak_transaction_add_ref (self, remote, ref, all_paths, checksum, FLATPAK_TRANSACTION_OP_KIND_INSTALL, NULL, NULL, error);
}
gboolean
@@ -578,7 +626,7 @@ flatpak_transaction_add_update (FlatpakTransaction *self,
const char *commit,
GError **error)
{
- return flatpak_transaction_add_ref (self, NULL, ref, subpaths, commit, TRUE, error);
+ return flatpak_transaction_add_ref (self, NULL, ref, subpaths, commit, FLATPAK_TRANSACTION_OP_KIND_UPDATE, NULL, NULL, error);
}
gboolean
@@ -599,18 +647,20 @@ flatpak_transaction_run (FlatpakTransaction *self,
gboolean res;
const char *pref;
const char *opname;
+ FlatpakTransactionOpKind kind;
- if (op->install && op->update)
+ kind = op->kind;
+ if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE)
{
if (dir_ref_is_installed (self->dir, op->ref, NULL))
- op->install = FALSE;
+ kind = FLATPAK_TRANSACTION_OP_KIND_UPDATE;
else
- op->update = FALSE;
+ kind = FLATPAK_TRANSACTION_OP_KIND_INSTALL;
}
pref = strchr (op->ref, '/') + 1;
- if (op->install)
+ if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL)
{
opname = _("install");
g_print (_("Installing: %s from %s\n"), pref, op->remote);
@@ -622,7 +672,7 @@ flatpak_transaction_run (FlatpakTransaction *self,
NULL,
cancellable, &local_error);
}
- else /* update */
+ else if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE)
{
opname = _("update");
g_print (_("Updating: %s from %s\n"), pref, op->remote);
@@ -651,6 +701,17 @@ flatpak_transaction_run (FlatpakTransaction *self,
g_clear_error (&local_error);
}
}
+ else if (kind == FLATPAK_TRANSACTION_OP_KIND_BUNDLE)
+ {
+ g_autofree char *bundle_basename = g_file_get_basename (op->bundle);
+ opname = _("install bundle");
+ g_print (_("Installing: %s from bundle %s\n"), pref, bundle_basename);
+ res = flatpak_dir_install_bundle (self->dir, op->bundle,
+ op->remote, NULL,
+ cancellable, &local_error);
+ }
+ else
+ g_assert_not_reached ();
if (!res)
{
diff --git a/app/flatpak-transaction.h b/app/flatpak-transaction.h
index 2eb81106..ae8a6f88 100644
--- a/app/flatpak-transaction.h
+++ b/app/flatpak-transaction.h
@@ -48,6 +48,10 @@ gboolean flatpak_transaction_add_install_oci (FlatpakTransaction *se
const char *uri,
const char *tag,
GError **error);
+gboolean flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
+ GFile *file,
+ GBytes *gpg_data,
+ GError **error);
gboolean flatpak_transaction_add_update (FlatpakTransaction *self,
const char *ref,
const char **subpaths,
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index cdad7886..4dd263cc 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -4310,45 +4310,125 @@ flatpak_dir_install (FlatpakDir *self,
return TRUE;
}
-gboolean
-flatpak_dir_install_bundle (FlatpakDir *self,
- GFile *file,
- GBytes *extra_gpg_data,
- char **out_ref,
- GCancellable *cancellable,
- GError **error)
+char *
+flatpak_dir_ensure_bundle_remote (FlatpakDir *self,
+ GFile *file,
+ GBytes *extra_gpg_data,
+ char **out_ref,
+ char **out_metadata,
+ gboolean *out_created_remote,
+ GCancellable *cancellable,
+ GError **error)
{
g_autofree char *ref = NULL;
- gboolean added_remote = FALSE;
+ gboolean created_remote = FALSE;
g_autoptr(GVariant) deploy_data = NULL;
g_autoptr(GVariant) metadata = NULL;
g_autofree char *origin = NULL;
+ g_autofree char *fp_metadata = NULL;
g_auto(GStrv) parts = NULL;
g_autofree char *basename = NULL;
g_autoptr(GBytes) included_gpg_data = NULL;
GBytes *gpg_data = NULL;
g_autofree char *to_checksum = NULL;
g_autofree char *remote = NULL;
- gboolean ret = FALSE;
+
+ if (!flatpak_dir_ensure_repo (self, cancellable, error))
+ return NULL;
+
+ metadata = flatpak_bundle_load (file, &to_checksum,
+ &ref,
+ &origin,
+ NULL, &fp_metadata, NULL,
+ &included_gpg_data,
+ error);
+ if (metadata == NULL)
+ return NULL;
+
+ gpg_data = extra_gpg_data ? extra_gpg_data : included_gpg_data;
+
+ parts = flatpak_decompose_ref (ref, error);
+ if (parts == NULL)
+ return NULL;
+
+ deploy_data = flatpak_dir_get_deploy_data (self, ref, cancellable, NULL);
+ if (deploy_data != NULL)
+ {
+ remote = g_strdup (flatpak_deploy_data_get_origin (deploy_data));
+
+ /* We need to import any gpg keys because otherwise the pull will fail */
+ if (gpg_data != NULL)
+ {
+ g_autoptr(GKeyFile) new_config = NULL;
+
+ new_config = ostree_repo_copy_config (flatpak_dir_get_repo (self));
+
+ if (!flatpak_dir_modify_remote (self, remote, new_config,
+ gpg_data, cancellable, error))
+ return NULL;
+ }
+ }
+ else
+ {
+ /* Add a remote for later updates */
+ basename = g_file_get_basename (file);
+ remote = flatpak_dir_create_origin_remote (self,
+ origin,
+ parts[1],
+ basename,
+ ref,
+ NULL, NULL,
+ gpg_data,
+ cancellable,
+ error);
+ if (remote == NULL)
+ return NULL;
+
+ /* From here we need to goto out on error, to clean up */
+ created_remote = TRUE;
+ }
+
+ if (out_created_remote)
+ *out_created_remote = created_remote;
+
+ if (out_ref)
+ *out_ref = g_steal_pointer (&ref);
+
+ if (out_metadata)
+ *out_metadata = g_steal_pointer (&fp_metadata);
+
+
+ return g_steal_pointer (&remote);
+}
+
+gboolean
+flatpak_dir_install_bundle (FlatpakDir *self,
+ GFile *file,
+ const char *remote,
+ char **out_ref,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autofree char *ref = NULL;
+ g_autoptr(GVariant) deploy_data = NULL;
+ g_autoptr(GVariant) metadata = NULL;
+ g_autofree char *origin = NULL;
+ g_auto(GStrv) parts = NULL;
+ g_autofree char *to_checksum = NULL;
+ gboolean gpg_verify;
if (flatpak_dir_use_system_helper (self))
{
FlatpakSystemHelper *system_helper;
- g_autoptr(GVariant) gpg_data_v = NULL;
const char *installation = flatpak_dir_get_id (self);
system_helper = flatpak_dir_get_system_helper (self);
g_assert (system_helper != NULL);
- if (gpg_data != NULL)
- gpg_data_v = variant_new_ay_bytes (gpg_data);
- else
- gpg_data_v = g_variant_ref_sink (g_variant_new_from_data (G_VARIANT_TYPE ("ay"), "", 0, TRUE, NULL, NULL));
-
g_debug ("Calling system helper: InstallBundle");
if (!flatpak_system_helper_call_install_bundle_sync (system_helper,
flatpak_file_get_path_cached (file),
- 0, gpg_data_v,
+ 0, remote,
installation ? installation : "",
&ref,
cancellable,
@@ -4367,14 +4447,12 @@ flatpak_dir_install_bundle (FlatpakDir *self,
metadata = flatpak_bundle_load (file, &to_checksum,
&ref,
&origin,
- NULL,
- &included_gpg_data,
+ NULL, NULL,
+ NULL, NULL,
error);
if (metadata == NULL)
return FALSE;
- gpg_data = extra_gpg_data ? extra_gpg_data : included_gpg_data;
-
parts = flatpak_decompose_ref (ref, error);
if (parts == NULL)
return FALSE;
@@ -4388,51 +4466,27 @@ flatpak_dir_install_bundle (FlatpakDir *self,
_("This version of %s is already installed"), parts[1]);
return FALSE;
}
- remote = g_strdup (flatpak_deploy_data_get_origin (deploy_data));
- /* We need to import any gpg keys because otherwise the pull will fail */
- if (gpg_data != NULL)
+ if (strcmp (remote, flatpak_deploy_data_get_origin (deploy_data)) != 0)
{
- g_autoptr(GInputStream) input_stream = g_memory_input_stream_new_from_bytes (gpg_data);
- guint imported = 0;
-
- if (!ostree_repo_remote_gpg_import (self->repo, remote, input_stream,
- NULL, &imported, cancellable, error))
- return FALSE;
-
- /* XXX If we ever add internationalization, use ngettext() here. */
- g_debug ("Imported %u GPG key%s to remote \"%s\"",
- imported, (imported == 1) ? "" : "s", remote);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Can't change remote during bundle install"));
+ return FALSE;
}
}
- else
- {
- /* Add a remote for later updates */
- basename = g_file_get_basename (file);
- remote = flatpak_dir_create_origin_remote (self,
- origin,
- parts[1],
- basename,
- ref,
- NULL, NULL,
- gpg_data,
- cancellable,
- error);
- if (remote == NULL)
- return FALSE;
- /* From here we need to goto out on error, to clean up */
- added_remote = TRUE;
- }
+ if (!ostree_repo_remote_get_gpg_verify (self->repo, remote,
+ &gpg_verify, error))
+ return FALSE;
if (!flatpak_pull_from_bundle (self->repo,
file,
remote,
ref,
- gpg_data != NULL,
+ gpg_verify,
cancellable,
error))
- goto out;
+ return FALSE;
if (deploy_data != NULL)
{
@@ -4466,24 +4520,18 @@ flatpak_dir_install_bundle (FlatpakDir *self,
if (deploy_data)
{
if (!flatpak_dir_deploy_update (self, ref, NULL, NULL, cancellable, error))
- goto out;
+ return FALSE;
}
else
{
if (!flatpak_dir_deploy_install (self, ref, remote, NULL, cancellable, error))
- goto out;
+ return FALSE;
}
if (out_ref)
*out_ref = g_steal_pointer (&ref);
- ret = TRUE;
-
-out:
- if (added_remote && !ret)
- ostree_repo_remote_delete (self->repo, remote, NULL, NULL);
-
- return ret;
+ return TRUE;
}
static gboolean
@@ -6340,6 +6388,7 @@ create_origin_remote_config (OstreeRepo *repo,
const char *main_ref,
const char *oci_uri,
const char *oci_tag,
+ gboolean gpg_verify,
GKeyFile *new_config)
{
g_autofree char *remote = NULL;
@@ -6370,8 +6419,16 @@ create_origin_remote_config (OstreeRepo *repo,
g_key_file_set_string (new_config, group, "xa.title", title);
g_key_file_set_string (new_config, group, "xa.noenumerate", "true");
g_key_file_set_string (new_config, group, "xa.prio", "0");
- g_key_file_set_string (new_config, group, "gpg-verify", "true");
- g_key_file_set_string (new_config, group, "gpg-verify-summary", "true");
+ if (gpg_verify)
+ {
+ g_key_file_set_string (new_config, group, "gpg-verify", "true");
+ g_key_file_set_string (new_config, group, "gpg-verify-summary", "true");
+ }
+ else
+ {
+ g_key_file_set_string (new_config, group, "gpg-verify", "false");
+ g_key_file_set_string (new_config, group, "gpg-verify-summary", "false");
+ }
if (main_ref)
g_key_file_set_string (new_config, group, "xa.main-ref", main_ref);
if (oci_uri)
@@ -6397,7 +6454,7 @@ flatpak_dir_create_origin_remote (FlatpakDir *self,
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, oci_uri, oci_tag, new_config);
+ remote = create_origin_remote_config (self->repo, url, id, title, main_ref, oci_uri, oci_tag, gpg_data != NULL, new_config);
if (!flatpak_dir_modify_remote (self, remote, new_config,
gpg_data, cancellable, error))
diff --git a/common/flatpak-dir.h b/common/flatpak-dir.h
index 3812b491..195d6d77 100644
--- a/common/flatpak-dir.h
+++ b/common/flatpak-dir.h
@@ -370,9 +370,17 @@ gboolean flatpak_dir_install (FlatpakDir *self,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
+char *flatpak_dir_ensure_bundle_remote (FlatpakDir *self,
+ GFile *file,
+ GBytes *extra_gpg_data,
+ char **out_ref,
+ char **out_metadata,
+ gboolean *out_created_remote,
+ GCancellable *cancellable,
+ GError **error);
gboolean flatpak_dir_install_bundle (FlatpakDir *self,
GFile *file,
- GBytes *extra_gpg_data,
+ const char *remote,
char **out_ref,
GCancellable *cancellable,
GError **error);
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
index bc55e718..5bceb13a 100644
--- a/common/flatpak-utils.c
+++ b/common/flatpak-utils.c
@@ -3878,6 +3878,8 @@ flatpak_bundle_load (GFile *file,
char **commit,
char **ref,
char **origin,
+ char **runtime_repo,
+ char **app_metadata,
guint64 *installed_size,
GBytes **gpg_keys,
GError **error)
@@ -3947,6 +3949,18 @@ flatpak_bundle_load (GFile *file,
*origin = NULL;
}
+ if (runtime_repo != NULL)
+ {
+ if (!g_variant_lookup (metadata, "runtime-repo", "s", runtime_repo))
+ *runtime_repo = NULL;
+ }
+
+ if (app_metadata != NULL)
+ {
+ if (!g_variant_lookup (metadata, "metadata", "s", app_metadata))
+ *runtime_repo = NULL;
+ }
+
if (gpg_keys != NULL)
{
g_autoptr(GVariant) gpg_value = g_variant_lookup_value (metadata, "gpg-keys",
@@ -3991,12 +4005,10 @@ flatpak_pull_from_bundle (OstreeRepo *repo,
g_autoptr(GVariant) metadata = NULL;
gboolean metadata_valid;
- metadata = flatpak_bundle_load (file, &to_checksum, NULL, NULL, NULL, NULL, error);
+ metadata = flatpak_bundle_load (file, &to_checksum, NULL, NULL, NULL, &metadata_contents, NULL, NULL, error);
if (metadata == NULL)
return FALSE;
- g_variant_lookup (metadata, "metadata", "s", &metadata_contents);
-
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
return FALSE;
diff --git a/common/flatpak-utils.h b/common/flatpak-utils.h
index 8420263e..757fe067 100644
--- a/common/flatpak-utils.h
+++ b/common/flatpak-utils.h
@@ -295,6 +295,8 @@ GVariant * flatpak_bundle_load (GFile *file,
char **commit,
char **ref,
char **origin,
+ char **runtime_repo,
+ char **app_metadata,
guint64 *installed_size,
GBytes **gpg_keys,
GError **error);
diff --git a/data/org.freedesktop.Flatpak.xml b/data/org.freedesktop.Flatpak.xml
index c50d1a5f..a17e597e 100644
--- a/data/org.freedesktop.Flatpak.xml
+++ b/data/org.freedesktop.Flatpak.xml
@@ -84,9 +84,7 @@
-
-
-
+
diff --git a/doc/flatpak-build-bundle.xml b/doc/flatpak-build-bundle.xml
index 449ea9fa..80d07e0b 100644
--- a/doc/flatpak-build-bundle.xml
+++ b/doc/flatpak-build-bundle.xml
@@ -98,6 +98,16 @@
+
+
+
+
+ The URL for a .flatpakrepo file that contains
+ the information about the repository that supplies
+ the runtimes required by the app.
+
+
+
diff --git a/lib/flatpak-bundle-ref.c b/lib/flatpak-bundle-ref.c
index c92e3371..2e72c369 100644
--- a/lib/flatpak-bundle-ref.c
+++ b/lib/flatpak-bundle-ref.c
@@ -32,6 +32,7 @@ struct _FlatpakBundleRefPrivate
{
GFile *file;
char *origin;
+ char *runtime_repo;
GBytes *metadata;
GBytes *appstream;
GBytes *icon_64;
@@ -60,6 +61,7 @@ flatpak_bundle_ref_finalize (GObject *object)
g_bytes_unref (priv->icon_64);
g_bytes_unref (priv->icon_128);
g_free (priv->origin);
+ g_free (priv->runtime_repo);
G_OBJECT_CLASS (flatpak_bundle_ref_parent_class)->finalize (object);
}
@@ -221,6 +223,25 @@ flatpak_bundle_ref_get_origin (FlatpakBundleRef *self)
return g_strdup (priv->origin);
}
+
+/**
+ * flatpak_bundle_ref_get_runtime_repo:
+ * @self: a #FlatpakBundleRef
+ *
+ * Get the runtime flatpakrepo url stored in the bundle (if any)
+ *
+ * Returns: (transfer full) : an url string, or %NULL
+ *
+ * Since: 0.8.0
+ */
+char *
+flatpak_bundle_ref_get_runtime_repo_url (FlatpakBundleRef *self)
+{
+ FlatpakBundleRefPrivate *priv = flatpak_bundle_ref_get_instance_private (self);
+
+ return g_strdup (priv->runtime_repo);
+}
+
/**
* flatpak_bundle_ref_get_installed_size:
* @self: a FlatpakBundleRef
@@ -259,13 +280,14 @@ flatpak_bundle_ref_new (GFile *file,
g_autofree char *commit = NULL;
g_autofree char *full_ref = NULL;
g_autofree char *origin = NULL;
+ g_autofree char *runtime_repo = NULL;
g_autofree char *metadata_contents = NULL;
g_autoptr(GVariant) appstream = NULL;
g_autoptr(GVariant) icon_64 = NULL;
g_autoptr(GVariant) icon_128 = NULL;
guint64 installed_size;
- metadata = flatpak_bundle_load (file, &commit, &full_ref, &origin, &installed_size,
+ metadata = flatpak_bundle_load (file, &commit, &full_ref, &origin, &runtime_repo, &metadata_contents, &installed_size,
NULL, error);
if (metadata == NULL)
return NULL;
@@ -274,9 +296,6 @@ flatpak_bundle_ref_new (GFile *file,
if (parts == NULL)
return NULL;
- if (!g_variant_lookup (metadata, "metadata", "s", &metadata_contents))
- metadata_contents = NULL;
-
if (strcmp (parts[0], "app") != 0)
kind = FLATPAK_REF_KIND_RUNTIME;
@@ -310,6 +329,7 @@ flatpak_bundle_ref_new (GFile *file,
priv->installed_size = installed_size;
priv->origin = g_steal_pointer (&origin);
+ priv->runtime_repo = g_steal_pointer (&runtime_repo);
return ref;
}
diff --git a/lib/flatpak-bundle-ref.h b/lib/flatpak-bundle-ref.h
index 623cd724..20484dbd 100644
--- a/lib/flatpak-bundle-ref.h
+++ b/lib/flatpak-bundle-ref.h
@@ -55,6 +55,7 @@ FLATPAK_EXTERN GBytes *flatpak_bundle_ref_get_icon (FlatpakBundleRef *s
int size);
FLATPAK_EXTERN char *flatpak_bundle_ref_get_origin (FlatpakBundleRef *self);
FLATPAK_EXTERN guint64 flatpak_bundle_ref_get_installed_size (FlatpakBundleRef *self);
+FLATPAK_EXTERN char *flatpak_bundle_ref_get_runtime_repo_url (FlatpakBundleRef *self);
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
diff --git a/lib/flatpak-installation.c b/lib/flatpak-installation.c
index 388efcf5..0245ff0c 100644
--- a/lib/flatpak-installation.c
+++ b/lib/flatpak-installation.c
@@ -1225,14 +1225,22 @@ flatpak_installation_install_bundle (FlatpakInstallation *self,
g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir (self);
g_autoptr(FlatpakDir) dir_clone = NULL;
g_autofree char *ref = NULL;
+ g_autofree char *remote = NULL;
FlatpakInstalledRef *result = NULL;
+ remote = flatpak_dir_ensure_bundle_remote (dir, file, NULL, &ref, NULL, NULL, cancellable, error);
+ if (remote == NULL)
+ return NULL;
+
+ /* Make sure we pick up the new config */
+ flatpak_installation_drop_caches (self, NULL, NULL);
+
/* Pull, prune, etc are not threadsafe, so we work on a copy */
dir_clone = flatpak_dir_clone (dir);
if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error))
return NULL;
- if (!flatpak_dir_install_bundle (dir_clone, file, NULL, &ref,
+ if (!flatpak_dir_install_bundle (dir_clone, file, remote, NULL,
cancellable, error))
return NULL;
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
index d47efad5..47fe0072 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -428,16 +428,15 @@ handle_install_bundle (FlatpakSystemHelper *object,
GDBusMethodInvocation *invocation,
const gchar *arg_bundle_path,
guint32 arg_flags,
- GVariant *arg_gpg_key,
+ const gchar *arg_remote,
const gchar *arg_installation)
{
g_autoptr(FlatpakDir) system = NULL;
g_autoptr(GFile) path = g_file_new_for_path (arg_bundle_path);
g_autoptr(GError) error = NULL;
- g_autoptr(GBytes) gpg_data = NULL;
g_autofree char *ref = NULL;
- g_debug ("InstallBundle %s %u %p %s", arg_bundle_path, arg_flags, arg_gpg_key, arg_installation);
+ g_debug ("InstallBundle %s %u %s %s", arg_bundle_path, arg_flags, arg_remote, arg_installation);
system = dir_get_system (arg_installation, &error);
if (system == NULL)
@@ -460,10 +459,7 @@ handle_install_bundle (FlatpakSystemHelper *object,
return TRUE;
}
- if (g_variant_get_size (arg_gpg_key) > 0)
- gpg_data = g_variant_get_data_as_bytes (arg_gpg_key);
-
- if (!flatpak_dir_install_bundle (system, path, gpg_data, &ref, NULL, &error))
+ if (!flatpak_dir_install_bundle (system, path, arg_remote, &ref, NULL, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
diff --git a/tests/test-bundle.sh b/tests/test-bundle.sh
index 3ca6364e..5cb18477 100755
--- a/tests/test-bundle.sh
+++ b/tests/test-bundle.sh
@@ -26,17 +26,22 @@ skip_without_user_xattrs
echo "1..6"
+mkdir bundles
+
setup_repo
-${FLATPAK} build-bundle repo --repo-url=file://`pwd`/repo --gpg-keys=${FL_GPG_HOMEDIR}/pubring.gpg hello.flatpak org.test.Hello
-assert_has_file hello.flatpak
+${FLATPAK} build-bundle repo --repo-url=file://`pwd`/repo --gpg-keys=${FL_GPG_HOMEDIR}/pubring.gpg bundles/hello.flatpak org.test.Hello
+assert_has_file bundles/hello.flatpak
-${FLATPAK} build-bundle repo --runtime --repo-url=file://`pwd`/repo --gpg-keys=${FL_GPG_HOMEDIR}/pubring.gpg platform.flatpak org.test.Platform
-assert_has_file platform.flatpak
+${FLATPAK} build-bundle repo --runtime --repo-url=file://`pwd`/repo --gpg-keys=${FL_GPG_HOMEDIR}/pubring.gpg bundles/platform.flatpak org.test.Platform
+assert_has_file bundles/platform.flatpak
echo "ok create bundles"
-${FLATPAK} install ${U} --bundle hello.flatpak
+${FLATPAK} install ${U} -y --bundle bundles/hello.flatpak
+
+# This should have installed the runtime dependency too
+assert_has_file $FL_DIR/repo/refs/remotes/test-repo/runtime/org.test.Platform/$ARCH/master
assert_has_file $FL_DIR/repo/refs/remotes/org.test.Hello-origin/app/org.test.Hello/$ARCH/master
APP_COMMIT=`cat $FL_DIR/repo/refs/remotes/org.test.Hello-origin/app/org.test.Hello/$ARCH/master`
@@ -80,7 +85,11 @@ assert_has_file $FL_DIR/repo/org.test.Hello-origin.trustedkeys.gpg
echo "ok install app bundle"
-${FLATPAK} install ${U} --bundle platform.flatpak
+${FLATPAK} uninstall ${U} org.test.Platform
+
+assert_not_has_file $FL_DIR/repo/refs/remotes/org.test.Platform-origin/runtime/org.test.Platform/$ARCH/master
+
+${FLATPAK} install ${U} --bundle bundles/platform.flatpak
assert_has_file $FL_DIR/repo/refs/remotes/org.test.Platform-origin/runtime/org.test.Platform/$ARCH/master
RUNTIME_COMMIT=`cat $FL_DIR/repo/refs/remotes/org.test.Platform-origin/runtime/org.test.Platform/$ARCH/master`