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