mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-26 00:28:34 -05:00
Replace bash completion shell script with C-based version
This doesn't do everything yet, but its got the basics covered.
This commit is contained in:
@@ -165,3 +165,102 @@ flatpak_builtin_info (int argc, char **argv, GCancellable *cancellable, GError *
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_complete_info (FlatpakCompletion *completion)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(FlatpakDir) user_dir = NULL;
|
||||
g_autoptr(FlatpakDir) system_dir = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) refs = NULL;
|
||||
int i;
|
||||
|
||||
context = g_option_context_new ("");
|
||||
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
if (!opt_app && !opt_runtime)
|
||||
opt_app = opt_runtime = TRUE;
|
||||
|
||||
if (!opt_user && !opt_system)
|
||||
opt_user = opt_system = TRUE;
|
||||
|
||||
if (opt_user)
|
||||
user_dir = flatpak_dir_get_user ();
|
||||
|
||||
if (opt_system)
|
||||
system_dir = flatpak_dir_get_system ();
|
||||
|
||||
switch (completion->argc)
|
||||
{
|
||||
case 0:
|
||||
case 1: /* NAME */
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, options);
|
||||
|
||||
if (user_dir)
|
||||
{
|
||||
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find local refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (system_dir)
|
||||
{
|
||||
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, NULL, NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find local refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* BRANCH */
|
||||
if (user_dir)
|
||||
{
|
||||
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, completion->argv[1], NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find remote refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[3]);
|
||||
}
|
||||
}
|
||||
if (user_dir)
|
||||
{
|
||||
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, completion->argv[1], NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find remote refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[3]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ static GOptionEntry options[] = {
|
||||
{ "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" },
|
||||
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only install this subpath", "path" },
|
||||
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only install this subpath", "PATH" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -252,3 +252,76 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_complete_install (FlatpakCompletion *completion)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(FlatpakDir) dir = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) refs = NULL;
|
||||
int i;
|
||||
|
||||
context = g_option_context_new ("");
|
||||
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
if (!opt_app && !opt_runtime)
|
||||
opt_app = opt_runtime = TRUE;
|
||||
|
||||
flatpak_completion_debug ("install argc %d", completion->argc);
|
||||
|
||||
switch (completion->argc)
|
||||
{
|
||||
case 0:
|
||||
case 1: /* REMOTE */
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, options);
|
||||
flatpak_complete_options (completion, user_entries);
|
||||
|
||||
{
|
||||
g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL);
|
||||
if (remotes == NULL)
|
||||
return FALSE;
|
||||
for (i = 0; remotes[i] != NULL; i++)
|
||||
flatpak_complete_word (completion, "%s ", remotes[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2: /* Name */
|
||||
refs = flatpak_dir_find_remote_refs (dir, completion->argv[1], NULL, NULL,
|
||||
opt_arch, opt_app, opt_runtime,
|
||||
NULL, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find remote refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[1]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3: /* Branch */
|
||||
refs = flatpak_dir_find_remote_refs (dir, completion->argv[1], completion->argv[2], NULL,
|
||||
opt_arch, opt_app, opt_runtime,
|
||||
NULL, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find remote refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[3]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -262,3 +262,11 @@ flatpak_builtin_list (int argc, char **argv, GCancellable *cancellable, GError *
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_complete_list (FlatpakCompletion *completion)
|
||||
{
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, options);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -135,3 +135,65 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
/* Not actually reached... */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_complete_run (FlatpakCompletion *completion)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(FlatpakDir) user_dir = NULL;
|
||||
g_autoptr(FlatpakDir) system_dir = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
int i;
|
||||
g_autoptr(FlatpakContext) arg_context = NULL;
|
||||
|
||||
context = g_option_context_new ("");
|
||||
|
||||
arg_context = flatpak_context_new ();
|
||||
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
|
||||
|
||||
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
|
||||
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
switch (completion->argc)
|
||||
{
|
||||
case 0:
|
||||
case 1: /* NAME */
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, options);
|
||||
flatpak_context_complete (arg_context, completion);
|
||||
|
||||
user_dir = flatpak_dir_get_user ();
|
||||
{
|
||||
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, opt_arch,
|
||||
TRUE, FALSE, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find local refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
system_dir = flatpak_dir_get_system ();
|
||||
{
|
||||
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, NULL, NULL, opt_arch,
|
||||
TRUE, FALSE, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find local refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ flatpak_builtin_uninstall (int argc, char **argv, GCancellable *cancellable, GEr
|
||||
gboolean is_app;
|
||||
FlatpakHelperUninstallFlags flags = 0;
|
||||
|
||||
context = g_option_context_new ("APP [BRANCH] - Uninstall an application");
|
||||
context = g_option_context_new ("NAME [BRANCH] - Uninstall an application");
|
||||
|
||||
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
|
||||
return FALSE;
|
||||
@@ -94,3 +94,59 @@ flatpak_builtin_uninstall (int argc, char **argv, GCancellable *cancellable, GEr
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_complete_uninstall (FlatpakCompletion *completion)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(FlatpakDir) dir = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) refs = NULL;
|
||||
int i;
|
||||
|
||||
context = g_option_context_new ("");
|
||||
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
if (!opt_app && !opt_runtime)
|
||||
opt_app = opt_runtime = TRUE;
|
||||
|
||||
switch (completion->argc)
|
||||
{
|
||||
case 0:
|
||||
case 1: /* NAME */
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, options);
|
||||
flatpak_complete_options (completion, user_entries);
|
||||
|
||||
refs = flatpak_dir_find_installed_refs (dir, NULL, NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find local refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* Branch */
|
||||
refs = flatpak_dir_find_installed_refs (dir, completion->argv[1], NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find remote refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ static GOptionEntry options[] = {
|
||||
{ "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", },
|
||||
{ "appstream", 0, 0, G_OPTION_ARG_NONE, &opt_appstream, "Update appstream for remote", },
|
||||
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only update this subpath", "path" },
|
||||
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only update this subpath", "PATH" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -107,7 +107,6 @@ flatpak_builtin_update (int argc,
|
||||
g_autoptr(FlatpakDir) dir = NULL;
|
||||
const char *name = NULL;
|
||||
const char *branch = NULL;
|
||||
const char *arch = NULL;
|
||||
gboolean failed = FALSE;
|
||||
int i;
|
||||
|
||||
@@ -125,9 +124,7 @@ flatpak_builtin_update (int argc,
|
||||
branch = argv[2];
|
||||
|
||||
if (opt_arch == NULL)
|
||||
arch = flatpak_get_arch ();
|
||||
else
|
||||
arch = opt_arch;
|
||||
opt_arch = (char *)flatpak_get_arch ();
|
||||
|
||||
if (!opt_app && !opt_runtime)
|
||||
opt_app = opt_runtime = TRUE;
|
||||
@@ -155,7 +152,7 @@ flatpak_builtin_update (int argc,
|
||||
if (name != NULL && strcmp (parts[1], name) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp (parts[2], arch) != 0)
|
||||
if (strcmp (parts[2], opt_arch) != 0)
|
||||
continue;
|
||||
|
||||
g_print ("Updating application %s %s\n", parts[1], parts[3]);
|
||||
@@ -186,7 +183,7 @@ flatpak_builtin_update (int argc,
|
||||
if (name != NULL && strcmp (parts[1], name) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp (parts[2], arch) != 0)
|
||||
if (strcmp (parts[2], opt_arch) != 0)
|
||||
continue;
|
||||
|
||||
g_print ("Updating runtime %s %s\n", parts[1], parts[3]);
|
||||
@@ -207,7 +204,7 @@ flatpak_builtin_update (int argc,
|
||||
ref = flatpak_dir_find_installed_ref (dir,
|
||||
name,
|
||||
branch,
|
||||
arch,
|
||||
opt_arch,
|
||||
opt_app, opt_runtime, &is_app,
|
||||
error);
|
||||
if (ref == NULL)
|
||||
@@ -226,3 +223,59 @@ flatpak_builtin_update (int argc,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_complete_update (FlatpakCompletion *completion)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(FlatpakDir) dir = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_auto(GStrv) refs = NULL;
|
||||
int i;
|
||||
|
||||
context = g_option_context_new ("");
|
||||
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
if (!opt_app && !opt_runtime)
|
||||
opt_app = opt_runtime = TRUE;
|
||||
|
||||
switch (completion->argc)
|
||||
{
|
||||
case 0:
|
||||
case 1: /* NAME */
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, options);
|
||||
flatpak_complete_options (completion, user_entries);
|
||||
|
||||
refs = flatpak_dir_find_installed_refs (dir, NULL, NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find local refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s \n", parts[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* Branch */
|
||||
refs = flatpak_dir_find_installed_refs (dir, completion->argv[1], NULL, opt_arch,
|
||||
opt_app, opt_runtime, &error);
|
||||
if (refs == NULL)
|
||||
flatpak_completion_debug ("find remote refs error: %s", error->message);
|
||||
for (i = 0; refs != NULL && refs[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
|
||||
if (parts)
|
||||
flatpak_complete_word (completion, "%s ", parts[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <ostree.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "flatpak-utils.h"
|
||||
#include "flatpak-dir.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -42,36 +43,42 @@ gboolean flatpak_option_context_parse (GOptionContext *context,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
extern GOptionEntry user_entries[];
|
||||
extern GOptionEntry global_entries[];
|
||||
|
||||
gboolean usage_error (GOptionContext *context,
|
||||
const char *message,
|
||||
GError **error);
|
||||
|
||||
#define BUILTINPROTO(name) gboolean flatpak_builtin_ ## name (int argc, char **argv, GCancellable * cancellable, GError * *error)
|
||||
#define BUILTINPROTO(name) \
|
||||
gboolean flatpak_builtin_ ## name (int argc, char **argv, GCancellable * cancellable, GError * *error); \
|
||||
gboolean flatpak_complete_ ## name (FlatpakCompletion *completion);
|
||||
|
||||
BUILTINPROTO (add_remote);
|
||||
BUILTINPROTO (modify_remote);
|
||||
BUILTINPROTO (delete_remote);
|
||||
BUILTINPROTO (ls_remote);
|
||||
BUILTINPROTO (list_remotes);
|
||||
BUILTINPROTO (install);
|
||||
BUILTINPROTO (update);
|
||||
BUILTINPROTO (make_current_app);
|
||||
BUILTINPROTO (uninstall);
|
||||
BUILTINPROTO (install_bundle);
|
||||
BUILTINPROTO (list);
|
||||
BUILTINPROTO (info);
|
||||
BUILTINPROTO (run);
|
||||
BUILTINPROTO (enter);
|
||||
BUILTINPROTO (build_init);
|
||||
BUILTINPROTO (build);
|
||||
BUILTINPROTO (build_finish);
|
||||
BUILTINPROTO (build_sign);
|
||||
BUILTINPROTO (build_export);
|
||||
BUILTINPROTO (build_bundle);
|
||||
BUILTINPROTO (build_import);
|
||||
BUILTINPROTO (build_update_repo);
|
||||
BUILTINPROTO (export_file);
|
||||
BUILTINPROTO (override);
|
||||
|
||||
BUILTINPROTO (add_remote)
|
||||
BUILTINPROTO (modify_remote)
|
||||
BUILTINPROTO (delete_remote)
|
||||
BUILTINPROTO (ls_remote)
|
||||
BUILTINPROTO (list_remotes)
|
||||
BUILTINPROTO (install)
|
||||
BUILTINPROTO (update)
|
||||
BUILTINPROTO (make_current_app)
|
||||
BUILTINPROTO (uninstall)
|
||||
BUILTINPROTO (install_bundle)
|
||||
BUILTINPROTO (list)
|
||||
BUILTINPROTO (info)
|
||||
BUILTINPROTO (run)
|
||||
BUILTINPROTO (enter)
|
||||
BUILTINPROTO (build_init)
|
||||
BUILTINPROTO (build)
|
||||
BUILTINPROTO (build_finish)
|
||||
BUILTINPROTO (build_sign)
|
||||
BUILTINPROTO (build_export)
|
||||
BUILTINPROTO (build_bundle)
|
||||
BUILTINPROTO (build_import)
|
||||
BUILTINPROTO (build_update_repo)
|
||||
BUILTINPROTO (export_file)
|
||||
BUILTINPROTO (override)
|
||||
|
||||
#undef BUILTINPROTO
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "libglnx/libglnx.h"
|
||||
@@ -40,57 +41,62 @@ static gboolean opt_user;
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
const char *description;
|
||||
gboolean (*fn)(int argc,
|
||||
char **argv,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
const char *description;
|
||||
gboolean (*complete)(FlatpakCompletion *completion);
|
||||
gboolean deprecated;
|
||||
} FlatpakCommand;
|
||||
|
||||
static FlatpakCommand commands[] = {
|
||||
{ " Manage installed apps and runtimes" },
|
||||
{ "install", flatpak_builtin_install, "Install an application or runtime from a remote"},
|
||||
{ "update", flatpak_builtin_update, "Update an installed application or runtime"},
|
||||
{ "uninstall", flatpak_builtin_uninstall, "Uninstall an installed application or runtime" },
|
||||
{ "list", flatpak_builtin_list, "List installed apps and/or runtimes" },
|
||||
{ "info", flatpak_builtin_info, "Show info for installed app or runtime" },
|
||||
{ "install", "Install an application or runtime from a remote", flatpak_builtin_install, flatpak_complete_install },
|
||||
{ "update", "Update an installed application or runtime", flatpak_builtin_update, flatpak_complete_update },
|
||||
{ "uninstall", "Uninstall an installed application or runtime", flatpak_builtin_uninstall, flatpak_complete_uninstall },
|
||||
{ "list", "List installed apps and/or runtimes", flatpak_builtin_list, flatpak_complete_list },
|
||||
{ "info", "Show info for installed app or runtime", flatpak_builtin_info, flatpak_complete_info },
|
||||
|
||||
{ "\n Running applications" },
|
||||
{ "run", flatpak_builtin_run, "Run an application" },
|
||||
{ "override", flatpak_builtin_override, "Override permissions for an application" },
|
||||
{ "export-file", flatpak_builtin_export_file, "Grant an application access to a specific file" },
|
||||
{ "make-current", flatpak_builtin_make_current_app, "Specify default version to run" },
|
||||
{ "enter", flatpak_builtin_enter, "Enter the namespace of a running application" },
|
||||
{ "run", "Run an application", flatpak_builtin_run, flatpak_complete_run },
|
||||
{ "override", "Override permissions for an application", flatpak_builtin_override },
|
||||
{ "export-file", "Grant an application access to a specific file", flatpak_builtin_export_file},
|
||||
{ "make-current", "Specify default version to run", flatpak_builtin_make_current_app},
|
||||
{ "enter", "Enter the namespace of a running application", flatpak_builtin_enter },
|
||||
|
||||
{ "\n Manage remote repositories" },
|
||||
{ "remote-add", flatpak_builtin_add_remote, "Add a new remote repository (by URL)" },
|
||||
{ "remote-modify", flatpak_builtin_modify_remote, "Modify properties of a configured remote" },
|
||||
{ "remote-delete", flatpak_builtin_delete_remote, "Delete a configured remote" },
|
||||
{ "remote-list", flatpak_builtin_list_remotes, "List all configured remotes" },
|
||||
{ "remote-ls", flatpak_builtin_ls_remote, "List contents of a configured remote" },
|
||||
{ "remote-add", "Add a new remote repository (by URL)", flatpak_builtin_add_remote },
|
||||
{ "remote-modify", "Modify properties of a configured remote", flatpak_builtin_modify_remote},
|
||||
{ "remote-delete", "Delete a configured remote", flatpak_builtin_delete_remote},
|
||||
{ "remote-list", "List all configured remotes", flatpak_builtin_list_remotes},
|
||||
{ "remote-ls", "List contents of a configured remote", flatpak_builtin_ls_remote },
|
||||
|
||||
{ "\n Build applications" },
|
||||
{ "build-init", flatpak_builtin_build_init, "Initialize a directory for building" },
|
||||
{ "build", flatpak_builtin_build, "Run a build command inside the build dir" },
|
||||
{ "build-finish", flatpak_builtin_build_finish, "Finish a build dir for export" },
|
||||
{ "build-export", flatpak_builtin_build_export, "Export a build dir to a repository" },
|
||||
{ "build-bundle", flatpak_builtin_build_bundle, "Create a bundle file from a build directory" },
|
||||
{ "build-import-bundle", flatpak_builtin_build_import, "Import a bundle file" },
|
||||
{ "build-sign", flatpak_builtin_build_sign, "Sign an application or runtime" },
|
||||
{ "build-update-repo", flatpak_builtin_build_update_repo, "Update the summary file in a repository" },
|
||||
{ "build-init", "Initialize a directory for building", flatpak_builtin_build_init },
|
||||
{ "build", "Run a build command inside the build dir", flatpak_builtin_build },
|
||||
{ "build-finish", "Finish a build dir for export", flatpak_builtin_build_finish },
|
||||
{ "build-export", "Export a build dir to a repository", flatpak_builtin_build_export },
|
||||
{ "build-bundle", "Create a bundle file from a build directory", flatpak_builtin_build_bundle },
|
||||
{ "build-import-bundle", "Import a bundle file", flatpak_builtin_build_import },
|
||||
{ "build-sign", "Sign an application or runtime", flatpak_builtin_build_sign },
|
||||
{ "build-update-repo", "Update the summary file in a repository", flatpak_builtin_build_update_repo },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GOptionEntry global_entries[] = {
|
||||
GOptionEntry global_entries[] = {
|
||||
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information during command processing", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GOptionEntry empty_entries[] = {
|
||||
{ "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print version information and exit", NULL },
|
||||
{ "default-arch", 0, 0, G_OPTION_ARG_NONE, &opt_default_arch, "Print default arch and exit", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GOptionEntry user_entries[] = {
|
||||
GOptionEntry user_entries[] = {
|
||||
{ "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, "Work on user installations", NULL },
|
||||
{ "system", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_user, "Work on system-wide installations (default)", NULL },
|
||||
{ NULL }
|
||||
@@ -233,17 +239,12 @@ usage_error (GOptionContext *context, const char *message, GError **error)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
flatpak_run (int argc,
|
||||
char **argv,
|
||||
GError **res_error)
|
||||
FlatpakCommand *
|
||||
extract_command (int *argc,
|
||||
char **argv)
|
||||
{
|
||||
FlatpakCommand *command;
|
||||
GError *error = NULL;
|
||||
GCancellable *cancellable = NULL;
|
||||
const char *command_name = NULL;
|
||||
g_autofree char *prgname = NULL;
|
||||
gboolean success = FALSE;
|
||||
int in, out;
|
||||
|
||||
/*
|
||||
@@ -251,7 +252,7 @@ flatpak_run (int argc,
|
||||
* necessary, in order to pass relevant options through
|
||||
* to the commands, but also have them take effect globally.
|
||||
*/
|
||||
for (in = 1, out = 1; in < argc; in++, out++)
|
||||
for (in = 1, out = 1; in < *argc; in++, out++)
|
||||
{
|
||||
/* The non-option is the command, take it out of the arguments */
|
||||
if (argv[in][0] != '-')
|
||||
@@ -267,7 +268,8 @@ flatpak_run (int argc,
|
||||
argv[out] = argv[in];
|
||||
}
|
||||
|
||||
argc = out;
|
||||
*argc = out;
|
||||
argv[out] = NULL;
|
||||
|
||||
command = commands;
|
||||
while (command->name)
|
||||
@@ -278,31 +280,47 @@ flatpak_run (int argc,
|
||||
command++;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
flatpak_run (int argc,
|
||||
char **argv,
|
||||
GError **res_error)
|
||||
{
|
||||
FlatpakCommand *command;
|
||||
GError *error = NULL;
|
||||
GCancellable *cancellable = NULL;
|
||||
const char *command_name = NULL;
|
||||
g_autofree char *prgname = NULL;
|
||||
gboolean success = FALSE;
|
||||
|
||||
command = extract_command (&argc, argv);
|
||||
|
||||
if (!command->fn)
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
GOptionContext *context;
|
||||
g_autofree char *help;
|
||||
|
||||
context = flatpak_option_context_new_with_commands (commands);
|
||||
|
||||
if (command_name != NULL)
|
||||
/* This will not return for some options (e.g. --version). */
|
||||
if (flatpak_option_context_parse (context, empty_entries, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, &error))
|
||||
{
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Unknown command '%s'", command_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This will not return for some options (e.g. --version). */
|
||||
if (flatpak_option_context_parse (context, NULL, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, &error))
|
||||
{
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No command specified");
|
||||
}
|
||||
if (command_name == NULL)
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No command specified");
|
||||
else
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Unknown command '%s'", command_name);
|
||||
}
|
||||
|
||||
help = g_option_context_get_help (context, FALSE, NULL);
|
||||
g_printerr ("%s", help);
|
||||
|
||||
g_option_context_free (context);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -324,6 +342,48 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
complete (int argc,
|
||||
char **argv)
|
||||
{
|
||||
FlatpakCommand *command;
|
||||
g_autofree char *initial_completion_line = NULL;
|
||||
FlatpakCompletion *completion;
|
||||
|
||||
completion = flatpak_completion_new (argv[2], argv[3], argv[4]);
|
||||
if (completion == NULL)
|
||||
return 1;
|
||||
|
||||
command = extract_command (&completion->argc, completion->argv);
|
||||
flatpak_completion_debug ("command=%p '%s'", command->fn, command->name);
|
||||
|
||||
if (!command->fn)
|
||||
{
|
||||
FlatpakCommand *c = commands;
|
||||
while (c->name)
|
||||
{
|
||||
if (c->fn != NULL)
|
||||
flatpak_complete_word (completion, "%s ", c->name);
|
||||
c++;
|
||||
}
|
||||
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
flatpak_complete_options (completion, empty_entries);
|
||||
flatpak_complete_options (completion, user_entries);
|
||||
}
|
||||
else if (command->complete)
|
||||
{
|
||||
if (!command->complete (completion))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
flatpak_complete_options (completion, global_entries);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
@@ -347,6 +407,9 @@ main (int argc,
|
||||
else
|
||||
g_unsetenv ("GIO_USE_VFS");
|
||||
|
||||
if (argc >= 4 && strcmp (argv[1], "complete") == 0)
|
||||
return complete (argc, argv);
|
||||
|
||||
flatpak_migrate_from_xdg_app ();
|
||||
|
||||
ret = flatpak_run (argc, argv, &error);
|
||||
|
||||
@@ -3859,23 +3859,23 @@ flatpak_dir_remote_list_refs (FlatpakDir *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char *
|
||||
find_matching_ref (GHashTable *refs,
|
||||
const char *name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GError **error)
|
||||
GPtrArray *
|
||||
find_matching_refs (GHashTable *refs,
|
||||
const char *opt_name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) matched_refs = NULL;
|
||||
const char *arch = NULL;
|
||||
GHashTableIter hash_iter;
|
||||
gpointer key;
|
||||
|
||||
if (!flatpak_is_valid_name (name))
|
||||
if (opt_name && !flatpak_is_valid_name (opt_name))
|
||||
{
|
||||
flatpak_fail (error, "'%s' is not a valid name", name);
|
||||
flatpak_fail (error, "'%s' is not a valid name", opt_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3915,8 +3915,10 @@ find_matching_ref (GHashTable *refs,
|
||||
if (parts == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp (parts[1], name) != 0 ||
|
||||
strcmp (parts[2], arch) != 0)
|
||||
if (opt_name != NULL && strcmp (opt_name, parts[1]) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp (parts[2], arch) != 0)
|
||||
continue;
|
||||
|
||||
if (opt_branch != NULL && strcmp (opt_branch, parts[3]) != 0)
|
||||
@@ -3925,6 +3927,26 @@ find_matching_ref (GHashTable *refs,
|
||||
g_ptr_array_add (matched_refs, g_steal_pointer (&ref));
|
||||
}
|
||||
|
||||
return g_steal_pointer (&matched_refs);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
find_matching_ref (GHashTable *refs,
|
||||
const char *name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) matched_refs = NULL;
|
||||
|
||||
matched_refs = find_matching_refs (refs, name, opt_branch, opt_arch,
|
||||
app, runtime, error);
|
||||
if (matched_refs == NULL)
|
||||
return NULL;
|
||||
|
||||
if (matched_refs->len == 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||
@@ -3953,6 +3975,41 @@ find_matching_ref (GHashTable *refs,
|
||||
return g_strdup (g_ptr_array_index (matched_refs, 0));
|
||||
}
|
||||
|
||||
char **
|
||||
flatpak_dir_find_remote_refs (FlatpakDir *self,
|
||||
const char *remote,
|
||||
const char *name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *refspec_prefix = NULL;
|
||||
g_autofree char *remote_ref = NULL;
|
||||
g_autoptr(GHashTable) remote_refs = NULL;
|
||||
g_autoptr(GError) my_error = NULL;
|
||||
GPtrArray *matched_refs;
|
||||
|
||||
if (!flatpak_dir_ensure_repo (self, NULL, error))
|
||||
return NULL;
|
||||
|
||||
refspec_prefix = g_strconcat (remote, ":.", NULL);
|
||||
|
||||
if (!flatpak_dir_remote_list_refs (self, remote,
|
||||
&remote_refs, cancellable, error))
|
||||
return NULL;
|
||||
|
||||
matched_refs = find_matching_refs (remote_refs, name, opt_branch,
|
||||
opt_arch, app, runtime, error);
|
||||
if (matched_refs == NULL)
|
||||
return NULL;
|
||||
|
||||
g_ptr_array_add (matched_refs, NULL);
|
||||
return (char **)g_ptr_array_free (matched_refs, FALSE);
|
||||
}
|
||||
|
||||
char *
|
||||
flatpak_dir_find_remote_ref (FlatpakDir *self,
|
||||
const char *remote,
|
||||
@@ -3965,16 +4022,11 @@ flatpak_dir_find_remote_ref (FlatpakDir *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
const char *arch = NULL;
|
||||
g_autofree char *refspec_prefix = NULL;
|
||||
g_autofree char *remote_ref = NULL;
|
||||
g_autoptr(GHashTable) remote_refs = NULL;
|
||||
g_autoptr(GError) my_error = NULL;
|
||||
|
||||
arch = opt_arch;
|
||||
if (arch == NULL)
|
||||
arch = flatpak_get_arch ();
|
||||
|
||||
if (!flatpak_dir_ensure_repo (self, NULL, error))
|
||||
return NULL;
|
||||
|
||||
@@ -4010,25 +4062,15 @@ flatpak_dir_find_remote_ref (FlatpakDir *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
flatpak_dir_find_installed_ref (FlatpakDir *self,
|
||||
const char *name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
gboolean *is_app,
|
||||
GError **error)
|
||||
{
|
||||
const char *arch = NULL;
|
||||
g_autofree char *local_ref = NULL;
|
||||
g_autoptr(GHashTable) local_refs = NULL;
|
||||
g_autoptr(GError) my_error = NULL;
|
||||
int i;
|
||||
|
||||
arch = opt_arch;
|
||||
if (arch == NULL)
|
||||
arch = flatpak_get_arch ();
|
||||
static GHashTable *
|
||||
flatpak_dir_get_all_installed_refs (FlatpakDir *self,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GHashTable) local_refs = NULL;
|
||||
int i;
|
||||
|
||||
if (!flatpak_dir_ensure_repo (self, NULL, error))
|
||||
return NULL;
|
||||
@@ -4057,7 +4099,56 @@ flatpak_dir_find_installed_ref (FlatpakDir *self,
|
||||
GINT_TO_POINTER (1));
|
||||
}
|
||||
|
||||
local_ref = find_matching_ref (local_refs, name, opt_branch,
|
||||
return g_steal_pointer (&local_refs);
|
||||
}
|
||||
|
||||
char **
|
||||
flatpak_dir_find_installed_refs (FlatpakDir *self,
|
||||
const char *opt_name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *local_ref = NULL;
|
||||
g_autoptr(GHashTable) local_refs = NULL;
|
||||
g_autoptr(GError) my_error = NULL;
|
||||
GPtrArray *matched_refs;
|
||||
|
||||
local_refs = flatpak_dir_get_all_installed_refs (self, app, runtime, error);
|
||||
if (local_refs == NULL)
|
||||
return NULL;
|
||||
|
||||
matched_refs = find_matching_refs (local_refs, opt_name, opt_branch,
|
||||
opt_arch, app, runtime, error);
|
||||
if (matched_refs == NULL)
|
||||
return NULL;
|
||||
|
||||
g_ptr_array_add (matched_refs, NULL);
|
||||
return (char **)g_ptr_array_free (matched_refs, FALSE);
|
||||
|
||||
}
|
||||
|
||||
char *
|
||||
flatpak_dir_find_installed_ref (FlatpakDir *self,
|
||||
const char *opt_name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
gboolean *is_app,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *local_ref = NULL;
|
||||
g_autoptr(GHashTable) local_refs = NULL;
|
||||
g_autoptr(GError) my_error = NULL;
|
||||
|
||||
local_refs = flatpak_dir_get_all_installed_refs (self, app, runtime, error);
|
||||
if (local_refs == NULL)
|
||||
return NULL;
|
||||
|
||||
local_ref = find_matching_ref (local_refs, opt_name, opt_branch,
|
||||
opt_arch, app, runtime, &my_error);
|
||||
if (local_ref == NULL)
|
||||
{
|
||||
@@ -4078,7 +4169,7 @@ flatpak_dir_find_installed_ref (FlatpakDir *self,
|
||||
}
|
||||
|
||||
g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED,
|
||||
"%s %s not installed", name, opt_branch ? opt_branch : "master");
|
||||
"%s %s not installed", opt_name ? opt_name : "*unspecified*", opt_branch ? opt_branch : "master");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,14 +142,30 @@ char * flatpak_dir_find_remote_ref (FlatpakDir *self,
|
||||
gboolean *is_app,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
char ** flatpak_dir_find_remote_refs (FlatpakDir *self,
|
||||
const char *remote,
|
||||
const char *name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
char * flatpak_dir_find_installed_ref (FlatpakDir *self,
|
||||
const char *name,
|
||||
const char *opt_name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
gboolean *is_app,
|
||||
GError **error);
|
||||
char ** flatpak_dir_find_installed_refs (FlatpakDir *self,
|
||||
const char *opt_name,
|
||||
const char *opt_branch,
|
||||
const char *opt_arch,
|
||||
gboolean app,
|
||||
gboolean runtime,
|
||||
GError **error);
|
||||
FlatpakDeploy *flatpak_dir_load_deployed (FlatpakDir *self,
|
||||
const char *ref,
|
||||
const char *checksum,
|
||||
|
||||
@@ -60,7 +60,7 @@ typedef enum {
|
||||
|
||||
|
||||
/* Same order as enum */
|
||||
static const char *flatpak_context_shares[] = {
|
||||
const char *flatpak_context_shares[] = {
|
||||
"network",
|
||||
"ipc",
|
||||
NULL
|
||||
@@ -75,7 +75,7 @@ typedef enum {
|
||||
} FlatpakContextSockets;
|
||||
|
||||
/* Same order as enum */
|
||||
static const char *flatpak_context_sockets[] = {
|
||||
const char *flatpak_context_sockets[] = {
|
||||
"x11",
|
||||
"wayland",
|
||||
"pulseaudio",
|
||||
@@ -93,7 +93,7 @@ typedef enum {
|
||||
FLATPAK_CONTEXT_DEVICE_DRI = 1 << 0,
|
||||
} FlatpakContextDevices;
|
||||
|
||||
static const char *flatpak_context_devices[] = {
|
||||
const char *flatpak_context_devices[] = {
|
||||
"dri",
|
||||
NULL
|
||||
};
|
||||
@@ -861,6 +861,12 @@ static GOptionEntry context_options[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void
|
||||
flatpak_context_complete (FlatpakContext *context, FlatpakCompletion *completion)
|
||||
{
|
||||
flatpak_complete_options (completion, context_options);
|
||||
}
|
||||
|
||||
GOptionGroup *
|
||||
flatpak_context_get_options (FlatpakContext *context)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "libglnx/libglnx.h"
|
||||
#include "dbus-proxy/flatpak-proxy.h"
|
||||
#include "flatpak-common-types.h"
|
||||
#include "flatpak-utils.h"
|
||||
|
||||
gboolean flatpak_run_in_transient_unit (const char *app_id,
|
||||
GError **error);
|
||||
@@ -38,11 +39,17 @@ gboolean flatpak_run_in_transient_unit (const char *app_id,
|
||||
#define FLATPAK_METADATA_KEY_PERSISTENT "persistent"
|
||||
#define FLATPAK_METADATA_KEY_DEVICES "devices"
|
||||
|
||||
extern const char *flatpak_context_sockets[];
|
||||
extern const char *flatpak_context_devices[];
|
||||
extern const char *flatpak_context_shares[];
|
||||
|
||||
FlatpakContext *flatpak_context_new (void);
|
||||
void flatpak_context_free (FlatpakContext *context);
|
||||
void flatpak_context_merge (FlatpakContext *context,
|
||||
FlatpakContext *other);
|
||||
GOptionGroup *flatpak_context_get_options (FlatpakContext *context);
|
||||
void flatpak_context_complete (FlatpakContext *context,
|
||||
FlatpakCompletion *completion);
|
||||
gboolean flatpak_context_load_metadata (FlatpakContext *context,
|
||||
GKeyFile *metakey,
|
||||
GError **error);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "lib/flatpak-error.h"
|
||||
#include "flatpak-dir.h"
|
||||
#include "flatpak-portal-error.h"
|
||||
#include "flatpak-run.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -3046,3 +3047,235 @@ flatpak_allocate_tmpdir (int tmpdir_dfd,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Uncomment to get debug traces in /tmp/flatpak-completion-debug.txt (nice
|
||||
* to not have it interfere with stdout/stderr)
|
||||
*/
|
||||
#if 0
|
||||
void
|
||||
flatpak_completion_debug (const gchar *format, ...)
|
||||
{
|
||||
va_list var_args;
|
||||
gchar *s;
|
||||
static FILE *f = NULL;
|
||||
|
||||
va_start (var_args, format);
|
||||
s = g_strdup_vprintf (format, var_args);
|
||||
if (f == NULL)
|
||||
f = fopen ("/tmp/flatpak-completion-debug.txt", "a+");
|
||||
fprintf (f, "%s\n", s);
|
||||
fflush (f);
|
||||
g_free (s);
|
||||
}
|
||||
#else
|
||||
void
|
||||
flatpak_completion_debug (const gchar *format, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
is_word_separator (char c)
|
||||
{
|
||||
return g_ascii_isspace (c);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_complete_word (FlatpakCompletion *completion,
|
||||
char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
const char *rest;
|
||||
g_autofree char *string = NULL;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
va_start (args, format);
|
||||
string = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
if (!g_str_has_prefix (string, completion->cur))
|
||||
return;
|
||||
|
||||
/* I'm not sure exactly what bash is doing here, but this seems to work... */
|
||||
if (strcmp (completion->shell_cur, "=") == 0)
|
||||
rest = string + strlen (completion->cur) - strlen (completion->shell_cur) + 1;
|
||||
else
|
||||
rest = string + strlen (completion->cur) - strlen (completion->shell_cur);
|
||||
|
||||
flatpak_completion_debug ("completing word: '%s' (%s)", string, rest);
|
||||
|
||||
g_print ("%s\n", rest);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_complete_options (FlatpakCompletion *completion,
|
||||
GOptionEntry *entries)
|
||||
{
|
||||
GOptionEntry *e = entries;
|
||||
int i;
|
||||
|
||||
while (e->long_name != NULL)
|
||||
{
|
||||
if (e->arg_description)
|
||||
{
|
||||
g_autofree char *prefix = g_strdup_printf ("--%s=", e->long_name);
|
||||
|
||||
if (g_str_has_prefix (completion->cur, prefix))
|
||||
{
|
||||
if (strcmp (e->arg_description, "ARCH") == 0)
|
||||
{
|
||||
const char *arches[] = {"i386", "x86_64", "aarch64", "arm"};
|
||||
for (i = 0; i < G_N_ELEMENTS (arches); i++)
|
||||
flatpak_complete_word (completion, "%s%s ", prefix, arches[i]);
|
||||
}
|
||||
else if (strcmp (e->arg_description, "SHARE") == 0)
|
||||
{
|
||||
for (i = 0; flatpak_context_shares[i] != NULL; i++)
|
||||
flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_shares[i]);
|
||||
}
|
||||
else if (strcmp (e->arg_description, "DEVICE") == 0)
|
||||
{
|
||||
for (i = 0; flatpak_context_devices[i] != NULL; i++)
|
||||
flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_devices[i]);
|
||||
}
|
||||
else if (strcmp (e->arg_description, "SOCKET") == 0)
|
||||
{
|
||||
for (i = 0; flatpak_context_sockets[i] != NULL; i++)
|
||||
flatpak_complete_word (completion, "%s%s ", prefix, flatpak_context_sockets[i]);
|
||||
}
|
||||
else
|
||||
flatpak_complete_word (completion, "%s", prefix);
|
||||
}
|
||||
else
|
||||
flatpak_complete_word (completion, "%s", prefix);
|
||||
}
|
||||
else
|
||||
flatpak_complete_word (completion, "--%s ", e->long_name);
|
||||
if (e->short_name != 0)
|
||||
flatpak_complete_word (completion, "-%c ", e->short_name);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
pick_word_at (const char *s,
|
||||
int cursor,
|
||||
int *out_word_begins_at)
|
||||
{
|
||||
int begin, end;
|
||||
|
||||
if (s[0] == '\0')
|
||||
{
|
||||
if (out_word_begins_at != NULL)
|
||||
*out_word_begins_at = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_word_separator (s[cursor]) && ((cursor > 0 && is_word_separator(s[cursor-1])) || cursor == 0))
|
||||
{
|
||||
if (out_word_begins_at != NULL)
|
||||
*out_word_begins_at = cursor;
|
||||
return g_strdup ("");
|
||||
}
|
||||
|
||||
while (!is_word_separator (s[cursor - 1]) && cursor > 0)
|
||||
cursor--;
|
||||
begin = cursor;
|
||||
|
||||
end = begin;
|
||||
while (!is_word_separator (s[end]) && s[end] != '\0')
|
||||
end++;
|
||||
|
||||
if (out_word_begins_at != NULL)
|
||||
*out_word_begins_at = begin;
|
||||
|
||||
return g_strndup (s + begin, end - begin);
|
||||
}
|
||||
|
||||
FlatpakCompletion *
|
||||
flatpak_completion_new (const char *arg_line,
|
||||
const char *arg_point,
|
||||
const char *arg_cur)
|
||||
{
|
||||
FlatpakCompletion *completion;
|
||||
g_autofree char *initial_completion_line = NULL;
|
||||
int _point;
|
||||
char *endp;
|
||||
int cur_begin;
|
||||
int i;
|
||||
|
||||
_point = strtol (arg_point, &endp, 10);
|
||||
if (endp == arg_point || *endp != '\0')
|
||||
return NULL;
|
||||
|
||||
completion = g_new0 (FlatpakCompletion, 1);
|
||||
completion->line = g_strdup (arg_line);
|
||||
completion->shell_cur = g_strdup (arg_cur);
|
||||
completion->point = _point;
|
||||
|
||||
flatpak_completion_debug ("========================================");
|
||||
flatpak_completion_debug ("completion_point=%d", completion->point);
|
||||
flatpak_completion_debug ("completion_shell_cur='%s'", completion->shell_cur);
|
||||
flatpak_completion_debug ("----");
|
||||
flatpak_completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
|
||||
flatpak_completion_debug ("'%s'", completion->line);
|
||||
flatpak_completion_debug (" %*s^", completion->point, "");
|
||||
|
||||
/* compute cur and prev */
|
||||
completion->prev = NULL;
|
||||
completion->cur = pick_word_at (completion->line, completion->point, &cur_begin);
|
||||
if (cur_begin > 0)
|
||||
{
|
||||
gint prev_end;
|
||||
for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
|
||||
{
|
||||
if (!is_word_separator (completion->line[prev_end]))
|
||||
{
|
||||
completion->prev = pick_word_at (completion->line, prev_end, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
initial_completion_line = g_strndup (completion->line, cur_begin);
|
||||
}
|
||||
else
|
||||
initial_completion_line = g_strdup ("");
|
||||
|
||||
flatpak_completion_debug ("'%s'", initial_completion_line);
|
||||
flatpak_completion_debug ("----");
|
||||
|
||||
flatpak_completion_debug (" cur='%s'", completion->cur);
|
||||
flatpak_completion_debug ("prev='%s'", completion->prev);
|
||||
|
||||
if (!g_shell_parse_argv (initial_completion_line,
|
||||
&completion->argc,
|
||||
&completion->argv,
|
||||
NULL))
|
||||
{
|
||||
/* it's very possible the command line can't be parsed (for
|
||||
* example, missing quotes etc) - in that case, we just
|
||||
* don't autocomplete at all
|
||||
*/
|
||||
flatpak_completion_free (completion);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flatpak_completion_debug ("completion_argv:");
|
||||
for (i = 0; i < completion->argc; i++)
|
||||
flatpak_completion_debug (completion->argv[i]);
|
||||
|
||||
flatpak_completion_debug ("----");
|
||||
|
||||
return completion;
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_completion_free (FlatpakCompletion *completion)
|
||||
{
|
||||
g_free (completion->cur);
|
||||
g_free (completion->prev);
|
||||
g_free (completion->line);
|
||||
g_strfreev (completion->argv);
|
||||
g_free (completion);
|
||||
}
|
||||
|
||||
@@ -356,4 +356,26 @@ gboolean flatpak_allocate_tmpdir (int tmpdir_dfd,
|
||||
GError **error);
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *shell_cur;
|
||||
char *cur;
|
||||
char *prev;
|
||||
char *line;
|
||||
int point;
|
||||
char **argv;
|
||||
int argc;
|
||||
} FlatpakCompletion;
|
||||
|
||||
void flatpak_completion_debug (const gchar *format, ...);
|
||||
|
||||
FlatpakCompletion *flatpak_completion_new (const char *arg_line,
|
||||
const char *arg_point,
|
||||
const char *arg_cur);
|
||||
void flatpak_complete_word (FlatpakCompletion *completion,
|
||||
char *format,
|
||||
...);
|
||||
void flatpak_complete_options (FlatpakCompletion *completion,
|
||||
GOptionEntry *entries);
|
||||
void flatpak_completion_free (FlatpakCompletion *completion);
|
||||
|
||||
#endif /* __FLATPAK_UTILS_H__ */
|
||||
|
||||
@@ -1,405 +1,14 @@
|
||||
# Check for bash
|
||||
[ -z "$BASH_VERSION" ] && return
|
||||
|
||||
__contains_word () {
|
||||
local w word=$1; shift
|
||||
for w in "$@"; do
|
||||
[[ $w = "$word" ]] && return
|
||||
done
|
||||
####################################################################################################
|
||||
|
||||
__flatpak() {
|
||||
local IFS=$'\n'
|
||||
local cur=`_get_cword :`
|
||||
COMPREPLY=($(flatpak complete "${COMP_LINE}" "${COMP_POINT}" "${cur}"))
|
||||
}
|
||||
|
||||
_flatpak() {
|
||||
local cur prev
|
||||
local cur=${COMP_WORDS[COMP_CWORD]}
|
||||
local prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
####################################################################################################
|
||||
|
||||
if [[ $cur == "=" ]] && [[ "$prev" = -* ]]; then
|
||||
cur=""
|
||||
elif [[ $prev == "=" ]] && [[ "${COMP_WORDS[COMP_CWORD-2]}" = -* ]]; then
|
||||
prev=${COMP_WORDS[COMP_CWORD-2]}
|
||||
fi
|
||||
|
||||
local i verb comps mode kind bundle
|
||||
local remote name
|
||||
local file dir cmd sdk loc
|
||||
|
||||
local -A VERBS=(
|
||||
[ALL]='remote-add remote-modify remote-delete remote-ls remote-list install update uninstall list run override enter export-file build-init build build-finish build-export build-bundle build-update-repo make-current'
|
||||
[MODE]='remote-add remote-modify remote-delete remote-ls remote-list install update uninstall list list make-current'
|
||||
[KIND]='install update uninstall list remote-ls'
|
||||
[PERMS]='run override build build-finish'
|
||||
[UNINSTALL]='uninstall'
|
||||
[SHOW_DETAILS]='list remote-list remote-ls'
|
||||
[ARCH]='build-init install build-bundle run uninstall update make-current'
|
||||
[USER_AND_SYSTEM]='run remote-list list'
|
||||
[APP_AND_RUNTIME]='install update uninstall'
|
||||
)
|
||||
|
||||
local -A OPTS=(
|
||||
[GENERAL]='--help --verbose --version'
|
||||
[MODE]='--user --system'
|
||||
[KIND]='--app --runtime'
|
||||
[ARCH]='--arch='
|
||||
[SHOW_DETAILS]='-d --show-details'
|
||||
[PERMS]='--share= --unshare= --socket= --nosocket= --device= --nodevice= --filesystem= --env= --own-name= --talk-name= --persist='
|
||||
[ADD_REMOTE]='--no-gpg-verify --if-not-exists --title= --gpg-import= --gpg-key='
|
||||
[MODIFY_REMOTE]='--no-gpg-verify --gpg-verify --title= --gpg-import= --gpg-key='
|
||||
[LIST_REMOTES]='--show-details'
|
||||
[LS_REMOTE]='--show-details --updates'
|
||||
[UNINSTALL]='--keep-ref --force-remove'
|
||||
[INSTALL]='--bundle --gpg-file='
|
||||
[BUILD_BUNDLE]='--gpg-keys= --runtime --arch= --repo-url='
|
||||
[RUN]='--command= --branch= --devel --runtime='
|
||||
[BUILD_INIT]='--arch= --var='
|
||||
[BUILD]='--runtime'
|
||||
[BUILD_FINISH]='--command= --allow'
|
||||
[BUILD_EXPORT]='--subject= --body='
|
||||
[EXPORT_FILE]='--app= --allow-write --allow-delete --allow-grant-permission --unique --transient'
|
||||
|
||||
[ARG]='--arch --command --branch --var --share --unshare --socket --nosocket --device --nodevice --subject --body --title --runtime --filesystem'
|
||||
)
|
||||
|
||||
for ((i=0; i < COMP_CWORD; i++)); do
|
||||
if [[ "${COMP_WORDS[i]}" = -* ]]; then
|
||||
continue
|
||||
fi
|
||||
if __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
|
||||
continue
|
||||
fi
|
||||
if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
|
||||
test -z $first_verb; then
|
||||
first_verb=${COMP_WORDS[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
if __contains_word "--bundle" ${COMP_WORDS[*]}; then
|
||||
bundle="true"
|
||||
else
|
||||
bundle="false"
|
||||
fi
|
||||
|
||||
if __contains_word "--user" ${COMP_WORDS[*]}; then
|
||||
if __contains_word "--system" ${COMP_WORDS[*]}; then
|
||||
mode="--user --system"
|
||||
else
|
||||
mode="--user"
|
||||
fi
|
||||
else
|
||||
if __contains_word "--system" ${COMP_WORDS[*]}; then
|
||||
mode=--system
|
||||
else
|
||||
if __contains_word "$first_verb" ${VERBS[USER_AND_SYSTEM]}; then
|
||||
mode="--user --system"
|
||||
else
|
||||
mode="--system"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if __contains_word "--app" ${COMP_WORDS[*]}; then
|
||||
if __contains_word "--runtime" ${COMP_WORDS[*]}; then
|
||||
kind="--app --runtime"
|
||||
else
|
||||
kind="--app"
|
||||
fi
|
||||
else
|
||||
if __contains_word "--runtime" ${COMP_WORDS[*]}; then
|
||||
kind="--runtime"
|
||||
else
|
||||
if __contains_word "$first_verb" ${VERBS[APP_AND_RUNTIME]}; then
|
||||
kind="--app --runtime"
|
||||
else
|
||||
kind="--app"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if __contains_word "$prev" ${OPTS[ARG]}; then
|
||||
case $prev in
|
||||
--arch)
|
||||
comps='x86_64 i686'
|
||||
;;
|
||||
--command)
|
||||
comps=$(compgen -A command)
|
||||
;;
|
||||
--var)
|
||||
comps=$(flatpak $mode list --runtime)
|
||||
;;
|
||||
--runtime)
|
||||
if __contains_word "$verb" ${VERBS[KIND]}; then
|
||||
comps=XXX
|
||||
else
|
||||
comps=$(flatpak $mode list --runtime)
|
||||
fi
|
||||
;;
|
||||
--share|--noshare)
|
||||
comps='network ipc'
|
||||
;;
|
||||
--device|--nodevice)
|
||||
comps='dri'
|
||||
;;
|
||||
--socket|--nosocket)
|
||||
comps='x11 wayland pulseaudio system-bus session-bus'
|
||||
;;
|
||||
--branch|--subject|--body|--title)
|
||||
comps=''
|
||||
;;
|
||||
--filesystem)
|
||||
comps='host home xdg-desktop xdg-documents xdg-download xdg-music xdg-pictures xdg-public-share xdg-templates xdg-videos'
|
||||
;;
|
||||
esac
|
||||
if [[ $comps != "XXXX" ]] ; then
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
for ((i=0; i < COMP_CWORD; i++)); do
|
||||
if [[ "${COMP_WORDS[i]}" = -* ]]; then
|
||||
continue
|
||||
fi
|
||||
if __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
|
||||
continue
|
||||
fi
|
||||
if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
|
||||
test -z $verb; then
|
||||
verb=${COMP_WORDS[i]}
|
||||
elif [[ $verb = install && $bundle = "true" ]]; then
|
||||
if [[ -z $file ]]; then
|
||||
file=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = install ]]; then
|
||||
if [[ -z $remote ]]; then
|
||||
remote=${COMP_WORDS[i]}
|
||||
elif [[ -z $name ]]; then
|
||||
name=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb =~ (update|uninstall|run) ]]; then
|
||||
if [[ -z $name ]]; then
|
||||
name=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = build-init ]]; then
|
||||
if [[ -z $dir ]]; then
|
||||
dir=${COMP_WORDS[i]}
|
||||
elif [[ -z $sdk ]]; then
|
||||
sdk=${COMP_WORDS[i]}
|
||||
elif [[ -z $name ]]; then
|
||||
name=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = build ]]; then
|
||||
if [[ -z $dir ]]; then
|
||||
dir=${COMP_WORDS[i]}
|
||||
elif [[ -z $cmd ]]; then
|
||||
cmd=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = build-finish ]]; then
|
||||
if [[ -z $dir ]]; then
|
||||
dir=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = build-export ]]; then
|
||||
if [[ -z $loc ]]; then
|
||||
loc=${COMP_WORDS[i]}
|
||||
elif [[ -z $dir ]]; then
|
||||
dir=${COMP_WORDS[i]}
|
||||
elif [[ -z $name ]]; then
|
||||
name=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = build-bundle ]]; then
|
||||
if [[ -z $loc ]]; then
|
||||
loc=${COMP_WORDS[i]}
|
||||
elif [[ -z $file ]]; then
|
||||
file=${COMP_WORDS[i]}
|
||||
elif [[ -z $name ]]; then
|
||||
name=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = build-update-repo ]]; then
|
||||
if [[ -z $loc ]]; then
|
||||
loc=${COMP_WORDS[i]}
|
||||
fi
|
||||
elif [[ $verb = export-file ]]; then
|
||||
if [[ -z $file ]]; then
|
||||
file=${COMP_WORDS[i]}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z $verb ]]; then
|
||||
comps="${VERBS[*]}"
|
||||
|
||||
elif [[ "$cur" = -* ]]; then
|
||||
comps="${OPTS[GENERAL]}"
|
||||
if __contains_word "$verb" ${VERBS[MODE]}; then
|
||||
comps="$comps ${OPTS[MODE]}"
|
||||
fi
|
||||
if __contains_word "$verb" ${VERBS[KIND]}; then
|
||||
comps="$comps ${OPTS[KIND]}"
|
||||
fi
|
||||
if __contains_word "$verb" ${VERBS[PERMS]}; then
|
||||
comps="$comps ${OPTS[PERMS]}"
|
||||
fi
|
||||
if [ "$verb" = "remote-list" ]; then
|
||||
comps="$comps ${OPTS[LIST_REMOTES]}"
|
||||
fi
|
||||
if __contains_word "$verb" ${VERBS[ARCH]}; then
|
||||
comps="$comps ${OPTS[ARCH]}"
|
||||
fi
|
||||
if __contains_word "$verb" ${VERBS[SHOW_DETAILS]}; then
|
||||
comps="$comps ${OPTS[SHOW_DETAILS]}"
|
||||
fi
|
||||
if __contains_word "$verb" ${VERBS[UNINSTALL]}; then
|
||||
comps="$comps ${OPTS[UNINSTALL]}"
|
||||
fi
|
||||
if [ "$verb" = "run" ]; then
|
||||
comps="$comps ${OPTS[RUN]}"
|
||||
fi
|
||||
if [ "$verb" = "export-file" ]; then
|
||||
comps="$comps ${OPTS[EXPORT_FILE]}"
|
||||
fi
|
||||
if [ "$verb" = "remote-ls" ]; then
|
||||
comps="$comps ${OPTS[LS_REMOTE]}"
|
||||
fi
|
||||
if [ "$verb" = "build-init" ]; then
|
||||
comps="$comps ${OPTS[BUILD_INIT]}"
|
||||
fi
|
||||
if [ "$verb" = "build" ]; then
|
||||
comps="$comps ${OPTS[BUILD]}"
|
||||
fi
|
||||
if [ "$verb" = "build-finish" ]; then
|
||||
comps="$comps ${OPTS[BUILD_FINISH]}"
|
||||
fi
|
||||
if [ "$verb" = "build-bundle" ]; then
|
||||
comps="$comps ${OPTS[BUILD_BUNDLE]}"
|
||||
fi
|
||||
if [ "$verb" = "install" ]; then
|
||||
comps="$comps ${OPTS[INSTALL]}"
|
||||
fi
|
||||
if [ "$verb" = "build-export" ]; then
|
||||
comps="$comps ${OPTS[BUILD_EXPORT]}"
|
||||
fi
|
||||
if [ "$verb" = "repo-update" ]; then
|
||||
comps="$comps ${OPTS[REPO_UPDATE]}"
|
||||
fi
|
||||
if [ "$verb" = "remote-add" ]; then
|
||||
comps="$comps ${OPTS[ADD_REMOTE]}"
|
||||
fi
|
||||
if [ "$verb" = "remote-modify" ]; then
|
||||
comps="$comps ${OPTS[MODIFY_REMOTE]}"
|
||||
fi
|
||||
else
|
||||
case "$verb" in
|
||||
remote-add|remote-modify|remote-delete|remote-ls)
|
||||
comps=$(flatpak $mode remote-list)
|
||||
;;
|
||||
|
||||
install)
|
||||
if [[ $bundle == "true" ]]; then
|
||||
comps=''
|
||||
compopt -o filenames
|
||||
else
|
||||
if [[ -z $remote ]]; then
|
||||
comps=$(flatpak $mode remote-list)
|
||||
if [[ $mode == "--system" ]]; then
|
||||
comps="$comps --user"
|
||||
fi
|
||||
elif [[ -z $name ]]; then
|
||||
comps=$(flatpak remote-ls $mode $kind $remote)
|
||||
else
|
||||
comps='' # FIXME: branches
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
remote-list|list)
|
||||
comps=''
|
||||
;;
|
||||
|
||||
update|uninstall)
|
||||
if [[ -z $name ]]; then
|
||||
comps=$(flatpak $mode $kind list)
|
||||
else
|
||||
comps='' # FIXME: branches
|
||||
fi
|
||||
;;
|
||||
|
||||
run|override)
|
||||
# run doesn't take --user or --system, so don't use mode here
|
||||
if [[ -z $name ]]; then
|
||||
comps=$(flatpak list --app)
|
||||
fi
|
||||
;;
|
||||
|
||||
|
||||
build-init)
|
||||
if [[ -z $dir ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
elif [[ -z $sdk ]]; then
|
||||
comps="$(flatpak list --runtime) $(flatpak --user list --runtime)"
|
||||
elif [[ -z $name ]]; then
|
||||
comps="$(flatpak list --runtime) $(flatpak --user list --runtime)"
|
||||
else
|
||||
comps='' # FIXME: branches
|
||||
fi
|
||||
;;
|
||||
|
||||
build)
|
||||
if [[ -z $dir ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
elif [[ -z $cmd ]]; then
|
||||
comps=''
|
||||
compopt -o bashdefault
|
||||
fi
|
||||
;;
|
||||
|
||||
build-finish)
|
||||
if [[ -z $dir ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
fi
|
||||
;;
|
||||
|
||||
build-export)
|
||||
if [[ -z $loc ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
elif [[ -z $dir ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
fi
|
||||
;;
|
||||
|
||||
build-bundle)
|
||||
if [[ -z $loc ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
elif [[ -z $file ]]; then
|
||||
comps=''
|
||||
compopt -o filenames
|
||||
else
|
||||
comps='' # FIXME: list apps/runtimes
|
||||
fi
|
||||
;;
|
||||
|
||||
build-update-repo)
|
||||
if [[ -z $loc ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
fi
|
||||
;;
|
||||
|
||||
export-file)
|
||||
if [[ -z $file ]]; then
|
||||
comps=''
|
||||
compopt -o dirnames
|
||||
fi
|
||||
;;
|
||||
|
||||
esac
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _flatpak flatpak
|
||||
complete -o nospace -F __flatpak flatpak
|
||||
|
||||
Reference in New Issue
Block a user