Add a --column option

Allow the user to specify what fields to show.
This is ps, after all :)

Closes: #2023
Approved by: alexlarsson
This commit is contained in:
Matthias Clasen 2018-08-26 23:31:21 -04:00 committed by Atomic Bot
parent a9d4cc5838
commit e6f8b564cb

View File

@ -35,11 +35,75 @@
#include "flatpak-table-printer.h"
#include "flatpak-run-private.h"
static gboolean opt_show_cols;
static const char **opt_cols;
static GOptionEntry options[] = {
{ "show-columns", 0, 0, G_OPTION_ARG_NONE, &opt_show_cols, N_("Show available columns"), NULL },
{ "columns", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_cols, N_("What information to show"), N_("FIELD,…") },
{ NULL }
};
static struct {
const char *name;
const char *title;
const char *desc;
} all_columns[] = {
{ "application", N_("Application"), N_("Show the application ID") },
{ "arch", N_("Architecture"), N_("Show the architecture") },
{ "branch", N_("Branch"), N_("Show the application branch") },
{ "runtime", N_("Runtime"), N_("Show the runtime ID") },
{ "runtime-branch", N_("Runtime Branch"), N_("Show the runtime branch") },
{ "pid", N_("PID"), N_("Show the PID of the main process") },
};
#define ALL_COLUMNS "pid,application,arch,branch,runtime,runtime-branch"
#define DEFAULT_COLUMNS "pid,application,runtime"
static int
find_column (const char *name)
{
int i;
for (i = 0; i < G_N_ELEMENTS(all_columns); i++)
{
if (strcmp (name, all_columns[i].name) == 0)
return i;
}
return -1;
}
static char *
column_help (void)
{
GString *s = g_string_new ("");
int len;
int i;
g_string_append (s, _("Available columns:\n"));
len = 0;
for (i = 0; i < G_N_ELEMENTS(all_columns); i++)
len = MAX (len, strlen (all_columns[i].name));
len += 4;
for (i = 0; i < G_N_ELEMENTS(all_columns); i++)
g_string_append_printf (s, " %-*s %s\n", len, all_columns[i].name, all_columns[i].desc);
g_string_append_printf (s, " %-*s %s\n", len, "all", _("Show all columns"));
g_string_append_printf (s, " %-*s %s\n", len, "help", _("Show available columns"));
return g_string_free (s, FALSE);
}
static void
show_columns (void)
{
g_autofree char *col_help = column_help ();
g_print ("%s", col_help);
}
static char *
get_instance_pid (const char *instance)
{
@ -52,18 +116,17 @@ get_instance_pid (const char *instance)
if (!g_file_get_contents (path, &pid, NULL, &error))
{
g_debug ("Failed to load pid file for instance '%s': %s", instance, error->message);
return g_strdup ("?");
return NULL;
}
return pid;
}
static char *
get_instance_app_id (const char *instance)
static GKeyFile *
get_instance_info (const char *instance)
{
g_autofree char *path = NULL;
g_autoptr(GKeyFile) key_file = NULL;
char *app_id = NULL;
GKeyFile *key_file = NULL;
g_autoptr(GError) error = NULL;
path = g_build_filename (g_get_user_runtime_dir (), ".flatpak", instance, "info", NULL);
@ -72,53 +135,102 @@ get_instance_app_id (const char *instance)
if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error))
{
g_debug ("Failed to load info file for instance '%s': %s", instance, error->message);
goto out;
return NULL;
}
app_id = g_key_file_get_string (key_file, "Application", "name", &error);
if (error)
return key_file;
}
static char *
get_instance_column (GKeyFile *info,
const char *name)
{
if (info == NULL)
return NULL;
if (strcmp (name, "application") == 0)
return g_key_file_get_string (info, "Application", "name", NULL);
if (strcmp (name, "arch") == 0)
return g_key_file_get_string (info, "Instance", "arch", NULL);
if (strcmp (name, "branch") == 0)
return g_key_file_get_string (info, "Instance", "branch", NULL);
else if (strcmp (name, "runtime") == 0)
{
g_debug ("Failed to get app ID for instance '%s': %s", instance, error->message);
g_autofree char *full_ref = g_key_file_get_string (info, "Application", "runtime", NULL);
g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL);
return g_strdup (ref[1]);
}
else if (strcmp (name, "runtime-branch") == 0)
{
g_autofree char *full_ref = g_key_file_get_string (info, "Application", "runtime", NULL);
g_auto(GStrv) ref = flatpak_decompose_ref (full_ref, NULL);
return g_strdup (ref[3]);
}
out:
return app_id ? app_id : g_strdup ("?");
return NULL;
}
static gboolean
enumerate_instances (GError **error)
enumerate_instances (const char *columns,
GError **error)
{
g_autofree char *base_dir = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GFileEnumerator) enumerator = NULL;
GFileInfo *info;
GFileInfo *dir_info;
FlatpakTablePrinter *printer;
g_auto(GStrv) cols = NULL;
g_autofree int *col_idx = NULL;
int n_cols;
int i;
cols = g_strsplit (columns, ",", 0);
n_cols = g_strv_length (cols);
col_idx = g_new (int, n_cols);
for (i = 0; i < n_cols; i++)
{
col_idx[i] = find_column (cols[i]);
if (col_idx[i] == -1)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unknown colum: %s"), cols[i]);
return FALSE;
}
}
printer = flatpak_table_printer_new ();
flatpak_table_printer_set_column_title (printer, 0, _("Instance"));
flatpak_table_printer_set_column_title (printer, 1, _("Application"));
flatpak_table_printer_set_column_title (printer, 2, _("PID"));
flatpak_run_gc_ids ();
for (i = 0; i < n_cols; i++)
flatpak_table_printer_set_column_title (printer, i + 1, all_columns[col_idx[i]].title);
base_dir = g_build_filename (g_get_user_runtime_dir (), ".flatpak", NULL);
file = g_file_new_for_path (base_dir);
enumerator = g_file_enumerate_children (file, "standard::name", G_FILE_QUERY_INFO_NONE, NULL, error);
if (enumerator == NULL)
return FALSE;
while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL)
while ((dir_info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL)
{
g_autofree char *instance = g_file_info_get_attribute_as_string (info, "standard::name");
g_autofree char *app_id = get_instance_app_id (instance);
g_autofree char *pid = get_instance_pid (instance);
g_autofree char *instance = g_file_info_get_attribute_as_string (dir_info, "standard::name");
g_autoptr(GKeyFile) info = get_instance_info (instance);
flatpak_table_printer_add_column (printer, instance);
flatpak_table_printer_add_column (printer, app_id);
flatpak_table_printer_add_column (printer, pid);
for (i = 0; i < n_cols; i++)
{
g_autofree char *col = NULL;
if (strcmp (all_columns[col_idx[i]].name, "pid") == 0)
col = get_instance_pid (instance);
else
col = get_instance_column (info, all_columns[col_idx[i]].name);
flatpak_table_printer_add_column (printer, col ? col : "");
}
flatpak_table_printer_finish_row (printer);
g_object_unref (info);
g_object_unref (dir_info);
}
flatpak_table_printer_print (printer);
@ -137,9 +249,13 @@ flatpak_builtin_ps (int argc,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autofree char *col_help = NULL;
g_autofree char *cols = NULL;
context = g_option_context_new (_(" - Enumerate running sandboxes"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
col_help = column_help ();
g_option_context_set_description (context, col_help);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
@ -150,7 +266,60 @@ flatpak_builtin_ps (int argc,
return FALSE;
}
return enumerate_instances (error);
flatpak_run_gc_ids ();
if (opt_show_cols)
{
show_columns ();
return TRUE;
}
if (opt_cols)
{
gboolean show_help = FALSE;
gboolean show_all = FALSE;
int i;
for (i = 0; opt_cols[i]; i++)
{
const char *p;
p = strstr (opt_cols[i], "help");
if (p &&
(p == opt_cols[i] || p[-1] == ',') &&
(p[strlen("help")] == '\0' || p[strlen("help")] == ','))
{
show_help = TRUE;
break;
}
p = strstr (opt_cols[i], "all");
if (p &&
(p == opt_cols[i] || p[-1] == ',') &&
(p[strlen("all")] == '\0' || p[strlen("all")] == ','))
{
show_all = TRUE;
break;
}
}
if (show_help)
{
show_columns ();
return TRUE;
}
else if (show_all)
{
cols = g_strdup (ALL_COLUMNS);
}
else
{
cols = g_strjoinv (",", (char **)opt_cols);
}
}
else
cols = g_strdup (DEFAULT_COLUMNS);
return enumerate_instances (cols, error);
}
gboolean