2 The B{0install} command-line interface.
5 # Copyright (C) 2011, Thomas Leonard
6 # See the README file for details, or visit http://0install.net.
8 from __future__
import print_function
10 from zeroinstall
import _
12 from optparse
import OptionParser
15 from zeroinstall
import SafeException
17 valid_commands
= ['add', 'select', 'download', 'run', 'update', 'whatchanged', 'destroy',
18 'config', 'import', 'list', 'add-feed', 'remove-feed', 'list-feeds',
21 class UsageError(Exception): pass
23 def _ensure_standard_fds():
24 "Ensure stdin, stdout and stderr FDs exist, to avoid confusion."
29 fd
= os
.open(os
.devnull
, os
.O_RDONLY
)
34 def _no_command(command_args
):
35 """Handle --help and --version"""
36 parser
= OptionParser(usage
=_("usage: %prog COMMAND\n\nTry --help with one of these:") +
37 "\n\n0install " + '\n0install '.join(valid_commands
))
38 parser
.add_option("-V", "--version", help=_("display version information"), action
='store_true')
40 (options
, args
) = parser
.parse_args(command_args
)
43 print("0install (zero-install) " + zeroinstall
.version
)
44 print("Copyright (C) 2011 Thomas Leonard")
45 print(_("This program comes with ABSOLUTELY NO WARRANTY,"
46 "\nto the extent permitted by law."
47 "\nYou may redistribute copies of this program"
48 "\nunder the terms of the GNU Lesser General Public License."
49 "\nFor more information about these matters, see the file named COPYING."))
54 def main(command_args
, config
= None):
55 """Act as if 0install was run with the given arguments.
56 @arg command_args: array of arguments (e.g. C{sys.argv[1:]})
57 @type command_args: [str]
59 _ensure_standard_fds()
62 from zeroinstall
.injector
.config
import load_config
63 config
= load_config()
65 # The first non-option argument is the command name (or "help" if none is found).
67 for i
, arg
in enumerate(command_args
):
68 if not arg
.startswith('-'):
78 return _no_command(command_args
)
80 if command
not in valid_commands
:
81 raise SafeException(_("Unknown sub-command '%s': try --help") % command
)
83 # Configure a parser for the given command
84 module_name
= command
.replace('-', '_')
85 cmd
= __import__('zeroinstall.cmd.' + module_name
, globals(), locals(), [module_name
], 0)
86 parser
= OptionParser(usage
=_("usage: %%prog %s [OPTIONS] %s") % (command
, cmd
.syntax
))
88 parser
.add_option("-c", "--console", help=_("never use GUI"), action
='store_false', dest
='gui')
89 parser
.add_option("", "--dry-run", help=_("just print what would be executed"), action
='store_true')
90 parser
.add_option("-g", "--gui", help=_("show graphical policy editor"), action
='store_true')
91 parser
.add_option("-v", "--verbose", help=_("more verbose output"), action
='count')
92 parser
.add_option("", "--with-store", help=_("add an implementation cache"), action
='append', metavar
='DIR')
94 cmd
.add_options(parser
)
95 (options
, args
) = parser
.parse_args(command_args
)
98 logger
= logging
.getLogger()
99 if options
.verbose
== 1:
100 logger
.setLevel(logging
.INFO
)
102 logger
.setLevel(logging
.DEBUG
)
104 logging
.info(_("Running 0install %(version)s %(args)s; Python %(python_version)s"), {'version': zeroinstall
.version
, 'args': repr(command_args
), 'python_version': sys
.version
})
106 if options
.with_store
:
107 from zeroinstall
import zerostore
108 for x
in options
.with_store
:
109 config
.stores
.stores
.append(zerostore
.Store(os
.path
.abspath(x
)))
110 logging
.info(_("Stores search path is now %s"), config
.stores
.stores
)
112 config
.handler
.dry_run
= bool(options
.dry_run
)
114 cmd
.handle(config
, options
, args
)
115 except KeyboardInterrupt:
116 logging
.info("KeyboardInterrupt")
121 except SafeException
as ex
:
124 print(unicode(ex
), file=sys
.stderr
)
126 print(repr(ex
), file=sys
.stderr
)