diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2019-12-19 14:12:55 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2019-12-29 22:46:16 +0100 |
commit | 8da1f13c7df386163b26277cfb92b80d1e0c7f8a (patch) | |
tree | 338b108ff1007d2c229821e089d7568197c584e9 | |
parent | 7bd6b4cce0de53f43833a8b1b270087ead8f8e5f (diff) | |
download | tracker-8da1f13c7df386163b26277cfb92b80d1e0c7f8a.tar.gz |
tracker: Allow extending the CLI tool with additional subcommands
We still link all the builtin tools in a single binary, and create specific
links in $libexecdir/tracker/. External subcommands may install their binaries
on $libexecdir/tracker right away.
During (sub)command execution, the tracker binary will look for the proper
subcommand and execve it. As the same tracker binary implements those same
subcommands, it does check argv[0] to know if it is running as one of those
subcommands. This keeps a single binary around, but allows transparently
falling back to other executables.
-rw-r--r-- | src/tracker/make-subcommand-links.sh | 25 | ||||
-rw-r--r-- | src/tracker/meson.build | 16 | ||||
-rw-r--r-- | src/tracker/tracker-main.c | 75 |
3 files changed, 83 insertions, 33 deletions
diff --git a/src/tracker/make-subcommand-links.sh b/src/tracker/make-subcommand-links.sh new file mode 100644 index 000000000..a257d1612 --- /dev/null +++ b/src/tracker/make-subcommand-links.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +bindir=$MESON_INSTALL_PREFIX/bin +libexecdir=$MESON_INSTALL_PREFIX/libexec + +if [ -d $libexecdir/tracker ] +then + for l in `find $libexecdir/tracker -type l` + do + # Delete all previous links to our own binary + if [[ `readlink $l` = "$bindir/tracker" ]] + then + rm $l + fi + done +fi + +mkdir -p $libexecdir/tracker + +for subcommand in $@ +do + ln -s $bindir/tracker $libexecdir/tracker/$subcommand +done diff --git a/src/tracker/meson.build b/src/tracker/meson.build index 48bc3e7c5..af6e5f7b7 100644 --- a/src/tracker/meson.build +++ b/src/tracker/meson.build @@ -1,11 +1,18 @@ +modules = [ + 'help', + 'info', + 'sparql', + 'sql', +] + sources = [ 'tracker-main.c', - 'tracker-help.c', - 'tracker-info.c', - 'tracker-sparql.c', - 'tracker-sql.c', ] +foreach m: modules + sources += 'tracker-@0@.c'.format(m) +endforeach + executable('tracker', sources, c_args: tracker_c_args + [ '-DLIBEXECDIR="@0@"'.format(join_paths(get_option('prefix'), get_option('libexecdir'))), @@ -19,6 +26,7 @@ executable('tracker', sources, include_directories: [commoninc, configinc, srcinc], ) +meson.add_install_script('make-subcommand-links.sh', modules) if install_bash_completion install_data( diff --git a/src/tracker/tracker-main.c b/src/tracker/tracker-main.c index fde5be4f6..b65ee5bbc 100644 --- a/src/tracker/tracker-main.c +++ b/src/tracker/tracker-main.c @@ -66,7 +66,7 @@ tracker_help (int argc, const char **argv) } static int -tracker_version (int argc, const char **argv) +print_version (void) { puts (about); return 0; @@ -91,7 +91,6 @@ static struct cmd_struct commands[] = { { "info", tracker_info, NEED_WORK_TREE, N_("Show information known about local files or items indexed") }, { "sparql", tracker_sparql, NEED_WORK_TREE, N_("Query and update the index using SPARQL or search, list and tree the ontology") }, { "sql", tracker_sql, NEED_WORK_TREE, N_("Query the database at the lowest level using SQL") }, - { "version", tracker_version, NEED_NOTHING, N_("Show the license and version in use") }, }; static int @@ -118,15 +117,9 @@ static void handle_command (int argc, const char **argv) { gchar *log_filename = NULL; - const char *cmd = argv[0]; + char *cmd = g_path_get_basename (argv[0]); int i; - /* Turn "tracker cmd --help" into "tracker help cmd" */ - if (argc > 1 && !strcmp (argv[1], "--help")) { - argv[1] = argv[0]; - argv[0] = cmd = "help"; - } - tracker_log_init (0, &log_filename); if (log_filename != NULL) { g_message ("Using log file:'%s'", log_filename); @@ -140,11 +133,13 @@ handle_command (int argc, const char **argv) continue; } + g_free (cmd); exit (run_builtin (p, argc, argv)); } g_printerr (_("“%s” is not a tracker command. See “tracker --help”"), argv[0]); g_printerr ("\n"); + g_free (cmd); exit (EXIT_FAILURE); } @@ -190,10 +185,10 @@ print_usage (void) } int -main (int original_argc, char **original_argv) +main (int argc, char *argv[]) { - const char **argv = (const char **) original_argv; - int argc = original_argc; + gboolean basename_is_bin = FALSE; + gchar *command_basename; setlocale (LC_ALL, ""); @@ -201,24 +196,46 @@ main (int original_argc, char **original_argv) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - argv++; - argc--; - - if (argc > 0) { - /* For cases like --version */ - if (g_str_has_prefix (argv[0], "--")) { - argv[0] += 2; + command_basename = g_path_get_basename (argv[0]); + basename_is_bin = g_strcmp0 (command_basename, "tracker") == 0; + g_free (command_basename); + + if (g_path_is_absolute (argv[0]) && + g_str_has_prefix (argv[0], LIBEXECDIR "/tracker/")) { + /* This is a subcommand call */ + handle_command (argc, (const gchar **) argv); + exit (EXIT_FAILURE); + } else if (basename_is_bin) { + /* This is a call to the main tracker executable, + * look up and exec the subcommand if any. + */ + if (argc > 1) { + const gchar *subcommand = argv[1]; + gchar *path; + + if (g_strcmp0 (subcommand, "--version") == 0) { + print_version (); + exit (EXIT_SUCCESS); + } else if (g_strcmp0 (subcommand, "--help") == 0) { + subcommand = "help"; + } + + path = g_build_filename (LIBEXECDIR, "tracker", subcommand, NULL); + + if (g_file_test (path, G_FILE_TEST_EXISTS)) { + /* Manipulate argv in place, in order to launch subcommand */ + argv[1] = path; + execv (path, &argv[1]); + } else { + print_usage (); + } + + g_free (path); + } else { + /* The user didn't specify a command; give them help */ + print_usage (); + exit (EXIT_SUCCESS); } - } else { - /* The user didn't specify a command; give them help */ - print_usage (); - exit (1); - } - - handle_command (argc, argv); - - if ((char **) argv != original_argv) { - g_strfreev ((char **) argv); } return EXIT_FAILURE; |