run: Support running a runtime directly

This means you can do:
  flatpak run org.freedesktop.Sdk
to get a shell in a sandbox with that runtime, but with an
empty /app.

You can also specify a particular runtime branch and command like so:
  flatpak run --command=ls org.gnome.Platform//3.22 /
This commit is contained in:
Alexander Larsson
2016-10-19 17:30:58 +02:00
parent 944c1d58c7
commit f9c1cc40bb
2 changed files with 94 additions and 32 deletions

View File

@@ -33,6 +33,7 @@
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-error.h"
#include "flatpak-dbus.h"
#include "flatpak-run.h"
@@ -63,6 +64,7 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDeploy) app_deploy = NULL;
g_autofree char *app_ref = NULL;
g_autofree char *runtime_ref = NULL;
const char *pref;
int i;
int rest_argv_start, rest_argc;
@@ -71,6 +73,7 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
FlatpakKinds kinds;
g_autoptr(GError) local_error = NULL;
context = g_option_context_new (_("APP [args...] - Run an app"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
@@ -99,7 +102,8 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
pref = argv[rest_argv_start];
if (!flatpak_split_partial_ref_arg (pref, FLATPAK_KINDS_APP, opt_arch, opt_branch,
if (!flatpak_split_partial_ref_arg (pref, FLATPAK_KINDS_APP | FLATPAK_KINDS_RUNTIME,
opt_arch, opt_branch,
&kinds, &id, &arch, &branch, error))
return FALSE;
@@ -126,18 +130,46 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
}
}
if (app_ref == NULL)
if ((kinds & FLATPAK_KINDS_APP) != 0)
{
app_ref = flatpak_compose_ref (TRUE, id, branch, arch, error);
app_ref = flatpak_compose_ref (TRUE, id, branch, arch, &local_error);
if (app_ref == NULL)
return FALSE;
app_deploy = flatpak_find_deploy_for_ref (app_ref, cancellable, &local_error);
if (app_deploy == NULL &&
(!g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED) ||
(kinds & FLATPAK_KINDS_RUNTIME) == 0))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
/* On error, local_error is set after this point so we can reuse
this error rather than later errors, as the app-kind error
is more likely interesting. */
}
app_deploy = flatpak_find_deploy_for_ref (app_ref, cancellable, error);
if (app_deploy == NULL)
return FALSE;
{
g_autoptr(FlatpakDeploy) runtime_deploy = NULL;
if (!flatpak_run_app (app_ref, app_deploy,
runtime_ref = flatpak_compose_ref (FALSE, id, branch, arch, error);
if (runtime_ref == NULL)
return FALSE;
runtime_deploy = flatpak_find_deploy_for_ref (runtime_ref, cancellable, NULL);
if (runtime_deploy == NULL)
{
/* Report old app-kind error, as its more likely right */
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
/* Clear app-kind error */
g_clear_error (&local_error);
}
if (!flatpak_run_app (app_deploy ? app_ref : runtime_ref,
app_deploy,
arg_context,
opt_runtime,
opt_runtime_version,

View File

@@ -2580,7 +2580,8 @@ compute_permissions (GKeyFile *app_metadata,
if (!flatpak_context_load_metadata (app_context, runtime_metadata, error))
return NULL;
if (!flatpak_context_load_metadata (app_context, app_metadata, error))
if (app_metadata != NULL &&
!flatpak_context_load_metadata (app_context, app_metadata, error))
return NULL;
return g_steal_pointer (&app_context);
@@ -2601,10 +2602,10 @@ flatpak_run_add_app_info_args (GPtrArray *argv_array,
g_autofree char *tmp_path = NULL;
int fd;
g_autoptr(GKeyFile) keyfile = NULL;
g_autofree char *app_path = NULL;
g_autofree char *runtime_path = NULL;
g_autofree char *fd_str = NULL;
g_autofree char *old_dest = g_strdup_printf ("/run/user/%d/flatpak-info", getuid ());
const char *group;
fd = g_file_open_tmp ("flatpak-context-XXXXXX", &tmp_path, NULL);
if (fd < 0)
@@ -2619,11 +2620,19 @@ flatpak_run_add_app_info_args (GPtrArray *argv_array,
keyfile = g_key_file_new ();
g_key_file_set_string (keyfile, "Application", "name", app_id);
g_key_file_set_string (keyfile, "Application", "runtime", runtime_ref);
if (app_files)
group = "Application";
else
group = "Runtime";
app_path = g_file_get_path (app_files);
g_key_file_set_string (keyfile, "Instance", "app-path", app_path);
g_key_file_set_string (keyfile, group, "name", app_id);
g_key_file_set_string (keyfile, group, "runtime", runtime_ref);
if (app_files)
{
g_autofree char *app_path = g_file_get_path (app_files);
g_key_file_set_string (keyfile, "Instance", "app-path", app_path);
}
runtime_path = g_file_get_path (runtime_files);
g_key_file_set_string (keyfile, "Instance", "runtime-path", runtime_path);
if (app_branch != NULL)
@@ -3449,8 +3458,6 @@ flatpak_run_app (const char *app_ref,
if (app_ref_parts == NULL)
return FALSE;
metakey = flatpak_deploy_get_metadata (app_deploy);
argv_array = g_ptr_array_new_with_free_func (g_free);
fd_array = g_array_new (FALSE, TRUE, sizeof (int));
g_array_set_clear_func (fd_array, clear_fd);
@@ -3458,13 +3465,22 @@ flatpak_run_app (const char *app_ref,
session_bus_proxy_argv = g_ptr_array_new_with_free_func (g_free);
system_bus_proxy_argv = g_ptr_array_new_with_free_func (g_free);
default_runtime = g_key_file_get_string (metakey, "Application",
(flags & FLATPAK_RUN_FLAG_DEVEL) != 0 ? "sdk" : "runtime",
&my_error);
if (my_error)
if (app_deploy == NULL)
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
g_assert (g_str_has_prefix (app_ref, "runtime/"));
default_runtime = g_strdup (app_ref + strlen ("runtime/"));
}
else
{
metakey = flatpak_deploy_get_metadata (app_deploy);
default_runtime = g_key_file_get_string (metakey, "Application",
(flags & FLATPAK_RUN_FLAG_DEVEL) != 0 ? "sdk" : "runtime",
&my_error);
if (my_error)
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
}
runtime_parts = g_strsplit (default_runtime, "/", 0);
@@ -3509,30 +3525,44 @@ flatpak_run_app (const char *app_ref,
if (app_context == NULL)
return FALSE;
overrides = flatpak_deploy_get_overrides (app_deploy);
flatpak_context_merge (app_context, overrides);
if (app_deploy != NULL)
{
overrides = flatpak_deploy_get_overrides (app_deploy);
flatpak_context_merge (app_context, overrides);
}
if (extra_context)
flatpak_context_merge (app_context, extra_context);
runtime_files = flatpak_deploy_get_files (runtime_deploy);
app_files = flatpak_deploy_get_files (app_deploy);
if ((app_id_dir = flatpak_ensure_data_dir (app_ref_parts[1], cancellable, error)) == NULL)
return FALSE;
if (app_deploy != NULL)
{
app_files = flatpak_deploy_get_files (app_deploy);
if ((app_id_dir = flatpak_ensure_data_dir (app_ref_parts[1], cancellable, error)) == NULL)
return FALSE;
}
envp = g_get_environ ();
envp = flatpak_run_apply_env_default (envp);
envp = flatpak_run_apply_env_vars (envp, app_context);
envp = flatpak_run_apply_env_appid (envp, app_id_dir);
if (app_id_dir != NULL)
envp = flatpak_run_apply_env_appid (envp, app_id_dir);
add_args (argv_array,
"--ro-bind", flatpak_file_get_path_cached (runtime_files), "/usr",
"--lock-file", "/usr/.ref",
"--ro-bind", flatpak_file_get_path_cached (app_files), "/app",
"--lock-file", "/app/.ref",
NULL);
if (app_files != NULL)
add_args (argv_array,
"--ro-bind", flatpak_file_get_path_cached (app_files), "/app",
"--lock-file", "/app/.ref",
NULL);
else
add_args (argv_array,
"--dir", "/app",
NULL);
if (app_context->features & FLATPAK_CONTEXT_FEATURE_DEVEL)
flags |= FLATPAK_RUN_FLAG_DEVEL;
@@ -3546,7 +3576,8 @@ flatpak_run_app (const char *app_ref,
runtime_ref, app_context, &app_info_path, error))
return FALSE;
if (!flatpak_run_add_extension_args (argv_array, metakey, app_ref, cancellable, error))
if (metakey != NULL &&
!flatpak_run_add_extension_args (argv_array, metakey, app_ref, cancellable, error))
return FALSE;
if (!flatpak_run_add_extension_args (argv_array, runtime_metakey, runtime_ref, cancellable, error))
@@ -3592,7 +3623,7 @@ flatpak_run_app (const char *app_ref,
{
command = custom_command;
}
else
else if (metakey)
{
default_command = g_key_file_get_string (metakey, "Application", "command", &my_error);
if (my_error)
@@ -3600,7 +3631,6 @@ flatpak_run_app (const char *app_ref,
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
command = default_command;
}