xdg-app: Deprecate install/update/uninstall-app/runtime

We just have install/updata/uninstall and have --app and --runtime
options if you really want to specify the type. Otherwise we just
automatically chose the right thing.
tingping/wmclass
Alexander Larsson 2016-01-13 15:34:08 +01:00
parent f8894af8d7
commit f7a1fdaa99
10 changed files with 478 additions and 373 deletions

View File

@ -38,16 +38,18 @@ static char *opt_arch;
static char **opt_gpg_file;
static gboolean opt_no_pull;
static gboolean opt_no_deploy;
static gboolean opt_runtime;
static gboolean opt_app;
static gboolean opt_bundle;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Arch to install for", "ARCH" },
{ "no-pull", 0, 0, G_OPTION_ARG_NONE, &opt_no_pull, "Don't pull, only install from local cache", },
{ "no-deploy", 0, 0, G_OPTION_ARG_NONE, &opt_no_deploy, "Don't deploy, only download to local cache", },
{ NULL }
};
static GOptionEntry options_bundle[] = {
{ "gpg-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, "Check signatures with GPG key from FILE (- for stdin)", "FILE" },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, "Look for runtime with the specified name", },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, "Look for app with the specified name", },
{ "bundle", 0, 0, G_OPTION_ARG_NONE, &opt_bundle, "Install from local bundle file", },
{ "gpg-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, "Check bundle signatures with GPG key from FILE (- for stdin)", "FILE" },
{ NULL }
};
@ -98,184 +100,18 @@ read_gpg_data (GCancellable *cancellable,
return g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (mem_stream));
}
gboolean
xdg_app_builtin_install_runtime (int argc, char **argv, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
g_autoptr(GFile) deploy_base = NULL;
const char *repository;
const char *runtime;
const char *branch = NULL;
g_autofree char *ref = NULL;
gboolean created_deploy_base = FALSE;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("REPOSITORY RUNTIME [BRANCH] - Install a runtime");
if (!xdg_app_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
goto out;
if (argc < 3)
{
usage_error (context, "REPOSITORY and RUNTIME must be specified", error);
goto out;
}
repository = argv[1];
runtime = argv[2];
if (argc >= 4)
branch = argv[3];
ref = xdg_app_compose_ref (FALSE, runtime, branch, opt_arch, error);
if (ref == NULL)
goto out;
deploy_base = xdg_app_dir_get_deploy_dir (dir, ref);
if (g_file_query_exists (deploy_base, cancellable))
{
xdg_app_fail (error, "Runtime %s branch %s already installed", runtime, branch ? branch : "master");
goto out;
}
if (!opt_no_pull)
{
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
cancellable, error))
goto out;
}
if (!opt_no_deploy)
{
if (!xdg_app_dir_lock (dir, &lock,
cancellable, error))
goto out;
if (!g_file_make_directory_with_parents (deploy_base, cancellable, error))
goto out;
created_deploy_base = TRUE;
if (!xdg_app_dir_set_origin (dir, ref, repository, cancellable, error))
goto out;
if (!xdg_app_dir_deploy (dir, ref, NULL, cancellable, error))
goto out;
glnx_release_lock_file (&lock);
}
xdg_app_dir_cleanup_removed (dir, cancellable, NULL);
if (!xdg_app_dir_mark_changed (dir, error))
goto out;
ret = TRUE;
out:
if (created_deploy_base && !ret)
gs_shutil_rm_rf (deploy_base, cancellable, NULL);
return ret;
}
gboolean
xdg_app_builtin_install_app (int argc, char **argv, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
g_autoptr(GFile) deploy_base = NULL;
const char *repository;
const char *app;
const char *branch = NULL;
g_autofree char *ref = NULL;
gboolean created_deploy_base = FALSE;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("REPOSITORY APP [BRANCH] - Install an application");
if (!xdg_app_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
goto out;
if (argc < 3)
{
usage_error (context, "REPOSITORY and APP must be specified", error);
goto out;
}
repository = argv[1];
app = argv[2];
if (argc >= 4)
branch = argv[3];
ref = xdg_app_compose_ref (TRUE, app, branch, opt_arch, error);
if (ref == NULL)
goto out;
deploy_base = xdg_app_dir_get_deploy_dir (dir, ref);
if (g_file_query_exists (deploy_base, cancellable))
{
xdg_app_fail (error, "App %s branch %s already installed", app, branch ? branch : "master");
goto out;
}
if (!opt_no_pull)
{
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
cancellable, error))
goto out;
}
if (!opt_no_deploy)
{
if (!xdg_app_dir_lock (dir, &lock,
cancellable, error))
goto out;
if (!g_file_make_directory_with_parents (deploy_base, cancellable, error))
goto out;
created_deploy_base = TRUE;
if (!xdg_app_dir_set_origin (dir, ref, repository, cancellable, error))
goto out;
if (!xdg_app_dir_deploy (dir, ref, NULL, cancellable, error))
goto out;
if (!xdg_app_dir_make_current_ref (dir, ref, cancellable, error))
goto out;
if (!xdg_app_dir_update_exports (dir, app, cancellable, error))
goto out;
glnx_release_lock_file (&lock);
}
xdg_app_dir_cleanup_removed (dir, cancellable, NULL);
if (!xdg_app_dir_mark_changed (dir, error))
goto out;
ret = TRUE;
out:
if (created_deploy_base && !ret)
gs_shutil_rm_rf (deploy_base, cancellable, NULL);
return ret;
}
#define OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "(uayttay)"
#define OSTREE_STATIC_DELTA_FALLBACK_FORMAT "(yaytt)"
#define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")"
gboolean
xdg_app_builtin_install_bundle (int argc, char **argv, GCancellable *cancellable, GError **error)
install_bundle (XdgAppDir *dir,
GOptionContext *context,
int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
g_autoptr(GFile) deploy_base = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GFile) gpg_tmp_file = NULL;
@ -293,13 +129,8 @@ xdg_app_builtin_install_bundle (int argc, char **argv, GCancellable *cancellable
g_autoptr(GError) my_error = NULL;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("BUNDLE - Install a application or runtime from a bundle");
if (!xdg_app_option_context_parse (context, options_bundle, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, "BUNDLE must be specified", error);
return usage_error (context, "bundle filename must be specified", error);
filename = argv[1];
@ -524,3 +355,143 @@ xdg_app_builtin_install_bundle (int argc, char **argv, GCancellable *cancellable
return ret;
}
gboolean
xdg_app_builtin_install (int argc, char **argv, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
g_autoptr(GFile) deploy_base = NULL;
const char *repository;
const char *name;
const char *branch = NULL;
g_autofree char *ref = NULL;
g_autofree char *installed_ref = NULL;
gboolean is_app;
gboolean created_deploy_base = FALSE;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
g_autoptr(GError) my_error = NULL;
context = g_option_context_new ("REPOSITORY NAME [BRANCH] - Install an application or runtime");
if (!xdg_app_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (opt_bundle)
return install_bundle (dir, context, argc, argv, cancellable, error);
if (argc < 3)
return usage_error (context, "REPOSITORY and NAME must be specified", error);
repository = argv[1];
name = argv[2];
if (argc >= 4)
branch = argv[3];
if (!opt_app && !opt_runtime)
opt_app = opt_runtime = TRUE;
installed_ref = xdg_app_dir_find_installed_ref (dir,
name,
branch,
opt_arch,
opt_app, opt_runtime, &is_app,
&my_error);
if (installed_ref != NULL)
{
return xdg_app_fail (error, "%s %s, branch %s is already installed",
is_app ? "App" : "Runtime", name, branch ? branch : "master");
}
if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
ref = xdg_app_dir_find_remote_ref (dir, repository, name, branch, opt_arch,
opt_app, opt_runtime, &is_app, cancellable, error);
if (ref == NULL)
return FALSE;
deploy_base = xdg_app_dir_get_deploy_dir (dir, ref);
if (g_file_query_exists (deploy_base, cancellable))
return xdg_app_fail (error, "Ref %s already deployed", ref);
if (!opt_no_pull)
{
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
cancellable, error))
return FALSE;
}
/* After we create the deploy base we must goto out on errors */
if (!opt_no_deploy)
{
if (!xdg_app_dir_lock (dir, &lock,
cancellable, error))
goto out;
if (!g_file_make_directory_with_parents (deploy_base, cancellable, error))
goto out;
created_deploy_base = TRUE;
if (!xdg_app_dir_set_origin (dir, ref, repository, cancellable, error))
goto out;
if (!xdg_app_dir_deploy (dir, ref, NULL, cancellable, error))
goto out;
if (is_app)
{
if (!xdg_app_dir_make_current_ref (dir, ref, cancellable, error))
goto out;
if (!xdg_app_dir_update_exports (dir, name, cancellable, error))
goto out;
}
glnx_release_lock_file (&lock);
}
xdg_app_dir_cleanup_removed (dir, cancellable, NULL);
if (!xdg_app_dir_mark_changed (dir, error))
goto out;
ret = TRUE;
out:
if (created_deploy_base && !ret)
gs_shutil_rm_rf (deploy_base, cancellable, NULL);
return ret;
}
gboolean
xdg_app_builtin_install_runtime (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_runtime = TRUE;
opt_app = FALSE;
return xdg_app_builtin_install (argc, argv, cancellable, error);
}
gboolean
xdg_app_builtin_install_app (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_runtime = TRUE;
opt_app = FALSE;
return xdg_app_builtin_install (argc, argv, cancellable, error);
}
gboolean
xdg_app_builtin_install_bundle (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_bundle = TRUE;
return xdg_app_builtin_install (argc, argv, cancellable, error);
}

View File

@ -34,84 +34,20 @@
static char *opt_arch;
static gboolean opt_keep_ref;
static gboolean opt_force_remove;
static gboolean opt_runtime;
static gboolean opt_app;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Arch to uninstall", "ARCH" },
{ "keep-ref", 0, 0, G_OPTION_ARG_NONE, &opt_keep_ref, "Keep ref in local repository", NULL },
{ "force-remove", 0, 0, G_OPTION_ARG_NONE, &opt_force_remove, "Remove files even if running", NULL },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, "Look for runtime with the specified name", },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, "Look for app with the specified name", },
{ NULL }
};
gboolean
xdg_app_builtin_uninstall_runtime (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
const char *name = NULL;
const char *branch = NULL;
g_autofree char *ref = NULL;
g_autofree char *repository = NULL;
gboolean was_deployed;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("RUNTIME [BRANCH] - Uninstall a runtime");
if (!xdg_app_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, "RUNTIME must be specified", error);
name = argv[1];
if (argc > 2)
branch = argv[2];
ref = xdg_app_compose_ref (FALSE, name, branch, opt_arch, error);
if (ref == NULL)
return FALSE;
/* TODO: look for apps, require --force */
if (!xdg_app_dir_lock (dir, &lock,
cancellable, error))
return FALSE;
repository = xdg_app_dir_get_origin (dir, ref, cancellable, NULL);
g_debug ("dropping active ref");
if (!xdg_app_dir_set_active (dir, ref, NULL, cancellable, error))
return FALSE;
if (!xdg_app_dir_undeploy_all (dir, ref, opt_force_remove, &was_deployed, cancellable, error))
return FALSE;
if (!opt_keep_ref)
{
if (!xdg_app_dir_remove_ref (dir, repository, ref, cancellable, error))
return FALSE;
}
glnx_release_lock_file (&lock);
if (!opt_keep_ref)
{
if (!xdg_app_dir_prune (dir, cancellable, error))
return FALSE;
}
xdg_app_dir_cleanup_removed (dir, cancellable, NULL);
if (!xdg_app_dir_mark_changed (dir, error))
return FALSE;
if (!was_deployed)
return xdg_app_fail (error, "Nothing to uninstall");
return TRUE;
}
gboolean
xdg_app_builtin_uninstall_app (int argc, char **argv, GCancellable *cancellable, GError **error)
xdg_app_builtin_uninstall (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
@ -121,6 +57,7 @@ xdg_app_builtin_uninstall_app (int argc, char **argv, GCancellable *cancellable,
g_autofree char *repository = NULL;
g_autofree char *current_ref = NULL;
gboolean was_deployed;
gboolean is_app;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("APP [BRANCH] - Uninstall an application");
@ -135,10 +72,20 @@ xdg_app_builtin_uninstall_app (int argc, char **argv, GCancellable *cancellable,
if (argc > 2)
branch = argv[2];
ref = xdg_app_compose_ref (TRUE, name, branch, opt_arch, error);
if (!opt_app && !opt_runtime)
opt_app = opt_runtime = TRUE;
ref = xdg_app_dir_find_installed_ref (dir,
name,
branch,
opt_arch,
opt_app, opt_runtime, &is_app,
error);
if (ref == NULL)
return FALSE;
/* TODO: when removing runtimes, look for apps that use it, require --force */
if (!xdg_app_dir_lock (dir, &lock,
cancellable, error))
return FALSE;
@ -149,12 +96,15 @@ xdg_app_builtin_uninstall_app (int argc, char **argv, GCancellable *cancellable,
if (!xdg_app_dir_set_active (dir, ref, NULL, cancellable, error))
return FALSE;
current_ref = xdg_app_dir_current_ref (dir, name, cancellable);
if (current_ref != NULL && strcmp (ref, current_ref) == 0)
if (is_app)
{
g_debug ("dropping current ref");
if (!xdg_app_dir_drop_current_ref (dir, name, cancellable, error))
return FALSE;
current_ref = xdg_app_dir_current_ref (dir, name, cancellable);
if (current_ref != NULL && strcmp (ref, current_ref) == 0)
{
g_debug ("dropping current ref");
if (!xdg_app_dir_drop_current_ref (dir, name, cancellable, error))
return FALSE;
}
}
if (!xdg_app_dir_undeploy_all (dir, ref, opt_force_remove, &was_deployed, cancellable, error))
@ -184,3 +134,21 @@ xdg_app_builtin_uninstall_app (int argc, char **argv, GCancellable *cancellable,
return TRUE;
}
gboolean
xdg_app_builtin_uninstall_runtime (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_runtime = TRUE;
opt_app = FALSE;
return xdg_app_builtin_uninstall (argc, argv, cancellable, error);
}
gboolean
xdg_app_builtin_uninstall_app (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_runtime = FALSE;
opt_app = TRUE;
return xdg_app_builtin_uninstall (argc, argv, cancellable, error);
}

View File

@ -36,6 +36,8 @@ static char *opt_commit;
static gboolean opt_force_remove;
static gboolean opt_no_pull;
static gboolean opt_no_deploy;
static gboolean opt_runtime;
static gboolean opt_app;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Arch to update for", "ARCH" },
@ -43,84 +45,22 @@ static GOptionEntry options[] = {
{ "force-remove", 0, 0, G_OPTION_ARG_NONE, &opt_force_remove, "Remove old files even if running", NULL },
{ "no-pull", 0, 0, G_OPTION_ARG_NONE, &opt_no_pull, "Don't pull, only update from local cache", },
{ "no-deploy", 0, 0, G_OPTION_ARG_NONE, &opt_no_deploy, "Don't deploy, only download to local cache", },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, "Look for runtime with the specified name", },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, "Look for app with the specified name", },
{ NULL }
};
gboolean
xdg_app_builtin_update_runtime (int argc, char **argv, GCancellable *cancellable, GError **error)
xdg_app_builtin_update (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
const char *runtime;
const char *branch = NULL;
g_autofree char *ref = NULL;
g_autofree char *repository = NULL;
gboolean was_updated;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("RUNTIME [BRANCH] - Update a runtime");
if (!xdg_app_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, "RUNTIME must be specified", error);
runtime = argv[1];
if (argc >= 3)
branch = argv[2];
ref = xdg_app_compose_ref (FALSE, runtime, branch, opt_arch, error);
if (ref == NULL)
return FALSE;
repository = xdg_app_dir_get_origin (dir, ref, cancellable, error);
if (repository == NULL)
return FALSE;
if (!opt_no_pull)
{
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
cancellable, error))
return FALSE;
}
if (!opt_no_deploy)
{
if (!xdg_app_dir_lock (dir, &lock,
cancellable, error))
return FALSE;
if (!xdg_app_dir_deploy_update (dir, ref, opt_commit, &was_updated, cancellable, error))
return FALSE;
glnx_release_lock_file (&lock);
}
if (was_updated)
{
if (!xdg_app_dir_prune (dir, cancellable, error))
return FALSE;
}
xdg_app_dir_cleanup_removed (dir, cancellable, NULL);
if (!xdg_app_dir_mark_changed (dir, error))
return FALSE;
return TRUE;
}
gboolean
xdg_app_builtin_update_app (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(XdgAppDir) dir = NULL;
const char *app;
const char *name;
const char *branch = NULL;
g_autofree char *ref = NULL;
g_autofree char *repository = NULL;
gboolean was_updated;
gboolean is_app;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
context = g_option_context_new ("APP [BRANCH] - Update an application");
@ -131,11 +71,19 @@ xdg_app_builtin_update_app (int argc, char **argv, GCancellable *cancellable, GE
if (argc < 2)
return usage_error (context, "APP must be specified", error);
app = argv[1];
name = argv[1];
if (argc >= 3)
branch = argv[2];
ref = xdg_app_compose_ref (TRUE, app, branch, opt_arch, error);
if (!opt_app && !opt_runtime)
opt_app = opt_runtime = TRUE;
ref = xdg_app_dir_find_installed_ref (dir,
name,
branch,
opt_arch,
opt_app, opt_runtime, &is_app,
error);
if (ref == NULL)
return FALSE;
@ -158,26 +106,44 @@ xdg_app_builtin_update_app (int argc, char **argv, GCancellable *cancellable, GE
if (!xdg_app_dir_deploy_update (dir, ref, opt_commit, &was_updated, cancellable, error))
return FALSE;
}
if (was_updated)
{
if (!xdg_app_dir_update_exports (dir, app, cancellable, error))
return FALSE;
}
if (was_updated && is_app)
{
if (!xdg_app_dir_update_exports (dir, name, cancellable, error))
return FALSE;
}
glnx_release_lock_file (&lock);
glnx_release_lock_file (&lock);
}
if (was_updated)
{
if (!xdg_app_dir_prune (dir, cancellable, error))
return FALSE;
if (!xdg_app_dir_mark_changed (dir, error))
return FALSE;
}
xdg_app_dir_cleanup_removed (dir, cancellable, NULL);
if (!xdg_app_dir_mark_changed (dir, error))
return FALSE;
return TRUE;
}
gboolean
xdg_app_builtin_update_runtime (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_runtime = TRUE;
opt_app = FALSE;
return xdg_app_builtin_update (argc, argv, cancellable, error);
}
gboolean
xdg_app_builtin_update_app (int argc, char **argv, GCancellable *cancellable, GError **error)
{
opt_runtime = FALSE;
opt_app = TRUE;
return xdg_app_builtin_update (argc, argv, cancellable, error);
}

View File

@ -53,14 +53,11 @@ BUILTINPROTO(modify_remote);
BUILTINPROTO(delete_remote);
BUILTINPROTO(ls_remote);
BUILTINPROTO(list_remotes);
BUILTINPROTO(install_runtime);
BUILTINPROTO(update_runtime);
BUILTINPROTO(uninstall_runtime);
BUILTINPROTO(install);
BUILTINPROTO(update);
BUILTINPROTO(list_runtimes);
BUILTINPROTO(install_app);
BUILTINPROTO(make_current_app);
BUILTINPROTO(update_app);
BUILTINPROTO(uninstall_app);
BUILTINPROTO(uninstall);
BUILTINPROTO(install_bundle);
BUILTINPROTO(list_apps);
BUILTINPROTO(run);
@ -74,6 +71,14 @@ BUILTINPROTO(repo_update);
BUILTINPROTO(export_file);
BUILTINPROTO(override);
/* Deprecated */
BUILTINPROTO(install_runtime);
BUILTINPROTO(install_app);
BUILTINPROTO(update_runtime);
BUILTINPROTO(update_app);
BUILTINPROTO(uninstall_runtime);
BUILTINPROTO(uninstall_app);
#undef BUILTINPROTO
G_END_DECLS

View File

@ -38,26 +38,24 @@ static gboolean opt_user;
typedef struct {
const char *name;
gboolean (*fn) (int argc, char **argv, GCancellable *cancellable, GError **error);
gboolean deprecated;
} XdgAppCommand;
static XdgAppCommand commands[] = {
{ "run", xdg_app_builtin_run },
{ "install", xdg_app_builtin_install },
{ "update", xdg_app_builtin_update },
{ "uninstall", xdg_app_builtin_uninstall },
{ "make-current", xdg_app_builtin_make_current_app },
{ "enter", xdg_app_builtin_enter },
{ "add-remote", xdg_app_builtin_add_remote },
{ "delete-remote", xdg_app_builtin_delete_remote },
{ "modify-remote", xdg_app_builtin_modify_remote },
{ "ls-remote", xdg_app_builtin_ls_remote },
{ "list-remotes", xdg_app_builtin_list_remotes },
{ "install-runtime", xdg_app_builtin_install_runtime },
{ "update-runtime", xdg_app_builtin_update_runtime },
{ "uninstall-runtime", xdg_app_builtin_uninstall_runtime },
{ "list-runtimes", xdg_app_builtin_list_runtimes },
{ "install-app", xdg_app_builtin_install_app },
{ "update-app", xdg_app_builtin_update_app },
{ "make-app-current", xdg_app_builtin_make_current_app },
{ "uninstall-app", xdg_app_builtin_uninstall_app },
{ "list-apps", xdg_app_builtin_list_apps },
{ "install-bundle", xdg_app_builtin_install_bundle },
{ "run", xdg_app_builtin_run },
{ "enter", xdg_app_builtin_enter },
{ "override", xdg_app_builtin_override },
{ "export-file", xdg_app_builtin_export_file },
{ "build-init", xdg_app_builtin_build_init },
@ -66,6 +64,16 @@ static XdgAppCommand commands[] = {
{ "build-export", xdg_app_builtin_build_export },
{ "build-bundle", xdg_app_builtin_build_bundle },
{ "repo-update", xdg_app_builtin_repo_update },
/* Deprecated */
{ "install-runtime", xdg_app_builtin_install_runtime, TRUE },
{ "install-app", xdg_app_builtin_install_app, TRUE },
{ "update-app", xdg_app_builtin_update_app, TRUE },
{ "update-runtime", xdg_app_builtin_update_runtime, TRUE },
{ "uninstall-runtime", xdg_app_builtin_uninstall_runtime },
{ "uninstall-app", xdg_app_builtin_uninstall_app, TRUE },
{ "install-bundle", xdg_app_builtin_install_bundle, TRUE },
{ "make-app-current", xdg_app_builtin_make_current_app, TRUE },
{ NULL }
};
@ -106,7 +114,8 @@ xdg_app_option_context_new_with_commands (XdgAppCommand *commands)
while (commands->name != NULL)
{
g_string_append_printf (summary, "\n %s", commands->name);
if (!commands->deprecated)
g_string_append_printf (summary, "\n %s", commands->name);
commands++;
}
@ -202,7 +211,6 @@ usage_error (GOptionContext *context, const char *message, GError **error)
int
xdg_app_run (int argc,
char **argv,
XdgAppCommand *commands,
GError **res_error)
{
XdgAppCommand *command;
@ -315,7 +323,7 @@ main (int argc,
else
g_unsetenv ("GIO_USE_VFS");
ret = xdg_app_run (argc, argv, commands, &error);
ret = xdg_app_run (argc, argv, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
xdg_app_usage (commands, TRUE);

View File

@ -63,7 +63,6 @@ typedef struct {
GObjectClass parent_class;
} XdgAppDeployClass;
G_DEFINE_TYPE (XdgAppDir, xdg_app_dir, G_TYPE_OBJECT)
G_DEFINE_TYPE (XdgAppDeploy, xdg_app_deploy, G_TYPE_OBJECT)
@ -2160,6 +2159,137 @@ xdg_app_dir_get_if_deployed (XdgAppDir *self,
return NULL;
}
char *
xdg_app_dir_find_remote_ref (XdgAppDir *self,
const char *remote,
const char *name,
const char *opt_branch,
const char *opt_arch,
gboolean app,
gboolean runtime,
gboolean *is_app,
GCancellable *cancellable,
GError **error)
{
g_autofree char *app_ref = NULL;
g_autofree char *runtime_ref = NULL;
g_autofree char *app_ref_with_remote = NULL;
g_autofree char *runtime_ref_with_remote = NULL;
g_autoptr(GVariant) summary = NULL;
g_autoptr(GVariant) refs = NULL;
g_autoptr(GBytes) summary_bytes = NULL;
int pos;
if (!xdg_app_dir_ensure_repo (self, NULL, error))
return NULL;
if (app)
{
app_ref = xdg_app_compose_ref (TRUE, name, opt_branch, opt_arch, error);
if (app_ref == NULL)
return NULL;
app_ref_with_remote = g_strconcat (remote, ":", app_ref, NULL);
}
if (runtime)
{
runtime_ref = xdg_app_compose_ref (FALSE, name, opt_branch, opt_arch, error);
if (runtime_ref == NULL)
return NULL;
runtime_ref_with_remote = g_strconcat (remote, ":", app_ref, NULL);
}
/* First look for a local ref */
if (app_ref &&
ostree_repo_resolve_rev (self->repo, app_ref_with_remote,
FALSE, NULL, NULL))
return g_steal_pointer (&app_ref);
if (runtime_ref &&
ostree_repo_resolve_rev (self->repo, runtime_ref_with_remote,
FALSE, NULL, NULL))
return g_steal_pointer (&runtime_ref);
if (!ostree_repo_remote_fetch_summary (self->repo, remote,
&summary_bytes, NULL,
cancellable, error))
return FALSE;
if (summary_bytes == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Can't find %s in remote %s; server has no summary file", name, remote);
return NULL;
}
summary = g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, summary_bytes, FALSE);
refs = g_variant_get_child_value (summary, 0);
if (app_ref && xdg_app_variant_bsearch_str (refs, app_ref, &pos))
return g_steal_pointer (&app_ref);
if (runtime_ref && xdg_app_variant_bsearch_str (refs, runtime_ref, &pos))
return g_steal_pointer (&runtime_ref);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Can't find %s %s in remote %s", name, opt_branch ? opt_branch : "master", remote);
return NULL;
}
char *
xdg_app_dir_find_installed_ref (XdgAppDir *self,
const char *name,
const char *opt_branch,
const char *opt_arch,
gboolean app,
gboolean runtime,
gboolean *is_app,
GError **error)
{
if (app)
{
g_autofree char *app_ref = NULL;
g_autoptr(GFile) deploy_base = NULL;
app_ref = xdg_app_compose_ref (TRUE, name, opt_branch, opt_arch, error);
if (app_ref == NULL)
return NULL;
deploy_base = xdg_app_dir_get_deploy_dir (self, app_ref);
if (g_file_query_exists (deploy_base, NULL))
{
if (is_app)
*is_app = TRUE;
return g_steal_pointer (&app_ref);
}
}
if (runtime)
{
g_autofree char *runtime_ref = NULL;
g_autoptr(GFile) deploy_base = NULL;
runtime_ref = xdg_app_compose_ref (FALSE, name, opt_branch, opt_arch, error);
if (runtime_ref == NULL)
return NULL;
deploy_base = xdg_app_dir_get_deploy_dir (self, runtime_ref);
if (g_file_query_exists (deploy_base, NULL))
{
if (is_app)
*is_app = FALSE;
return g_steal_pointer (&runtime_ref);
}
}
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"%s %s not installed", name, opt_branch ? opt_branch : "master");
return NULL;
}
XdgAppDir*
xdg_app_dir_new (GFile *path, gboolean user)
{

View File

@ -76,7 +76,7 @@ XdgAppDir *xdg_app_dir_get_system (void);
XdgAppDir *xdg_app_dir_get_user (void);
gboolean xdg_app_dir_is_user (XdgAppDir *self);
GFile * xdg_app_dir_get_path (XdgAppDir *self);
GFile * xdg_app_dir_get_changed_path (XdgAppDir *self);
GFile * xdg_app_dir_get_changed_path (XdgAppDir *self);
GFile * xdg_app_dir_get_deploy_dir (XdgAppDir *self,
const char *ref);
char * xdg_app_dir_get_origin (XdgAppDir *self,
@ -94,6 +94,24 @@ GFile * xdg_app_dir_get_if_deployed (XdgAppDir *self,
const char *ref,
const char *checksum,
GCancellable *cancellable);
char * xdg_app_dir_find_remote_ref (XdgAppDir *self,
const char *remote,
const char *name,
const char *opt_branch,
const char *opt_arch,
gboolean app,
gboolean runtime,
gboolean *is_app,
GCancellable *cancellable,
GError **error);
char * xdg_app_dir_find_installed_ref (XdgAppDir *self,
const char *name,
const char *opt_branch,
const char *opt_arch,
gboolean app,
gboolean runtime,
gboolean *is_app,
GError **error);
XdgAppDeploy *xdg_app_dir_load_deployed (XdgAppDir *self,
const char *ref,
const char *checksum,

View File

@ -380,10 +380,7 @@ xdg_app_compose_ref (gboolean app,
{
if (!xdg_app_is_valid_name (name))
{
if (app)
xdg_app_fail (error, "'%s' is not a valid app name", name);
else
xdg_app_fail (error, "'%s' is not a valid runtime name", name);
xdg_app_fail (error, "'%s' is not a valid name", name);
return NULL;
}
@ -1250,3 +1247,49 @@ xdg_app_spawn (GFile *dir,
return TRUE;
}
gboolean
xdg_app_variant_bsearch_str (GVariant *array,
const char *str,
int *out_pos)
{
gsize imax, imin;
gsize imid;
gsize n;
n = g_variant_n_children (array);
if (n == 0)
return FALSE;
imax = n - 1;
imin = 0;
while (imax >= imin)
{
g_autoptr(GVariant) child = NULL;
const char *cur;
int cmp;
imid = (imin + imax) / 2;
child = g_variant_get_child_value (array, imid);
g_variant_get_child (child, 0, "&s", &cur, NULL);
cmp = strcmp (cur, str);
if (cmp < 0)
imin = imid + 1;
else if (cmp > 0)
{
if (imid == 0)
break;
imax = imid - 1;
}
else
{
*out_pos = imid;
return TRUE;
}
}
*out_pos = imid;
return FALSE;
}

View File

@ -40,6 +40,10 @@ const char * xdg_app_path_match_prefix (const char *pattern,
const char * xdg_app_get_arch (void);
gboolean xdg_app_variant_bsearch_str (GVariant *array,
const char *str,
int *out_pos);
gboolean xdg_app_has_name_prefix (const char *string,
const char *name);
gboolean xdg_app_is_valid_name (const char *string);

View File

@ -844,14 +844,6 @@ xdg_app_installation_update (XdgAppInstallation *self,
cancellable, error))
goto out;
if (!g_file_query_exists (deploy_base, cancellable))
{
g_set_error (error,
XDG_APP_ERROR, XDG_APP_ERROR_NOT_INSTALLED,
"%s branch %s is not installed", name, branch ? branch : "master");
return NULL;
}
if (!xdg_app_dir_deploy_update (dir_clone, ref, NULL, &was_updated, cancellable, error))
return FALSE;
@ -939,12 +931,12 @@ xdg_app_installation_uninstall (XdgAppInstallation *self,
/* prune, etc are not threadsafe, so we work on a copy */
dir_clone = xdg_app_dir_clone (priv->dir);
g_debug ("dropping active ref");
if (!xdg_app_dir_set_active (dir_clone, ref, NULL, cancellable, error))
return FALSE;
if (kind == XDG_APP_REF_KIND_APP)
{
g_debug ("dropping active ref");
if (!xdg_app_dir_set_active (dir_clone, ref, NULL, cancellable, error))
return FALSE;
current_ref = xdg_app_dir_current_ref (dir_clone, name, cancellable);
if (current_ref != NULL && strcmp (ref, current_ref) == 0)
{