From 289316e853091bba49dade1e5155d9b36c6a4e56 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Sun, 14 Aug 2011 18:01:45 +0100 Subject: [PATCH] Added --command option to 0alias Suggested by Tim Diels. --- 0alias | 18 +++++++++++----- 0alias.1 | 14 ++++++++++--- tests/testalias.py | 28 +++++++++++++++++++++++++ zeroinstall/alias.py | 48 +++++++++++++++++++++++++++++++------------ zeroinstall/injector/model.py | 3 +-- 5 files changed, 88 insertions(+), 23 deletions(-) diff --git a/0alias b/0alias index fb76355..7c0aa87 100755 --- a/0alias +++ b/0alias @@ -50,10 +50,11 @@ if not in_path: parser = OptionParser(usage="usage: %%prog [options] alias [interface [main]]\n\n" "Creates a script to run 'interface' (will be created in\n" - "%s unless overridden by --dir).\n" + "%s unless overridden by --dir).\n\n" "If no interface is given, edits the policy for an existing alias.\n" "For interfaces providing more than one executable, the desired\n" - "'main' binary may also be given." % first_path) + "'main' binary or command may also be given." % first_path) +parser.add_option("-c", "--command", help="the command the alias will run (default 'run')", metavar='COMMNAD') parser.add_option("-m", "--manpage", help="show the manual page for an existing alias", action='store_true') parser.add_option("-r", "--resolve", help="show the URI for an alias", action='store_true') parser.add_option("-V", "--version", help="display version information", action='store_true') @@ -82,6 +83,7 @@ if len(args) < 1 or len(args) > 3: parser.print_help() sys.exit(1) alias_prog, interface_uri, main = (list(args) + [None, None])[:3] +command = options.command or 'run' if options.resolve or options.manpage: if interface_uri is not None: @@ -92,6 +94,9 @@ if options.user_path: first_path = options.user_path if interface_uri is None: + if options.command: + print >>sys.stderr, "Can't use --command when editing an existing alias" + sys.exit(1) try: if not os.path.isabs(alias_prog): full_path = support.find_in_path(alias_prog) @@ -100,7 +105,10 @@ if interface_uri is None: else: full_path = alias_prog - interface_uri, main = alias.parse_script(full_path) + alias_info = alias.parse_script(full_path) + interface_uri = alias_info.uri + main = alias_info.main + command = alias_info.command except alias.NotAnAliasScript as ex: if options.manpage: os.execlp('man', 'man', *args) @@ -114,7 +122,7 @@ if options.resolve: sys.exit(0) if options.manpage: - sels = helpers.ensure_cached(interface_uri) + sels = helpers.ensure_cached(interface_uri, command = command) if not sels: # Cancelled by user sys.exit(1) @@ -201,7 +209,7 @@ except model.SafeException as ex: sys.exit(1) wrapper = file(script, 'w') -alias.write_script(wrapper, interface_uri, main) +alias.write_script(wrapper, interface_uri, main, command = command) # Make new script executable os.chmod(script, 0o111 | os.fstat(wrapper.fileno()).st_mode) diff --git a/0alias.1 b/0alias.1 index 0a005d1..ec42c6f 100644 --- a/0alias.1 +++ b/0alias.1 @@ -1,11 +1,11 @@ -.TH 0ALIAS 1 "2010" "Thomas Leonard" "" +.TH 0ALIAS 1 "2011" "Thomas Leonard" "" .SH NAME 0alias \(em create quick scripts to run 0launch .SH SYNOPSIS .B 0alias -\fBALIAS\fP [\fBINTERFACE\fP [\fBCOMMAND\fP]] +\fBALIAS\fP [\fBINTERFACE\fP [\fBMAIN\fP]] .SH DESCRIPTION .PP @@ -43,10 +43,18 @@ one to use instead of the default. e.g. .B 0alias svnadmin http://example.com/subversion svnadmin +.PP +(this is for older programs that use MAIN; for newer programs you may need to +use \-\-command instead) + .SH COMMAND-LINE OPTIONS .TP +\fB\-c=COMMAND\fP, \fB\-\-command=COMMAND\fP +The generated script will execute COMMAND rather than the default ("run"). + +.TP \fB\-d=DIR\fP, \fB\-\-dir=DIR\fP Install the script into directory DIR, rather than searching for a suitable directory in $PATH. @@ -75,7 +83,7 @@ Display version information. .SH LICENSE .PP -Copyright (C) 2007 Thomas Leonard. +Copyright (C) 2011 Thomas Leonard. .PP You may redistribute copies of this program under the terms of the GNU Lesser General Public License. diff --git a/tests/testalias.py b/tests/testalias.py index a2d4366..4c134da 100755 --- a/tests/testalias.py +++ b/tests/testalias.py @@ -24,6 +24,10 @@ expected_script_main = """#!/bin/sh exec 0launch --main 'a'\\'''\\''\\test' 'http://example.com/foo.xml' "$@" """ +expected_script_command = """#!/bin/sh +exec 0launch --command 'a'\\'''\\''\\test' 'http://example.com/foo.xml' "$@" +""" + old_script_main = """#!/bin/sh if [ "$*" = "--versions" ]; then exec 0launch -gd 'http://example.com/foo.xml' "$@" @@ -45,6 +49,10 @@ class TestAlias(BaseTest): alias.write_script(buf, 'http://example.com/foo.xml', 'a\'\'\\test') self.assertEquals(expected_script_main, buf.getvalue()) + buf = StringIO() + alias.write_script(buf, 'http://example.com/foo.xml', command = 'a\'\'\\test') + self.assertEquals(expected_script_command, buf.getvalue()) + def testParse(self): tmp = tempfile.NamedTemporaryFile() tmp.write(expected_script) @@ -62,6 +70,15 @@ class TestAlias(BaseTest): self.assertEquals('http://example.com/foo.xml', uri) self.assertEquals('a\'\'\\test', main) + tmp = tempfile.NamedTemporaryFile() + tmp.write(expected_script_command) + tmp.flush() + tmp.seek(0) + info = alias.parse_script(tmp.name) + self.assertEquals('http://example.com/foo.xml', info.uri) + self.assertEquals('a\'\'\\test', info.command) + self.assertEquals(None, info.main) + def testParseOld(self): tmp = tempfile.NamedTemporaryFile() tmp.write(old_script) @@ -90,5 +107,16 @@ class TestAlias(BaseTest): except alias.NotAnAliasScript: pass + tmp = tempfile.NamedTemporaryFile() + tmp.write(expected_script_command.replace('command', 'bob')) + tmp.flush() + tmp.seek(0) + try: + alias.parse_script(tmp.name) + assert False + except alias.NotAnAliasScript, ex: + assert 'bob' in str(ex) + pass + if __name__ == '__main__': unittest.main() diff --git a/zeroinstall/alias.py b/zeroinstall/alias.py index f46b59c..1a19758 100644 --- a/zeroinstall/alias.py +++ b/zeroinstall/alias.py @@ -23,11 +23,21 @@ exec 0launch %s'%s' "$@" class NotAnAliasScript(Exception): pass +class ScriptInfo: + """@since: 1.3""" + uri = None + main = None + command = None + + # For backwards compatibility + def __iter__(self): + return iter([self.uri, self.main]) + def parse_script(pathname): """Extract the URI and main values from a 0alias script. @param pathname: the script to be examined - @return: a tuple containing the URI and the main (or None if not set) - @rtype: (str, str | None) + @return: information about the alias script + @rtype: L{ScriptInfo} @raise NotAnAliasScript: if we can't parse the script """ stream = file(pathname) @@ -47,28 +57,40 @@ def parse_script(pathname): rest = stream.read() line = rest.split('\n')[2] + info = ScriptInfo() split = line.rfind("' '") if split != -1: - # We have a --main - uri = line[split + 3:].split("'")[0] - main = line[:split].split("'", 1)[1].replace("'\\''", "'") + # We have a --main or --command + info.uri = line[split + 3:].split("'")[0] + start, value = line[:split].split("'", 1) + option = start.split('--', 1)[1].strip() + value = value.replace("'\\''", "'") + if option == 'main': + info.main = value + elif option == 'command': + info.command = value + else: + raise NotAnAliasScript("Unknown option '{option}' in alias script".format(option = option)) else: - main = None - uri = line.split("'",2)[1] + info.uri = line.split("'",2)[1] - return (uri, main) + return info -def write_script(stream, interface_uri, main = None): +def write_script(stream, interface_uri, main = None, command = None): """Write a shell script to stream that will launch the given program. @param stream: the stream to write to @param interface_uri: the program to launch - @param main: the --main argument to pass to 0launch, if any""" + @param main: the --main argument to pass to 0launch, if any + @param command: the --command argument to pass to 0launch, if any""" assert "'" not in interface_uri assert "\\" not in interface_uri + assert main is None or command is None, "Can't set --main and --command together" if main is not None: - main_arg = "--main '%s' " % main.replace("'", "'\\''") + option = "--main '%s' " % main.replace("'", "'\\''") + elif command is not None: + option = "--command '%s' " % command.replace("'", "'\\''") else: - main_arg = "" + option = "" - stream.write(_template % (main_arg, interface_uri)) + stream.write(_template % (option, interface_uri)) diff --git a/zeroinstall/injector/model.py b/zeroinstall/injector/model.py index c0bcbc0..4cef2c7 100644 --- a/zeroinstall/injector/model.py +++ b/zeroinstall/injector/model.py @@ -1209,8 +1209,7 @@ def canonical_iface_uri(uri): raise alias.NotAnAliasScript("Not found in $PATH: " + alias_prog) else: full_path = alias_prog - interface_uri, main = alias.parse_script(full_path) - return interface_uri + return alias.parse_script(full_path).uri else: iface_uri = os.path.realpath(uri) if os.path.isfile(iface_uri): -- 2.11.4.GIT