1 """
2 The B{0launch} command-line interface.
3
4 This code is here, rather than in B{0launch} itself, simply so that it gets byte-compiled at
5 install time.
6 """
7
8 from __future__ import print_function
9
10 from zeroinstall import _
11 import os, sys
12 from optparse import OptionParser
13 import logging
14
15 from zeroinstall import SafeException, NeedDownload
16 from zeroinstall.injector.config import load_config
17 from zeroinstall.cmd import UsageError
18 from zeroinstall import support
19
20
21
22
23
24
25 -def main(command_args, config = None):
26 """Act as if 0launch was run with the given arguments.
27 @param command_args: array of arguments (e.g. C{sys.argv[1:]})
28 @type command_args: [str]
29 @type config: L{zeroinstall.injector.config.Config} | None"""
30
31 for std in (0, 1, 2):
32 try:
33 os.fstat(std)
34 except OSError:
35 fd = os.open(os.devnull, os.O_RDONLY)
36 if fd != std:
37 os.dup2(fd, std)
38 os.close(fd)
39
40 parser = OptionParser(usage=_("usage: %prog [options] interface [args]\n"
41 " %prog --list [search-term]\n"
42 " %prog --import [signed-interface-files]\n"
43 " %prog --feed [interface]"))
44 parser.add_option("", "--before", help=_("choose a version before this"), metavar='VERSION')
45 parser.add_option("", "--command", help=_("command to select"), metavar='COMMAND')
46 parser.add_option("-c", "--console", help=_("never use GUI"), action='store_false', dest='gui')
47 parser.add_option("", "--cpu", help=_("target CPU type"), metavar='CPU')
48 parser.add_option("-d", "--download-only", help=_("fetch but don't run"), action='store_true')
49 parser.add_option("-D", "--dry-run", help=_("just print actions"), action='store_true')
50 parser.add_option("-f", "--feed", help=_("add or remove a feed"), action='store_true')
51 parser.add_option("", "--get-selections", help=_("write selected versions as XML"), action='store_true', dest='xml')
52 parser.add_option("-g", "--gui", help=_("show graphical policy editor"), action='store_true')
53 parser.add_option("-i", "--import", help=_("import from files, not from the network"), action='store_true')
54 parser.add_option("-l", "--list", help=_("list all known interfaces"), action='store_true')
55 parser.add_option("-m", "--main", help=_("name of the file to execute"))
56 parser.add_option("", "--message", help=_("message to display when interacting with user"))
57 parser.add_option("", "--not-before", help=_("minimum version to choose"), metavar='VERSION')
58 parser.add_option("", "--os", help=_("target operation system type"), metavar='OS')
59 parser.add_option("-o", "--offline", help=_("try to avoid using the network"), action='store_true')
60 parser.add_option("-r", "--refresh", help=_("refresh all used interfaces"), action='store_true')
61 parser.add_option("", "--select-only", help=_("only download the feeds"), action='store_true')
62 parser.add_option("", "--set-selections", help=_("run versions specified in XML file"), metavar='FILE')
63 parser.add_option("", "--show", help=_("show where components are installed"), action='store_true')
64 parser.add_option("-s", "--source", help=_("select source code"), action='store_true')
65 parser.add_option("-v", "--verbose", help=_("more verbose output"), action='count')
66 parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR')
67 parser.add_option("-w", "--wrapper", help=_("execute program using a debugger, etc"), metavar='COMMAND')
68 parser.disable_interspersed_args()
69
70
71 allow_version_expr = any(not arg.startswith('-') for arg in command_args)
72 if allow_version_expr:
73 parser.add_option("", "--version", help=_("specify version constraint (e.g. '3' or '3..')"), metavar='RANGE')
74 parser.add_option("", "--version-for", help=_("set version constraints for a specific interface"),
75 nargs=2, metavar='URI RANGE', action='append')
76 else:
77 parser.add_option("-V", "--version", help=_("display version information"), action='store_true')
78
79 (options, args) = parser.parse_args(command_args)
80
81 if options.verbose:
82 logger = logging.getLogger()
83 if options.verbose == 1:
84 logger.setLevel(logging.INFO)
85 else:
86 logger.setLevel(logging.DEBUG)
87 import zeroinstall
88 logging.info(_("Running 0launch %(version)s %(args)s; Python %(python_version)s"), {'version': zeroinstall.version, 'args': repr(args), 'python_version': sys.version})
89
90 if options.select_only or options.show:
91 options.download_only = True
92
93 if config is None:
94 config = load_config()
95 config.handler.dry_run = bool(options.dry_run)
96
97 if options.with_store:
98 from zeroinstall import zerostore
99 for x in options.with_store:
100 config.stores.stores.append(zerostore.Store(os.path.abspath(x)))
101 logging.info(_("Stores search path is now %s"), config.stores.stores)
102
103 if options.set_selections:
104 args = [options.set_selections] + args
105
106 try:
107 if options.list:
108 from zeroinstall.cmd import list
109 list.handle(config, options, args)
110 elif options.version and not allow_version_expr:
111 import zeroinstall
112 print("0launch (zero-install) " + zeroinstall.version)
113 print("Copyright (C) 2010 Thomas Leonard")
114 print(_("This program comes with ABSOLUTELY NO WARRANTY,"
115 "\nto the extent permitted by law."
116 "\nYou may redistribute copies of this program"
117 "\nunder the terms of the GNU Lesser General Public License."
118 "\nFor more information about these matters, see the file named COPYING."))
119 elif getattr(options, 'import'):
120
121 cmd = __import__('zeroinstall.cmd.import', globals(), locals(), ["import"], 0)
122 cmd.handle(config, options, args)
123 elif options.feed:
124 from zeroinstall.cmd import add_feed
125 add_feed.handle(config, options, args, add_ok = True, remove_ok = True)
126 elif options.select_only:
127 from zeroinstall.cmd import select
128 if not options.show:
129 options.quiet = True
130 select.handle(config, options, args)
131 elif options.download_only or options.xml or options.show:
132 from zeroinstall.cmd import download
133 download.handle(config, options, args)
134 else:
135 if len(args) < 1:
136 if options.gui:
137
138 from zeroinstall import helpers
139 helpers.get_selections_gui(None, [])
140 else:
141 raise UsageError()
142 else:
143 from zeroinstall.cmd import run
144 run.handle(config, options, args)
145 except NeedDownload as ex:
146
147 print(ex)
148 except KeyboardInterrupt:
149 logging.info("KeyboardInterrupt")
150 sys.exit(1)
151 except UsageError:
152 parser.print_help()
153 sys.exit(1)
154 except SafeException as ex:
155 if options.verbose: raise
156 try:
157 print(support.unicode(ex), file=sys.stderr)
158 except:
159 print(repr(ex), file=sys.stderr)
160 sys.exit(1)
161