forked from Mirrors/flatpak-builder
Add initial version of run command
parent
3b53ae6489
commit
13261318e0
|
@ -2,6 +2,7 @@ NULL =
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
-DXDG_APP_BASEDIR=\"$(datadir)/xdg-app\" \
|
-DXDG_APP_BASEDIR=\"$(datadir)/xdg-app\" \
|
||||||
|
-DHELPER=\"$(bindir)/xdg-app-helper\" \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
bin_PROGRAMS = \
|
bin_PROGRAMS = \
|
||||||
|
@ -17,6 +18,7 @@ xdg_app_SOURCES = \
|
||||||
xdg-app-builtins-add-repo.c \
|
xdg-app-builtins-add-repo.c \
|
||||||
xdg-app-builtins-install.c \
|
xdg-app-builtins-install.c \
|
||||||
xdg-app-builtins-update.c \
|
xdg-app-builtins-update.c \
|
||||||
|
xdg-app-builtins-run.c \
|
||||||
xdg-app-dir.c \
|
xdg-app-dir.c \
|
||||||
xdg-app-dir.h \
|
xdg-app-dir.h \
|
||||||
xdg-app-utils.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(update_runtime);
|
||||||
BUILTINPROTO(install_app);
|
BUILTINPROTO(install_app);
|
||||||
BUILTINPROTO(update_app);
|
BUILTINPROTO(update_app);
|
||||||
|
BUILTINPROTO(run);
|
||||||
|
|
||||||
#undef BUILTINPROTO
|
#undef BUILTINPROTO
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,23 @@ xdg_app_dir_deploy (XdgAppDir *self,
|
||||||
return ret;
|
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*
|
XdgAppDir*
|
||||||
xdg_app_dir_new (GFile *path, gboolean user)
|
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_path (XdgAppDir *self);
|
||||||
GFile * xdg_app_dir_get_deploy_dir (XdgAppDir *self,
|
GFile * xdg_app_dir_get_deploy_dir (XdgAppDir *self,
|
||||||
const char *ref);
|
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,
|
GFile * xdg_app_dir_get_app_data (XdgAppDir *self,
|
||||||
const char *app);
|
const char *app);
|
||||||
OstreeRepo *xdg_app_dir_get_repo (XdgAppDir *self);
|
OstreeRepo *xdg_app_dir_get_repo (XdgAppDir *self);
|
||||||
|
|
|
@ -24,6 +24,7 @@ static XdgAppCommand commands[] = {
|
||||||
{ "update-runtime", xdg_app_builtin_update_runtime },
|
{ "update-runtime", xdg_app_builtin_update_runtime },
|
||||||
{ "install-app", xdg_app_builtin_install_app },
|
{ "install-app", xdg_app_builtin_install_app },
|
||||||
{ "update-app", xdg_app_builtin_update_app },
|
{ "update-app", xdg_app_builtin_update_app },
|
||||||
|
{ "run", xdg_app_builtin_run },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,10 +181,6 @@ xdg_app_run (int argc,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (g_str_equal (argv[in], "--"))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[out] = argv[in];
|
argv[out] = argv[in];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue