diff options
-rw-r--r-- | README.md | 37 | ||||
-rwxr-xr-x | utils/sandbox/tracker-sandbox.py | 632 |
2 files changed, 248 insertions, 421 deletions
@@ -98,34 +98,37 @@ in the top of the tracker source tree and type this to see the --help output: ./utils/sandbox/tracker-sandbox.py --help You should always pass the `--prefix` option, which should be the same as the ---prefix argument you passed to Meson. You also need to use `--index` which -controls where internal state files like the database are kept. You may also -want to pass `--debug` to see detailed log output. +--prefix argument you passed to Meson. You may pass `--index` which to controls +where Tracker's database is kept. You may also want to pass `--debug` to see +detailed log output. -Now you can index some files using `--update` mode. Here's how to index files -in `~/Documents` for example: +The remaining arguments you pass to `tracker-sandbox` are shell commands which +get run inside the sandbox. Use the `--` sentinel to ensure that the +commandline arguments are processed correctly. First, let's see the status of +the Tracker daemons: - ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker --index ~/tracker-content \ - --update --content ~/Documents + ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker -- tracker daemon status -You can then list the files that have been indexed... +Let's try and index some content... - ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker --index ~/tracker-content \ - --list-files + ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker -- tracker index ~/Music + +... let's see what files were found ... + + ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker -- tracker sparql --list-files ... run a full-text search ... - ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker --index ~/tracker-content \ - --search "bananas" + ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker -- tracker search "bananas" ... or run a SPARQL query on the content: - ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker --index ~/tracker-content \ - --sparql "SELECT ?url { ?resource a nfo:FileDataObject ; nie:url ?url . }" + ./utils/sandbox/tracker-sandbox.py --prefix ~/opt/tracker -- tracker sparql + --query "SELECT ?url { ?resource a nfo:FileDataObject ; nie:url ?url . }" -You can also open a shell inside the sandbox environment. From here you can run -the `tracker` commandline tool, and you can run the Tracker daemons manually -under a debugger such as GDB. +If you run `tracker-sandbox` without a command argument, it will open an +interactive shell inside the sandbox. From here you can use debugging tools +such as GDB. For more information about developing Tracker, look at https://wiki.gnome.org/Projects/Tracker. diff --git a/utils/sandbox/tracker-sandbox.py b/utils/sandbox/tracker-sandbox.py index 06bc6afb0..cc8ebd786 100755 --- a/utils/sandbox/tracker-sandbox.py +++ b/utils/sandbox/tracker-sandbox.py @@ -2,33 +2,11 @@ # # Copyright (C) 2012-2013 Martyn Russell <martyn@lanedo.com> # Copyright (C) 2012 Sam Thursfield <sam.thursfield@codethink.co.uk> -# Copyright (C) 2016 Sam Thursfield <sam@afuera.me.uk> +# Copyright (C) 2016,2019 Sam Thursfield <sam@afuera.me.uk> # -# This script allows a user to utilise Tracker for local instances by -# specifying an index directory location where the Tracker data is -# stored and a content directory location where the content to be -# indexed is kept. From there, queries or a shell can be launched to -# use that data. -# -# This was initially a shell script by Sam and later converted into a -# more comprehensive python script by Martyn. -# -# Usage: -# - Create or update an index stored in tracker/ subdir with content in html/ -# tracker-sandbox.py -i tracker -c html -u -# - Query for 'foo' -# tracker-sandbox.py -i tracker -c html -q foo -# - List files in index -# tracker-sandbox.py -i tracker -c html -l -# - Start shell with environment set up -# tracker-sandbox.py -i tracker -c html -s -# - Test with different prefixes, e.g. /usr/local installs -# tracker-sandbox.py -i tracker -c html -s -p /usr/local -# ... -# -# Changes: -# - If you make _ANY_ changes, please send them in so I can incorporate them. +# This is a tool for running development versions of Tracker. # +# See README.md for usage information. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -45,34 +23,27 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # +import argparse import locale +import logging import os -import subprocess -import optparse +import shlex import signal +import subprocess import sys -import errno +import threading import configparser -import gi -gi.require_version('Tracker', '2.0') -from gi.repository import Tracker, GLib +from gi.repository import GLib # Script script_name = 'tracker-sandbox' -script_version = '0.1' -script_about = 'Localised Tracker sandbox for content indexing and search' - -index_location_abs = '' +script_version = '1.0' +script_about = "Tracker Sandbox developer tool." default_prefix = '/usr' -default_debug_verbosity = 2 - -# Session -dbus_session_pid = -1 -dbus_session_address = '' -dbus_session_file = '' +default_index_location = '/tmp/tracker-sandbox' store_pid = -1 store_proc = None @@ -108,212 +79,138 @@ removable-days-threshold=3 enable-writeback=false """ -# Utilities - - -def mkdir_p(path): - try: - os.makedirs(path) - except OSError as exc: - if exc.errno == errno.EEXIST: - pass - else: - raise - - -def debug(message): - if opts.debug: - print(message) - -# DB functions (sync for now) - - -def db_query_have_files(): - # Set this here in case we used 'bus' for an update() before this. - # os.environ['TRACKER_SPARQL_BACKEND'] = 'direct' - - print('Using query to check index has data in it...') - - conn = Tracker.SparqlConnection.get(None) - cursor = conn.query( - 'select count(?urn) where { ?urn a nfo:FileDataObject }', None) - - # Only expect one result here... - while (cursor.next(None)): - print(' Currently %d file(s) exist in our index' % - (cursor.get_integer(0))) +log = logging.getLogger('sandbox') +dbuslog = logging.getLogger('dbus') -def db_query_list_files(): - # Set this here in case we used 'bus' for an update() before this. - # os.environ['TRACKER_SPARQL_BACKEND'] = 'direct' - print('Using query to list files indexed...') +# Private DBus daemon - conn = Tracker.SparqlConnection.get(None) - cursor = conn.query( - 'select nie:url(?urn) where { ?urn a nfo:FileDataObject }', None) +class DBusDaemon: + """The private D-Bus instance that provides the sandbox's session bus. - # Only expect one result here... - while (cursor.next(None)): - print(' ' + cursor.get_string(0)[0]) + We support reading and writing the session information to a file. This + means that if the user runs two sandbox instances on the same data + directory at the same time, they will share the same message bus. + """ + def __init__(self, session_file=None): + self.session_file = session_file + self.existing_session = False + self.process = None -def db_search(search_text): - conn = Tracker.SparqlConnection.get(None) - query = ('select nie:url(?urn) where { ?urn a nfo:FileDataObject . ' - '?urn fts:match "%s" }') - cursor = conn.query(query % (search_text), None) - - print('Found:') - - while (cursor.next(None)): - print(' ' + cursor.get_string(0)[0]) - - -def db_sparql_query(sparql): - conn = Tracker.SparqlConnection.get(None) - cursor = conn.query(sparql) - - print('Results:') - - while (cursor.next(None)): - row = [] - for column in range(0, cursor.get_n_columns()): - row.append(cursor.get_string(column)[0]) - print(' ' + '\t'.join(row)) - - -# Index functions - -def index_clean(): - # tracker reset --hard - debug('Cleaning index, FIXME: Does nothing.') + try: + self.address, self.pid = self.read_session_file(session_file) + self.existing_session = True + except FileNotFoundError: + log.debug("No existing D-Bus session file was found.") + self.address = None + self.pid = None -def find_libexec_binaries(command): - binary = os.path.join(opts.prefix, 'libexec', command) - if not os.path.exists(binary): - binary = os.path.join(opts.prefix, 'libexec', command) - if not os.path.exists(binary): + def get_session_file(self): + """Returns the path to the session file if we created it, or None.""" + if self.existing_session: return None + return self.session_file - return binary - - -def index_update(): - debug('Updating index ...') - debug('--') - - # FIXME: Need to start tracker-extract to make sure extended - # metadata is created, but the problem is, after miner-fs - # stops, we return to the prompt, so how do we handle that? - # - # We need to listen to signals from tracker-extract and then - # quit after some inactivity I think ... OR listen to - # GraphUpdated and when there are no more objects without a - # data-source, we know all data was indexed. - - # Start tracker-miner-fs - binary = find_libexec_binaries('tracker-miner-fs') - if binary is None: - print('Could not find "tracker-miner-fs" in $prefix/lib{exec} ' - 'directories', file=sys.stderr) - print('Is Tracker installed properly?', file=sys.stderr) - sys.exit(1) - - try: - # Mine data WITHOUT being a daemon, exit when done. Ignore desktop - # files - subprocess.check_output([binary, "--no-daemon"]).decode('utf-8') - except subprocess.CalledProcessError as e: - print('Could not run %s, %s' % (binary, e.output)) - sys.exit(1) - - debug('--') - - # We've now finished updating the index now OR we completely failed - print('Index now up to date!') - - # Check we have data in our index... - db_query_have_files() + def get_address(self): + return self.address - -def index_shell(): - print('Starting shell... (type "exit" to finish)') - print() - - os.system("/bin/bash") - -# Environment / Clean up - - -def dbus_session_get_from_content(content): - global dbus_session_address - global dbus_session_pid - - if len(content) < 1: - print('Content was empty ... can not get DBus session information from' - ' empty string', file=sys.stderr) - return False - - dbus_session_address = content.splitlines()[0] - dbus_session_pid = int(content.splitlines()[1]) - - err_msg = 'DBus session file was corrupt (%s), please remove "%s"' - if dbus_session_address == '': - print(err_msg % ("no address", dbus_session_file), file=sys.stderr) - sys.exit(1) - if dbus_session_pid < 0: - print(err_msg % ("no PID", dbus_session_file), file=sys.stderr) - sys.exit(1) - - return True - - -def dbus_session_file_get(): - try: - with open(dbus_session_file, 'r') as f: + @staticmethod + def read_session_file(session_file): + with open(session_file, 'r') as f: content = f.read() - return dbus_session_get_from_content(content) - except FileNotFoundError as e: - # Expect this if we have a new session to set up - return False - - -def dbus_session_file_set(): - mkdir_p(os.environ['XDG_RUNTIME_DIR']) - content = '%s\n%s' % (dbus_session_address, dbus_session_pid) - with open(dbus_session_file, 'w') as f: - f.write(content) + try: + address = content.splitlines()[0] + pid = int(content.splitlines()[1]) + except ValueError: + raise RuntimeError(f"D-Bus session file {session_file} is not valid. " + "Remove this file to start a new session.") + + return address, pid + + @staticmethod + def write_session_file(session_file, address, pid): + os.makedirs(os.path.dirname(session_file), exist_ok=True) + + content = '%s\n%s' % (address, pid) + with open(session_file, 'w') as f: + f.write(content) + + def start_if_needed(self): + if self.existing_session: + log.debug('Using existing D-Bus session from file "%s" with address "%s"' + ' with PID %d' % (self.session_file, self.address, self.pid)) + else: + dbus_command = ['dbus-daemon', '--session', '--print-address=1', '--print-pid=1'] + self.process = subprocess.Popen(dbus_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + try: + self.address = self.process.stdout.readline().strip().decode('ascii') + self.pid = int(self.process.stdout.readline().strip().decode('ascii')) + except ValueError: + error = self.process.stderr.read().strip().decode('unicode-escape') + raise RuntimeError(f"Failed to start D-Bus daemon.\n{error}") + + log.debug("Using new D-Bus session with address '%s' with PID %d", + self.address, self.pid) + + self.write_session_file(self.session_file, self.address, self.pid) + log.debug("Wrote D-Bus session file at %s", self.session_file) + + # We must read from the pipes continuously, otherwise the daemon + # process will block. + self._threads=[threading.Thread(target=self.pipe_to_log, args=(self.process.stdout, 'stdout'), daemon=True), + threading.Thread(target=self.pipe_to_log, args=(self.process.stderr, 'stderr'), daemon=True)] + self._threads[0].start() + self._threads[1].start() + + def stop(self): + if self.process: + log.debug(" Stopping DBus daemon") + self.process.terminate() + self.process.wait() + + def pipe_to_log(self, pipe, source): + """This function processes the output from our dbus-daemon instance.""" + while True: + line_raw = pipe.readline() + + if len(line_raw) == 0: + break + + line = line_raw.decode('utf-8').rstrip() + + if line.startswith('(tracker-'): + # We set G_MESSAGES_PREFIXED=all, meaning that all log messages + # output by Tracker processes have a prefix. Note that + # g_print() will NOT be captured here. + dbuslog.info(line) + else: + # Log messages from other daemons, including the dbus-daemon + # itself, go here. Any g_print() messages also end up here. + dbuslog.debug(line) -def environment_unset(): - debug('Cleaning up files ...') +# Environment / Clean up - if not dbus_session_file == '': - debug(' Removing DBus session file') - os.unlink(dbus_session_file) +def environment_unset(dbus): + log.debug('Cleaning up files ...') - debug('Cleaning up processes ...') + if dbus.get_session_file(): + log.debug(' Removing DBus session file') + os.unlink(dbus.get_session_file()) - if dbus_session_pid > 0: - debug(' Killing DBus session') - try: - os.kill(dbus_session_pid, signal.SIGTERM) - # (3, 'No such process') old python-schedutils incorrectly - # raised SystemError - except (SystemError, OSError): - debug(' Process %d not found', dbus_session_pid) + log.debug('Cleaning up processes ...') - if not opts.update: - return + dbus.stop() # FIXME: clean up tracker-store, can't use 'tracker daemon ...' for this, # that kills everything it finds in /proc sadly. if store_pid > 0: - debug(' Killing Tracker store') + log.debug(' Killing Tracker store') os.kill(store_pid, signal.SIGTERM) @@ -329,27 +226,22 @@ def environment_set_and_add_path(env, prefix, suffix): os.environ[env] = full -def environment_set(): +def environment_set(index_location, prefix, verbosity=0): # Environment - global dbus_session_address - global dbus_session_pid - global dbus_session_file - global index_location_abs - global default_debug_verbosity - - index_location_abs = os.path.abspath(opts.index_location) + index_location = os.path.abspath(index_location) + prefix = os.path.abspath(os.path.expanduser(prefix)) # Data - os.environ['XDG_DATA_HOME'] = '%s/data/' % index_location_abs - os.environ['XDG_CONFIG_HOME'] = '%s/config/' % index_location_abs - os.environ['XDG_CACHE_HOME'] = '%s/cache/' % index_location_abs - os.environ['XDG_RUNTIME_DIR'] = '%s/run/' % index_location_abs + os.environ['XDG_DATA_HOME'] = '%s/data/' % index_location + os.environ['XDG_CONFIG_HOME'] = '%s/config/' % index_location + os.environ['XDG_CACHE_HOME'] = '%s/cache/' % index_location + os.environ['XDG_RUNTIME_DIR'] = '%s/run/' % index_location # Prefix - only set if non-standard - if opts.prefix != default_prefix: - environment_set_and_add_path('PATH', opts.prefix, 'bin') - environment_set_and_add_path('LD_LIBRARY_PATH', opts.prefix, 'lib') - environment_set_and_add_path('XDG_DATA_DIRS', opts.prefix, 'share') + if prefix != default_prefix: + environment_set_and_add_path('PATH', prefix, 'bin') + environment_set_and_add_path('LD_LIBRARY_PATH', prefix, 'lib') + environment_set_and_add_path('XDG_DATA_DIRS', prefix, 'share') # Preferences os.environ['TRACKER_USE_CONFIG_FILES'] = 'yes' @@ -357,69 +249,57 @@ def environment_set(): # if opts.debug: # os.environ['TRACKER_USE_LOG_FILES'] = 'yes' - if opts.debug: - os.environ['G_MESSAGES_DEBUG'] = 'all' - os.environ['TRACKER_VERBOSITY'] = '%d' % default_debug_verbosity - os.environ['DBUS_VERBOSE'] = '1' - else: - os.environ['TRACKER_VERBOSITY'] = '0' + os.environ['G_MESSAGES_PREFIXED'] = 'all' + os.environ['TRACKER_VERBOSITY'] = str(verbosity) - debug('Using prefix location "%s"' % opts.prefix) - debug('Using index location "%s"' % index_location_abs) + log.debug('Using prefix location "%s"' % prefix) + log.debug('Using index location "%s"' % index_location) # Ensure directory exists # DBus specific instance dbus_session_file = os.path.join( os.environ['XDG_RUNTIME_DIR'], 'dbus-session') - if dbus_session_file_get() is False: - output = subprocess.check_output(["dbus-daemon", - "--session", - "--print-address=1", - "--print-pid=1", - "--fork"]).decode('utf-8') - - dbus_session_get_from_content(output) - dbus_session_file_set() - debug('Using new D-Bus session with address "%s" with PID %d' % - (dbus_session_address, dbus_session_pid)) - else: - debug('Using existing D-Bus session from file "%s" with address "%s"' - ' with PID %d' % - (dbus_session_file, dbus_session_address, dbus_session_pid)) + dbus = DBusDaemon(dbus_session_file) + dbus.start_if_needed() # Important, other subprocesses must use our new bus - os.environ['DBUS_SESSION_BUS_ADDRESS'] = dbus_session_address + os.environ['DBUS_SESSION_BUS_ADDRESS'] = dbus.get_address() + + # So tests can detect if they are run under sandbox or not. + os.environ['TRACKER_SANDBOX'] = '1' + + return dbus -def config_set(): +def config_set(content_locations_recursive=None, content_locations_single=None): # Make sure File System miner is configured correctly config_dir = os.path.join(os.environ['XDG_CONFIG_HOME'], 'tracker') config_filename = os.path.join(config_dir, 'tracker-miner-fs.cfg') - debug('Using config file "%s"' % config_filename) + log.debug('Using config file "%s"' % config_filename) # Only update config if we're updating the database - mkdir_p(config_dir) + os.makedirs(config_dir, exist_ok=True) if not os.path.exists(config_filename): f = open(config_filename, 'w') f.write(config_template) f.close() - debug(' Miner config file written') + log.debug(' Miner config file written') # Set content path config = configparser.ConfigParser() config.optionxform = str config.read(config_filename) - if opts.content_locations_recursive: - debug("Using content locations: %s" % - opts.content_locations_recursive) - if opts.content_locations_single: - debug("Using non-recursive content locations: %s" % - opts.content_locations_single) + if content_locations_recursive: + log.debug("Using content locations: %s" % + content_locations_recursive) + if content_locations_single: + log.debug("Using non-recursive content locations: %s" % + content_locations_single) def locations_gsetting(locations): locations = [dir if dir.startswith('&') else os.path.abspath(dir) @@ -430,9 +310,9 @@ def config_set(): config.add_section('General') config.set('General', 'index-recursive-directories', - locations_gsetting(opts.content_locations_recursive or [])) + locations_gsetting(content_locations_recursive or [])) config.set('General', 'index-single-directories', - locations_gsetting(opts.content_locations_single or [])) + locations_gsetting(content_locations_single or [])) with open(config_filename, 'w') as f: config.write(f) @@ -452,150 +332,94 @@ def link_to_mime_data(): new_mime_dir = os.path.join(new_xdg_data_home, 'mime') if (not os.path.exists(new_mime_dir) and not os.path.islink(new_mime_dir)): - mkdir_p(new_xdg_data_home) + os.makedirs(new_xdg_data_home, exist_ok=True) os.symlink( os.path.join(original_xdg_data_home, 'mime'), new_mime_dir) +def argument_parser(): + parser = argparse.ArgumentParser(description=script_about) + parser.add_argument('--version', action='store_true', + help="show version information") + parser.add_argument('--debug-dbus', action='store_true', + help="show stdout and stderr messages from every daemon " + "running on the sandbox session bus. By default we " + "only show messages logged by Tracker daemons.") + parser.add_argument('--debug-sandbox', action='store_true', + help="show debugging info from tracker-sandbox") + parser.add_argument('-v', '--verbosity', default='0', + choices=['0', '1', '2', '3', 'errors', 'minimal', 'detailed', 'debug'], + help="show debugging info from Tracker processes") + parser.add_argument('-p', '--prefix', metavar='DIR', type=str, default=default_prefix, + help=f"run Tracker from the given install prefix (default={default_prefix})") + parser.add_argument('-i', '--index', metavar='DIR', type=str, + default=default_index_location, dest='index_location', + help=f"directory to the index (default={default_index_location})") + parser.add_argument('command', type=str, nargs='*', help="Command to run inside the shell") + + return parser + + +def verbosity_as_int(verbosity): + verbosity_map = { + 'errors': 0, + 'minimal': 1, + 'detailed': 2, + 'debug': 3 + } + return verbosity_map.get(verbosity, int(args.verbosity)) + + +def init_logging(debug_sandbox, debug_dbus): + SANDBOX_FORMAT = "sandbox: %(message)s" + DBUS_FORMAT = "|%(message)s" + + if debug_sandbox: + sandbox_log_handler = logging.StreamHandler() + sandbox_log_handler.setFormatter(logging.Formatter(SANDBOX_FORMAT)) + log.setLevel(logging.DEBUG) + log.addHandler(sandbox_log_handler) + + dbus_log_handler = logging.StreamHandler() + dbus_log_handler.setFormatter(logging.Formatter(DBUS_FORMAT)) + if debug_dbus: + dbuslog.setLevel(logging.DEBUG) + else: + dbuslog.setLevel(logging.INFO) + dbuslog.addHandler(dbus_log_handler) + + # Entry point/start if __name__ == "__main__": locale.setlocale(locale.LC_ALL, '') - # Parse command line - usage_oneline = '%s -i <DIR> -c <DIR> [OPTION...]' % ( - os.path.basename(sys.argv[0])) - usage = '\n %s - %s' % (usage_oneline, script_about) - usage_invalid = 'Usage:\n %s' % (usage_oneline) - - popt = optparse.OptionParser(usage) - popt.add_option('-v', '--version', - action='count', - dest='version', - help='show version information') - popt.add_option('-d', '--debug', - action='count', - dest='debug', - help='show additional debugging') - popt.add_option('-p', '--prefix', - action='store', - metavar='PATH', - dest='prefix', - default=default_prefix, - help='use a non-standard prefix (default="%s")' % - (default_prefix)) - popt.add_option('-i', '--index', - action='store', - metavar='DIR', - dest='index_location', - help='directory storing the index') - popt.add_option('-c', '--content', - action='append', - metavar='DIR', - dest='content_locations_recursive', - help='directory storing the content which is indexed (can ' - 'be specified multiple times)') - popt.add_option('-C', '--content-non-recursive', - action='append', - metavar='DIR', - dest='content_locations_single', - help='directory storing the content which is indexed, ' - 'non-recursive variant (can be specified multiple times)') - popt.add_option('-u', '--update', - action='count', - dest='update', - help='update index/database from content') - popt.add_option('-l', '--list-files', - action='count', - dest='list_files', - help='list files indexed') - popt.add_option('-s', '--shell', - action='count', - dest='shell', - help='start a shell with the environment set up') - popt.add_option('--search', - action='store', - metavar='CRITERIA', - dest='search', - help='what content to look for in files') - popt.add_option('-q', '--sparql', - action='store', - metavar='CRITERIA', - dest='sparql_query', - help='SPARQL query to execute') - - (opts, args) = popt.parse_args() - - if opts.version: - print('%s %s\n%s\n' % (script_name, script_version, script_about)) + args = argument_parser().parse_args() + + if args.version: + print(f"{script_name} {script_version}\n{script_about}\n") sys.exit(0) - if not opts.index_location: - if not opts.content_locations_recursive and not \ - opts.content_locations_single: - print('Expected index (-i) or content (-c) locations to be ' - 'specified', file=sys.stderr) - print(usage_invalid) - sys.exit(1) - - if opts.update: - if not opts.index_location or not (opts.content_locations_recursive or - opts.content_locations_single): - print('Expected index (-i) and content (-c) locations to be ' - 'specified', file=sys.stderr) - print('These arguments are required to update the index databases', - file=sys.stderr) - sys.exit(1) - - if ((opts.sparql_query or opts.search or opts.list_files or opts.shell) - and not opts.index_location): - print('Expected index location (-i) to be specified', file=sys.stderr) - print('This arguments is required to use the content that has been ' - 'indexed', file=sys.stderr) - sys.exit(1) - - if (not opts.update - and not opts.sparql_query - and not opts.search - and not opts.list_files - and not opts.shell): - print('No action specified (e.g. update (-u), shell (-s), ' - 'list files (-l), etc)\n', file=sys.stderr) - print('%s %s\n%s\n' % (script_name, script_version, script_about), - file=sys.stderr) - print(usage_invalid, file=sys.stderr) - sys.exit(1) + init_logging(args.debug_sandbox, args.debug_dbus) + + shell = os.environ.get('SHELL', '/bin/bash') + + verbosity = verbosity_as_int(args.verbosity) # Set up environment variables and foo needed to get started. - environment_set() + dbus = environment_set(args.index_location, args.prefix, verbosity) config_set() link_to_mime_data() try: - if opts.update: - index_update() - - if opts.list_files: - db_query_list_files() - - if opts.shell: - index_shell() - sys.exit(0) - - if opts.search or opts.sparql_query: - if not os.path.exists(index_location_abs): - print('Can not query yet, index has not been created, see ' - '--update or -u', file=sys.stderr) - print(usage_invalid, file=sys.stderr) - sys.exit(1) - - if opts.search: - db_search(opts.search) - - if opts.sparql_query: - db_sparql_query(opts.sparql_query) - - except KeyboardInterrupt: - print('Handling Ctrl+C') + if args.command: + command = [shell, '-c', ' '.join(shlex.quote(c) for c in args.command)] + log.debug("Running: %s", command) + subprocess.run(command) + else: + print('Starting shell... (type "exit" to finish)') + print() - environment_unset() + os.system(shell) + finally: + environment_unset(dbus) |