All unit-tests now pass with Python 3
[zeroinstall/solver.git] / zeroinstall / injector / cli.py
bloba65f59f7a7191e2eb9caca6a98d81f16a927be62
1 """
2 The B{0launch} command-line interface.
4 This code is here, rather than in B{0launch} itself, simply so that it gets byte-compiled at
5 install time.
6 """
8 from __future__ import print_function
10 from zeroinstall import _
11 import os, sys
12 from optparse import OptionParser
13 import logging
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
20 #def program_log(msg): os.access('MARK: 0launch: ' + msg, os.F_OK)
21 #import __main__
22 #__main__.__builtins__.program_log = program_log
23 #program_log('0launch ' + ' '.join((sys.argv[1:])))
25 def main(command_args, config = None):
26 """Act as if 0launch was run with the given arguments.
27 @arg command_args: array of arguments (e.g. C{sys.argv[1:]})
28 @type command_args: [str]
29 """
30 # Ensure stdin, stdout and stderr FDs exist, to avoid confusion
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)
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("-V", "--version", help=_("display version information"), action='store_true')
67 parser.add_option("", "--with-store", help=_("add an implementation cache"), action='append', metavar='DIR')
68 parser.add_option("-w", "--wrapper", help=_("execute program using a debugger, etc"), metavar='COMMAND')
69 parser.disable_interspersed_args()
71 (options, args) = parser.parse_args(command_args)
73 if options.verbose:
74 logger = logging.getLogger()
75 if options.verbose == 1:
76 logger.setLevel(logging.INFO)
77 else:
78 logger.setLevel(logging.DEBUG)
79 import zeroinstall
80 logging.info(_("Running 0launch %(version)s %(args)s; Python %(python_version)s"), {'version': zeroinstall.version, 'args': repr(args), 'python_version': sys.version})
82 if options.select_only or options.show:
83 options.download_only = True
85 if config is None:
86 config = load_config()
87 config.handler.dry_run = bool(options.dry_run)
89 if options.with_store:
90 from zeroinstall import zerostore
91 for x in options.with_store:
92 config.stores.stores.append(zerostore.Store(os.path.abspath(x)))
93 logging.info(_("Stores search path is now %s"), config.stores.stores)
95 if options.set_selections:
96 args = [options.set_selections] + args
98 try:
99 if options.list:
100 from zeroinstall.cmd import list
101 list.handle(config, options, args)
102 elif options.version:
103 import zeroinstall
104 print("0launch (zero-install) " + zeroinstall.version)
105 print("Copyright (C) 2010 Thomas Leonard")
106 print(_("This program comes with ABSOLUTELY NO WARRANTY,"
107 "\nto the extent permitted by law."
108 "\nYou may redistribute copies of this program"
109 "\nunder the terms of the GNU Lesser General Public License."
110 "\nFor more information about these matters, see the file named COPYING."))
111 elif getattr(options, 'import'):
112 # (import is a keyword)
113 cmd = __import__('zeroinstall.cmd.import', globals(), locals(), ["import"], 0)
114 cmd.handle(config, options, args)
115 elif options.feed:
116 from zeroinstall.cmd import add_feed
117 add_feed.handle(config, options, args, add_ok = True, remove_ok = True)
118 elif options.select_only:
119 from zeroinstall.cmd import select
120 if not options.show:
121 options.quiet = True
122 select.handle(config, options, args)
123 elif options.download_only or options.xml or options.show:
124 from zeroinstall.cmd import download
125 download.handle(config, options, args)
126 else:
127 if len(args) < 1:
128 if options.gui:
129 from zeroinstall import helpers
130 return helpers.get_selections_gui(None, [])
131 else:
132 raise UsageError()
133 else:
134 from zeroinstall.cmd import run
135 run.handle(config, options, args)
136 except NeedDownload as ex:
137 # This only happens for dry runs
138 print(ex)
139 except KeyboardInterrupt:
140 logging.info("KeyboardInterrupt")
141 sys.exit(1)
142 except UsageError:
143 parser.print_help()
144 sys.exit(1)
145 except SafeException as ex:
146 if options.verbose: raise
147 try:
148 print(support.unicode(ex), file=sys.stderr)
149 except:
150 print(repr(ex), file=sys.stderr)
151 sys.exit(1)