forked from Mirrors/flatpak-builder
Add initial version of run command
parent
3b53ae6489
commit
13261318e0
|
@ -2,6 +2,7 @@ NULL =
|
|||
|
||||
AM_CPPFLAGS = \
|
||||
-DXDG_APP_BASEDIR=\"$(datadir)/xdg-app\" \
|
||||
-DHELPER=\"$(bindir)/xdg-app-helper\" \
|
||||
$(NULL)
|
||||
|
||||
bin_PROGRAMS = \
|
||||
|
@ -17,6 +18,7 @@ xdg_app_SOURCES = \
|
|||
xdg-app-builtins-add-repo.c \
|
||||
xdg-app-builtins-install.c \
|
||||
xdg-app-builtins-update.c \
|
||||
xdg-app-builtins-run.c \
|
||||
xdg-app-dir.c \
|
||||
xdg-app-dir.h \
|
||||
xdg-app-utils.h \
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libgsystem.h"
|
||||
|
||||
#include "xdg-app-builtins.h"
|
||||
#include "xdg-app-utils.h"
|
||||
|
||||
static char *opt_arch;
|
||||
static char *opt_branch;
|
||||
static gchar **opt_rest = NULL;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Arch to install for", NULL },
|
||||
{ "branch", 0, 0, G_OPTION_ARG_STRING, &opt_branch, "Branch to run", NULL },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_rest,
|
||||
"Special option that collects any remaining arguments for us" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
usage_error (GOptionContext *context, const char *message, GError **error)
|
||||
{
|
||||
gs_free gchar *help = g_option_context_get_help (context, TRUE, NULL);
|
||||
g_printerr ("%s", help);
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, message);
|
||||
}
|
||||
|
||||
#define _gs_unref_keyfile __attribute__ ((cleanup(gs_local_keyfile_unref)))
|
||||
|
||||
gboolean
|
||||
xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **error)
|
||||
{
|
||||
GOptionContext *context;
|
||||
gboolean ret = FALSE;
|
||||
gs_unref_object XdgAppDir *user_dir = NULL;
|
||||
gs_unref_object XdgAppDir *system_dir = NULL;
|
||||
gs_unref_variant_builder GVariantBuilder *optbuilder = NULL;
|
||||
gs_unref_object GFile *deploy_base = NULL;
|
||||
gs_unref_object GFile *var = NULL;
|
||||
gs_unref_object GFile *var_tmp = NULL;
|
||||
gs_unref_object GFile *var_run = NULL;
|
||||
gs_unref_object GFile *app_deploy = NULL;
|
||||
gs_unref_object GFile *app_files = NULL;
|
||||
gs_unref_object GFile *runtime_deploy = NULL;
|
||||
gs_unref_object GFile *runtime_files = NULL;
|
||||
gs_unref_object GFile *metadata = NULL;
|
||||
gs_free char *metadata_contents = NULL;
|
||||
gs_free char *runtime = NULL;
|
||||
gs_free char *runtime_ref = NULL;
|
||||
gs_free char *app_ref = NULL;
|
||||
_gs_unref_keyfile GKeyFile *metakey = NULL;
|
||||
gs_free_error GError *my_error = NULL;
|
||||
gs_free_error GError *my_error2 = NULL;
|
||||
gs_unref_ptrarray GPtrArray *argv_array = NULL;
|
||||
gsize metadata_size;
|
||||
const char *app;
|
||||
const char *branch = "master";
|
||||
int i;
|
||||
|
||||
context = g_option_context_new ("APP COMMAND - Run an app");
|
||||
|
||||
if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (g_strv_length (opt_rest) < 2)
|
||||
{
|
||||
usage_error (context, "APP and COMMAND must be specified", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
app = opt_rest[0];
|
||||
|
||||
if (opt_branch)
|
||||
branch = opt_branch;
|
||||
|
||||
app_ref = xdg_app_build_app_ref (app, branch, opt_arch);
|
||||
|
||||
user_dir = xdg_app_dir_get_user ();
|
||||
system_dir = xdg_app_dir_get_system ();
|
||||
|
||||
app_deploy = xdg_app_dir_get_if_deployed (user_dir, app_ref, NULL, cancellable);
|
||||
if (app_deploy == NULL)
|
||||
app_deploy = xdg_app_dir_get_if_deployed (system_dir, app_ref, NULL, cancellable);
|
||||
if (app_deploy == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "App %s branch %s not installed", app, branch);
|
||||
goto out;
|
||||
}
|
||||
|
||||
metadata = g_file_get_child (app_deploy, "metadata");
|
||||
if (!g_file_load_contents (metadata, cancellable, &metadata_contents, &metadata_size, NULL, error))
|
||||
goto out;
|
||||
|
||||
metakey = g_key_file_new ();
|
||||
if (!g_key_file_load_from_data (metakey, metadata_contents, metadata_size, 0, error))
|
||||
goto out;
|
||||
|
||||
runtime = g_key_file_get_string (metakey, "Application", "runtime", error);
|
||||
if (runtime == NULL)
|
||||
goto out;
|
||||
|
||||
runtime_ref = g_build_filename ("runtime", runtime, NULL);
|
||||
|
||||
runtime_deploy = xdg_app_dir_get_if_deployed (user_dir, runtime_ref, NULL, cancellable);
|
||||
if (runtime_deploy == NULL)
|
||||
runtime_deploy = xdg_app_dir_get_if_deployed (system_dir, runtime_ref, NULL, cancellable);
|
||||
if (runtime_deploy == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Required runtime %s not installed", runtime);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xdg_app_dir_ensure_path (user_dir, cancellable, error))
|
||||
goto out;
|
||||
|
||||
var = xdg_app_dir_get_app_data (user_dir, app);
|
||||
if (!gs_file_ensure_directory (var, TRUE, cancellable, error))
|
||||
goto out;
|
||||
|
||||
var_tmp = g_file_get_child (var, "tmp");
|
||||
var_run = g_file_get_child (var, "run");
|
||||
|
||||
if (!g_file_make_symbolic_link (var_tmp, "/tmp", cancellable, &my_error) &&
|
||||
!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
{
|
||||
g_propagate_error (error, my_error);
|
||||
my_error = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_file_make_symbolic_link (var_run, "/run", cancellable, &my_error2) &&
|
||||
!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
{
|
||||
g_propagate_error (error, my_error2);
|
||||
my_error2 = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
app_files = g_file_get_child (app_deploy, "files");
|
||||
runtime_files = g_file_get_child (runtime_deploy, "files");
|
||||
|
||||
argv_array = g_ptr_array_new ();
|
||||
g_ptr_array_add (argv_array, HELPER);
|
||||
g_ptr_array_add (argv_array, "-i");
|
||||
g_ptr_array_add (argv_array, "-a");
|
||||
g_ptr_array_add (argv_array, (char *)gs_file_get_path_cached (app_files));
|
||||
g_ptr_array_add (argv_array, "-v");
|
||||
g_ptr_array_add (argv_array, (char *)gs_file_get_path_cached (var));
|
||||
g_ptr_array_add (argv_array, (char *)gs_file_get_path_cached (runtime_files));
|
||||
|
||||
for (i = 1; opt_rest[i] != NULL; i++)
|
||||
g_ptr_array_add (argv_array, opt_rest[i]);
|
||||
|
||||
g_ptr_array_add (argv_array, NULL);
|
||||
|
||||
if (!execve (HELPER, (char **)argv_array->pdata, NULL))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to start app");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Not actually reached... */
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return ret;
|
||||
}
|
|
@ -29,6 +29,7 @@ BUILTINPROTO(install_runtime);
|
|||
BUILTINPROTO(update_runtime);
|
||||
BUILTINPROTO(install_app);
|
||||
BUILTINPROTO(update_app);
|
||||
BUILTINPROTO(run);
|
||||
|
||||
#undef BUILTINPROTO
|
||||
|
||||
|
|
|
@ -388,6 +388,23 @@ xdg_app_dir_deploy (XdgAppDir *self,
|
|||
return ret;
|
||||
}
|
||||
|
||||
GFile *
|
||||
xdg_app_dir_get_if_deployed (XdgAppDir *self,
|
||||
const char *ref,
|
||||
const char *hash,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
gs_unref_object GFile *deploy_base = NULL;
|
||||
gs_unref_object GFile *deploy_dir = NULL;
|
||||
|
||||
deploy_base = xdg_app_dir_get_deploy_dir (self, ref);
|
||||
deploy_dir = g_file_get_child (deploy_base, hash ? hash : "latest");
|
||||
|
||||
if (g_file_query_file_type (deploy_dir, G_FILE_QUERY_INFO_NONE, cancellable) == G_FILE_TYPE_DIRECTORY)
|
||||
return g_object_ref (deploy_dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XdgAppDir*
|
||||
xdg_app_dir_new (GFile *path, gboolean user)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,10 @@ gboolean xdg_app_dir_is_user (XdgAppDir *self);
|
|||
GFile * xdg_app_dir_get_path (XdgAppDir *self);
|
||||
GFile * xdg_app_dir_get_deploy_dir (XdgAppDir *self,
|
||||
const char *ref);
|
||||
GFile * xdg_app_dir_get_if_deployed(XdgAppDir *self,
|
||||
const char *ref,
|
||||
const char *hash,
|
||||
GCancellable *cancellable);
|
||||
GFile * xdg_app_dir_get_app_data (XdgAppDir *self,
|
||||
const char *app);
|
||||
OstreeRepo *xdg_app_dir_get_repo (XdgAppDir *self);
|
||||
|
|
|
@ -24,6 +24,7 @@ static XdgAppCommand commands[] = {
|
|||
{ "update-runtime", xdg_app_builtin_update_runtime },
|
||||
{ "install-app", xdg_app_builtin_install_app },
|
||||
{ "update-app", xdg_app_builtin_update_app },
|
||||
{ "run", xdg_app_builtin_run },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -180,10 +181,6 @@ xdg_app_run (int argc,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (g_str_equal (argv[in], "--"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
argv[out] = argv[in];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue