Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.py @ 4549:0c61124ad877
dispatch: move dispatching code to cmdutil
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 11 Jun 2007 21:09:24 -0500 |
parents | c9fcebbfc422 |
children | a73d80d6385a |
comparison
equal
deleted
inserted
replaced
4548:c9fcebbfc422 | 4549:0c61124ad877 |
---|---|
6 # of the GNU General Public License, incorporated herein by reference. | 6 # of the GNU General Public License, incorporated herein by reference. |
7 | 7 |
8 import demandimport; demandimport.enable() | 8 import demandimport; demandimport.enable() |
9 from node import * | 9 from node import * |
10 from i18n import _ | 10 from i18n import _ |
11 import bisect, os, re, sys, signal, urllib, pdb, shlex, stat | 11 import bisect, os, re, sys, urllib, shlex, stat |
12 import fancyopts, ui, hg, util, lock, revlog, bundlerepo, extensions | 12 import ui, hg, util, revlog, bundlerepo, extensions |
13 import difflib, patch, time, help, mdiff, tempfile | 13 import difflib, patch, time, help, mdiff, tempfile |
14 import traceback, errno, version, atexit, socket | 14 import errno, version, socket |
15 import archival, changegroup, cmdutil, hgweb.server, sshserver | 15 import archival, changegroup, cmdutil, hgweb.server, sshserver |
16 | |
17 class UnknownCommand(Exception): | |
18 """Exception raised if command is not in the command table.""" | |
19 class AmbiguousCommand(Exception): | |
20 """Exception raised if command shortcut matches more than one command.""" | |
21 | |
22 def bail_if_changed(repo): | |
23 modified, added, removed, deleted = repo.status()[:4] | |
24 if modified or added or removed or deleted: | |
25 raise util.Abort(_("outstanding uncommitted changes")) | |
26 | |
27 def logmessage(opts): | |
28 """ get the log message according to -m and -l option """ | |
29 message = opts['message'] | |
30 logfile = opts['logfile'] | |
31 | |
32 if message and logfile: | |
33 raise util.Abort(_('options --message and --logfile are mutually ' | |
34 'exclusive')) | |
35 if not message and logfile: | |
36 try: | |
37 if logfile == '-': | |
38 message = sys.stdin.read() | |
39 else: | |
40 message = open(logfile).read() | |
41 except IOError, inst: | |
42 raise util.Abort(_("can't read commit message '%s': %s") % | |
43 (logfile, inst.strerror)) | |
44 return message | |
45 | |
46 def setremoteconfig(ui, opts): | |
47 "copy remote options to ui tree" | |
48 if opts.get('ssh'): | |
49 ui.setconfig("ui", "ssh", opts['ssh']) | |
50 if opts.get('remotecmd'): | |
51 ui.setconfig("ui", "remotecmd", opts['remotecmd']) | |
52 | 16 |
53 # Commands start here, listed alphabetically | 17 # Commands start here, listed alphabetically |
54 | 18 |
55 def add(ui, repo, *pats, **opts): | 19 def add(ui, repo, *pats, **opts): |
56 """add the specified files on the next commit | 20 """add the specified files on the next commit |
203 raise util.Abort(_("please specify just one revision")) | 167 raise util.Abort(_("please specify just one revision")) |
204 | 168 |
205 if not rev: | 169 if not rev: |
206 rev = node | 170 rev = node |
207 | 171 |
208 bail_if_changed(repo) | 172 cmdutil.bail_if_changed(repo) |
209 op1, op2 = repo.dirstate.parents() | 173 op1, op2 = repo.dirstate.parents() |
210 if op2 != nullid: | 174 if op2 != nullid: |
211 raise util.Abort(_('outstanding uncommitted merge')) | 175 raise util.Abort(_('outstanding uncommitted merge')) |
212 node = repo.lookup(rev) | 176 node = repo.lookup(rev) |
213 p1, p2 = repo.changelog.parents(node) | 177 p1, p2 = repo.changelog.parents(node) |
333 for p in parents: | 297 for p in parents: |
334 if p not in seen: | 298 if p not in seen: |
335 seen[p] = 1 | 299 seen[p] = 1 |
336 visit.append(p) | 300 visit.append(p) |
337 else: | 301 else: |
338 setremoteconfig(ui, opts) | 302 cmdutil.setremoteconfig(ui, opts) |
339 dest, revs = cmdutil.parseurl( | 303 dest, revs = cmdutil.parseurl( |
340 ui.expandpath(dest or 'default-push', dest or 'default'), revs) | 304 ui.expandpath(dest or 'default-push', dest or 'default'), revs) |
341 other = hg.repository(ui, dest) | 305 other = hg.repository(ui, dest) |
342 o = repo.findoutgoing(other, force=opts['force']) | 306 o = repo.findoutgoing(other, force=opts['force']) |
343 | 307 |
405 It is possible to specify an ssh:// URL as the destination, but no | 369 It is possible to specify an ssh:// URL as the destination, but no |
406 .hg/hgrc and working directory will be created on the remote side. | 370 .hg/hgrc and working directory will be created on the remote side. |
407 Look at the help text for the pull command for important details | 371 Look at the help text for the pull command for important details |
408 about ssh:// URLs. | 372 about ssh:// URLs. |
409 """ | 373 """ |
410 setremoteconfig(ui, opts) | 374 cmdutil.setremoteconfig(ui, opts) |
411 hg.clone(ui, source, dest, | 375 hg.clone(ui, source, dest, |
412 pull=opts['pull'], | 376 pull=opts['pull'], |
413 stream=opts['uncompressed'], | 377 stream=opts['uncompressed'], |
414 rev=opts['rev'], | 378 rev=opts['rev'], |
415 update=not opts['noupdate']) | 379 update=not opts['noupdate']) |
423 will be committed. | 387 will be committed. |
424 | 388 |
425 If no commit message is specified, the editor configured in your hgrc | 389 If no commit message is specified, the editor configured in your hgrc |
426 or in the EDITOR environment variable is started to enter a message. | 390 or in the EDITOR environment variable is started to enter a message. |
427 """ | 391 """ |
428 message = logmessage(opts) | 392 message = cmdutil.logmessage(opts) |
429 | 393 |
430 if opts['addremove']: | 394 if opts['addremove']: |
431 cmdutil.addremove(repo, pats, opts) | 395 cmdutil.addremove(repo, pats, opts) |
432 fns, match, anypats = cmdutil.matchpats(repo, pats, opts) | 396 fns, match, anypats = cmdutil.matchpats(repo, pats, opts) |
433 if pats: | 397 if pats: |
683 | 647 |
684 if opts['options']: | 648 if opts['options']: |
685 options = [] | 649 options = [] |
686 otables = [globalopts] | 650 otables = [globalopts] |
687 if cmd: | 651 if cmd: |
688 aliases, entry = findcmd(ui, cmd) | 652 aliases, entry = cmdutil.findcmd(ui, cmd) |
689 otables.append(entry[1]) | 653 otables.append(entry[1]) |
690 for t in otables: | 654 for t in otables: |
691 for o in t: | 655 for o in t: |
692 if o[0]: | 656 if o[0]: |
693 options.append('-%s' % o[0]) | 657 options.append('-%s' % o[0]) |
694 options.append('--%s' % o[1]) | 658 options.append('--%s' % o[1]) |
695 ui.write("%s\n" % "\n".join(options)) | 659 ui.write("%s\n" % "\n".join(options)) |
696 return | 660 return |
697 | 661 |
698 clist = findpossible(ui, cmd).keys() | 662 clist = cmdutil.findpossible(ui, cmd).keys() |
699 clist.sort() | 663 clist.sort() |
700 ui.write("%s\n" % "\n".join(clist)) | 664 ui.write("%s\n" % "\n".join(clist)) |
701 | 665 |
702 def debugrebuildstate(ui, repo, rev=""): | 666 def debugrebuildstate(ui, repo, rev=""): |
703 """rebuild the dirstate as it would look like for the given revision""" | 667 """rebuild the dirstate as it would look like for the given revision""" |
1293 | 1257 |
1294 def helpcmd(name): | 1258 def helpcmd(name): |
1295 if with_version: | 1259 if with_version: |
1296 version_(ui) | 1260 version_(ui) |
1297 ui.write('\n') | 1261 ui.write('\n') |
1298 aliases, i = findcmd(ui, name) | 1262 aliases, i = cmdutil.findcmd(ui, name) |
1299 # synopsis | 1263 # synopsis |
1300 ui.write("%s\n\n" % i[2]) | 1264 ui.write("%s\n\n" % i[2]) |
1301 | 1265 |
1302 # description | 1266 # description |
1303 doc = i[0].__doc__ | 1267 doc = i[0].__doc__ |
1355 l = i.split('|') | 1319 l = i.split('|') |
1356 if name in l: | 1320 if name in l: |
1357 v = i | 1321 v = i |
1358 header = l[-1] | 1322 header = l[-1] |
1359 if not v: | 1323 if not v: |
1360 raise UnknownCommand(name) | 1324 raise cmdutil.UnknownCommand(name) |
1361 | 1325 |
1362 # description | 1326 # description |
1363 doc = help.helptable[v] | 1327 doc = help.helptable[v] |
1364 if not doc: | 1328 if not doc: |
1365 doc = _("(No help text available)") | 1329 doc = _("(No help text available)") |
1371 | 1335 |
1372 def helpext(name): | 1336 def helpext(name): |
1373 try: | 1337 try: |
1374 mod = extensions.find(name) | 1338 mod = extensions.find(name) |
1375 except KeyError: | 1339 except KeyError: |
1376 raise UnknownCommand(name) | 1340 raise cmdutil.UnknownCommand(name) |
1377 | 1341 |
1378 doc = (mod.__doc__ or _('No help text available')).splitlines(0) | 1342 doc = (mod.__doc__ or _('No help text available')).splitlines(0) |
1379 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0])) | 1343 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0])) |
1380 for d in doc[1:]: | 1344 for d in doc[1:]: |
1381 ui.write(d, '\n') | 1345 ui.write(d, '\n') |
1397 for f in (helpcmd, helptopic, helpext): | 1361 for f in (helpcmd, helptopic, helpext): |
1398 try: | 1362 try: |
1399 f(name) | 1363 f(name) |
1400 i = None | 1364 i = None |
1401 break | 1365 break |
1402 except UnknownCommand, inst: | 1366 except cmdutil.UnknownCommand, inst: |
1403 i = inst | 1367 i = inst |
1404 if i: | 1368 if i: |
1405 raise i | 1369 raise i |
1406 | 1370 |
1407 else: | 1371 else: |
1504 To read a patch from standard input, use patch name "-". | 1468 To read a patch from standard input, use patch name "-". |
1505 """ | 1469 """ |
1506 patches = (patch1,) + patches | 1470 patches = (patch1,) + patches |
1507 | 1471 |
1508 if opts.get('exact') or not opts['force']: | 1472 if opts.get('exact') or not opts['force']: |
1509 bail_if_changed(repo) | 1473 cmdutil.bail_if_changed(repo) |
1510 | 1474 |
1511 d = opts["base"] | 1475 d = opts["base"] |
1512 strip = opts["strip"] | 1476 strip = opts["strip"] |
1513 | 1477 |
1514 wlock = repo.wlock() | 1478 wlock = repo.wlock() |
1526 | 1490 |
1527 if tmpname is None: | 1491 if tmpname is None: |
1528 raise util.Abort(_('no diffs found')) | 1492 raise util.Abort(_('no diffs found')) |
1529 | 1493 |
1530 try: | 1494 try: |
1531 cmdline_message = logmessage(opts) | 1495 cmdline_message = cmdutil.logmessage(opts) |
1532 if cmdline_message: | 1496 if cmdline_message: |
1533 # pickup the cmdline msg | 1497 # pickup the cmdline msg |
1534 message = cmdline_message | 1498 message = cmdline_message |
1535 elif message: | 1499 elif message: |
1536 # pickup the patch msg | 1500 # pickup the patch msg |
1585 twice if the incoming is followed by a pull. | 1549 twice if the incoming is followed by a pull. |
1586 | 1550 |
1587 See pull for valid source format details. | 1551 See pull for valid source format details. |
1588 """ | 1552 """ |
1589 source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev']) | 1553 source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev']) |
1590 setremoteconfig(ui, opts) | 1554 cmdutil.setremoteconfig(ui, opts) |
1591 | 1555 |
1592 other = hg.repository(ui, source) | 1556 other = hg.repository(ui, source) |
1593 ui.status(_('comparing with %s\n') % source) | 1557 ui.status(_('comparing with %s\n') % source) |
1594 if revs: | 1558 if revs: |
1595 if 'lookup' in other.capabilities: | 1559 if 'lookup' in other.capabilities: |
1651 | 1615 |
1652 It is possible to specify an ssh:// URL as the destination. | 1616 It is possible to specify an ssh:// URL as the destination. |
1653 Look at the help text for the pull command for important details | 1617 Look at the help text for the pull command for important details |
1654 about ssh:// URLs. | 1618 about ssh:// URLs. |
1655 """ | 1619 """ |
1656 setremoteconfig(ui, opts) | 1620 cmdutil.setremoteconfig(ui, opts) |
1657 hg.repository(ui, dest, create=1) | 1621 hg.repository(ui, dest, create=1) |
1658 | 1622 |
1659 def locate(ui, repo, *pats, **opts): | 1623 def locate(ui, repo, *pats, **opts): |
1660 """locate files matching specific patterns | 1624 """locate files matching specific patterns |
1661 | 1625 |
1888 | 1852 |
1889 See pull for valid destination format details. | 1853 See pull for valid destination format details. |
1890 """ | 1854 """ |
1891 dest, revs = cmdutil.parseurl( | 1855 dest, revs = cmdutil.parseurl( |
1892 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev']) | 1856 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev']) |
1893 setremoteconfig(ui, opts) | 1857 cmdutil.setremoteconfig(ui, opts) |
1894 if revs: | 1858 if revs: |
1895 revs = [repo.lookup(rev) for rev in revs] | 1859 revs = [repo.lookup(rev) for rev in revs] |
1896 | 1860 |
1897 other = hg.repository(ui, dest) | 1861 other = hg.repository(ui, dest) |
1898 ui.status(_('comparing with %s\n') % dest) | 1862 ui.status(_('comparing with %s\n') % dest) |
2003 Compression yes | 1967 Compression yes |
2004 Alternatively specify "ssh -C" as your ssh command in your hgrc or | 1968 Alternatively specify "ssh -C" as your ssh command in your hgrc or |
2005 with the --ssh command line option. | 1969 with the --ssh command line option. |
2006 """ | 1970 """ |
2007 source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev']) | 1971 source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev']) |
2008 setremoteconfig(ui, opts) | 1972 cmdutil.setremoteconfig(ui, opts) |
2009 | 1973 |
2010 other = hg.repository(ui, source) | 1974 other = hg.repository(ui, source) |
2011 ui.status(_('pulling from %s\n') % (source)) | 1975 ui.status(_('pulling from %s\n') % (source)) |
2012 if revs: | 1976 if revs: |
2013 if 'lookup' in other.capabilities: | 1977 if 'lookup' in other.capabilities: |
2049 Pushing to http:// and https:// URLs is only possible, if this | 2013 Pushing to http:// and https:// URLs is only possible, if this |
2050 feature is explicitly enabled on the remote Mercurial server. | 2014 feature is explicitly enabled on the remote Mercurial server. |
2051 """ | 2015 """ |
2052 dest, revs = cmdutil.parseurl( | 2016 dest, revs = cmdutil.parseurl( |
2053 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev']) | 2017 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev']) |
2054 setremoteconfig(ui, opts) | 2018 cmdutil.setremoteconfig(ui, opts) |
2055 | 2019 |
2056 other = hg.repository(ui, dest) | 2020 other = hg.repository(ui, dest) |
2057 ui.status('pushing to %s\n' % (dest)) | 2021 ui.status('pushing to %s\n' % (dest)) |
2058 if revs: | 2022 if revs: |
2059 revs = [repo.lookup(rev) for rev in revs] | 2023 revs = [repo.lookup(rev) for rev in revs] |
2073 release, please use debugsetparents and commit instead. | 2037 release, please use debugsetparents and commit instead. |
2074 """ | 2038 """ |
2075 | 2039 |
2076 ui.warn(_("(the rawcommit command is deprecated)\n")) | 2040 ui.warn(_("(the rawcommit command is deprecated)\n")) |
2077 | 2041 |
2078 message = logmessage(opts) | 2042 message = cmdutil.logmessage(opts) |
2079 | 2043 |
2080 files, match, anypats = cmdutil.matchpats(repo, pats, opts) | 2044 files, match, anypats = cmdutil.matchpats(repo, pats, opts) |
2081 if opts['files']: | 2045 if opts['files']: |
2082 files += open(opts['files']).read().splitlines() | 2046 files += open(opts['files']).read().splitlines() |
2083 | 2047 |
3037 try: | 3001 try: |
3038 u = ui.ui(traceback='--traceback' in sys.argv[1:]) | 3002 u = ui.ui(traceback='--traceback' in sys.argv[1:]) |
3039 except util.Abort, inst: | 3003 except util.Abort, inst: |
3040 sys.stderr.write(_("abort: %s\n") % inst) | 3004 sys.stderr.write(_("abort: %s\n") % inst) |
3041 return -1 | 3005 return -1 |
3042 sys.exit(runcatch(u, sys.argv[1:])) | 3006 sys.exit(cmdutil.runcatch(u, sys.argv[1:])) |
3043 | 3007 |
3044 def runcatch(u, args): | |
3045 def catchterm(*args): | |
3046 raise util.SignalInterrupt | |
3047 | |
3048 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM': | |
3049 num = getattr(signal, name, None) | |
3050 if num: signal.signal(num, catchterm) | |
3051 | |
3052 try: | |
3053 return dispatch(u, args) | |
3054 except hg.RepoError, inst: | |
3055 u.warn(_("abort: %s!\n") % inst) | |
3056 except lock.LockHeld, inst: | |
3057 if inst.errno == errno.ETIMEDOUT: | |
3058 reason = _('timed out waiting for lock held by %s') % inst.locker | |
3059 else: | |
3060 reason = _('lock held by %s') % inst.locker | |
3061 u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason)) | |
3062 except lock.LockUnavailable, inst: | |
3063 u.warn(_("abort: could not lock %s: %s\n") % | |
3064 (inst.desc or inst.filename, inst.strerror)) | |
3065 except revlog.RevlogError, inst: | |
3066 u.warn(_("abort: %s!\n") % inst) | |
3067 except util.SignalInterrupt: | |
3068 u.warn(_("killed!\n")) | |
3069 except KeyboardInterrupt: | |
3070 try: | |
3071 u.warn(_("interrupted!\n")) | |
3072 except IOError, inst: | |
3073 if inst.errno == errno.EPIPE: | |
3074 if u.debugflag: | |
3075 u.warn(_("\nbroken pipe\n")) | |
3076 else: | |
3077 raise | |
3078 except socket.error, inst: | |
3079 u.warn(_("abort: %s\n") % inst[1]) | |
3080 except IOError, inst: | |
3081 if hasattr(inst, "code"): | |
3082 u.warn(_("abort: %s\n") % inst) | |
3083 elif hasattr(inst, "reason"): | |
3084 try: # usually it is in the form (errno, strerror) | |
3085 reason = inst.reason.args[1] | |
3086 except: # it might be anything, for example a string | |
3087 reason = inst.reason | |
3088 u.warn(_("abort: error: %s\n") % reason) | |
3089 elif hasattr(inst, "args") and inst[0] == errno.EPIPE: | |
3090 if u.debugflag: | |
3091 u.warn(_("broken pipe\n")) | |
3092 elif getattr(inst, "strerror", None): | |
3093 if getattr(inst, "filename", None): | |
3094 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) | |
3095 else: | |
3096 u.warn(_("abort: %s\n") % inst.strerror) | |
3097 else: | |
3098 raise | |
3099 except OSError, inst: | |
3100 if getattr(inst, "filename", None): | |
3101 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) | |
3102 else: | |
3103 u.warn(_("abort: %s\n") % inst.strerror) | |
3104 except util.UnexpectedOutput, inst: | |
3105 u.warn(_("abort: %s") % inst[0]) | |
3106 if not isinstance(inst[1], basestring): | |
3107 u.warn(" %r\n" % (inst[1],)) | |
3108 elif not inst[1]: | |
3109 u.warn(_(" empty string\n")) | |
3110 else: | |
3111 u.warn("\n%r\n" % util.ellipsis(inst[1])) | |
3112 except util.Abort, inst: | |
3113 u.warn(_("abort: %s\n") % inst) | |
3114 except TypeError, inst: | |
3115 # was this an argument error? | |
3116 tb = traceback.extract_tb(sys.exc_info()[2]) | |
3117 if len(tb) > 2: # no | |
3118 raise | |
3119 u.debug(inst, "\n") | |
3120 u.warn(_("%s: invalid arguments\n") % cmd) | |
3121 help_(u, cmd) | |
3122 except SystemExit, inst: | |
3123 # Commands shouldn't sys.exit directly, but give a return code. | |
3124 # Just in case catch this and and pass exit code to caller. | |
3125 return inst.code | |
3126 except: | |
3127 u.warn(_("** unknown exception encountered, details follow\n")) | |
3128 u.warn(_("** report bug details to " | |
3129 "http://www.selenic.com/mercurial/bts\n")) | |
3130 u.warn(_("** or mercurial@selenic.com\n")) | |
3131 u.warn(_("** Mercurial Distributed SCM (version %s)\n") | |
3132 % version.get_version()) | |
3133 raise | |
3134 | |
3135 return -1 | |
3136 | |
3137 def findpossible(ui, cmd): | |
3138 """ | |
3139 Return cmd -> (aliases, command table entry) | |
3140 for each matching command. | |
3141 Return debug commands (or their aliases) only if no normal command matches. | |
3142 """ | |
3143 choice = {} | |
3144 debugchoice = {} | |
3145 for e in table.keys(): | |
3146 aliases = e.lstrip("^").split("|") | |
3147 found = None | |
3148 if cmd in aliases: | |
3149 found = cmd | |
3150 elif not ui.config("ui", "strict"): | |
3151 for a in aliases: | |
3152 if a.startswith(cmd): | |
3153 found = a | |
3154 break | |
3155 if found is not None: | |
3156 if aliases[0].startswith("debug") or found.startswith("debug"): | |
3157 debugchoice[found] = (aliases, table[e]) | |
3158 else: | |
3159 choice[found] = (aliases, table[e]) | |
3160 | |
3161 if not choice and debugchoice: | |
3162 choice = debugchoice | |
3163 | |
3164 return choice | |
3165 | |
3166 def findcmd(ui, cmd): | |
3167 """Return (aliases, command table entry) for command string.""" | |
3168 choice = findpossible(ui, cmd) | |
3169 | |
3170 if choice.has_key(cmd): | |
3171 return choice[cmd] | |
3172 | |
3173 if len(choice) > 1: | |
3174 clist = choice.keys() | |
3175 clist.sort() | |
3176 raise AmbiguousCommand(cmd, clist) | |
3177 | |
3178 if choice: | |
3179 return choice.values()[0] | |
3180 | |
3181 raise UnknownCommand(cmd) | |
3182 | |
3183 class ParseError(Exception): | |
3184 """Exception raised on errors in parsing the command line.""" | |
3185 | |
3186 def parse(ui, args): | |
3187 options = {} | |
3188 cmdoptions = {} | |
3189 | |
3190 try: | |
3191 args = fancyopts.fancyopts(args, globalopts, options) | |
3192 except fancyopts.getopt.GetoptError, inst: | |
3193 raise ParseError(None, inst) | |
3194 | |
3195 if args: | |
3196 cmd, args = args[0], args[1:] | |
3197 aliases, i = findcmd(ui, cmd) | |
3198 cmd = aliases[0] | |
3199 defaults = ui.config("defaults", cmd) | |
3200 if defaults: | |
3201 args = shlex.split(defaults) + args | |
3202 c = list(i[1]) | |
3203 else: | |
3204 cmd = None | |
3205 c = [] | |
3206 | |
3207 # combine global options into local | |
3208 for o in globalopts: | |
3209 c.append((o[0], o[1], options[o[1]], o[3])) | |
3210 | |
3211 try: | |
3212 args = fancyopts.fancyopts(args, c, cmdoptions) | |
3213 except fancyopts.getopt.GetoptError, inst: | |
3214 raise ParseError(cmd, inst) | |
3215 | |
3216 # separate global options back out | |
3217 for o in globalopts: | |
3218 n = o[1] | |
3219 options[n] = cmdoptions[n] | |
3220 del cmdoptions[n] | |
3221 | |
3222 return (cmd, cmd and i[0] or None, args, options, cmdoptions) | |
3223 | |
3224 def parseconfig(config): | |
3225 """parse the --config options from the command line""" | |
3226 parsed = [] | |
3227 for cfg in config: | |
3228 try: | |
3229 name, value = cfg.split('=', 1) | |
3230 section, name = name.split('.', 1) | |
3231 if not section or not name: | |
3232 raise IndexError | |
3233 parsed.append((section, name, value)) | |
3234 except (IndexError, ValueError): | |
3235 raise util.Abort(_('malformed --config option: %s') % cfg) | |
3236 return parsed | |
3237 | |
3238 def dispatch(u, args): | |
3239 extensions.loadall(u) | |
3240 u.addreadhook(extensions.loadall) | |
3241 | |
3242 try: | |
3243 cmd, func, args, options, cmdoptions = parse(u, args) | |
3244 except ParseError, inst: | |
3245 if inst.args[0]: | |
3246 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1])) | |
3247 help_(u, inst.args[0]) | |
3248 else: | |
3249 u.warn(_("hg: %s\n") % inst.args[1]) | |
3250 help_(u, 'shortlist') | |
3251 return -1 | |
3252 except AmbiguousCommand, inst: | |
3253 u.warn(_("hg: command '%s' is ambiguous:\n %s\n") % | |
3254 (inst.args[0], " ".join(inst.args[1]))) | |
3255 return -1 | |
3256 except UnknownCommand, inst: | |
3257 u.warn(_("hg: unknown command '%s'\n") % inst.args[0]) | |
3258 help_(u, 'shortlist') | |
3259 return -1 | |
3260 | |
3261 if options["encoding"]: | |
3262 util._encoding = options["encoding"] | |
3263 if options["encodingmode"]: | |
3264 util._encodingmode = options["encodingmode"] | |
3265 if options["time"]: | |
3266 def get_times(): | |
3267 t = os.times() | |
3268 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock() | |
3269 t = (t[0], t[1], t[2], t[3], time.clock()) | |
3270 return t | |
3271 s = get_times() | |
3272 def print_time(): | |
3273 t = get_times() | |
3274 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") % | |
3275 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3])) | |
3276 atexit.register(print_time) | |
3277 | |
3278 if options['cwd']: | |
3279 os.chdir(options['cwd']) | |
3280 | |
3281 u.updateopts(options["verbose"], options["debug"], options["quiet"], | |
3282 not options["noninteractive"], options["traceback"], | |
3283 parseconfig(options["config"])) | |
3284 | |
3285 path = u.expandpath(options["repository"]) or "" | |
3286 repo = path and hg.repository(u, path=path) or None | |
3287 if repo and not repo.local(): | |
3288 raise util.Abort(_("repository '%s' is not local") % path) | |
3289 | |
3290 if options['help']: | |
3291 return help_(u, cmd, options['version']) | |
3292 elif options['version']: | |
3293 return version_(u) | |
3294 elif not cmd: | |
3295 return help_(u, 'shortlist') | |
3296 | |
3297 if cmd not in norepo.split(): | |
3298 try: | |
3299 if not repo: | |
3300 repo = hg.repository(u, path=path) | |
3301 u = repo.ui | |
3302 except hg.RepoError: | |
3303 if cmd not in optionalrepo.split(): | |
3304 raise | |
3305 d = lambda: func(u, repo, *args, **cmdoptions) | |
3306 else: | |
3307 d = lambda: func(u, *args, **cmdoptions) | |
3308 | |
3309 return cmdutil.runcommand(u, options, d) | |
3310 |