--- a/mercurial/commands.py Thu Jul 26 07:56:27 2007 -0400
+++ b/mercurial/commands.py Wed Feb 06 19:57:52 2008 -0800
@@ -5,14 +5,13 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-import demandimport; demandimport.enable()
from node import *
from i18n import _
-import bisect, os, re, sys, urllib, stat
-import ui, hg, util, revlog, bundlerepo, extensions
+import os, re, sys, urllib
+import hg, util, revlog, bundlerepo, extensions
import difflib, patch, time, help, mdiff, tempfile
import errno, version, socket
-import archival, changegroup, cmdutil, hgweb.server, sshserver
+import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
# Commands start here, listed alphabetically
@@ -27,17 +26,23 @@
If no names are given, add all files in the repository.
"""
+ rejected = None
+ exacts = {}
names = []
- for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
+ for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
+ badmatch=util.always):
if exact:
if ui.verbose:
ui.status(_('adding %s\n') % rel)
names.append(abs)
+ exacts[abs] = 1
elif abs not in repo.dirstate:
ui.status(_('adding %s\n') % rel)
names.append(abs)
if not opts.get('dry_run'):
- repo.add(names)
+ rejected = repo.add(names)
+ rejected = [p for p in rejected if p in exacts]
+ return rejected and 1 or 0
def addremove(ui, repo, *pats, **opts):
"""add all new files, delete all missing files
@@ -191,10 +196,13 @@
raise util.Abort(_("please specify a revision to backout"))
cmdutil.bail_if_changed(repo)
+ node = repo.lookup(rev)
+
op1, op2 = repo.dirstate.parents()
- if op2 != nullid:
- raise util.Abort(_('outstanding uncommitted merge'))
- node = repo.lookup(rev)
+ a = repo.changelog.ancestor(op1, node)
+ if a != node:
+ raise util.Abort(_('cannot back out change on a different branch'))
+
p1, p2 = repo.changelog.parents(node)
if p1 == nullid:
raise util.Abort(_('cannot back out a change with no parents'))
@@ -211,6 +219,7 @@
if opts['parent']:
raise util.Abort(_('cannot use --parent on non-merge changeset'))
parent = p1
+
hg.clean(repo, node, show_stats=False)
revert_opts = opts.copy()
revert_opts['date'] = None
@@ -237,6 +246,90 @@
ui.status(_('(use "backout --merge" '
'if you want to auto-merge)\n'))
+def bisect(ui, repo, rev=None, extra=None,
+ reset=None, good=None, bad=None, skip=None, noupdate=None):
+ """subdivision search of changesets
+
+ This command helps to find changesets which introduce problems.
+ To use, mark the earliest changeset you know exhibits the problem
+ as bad, then mark the latest changeset which is free from the
+ problem as good. Bisect will update your working directory to a
+ revision for testing. Once you have performed tests, mark the
+ working directory as bad or good and bisect will either update to
+ another candidate changeset or announce that it has found the bad
+ revision.
+ """
+ # backward compatibility
+ if rev in "good bad reset init".split():
+ ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
+ cmd, rev, extra = rev, extra, None
+ if cmd == "good":
+ good = True
+ elif cmd == "bad":
+ bad = True
+ else:
+ reset = True
+ elif extra or good + bad + skip + reset > 1:
+ raise util.Abort("Incompatible arguments")
+
+ if reset:
+ p = repo.join("bisect.state")
+ if os.path.exists(p):
+ os.unlink(p)
+ return
+
+ # load state
+ state = {'good': [], 'bad': [], 'skip': []}
+ if os.path.exists(repo.join("bisect.state")):
+ for l in repo.opener("bisect.state"):
+ kind, node = l[:-1].split()
+ node = repo.lookup(node)
+ if kind not in state:
+ raise util.Abort(_("unknown bisect kind %s") % kind)
+ state[kind].append(node)
+
+ # update state
+ node = repo.lookup(rev or '.')
+ if good:
+ state['good'].append(node)
+ elif bad:
+ state['bad'].append(node)
+ elif skip:
+ state['skip'].append(node)
+
+ # save state
+ f = repo.opener("bisect.state", "w", atomictemp=True)
+ wlock = repo.wlock()
+ try:
+ for kind in state:
+ for node in state[kind]:
+ f.write("%s %s\n" % (kind, hg.hex(node)))
+ f.rename()
+ finally:
+ del wlock
+
+ if not state['good'] or not state['bad']:
+ return
+
+ # actually bisect
+ node, changesets, good = hbisect.bisect(repo.changelog, state)
+ if changesets == 0:
+ ui.write(_("The first %s revision is:\n") % (good and "good" or "bad"))
+ displayer = cmdutil.show_changeset(ui, repo, {})
+ displayer.show(changenode=node)
+ elif node is not None:
+ # compute the approximate number of remaining tests
+ tests, size = 0, 2
+ while size <= changesets:
+ tests, size = tests + 1, size * 2
+ rev = repo.changelog.rev(node)
+ ui.write(_("Testing changeset %s:%s "
+ "(%s changesets remaining, ~%s tests)\n")
+ % (rev, hg.short(node), changesets, tests))
+ if not noupdate:
+ cmdutil.bail_if_changed(repo)
+ return hg.clean(repo, node)
+
def branch(ui, repo, label=None, **opts):
"""set or show the current branch name
@@ -246,6 +339,8 @@
Unless --force is specified, branch will not let you set a
branch name that shadows an existing branch.
+
+ Use the command 'hg update' to switch to an existing branch.
"""
if label:
@@ -265,6 +360,8 @@
inactive. If active is specified, only show active branches.
A branch is considered active if it contains unmerged heads.
+
+ Use the command 'hg update' to switch to an existing branch.
"""
b = repo.branchtags()
heads = dict.fromkeys(repo.heads(), 1)
@@ -295,6 +392,7 @@
If no destination repository is specified the destination is assumed
to have all the nodes specified by one or more --base parameters.
+ To create a bundle containing all changesets, use --base null.
The bundle file can then be transferred using conventional means and
applied to another repository with the unbundle or pull command.
@@ -336,7 +434,7 @@
visit.append(p)
else:
cmdutil.setremoteconfig(ui, opts)
- dest, revs = cmdutil.parseurl(
+ dest, revs, checkout = hg.parseurl(
ui.expandpath(dest or 'default-push', dest or 'default'), revs)
other = hg.repository(ui, dest)
o = repo.findoutgoing(other, force=opts['force'])
@@ -425,244 +523,13 @@
If a list of files is omitted, all changes reported by "hg status"
will be committed.
- If no commit message is specified, the editor configured in your hgrc
- or in the EDITOR environment variable is started to enter a message.
+ If no commit message is specified, the configured editor is started to
+ enter a message.
"""
- message = cmdutil.logmessage(opts)
-
- if opts['addremove']:
- cmdutil.addremove(repo, pats, opts)
- fns, match, anypats = cmdutil.matchpats(repo, pats, opts)
- if pats:
- status = repo.status(files=fns, match=match)
- modified, added, removed, deleted, unknown = status[:5]
- files = modified + added + removed
- slist = None
- for f in fns:
- if f == '.':
- continue
- if f not in files:
- rf = repo.wjoin(f)
- try:
- mode = os.lstat(rf)[stat.ST_MODE]
- except OSError:
- raise util.Abort(_("file %s not found!") % rf)
- if stat.S_ISDIR(mode):
- name = f + '/'
- if slist is None:
- slist = list(files)
- slist.sort()
- i = bisect.bisect(slist, name)
- if i >= len(slist) or not slist[i].startswith(name):
- raise util.Abort(_("no match under directory %s!")
- % rf)
- elif not (stat.S_ISREG(mode) or stat.S_ISLNK(mode)):
- raise util.Abort(_("can't commit %s: "
- "unsupported file type!") % rf)
- elif f not in repo.dirstate:
- raise util.Abort(_("file %s not tracked!") % rf)
- else:
- files = []
- try:
- repo.commit(files, message, opts['user'], opts['date'], match,
- force_editor=opts.get('force_editor'))
- except ValueError, inst:
- raise util.Abort(str(inst))
-
-def docopy(ui, repo, pats, opts):
- # called with the repo lock held
- #
- # hgsep => pathname that uses "/" to separate directories
- # ossep => pathname that uses os.sep to separate directories
- cwd = repo.getcwd()
- errors = 0
- copied = []
- targets = {}
-
- # abs: hgsep
- # rel: ossep
- # return: hgsep
- def okaytocopy(abs, rel, exact):
- reasons = {'?': _('is not managed'),
- 'r': _('has been marked for remove')}
- state = repo.dirstate[abs]
- reason = reasons.get(state)
- if reason:
- if exact:
- ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
- else:
- if state == 'a':
- origsrc = repo.dirstate.copied(abs)
- if origsrc is not None:
- return origsrc
- return abs
-
- # origsrc: hgsep
- # abssrc: hgsep
- # relsrc: ossep
- # otarget: ossep
- def copy(origsrc, abssrc, relsrc, otarget, exact):
- abstarget = util.canonpath(repo.root, cwd, otarget)
- reltarget = repo.pathto(abstarget, cwd)
- prevsrc = targets.get(abstarget)
- src = repo.wjoin(abssrc)
- target = repo.wjoin(abstarget)
- if prevsrc is not None:
- ui.warn(_('%s: not overwriting - %s collides with %s\n') %
- (reltarget, repo.pathto(abssrc, cwd),
- repo.pathto(prevsrc, cwd)))
- return
- if (not opts['after'] and os.path.exists(target) or
- opts['after'] and repo.dirstate[abstarget] in 'mn'):
- if not opts['force']:
- ui.warn(_('%s: not overwriting - file exists\n') %
- reltarget)
- return
- if not opts['after'] and not opts.get('dry_run'):
- os.unlink(target)
- if opts['after']:
- if not os.path.exists(target):
- return
- else:
- targetdir = os.path.dirname(target) or '.'
- if not os.path.isdir(targetdir) and not opts.get('dry_run'):
- os.makedirs(targetdir)
- try:
- restore = repo.dirstate[abstarget] == 'r'
- if restore and not opts.get('dry_run'):
- repo.undelete([abstarget])
- try:
- if not opts.get('dry_run'):
- util.copyfile(src, target)
- restore = False
- finally:
- if restore:
- repo.remove([abstarget])
- except IOError, inst:
- if inst.errno == errno.ENOENT:
- ui.warn(_('%s: deleted in working copy\n') % relsrc)
- else:
- ui.warn(_('%s: cannot copy - %s\n') %
- (relsrc, inst.strerror))
- errors += 1
- return
- if ui.verbose or not exact:
- ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
- targets[abstarget] = abssrc
- if abstarget != origsrc:
- if repo.dirstate[origsrc] == 'a':
- if not ui.quiet:
- ui.warn(_("%s has not been committed yet, so no copy "
- "data will be stored for %s.\n")
- % (repo.pathto(origsrc, cwd), reltarget))
- if abstarget not in repo.dirstate and not opts.get('dry_run'):
- repo.add([abstarget])
- elif not opts.get('dry_run'):
- repo.copy(origsrc, abstarget)
- copied.append((abssrc, relsrc, exact))
-
- # pat: ossep
- # dest ossep
- # srcs: list of (hgsep, hgsep, ossep, bool)
- # return: function that takes hgsep and returns ossep
- def targetpathfn(pat, dest, srcs):
- if os.path.isdir(pat):
- abspfx = util.canonpath(repo.root, cwd, pat)
- abspfx = util.localpath(abspfx)
- if destdirexists:
- striplen = len(os.path.split(abspfx)[0])
- else:
- striplen = len(abspfx)
- if striplen:
- striplen += len(os.sep)
- res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
- elif destdirexists:
- res = lambda p: os.path.join(dest,
- os.path.basename(util.localpath(p)))
- else:
- res = lambda p: dest
- return res
-
- # pat: ossep
- # dest ossep
- # srcs: list of (hgsep, hgsep, ossep, bool)
- # return: function that takes hgsep and returns ossep
- def targetpathafterfn(pat, dest, srcs):
- if util.patkind(pat, None)[0]:
- # a mercurial pattern
- res = lambda p: os.path.join(dest,
- os.path.basename(util.localpath(p)))
- else:
- abspfx = util.canonpath(repo.root, cwd, pat)
- if len(abspfx) < len(srcs[0][0]):
- # A directory. Either the target path contains the last
- # component of the source path or it does not.
- def evalpath(striplen):
- score = 0
- for s in srcs:
- t = os.path.join(dest, util.localpath(s[0])[striplen:])
- if os.path.exists(t):
- score += 1
- return score
-
- abspfx = util.localpath(abspfx)
- striplen = len(abspfx)
- if striplen:
- striplen += len(os.sep)
- if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
- score = evalpath(striplen)
- striplen1 = len(os.path.split(abspfx)[0])
- if striplen1:
- striplen1 += len(os.sep)
- if evalpath(striplen1) > score:
- striplen = striplen1
- res = lambda p: os.path.join(dest,
- util.localpath(p)[striplen:])
- else:
- # a file
- if destdirexists:
- res = lambda p: os.path.join(dest,
- os.path.basename(util.localpath(p)))
- else:
- res = lambda p: dest
- return res
-
-
- pats = util.expand_glob(pats)
- if not pats:
- raise util.Abort(_('no source or destination specified'))
- if len(pats) == 1:
- raise util.Abort(_('no destination specified'))
- dest = pats.pop()
- destdirexists = os.path.isdir(dest)
- if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
- raise util.Abort(_('with multiple sources, destination must be an '
- 'existing directory'))
- if opts['after']:
- tfn = targetpathafterfn
- else:
- tfn = targetpathfn
- copylist = []
- for pat in pats:
- srcs = []
- for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts,
- globbed=True):
- origsrc = okaytocopy(abssrc, relsrc, exact)
- if origsrc:
- srcs.append((origsrc, abssrc, relsrc, exact))
- if not srcs:
- continue
- copylist.append((tfn(pat, dest, srcs), srcs))
- if not copylist:
- raise util.Abort(_('no files to copy'))
-
- for targetpath, srcs in copylist:
- for origsrc, abssrc, relsrc, exact in srcs:
- copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
-
- if errors:
- ui.warn(_('(consider using --after)\n'))
- return errors, copied
+ def commitfunc(ui, repo, files, message, match, opts):
+ return repo.commit(files, message, opts['user'], opts['date'], match,
+ force_editor=opts.get('force_editor'))
+ cmdutil.commit(ui, repo, commitfunc, pats, opts)
def copy(ui, repo, *pats, **opts):
"""mark files as copied for the next commit
@@ -680,10 +547,9 @@
"""
wlock = repo.wlock(False)
try:
- errs, copied = docopy(ui, repo, pats, opts)
+ return cmdutil.copy(ui, repo, pats, opts)
finally:
del wlock
- return errs
def debugancestor(ui, index, rev1, rev2):
"""find the ancestor revision of two revisions in a given index"""
@@ -698,7 +564,7 @@
options = []
otables = [globalopts]
if cmd:
- aliases, entry = cmdutil.findcmd(ui, cmd)
+ aliases, entry = cmdutil.findcmd(ui, cmd, table)
otables.append(entry[1])
for t in otables:
for o in t:
@@ -708,10 +574,18 @@
ui.write("%s\n" % "\n".join(options))
return
- clist = cmdutil.findpossible(ui, cmd).keys()
+ clist = cmdutil.findpossible(ui, cmd, table).keys()
clist.sort()
ui.write("%s\n" % "\n".join(clist))
+def debugfsinfo(ui, path = "."):
+ file('.debugfsinfo', 'w').write('')
+ ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
+ ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
+ ui.write('case-sensitive: %s\n' % (util.checkfolding('.debugfsinfo')
+ and 'yes' or 'no'))
+ os.unlink('.debugfsinfo')
+
def debugrebuildstate(ui, repo, rev=""):
"""rebuild the dirstate as it would look like for the given revision"""
if rev == "":
@@ -795,20 +669,21 @@
def debugstate(ui, repo):
"""show the contents of the current dirstate"""
- dc = repo.dirstate._map
- k = dc.keys()
+ k = repo.dirstate._map.items()
k.sort()
- for file_ in k:
- if dc[file_][3] == -1:
+ for file_, ent in k:
+ if ent[3] == -1:
# Pad or slice to locale representation
- locale_len = len(time.strftime("%x %X", time.localtime(0)))
+ locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(0)))
timestr = 'unset'
timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
else:
- timestr = time.strftime("%x %X", time.localtime(dc[file_][3]))
- ui.write("%c %3o %10d %s %s\n"
- % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
- timestr, file_))
+ timestr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ent[3]))
+ if ent[1] & 020000:
+ mode = 'lnk'
+ else:
+ mode = '%3o' % (ent[1] & 0777)
+ ui.write("%c %s %10d %s %s\n" % (ent[0], mode, ent[2], timestr, file_))
for f in repo.dirstate.copies():
ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
@@ -839,7 +714,10 @@
" nodeid p1 p2\n")
for i in xrange(r.count()):
node = r.node(i)
- pp = r.parents(node)
+ try:
+ pp = r.parents(node)
+ except:
+ pp = [nullid, nullid]
ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
short(node), short(pp[0]), short(pp[1])))
@@ -899,82 +777,45 @@
# patch
ui.status(_("Checking patch...\n"))
- patcher = ui.config('ui', 'patch')
- patcher = ((patcher and util.find_exe(patcher)) or
- util.find_exe('gpatch') or
- util.find_exe('patch'))
- if not patcher:
- ui.write(_(" Can't find patch or gpatch in PATH\n"))
- ui.write(_(" (specify a patch utility in your .hgrc file)\n"))
- problems += 1
+ patchproblems = 0
+ a = "1\n2\n3\n4\n"
+ b = "1\n2\n3\ninsert\n4\n"
+ fa = writetemp(a)
+ d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
+ os.path.basename(fa))
+ fd = writetemp(d)
+
+ files = {}
+ try:
+ patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
+ except util.Abort, e:
+ ui.write(_(" patch call failed:\n"))
+ ui.write(" " + str(e) + "\n")
+ patchproblems += 1
else:
- # actually attempt a patch here
- a = "1\n2\n3\n4\n"
- b = "1\n2\n3\ninsert\n4\n"
- fa = writetemp(a)
- d = mdiff.unidiff(a, None, b, None, os.path.basename(fa))
- fd = writetemp(d)
-
- files = {}
- try:
- patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
- except util.Abort, e:
- ui.write(_(" patch call failed:\n"))
- ui.write(" " + str(e) + "\n")
- problems += 1
+ if list(files) != [os.path.basename(fa)]:
+ ui.write(_(" unexpected patch output!\n"))
+ patchproblems += 1
+ a = file(fa).read()
+ if a != b:
+ ui.write(_(" patch test failed!\n"))
+ patchproblems += 1
+
+ if patchproblems:
+ if ui.config('ui', 'patch'):
+ ui.write(_(" (Current patch tool may be incompatible with patch,"
+ " or misconfigured. Please check your .hgrc file)\n"))
else:
- if list(files) != [os.path.basename(fa)]:
- ui.write(_(" unexpected patch output!"))
- ui.write(_(" (you may have an incompatible version of patch)\n"))
- problems += 1
- a = file(fa).read()
- if a != b:
- ui.write(_(" patch test failed!"))
- ui.write(_(" (you may have an incompatible version of patch)\n"))
- problems += 1
-
- os.unlink(fa)
- os.unlink(fd)
-
- # merge helper
- ui.status(_("Checking merge helper...\n"))
- cmd = (os.environ.get("HGMERGE") or ui.config("ui", "merge")
- or "hgmerge")
- cmdpath = util.find_exe(cmd) or util.find_exe(cmd.split()[0])
- if not cmdpath:
- if cmd == 'hgmerge':
- ui.write(_(" No merge helper set and can't find default"
- " hgmerge script in PATH\n"))
- ui.write(_(" (specify a merge helper in your .hgrc file)\n"))
- else:
- ui.write(_(" Can't find merge helper '%s' in PATH\n") % cmd)
- ui.write(_(" (specify a merge helper in your .hgrc file)\n"))
- problems += 1
- else:
- # actually attempt a patch here
- fa = writetemp("1\n2\n3\n4\n")
- fl = writetemp("1\n2\n3\ninsert\n4\n")
- fr = writetemp("begin\n1\n2\n3\n4\n")
- r = util.system('%s "%s" "%s" "%s"' % (cmd, fl, fa, fr))
- if r:
- ui.write(_(" Got unexpected merge error %d!\n") % r)
- problems += 1
- m = file(fl).read()
- if m != "begin\n1\n2\n3\ninsert\n4\n":
- ui.write(_(" Got unexpected merge results!\n"))
- ui.write(_(" (your merge helper may have the"
- " wrong argument order)\n"))
- ui.write(_(" Result: %r\n") % m)
- problems += 1
- os.unlink(fa)
- os.unlink(fl)
- os.unlink(fr)
+ ui.write(_(" Internal patcher failure, please report this error"
+ " to http://www.selenic.com/mercurial/bts\n"))
+ problems += patchproblems
+
+ os.unlink(fa)
+ os.unlink(fd)
# editor
ui.status(_("Checking commit editor...\n"))
- editor = (os.environ.get("HGEDITOR") or
- ui.config("ui", "editor") or
- os.environ.get("EDITOR", "vi"))
+ editor = ui.geteditor()
cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
if not cmdpath:
if editor == 'vi':
@@ -1011,7 +852,8 @@
ctx = repo.changectx(opts.get('rev', 'tip'))
for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
ctx.node()):
- m = ctx.filectx(abs).renamed()
+ fctx = ctx.filectx(abs)
+ m = fctx.filelog().renamed(fctx.filenode())
if m:
ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
else:
@@ -1223,9 +1065,9 @@
for fn in fns:
if fn in skip:
continue
- fstate.setdefault(fn, {})
try:
grepbody(fn, rev, getfile(fn).read(mf[fn]))
+ fstate.setdefault(fn, [])
if follow:
copied = getfile(fn).renamed(mf[fn])
if copied:
@@ -1342,9 +1184,13 @@
if with_version:
version_(ui)
ui.write('\n')
- aliases, i = cmdutil.findcmd(ui, name)
+ aliases, i = cmdutil.findcmd(ui, name, table)
# synopsis
- ui.write("%s\n\n" % i[2])
+ ui.write("%s\n" % i[2])
+
+ # aliases
+ if not ui.quiet and len(aliases) > 1:
+ ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
# description
doc = i[0].__doc__
@@ -1352,13 +1198,9 @@
doc = _("(No help text available)")
if ui.quiet:
doc = doc.splitlines(0)[0]
- ui.write("%s\n" % doc.rstrip())
+ ui.write("\n%s\n" % doc.rstrip())
if not ui.quiet:
- # aliases
- if len(aliases) > 1:
- ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
-
# options
if i[1]:
option_lists.append((_("options:\n"), i[1]))
@@ -1505,12 +1347,16 @@
name for non-default branches.
"""
+ if not repo and not source:
+ raise util.Abort(_("There is no Mercurial repository here "
+ "(.hg not found)"))
+
hexfunc = ui.debugflag and hex or short
default = not (num or id or branch or tags)
output = []
if source:
- source, revs = cmdutil.parseurl(ui.expandpath(source), [])
+ source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
srepo = hg.repository(ui, source)
if not rev and revs:
rev = revs[0]
@@ -1603,8 +1449,10 @@
data = patch.extract(ui, sys.stdin)
else:
ui.status(_("applying %s\n") % p)
- data = patch.extract(ui, file(pf, 'rb'))
-
+ if os.path.exists(pf):
+ data = patch.extract(ui, file(pf, 'rb'))
+ else:
+ data = patch.extract(ui, urllib.urlopen(pf))
tmpname, message, user, date, branch, nodeid, p1, p2 = data
if tmpname is None:
@@ -1650,16 +1498,21 @@
files=files)
finally:
files = patch.updatedir(ui, repo, files)
- n = repo.commit(files, message, user, date)
- if opts.get('exact'):
- if hex(n) != nodeid:
- repo.rollback()
- raise util.Abort(_('patch is damaged' +
- ' or loses information'))
+ if not opts.get('no_commit'):
+ n = repo.commit(files, message, opts.get('user') or user,
+ opts.get('date') or date)
+ if opts.get('exact'):
+ if hex(n) != nodeid:
+ repo.rollback()
+ raise util.Abort(_('patch is damaged'
+ ' or loses information'))
+ # Force a dirstate write so that the next transaction
+ # backups an up-do-date file.
+ repo.dirstate.write()
finally:
os.unlink(tmpname)
finally:
- del wlock, lock
+ del lock, wlock
def incoming(ui, repo, source="default", **opts):
"""show new changesets found in source
@@ -1673,17 +1526,13 @@
See pull for valid source format details.
"""
- source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev'])
+ source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
cmdutil.setremoteconfig(ui, opts)
other = hg.repository(ui, source)
- ui.status(_('comparing with %s\n') % source)
+ ui.status(_('comparing with %s\n') % util.hidepassword(source))
if revs:
- if 'lookup' in other.capabilities:
- revs = [other.lookup(rev) for rev in revs]
- else:
- error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
- raise util.Abort(error)
+ revs = [other.lookup(rev) for rev in revs]
incoming = repo.findincoming(other, heads=revs, force=opts["force"])
if not incoming:
try:
@@ -1701,8 +1550,6 @@
if revs is None:
cg = other.changegroup(incoming, "incoming")
else:
- if 'changegroupsubset' not in other.capabilities:
- raise util.Abort(_("Partial incoming cannot be done because other repository doesn't support changegroupsubset."))
cg = other.changegroupsubset(incoming, revs, 'incoming')
bundletype = other.local() and "HG10BZ" or "HG10UN"
fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
@@ -1831,8 +1678,7 @@
endrev = repo.changelog.count()
rcache = {}
ncache = {}
- dcache = []
- def getrenamed(fn, rev, man):
+ def getrenamed(fn, rev):
'''looks up all renames for a file (up to endrev) the first
time the file is given. It indexes on the changerev and only
parses the manifest if linkrev != changerev.
@@ -1852,13 +1698,14 @@
break
if rev in rcache[fn]:
return rcache[fn][rev]
- mr = repo.manifest.rev(man)
- if repo.manifest.parentrevs(mr) != (mr - 1, nullrev):
- return ncache[fn].get(repo.manifest.find(man, fn)[0])
- if not dcache or dcache[0] != man:
- dcache[:] = [man, repo.manifest.readdelta(man)]
- if fn in dcache[1]:
- return ncache[fn].get(dcache[1][fn])
+
+ # If linkrev != rev (i.e. rev not found in rcache) fallback to
+ # filectx logic.
+
+ try:
+ return repo.changectx(rev).filectx(fn).renamed()
+ except revlog.LookupError:
+ pass
return None
df = False
@@ -1895,9 +1742,8 @@
copies = []
if opts.get('copies') and rev:
- mf = get(rev)[0]
for fn in get(rev)[3]:
- rename = getrenamed(fn, rev, mf)
+ rename = getrenamed(fn, rev)
if rename:
copies.append((fn, rename[0]))
displayer.show(rev, changenode, copies=copies)
@@ -1906,7 +1752,7 @@
if displayer.flush(rev):
count += 1
-def manifest(ui, repo, rev=None):
+def manifest(ui, repo, node=None, rev=None):
"""output the current or given revision of the project manifest
Print a list of version controlled files for the given revision.
@@ -1916,11 +1762,17 @@
The manifest is the list of files being version controlled. If no revision
is given then the first parent of the working directory is used.
- With -v flag, print file permissions. With --debug flag, print
- file revision hashes.
+ With -v flag, print file permissions, symlink and executable bits. With
+ --debug flag, print file revision hashes.
"""
- m = repo.changectx(rev).manifest()
+ if rev and node:
+ raise util.Abort(_("please specify just one revision"))
+
+ if not node:
+ node = rev
+
+ m = repo.changectx(node).manifest()
files = m.keys()
files.sort()
@@ -1928,7 +1780,9 @@
if ui.debugflag:
ui.write("%40s " % hex(m[f]))
if ui.verbose:
- ui.write("%3s " % (m.execf(f) and "755" or "644"))
+ type = m.execf(f) and "*" or m.linkf(f) and "@" or " "
+ perm = m.execf(f) and "755" or "644"
+ ui.write("%3s %1s " % (perm, type))
ui.write("%s\n" % f)
def merge(ui, repo, node=None, force=None, rev=None):
@@ -1947,7 +1801,6 @@
if rev and node:
raise util.Abort(_("please specify just one revision"))
-
if not node:
node = rev
@@ -1957,10 +1810,13 @@
raise util.Abort(_('repo has %d heads - '
'please merge with an explicit rev') %
len(heads))
+ parent = repo.dirstate.parents()[0]
if len(heads) == 1:
- raise util.Abort(_('there is nothing to merge - '
- 'use "hg update" instead'))
- parent = repo.dirstate.parents()[0]
+ msg = _('there is nothing to merge')
+ if parent != repo.lookup(repo.workingctx().branch()):
+ msg = _('%s - use "hg update" instead') % msg
+ raise util.Abort(msg)
+
if parent not in heads:
raise util.Abort(_('working dir not at a head rev - '
'use "hg update" or merge with an explicit rev'))
@@ -1976,14 +1832,14 @@
See pull for valid destination format details.
"""
- dest, revs = cmdutil.parseurl(
+ dest, revs, checkout = hg.parseurl(
ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
cmdutil.setremoteconfig(ui, opts)
if revs:
revs = [repo.lookup(rev) for rev in revs]
other = hg.repository(ui, dest)
- ui.status(_('comparing with %s\n') % dest)
+ ui.status(_('comparing with %s\n') % util.hidepassword(dest))
o = repo.findoutgoing(other, force=opts['force'])
if not o:
ui.status(_("no changes found\n"))
@@ -2008,16 +1864,30 @@
revision or the argument to --rev if given) is printed.
"""
rev = opts.get('rev')
+ if rev:
+ ctx = repo.changectx(rev)
+ else:
+ ctx = repo.workingctx()
+
if file_:
files, match, anypats = cmdutil.matchpats(repo, (file_,), opts)
if anypats or len(files) != 1:
raise util.Abort(_('can only specify an explicit file name'))
- ctx = repo.filectx(files[0], changeid=rev)
- elif rev:
- ctx = repo.changectx(rev)
+ file_ = files[0]
+ filenodes = []
+ for cp in ctx.parents():
+ if not cp:
+ continue
+ try:
+ filenodes.append(cp.filenode(file_))
+ except revlog.LookupError:
+ pass
+ if not filenodes:
+ raise util.Abort(_("'%s' not found in manifest!") % file_)
+ fl = repo.file(file_)
+ p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
else:
- ctx = repo.workingctx()
- p = [cp.node() for cp in ctx.parents()]
+ p = [cp.node() for cp in ctx.parents()]
displayer = cmdutil.show_changeset(ui, repo, opts)
for n in p:
@@ -2044,12 +1914,12 @@
for name, path in ui.configitems("paths"):
ui.write("%s = %s\n" % (name, path))
-def postincoming(ui, repo, modheads, optupdate):
+def postincoming(ui, repo, modheads, optupdate, checkout):
if modheads == 0:
return
if optupdate:
- if modheads == 1:
- return hg.update(repo, None)
+ if modheads <= 1 or checkout:
+ return hg.update(repo, checkout)
else:
ui.status(_("not updating, since new heads added\n"))
if modheads > 1:
@@ -2098,20 +1968,21 @@
Alternatively specify "ssh -C" as your ssh command in your hgrc or
with the --ssh command line option.
"""
- source, revs = cmdutil.parseurl(ui.expandpath(source), opts['rev'])
+ source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
cmdutil.setremoteconfig(ui, opts)
other = hg.repository(ui, source)
- ui.status(_('pulling from %s\n') % (source))
+ ui.status(_('pulling from %s\n') % util.hidepassword(source))
if revs:
- if 'lookup' in other.capabilities:
+ try:
revs = [other.lookup(rev) for rev in revs]
- else:
- error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
+ except repo.NoCapability:
+ error = _("Other repository doesn't support revision lookup, "
+ "so a rev cannot be specified.")
raise util.Abort(error)
modheads = repo.pull(other, heads=revs, force=opts['force'])
- return postincoming(ui, repo, modheads, opts['update'])
+ return postincoming(ui, repo, modheads, opts['update'], checkout)
def push(ui, repo, dest=None, **opts):
"""push changes to the specified destination
@@ -2143,12 +2014,12 @@
Pushing to http:// and https:// URLs is only possible, if this
feature is explicitly enabled on the remote Mercurial server.
"""
- dest, revs = cmdutil.parseurl(
+ dest, revs, checkout = hg.parseurl(
ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
cmdutil.setremoteconfig(ui, opts)
other = hg.repository(ui, dest)
- ui.status('pushing to %s\n' % (dest))
+ ui.status('pushing to %s\n' % util.hidepassword(dest))
if revs:
revs = [repo.lookup(rev) for rev in revs]
r = repo.push(other, opts['force'], revs=revs)
@@ -2228,6 +2099,7 @@
forget.append(abs)
continue
reason = _('has been marked for add (use -f to force removal)')
+ exact = 1 # force the message
elif abs not in repo.dirstate:
reason = _('is not managed')
elif opts['after'] and not exact and abs not in deleted:
@@ -2260,20 +2132,15 @@
"""
wlock = repo.wlock(False)
try:
- errs, copied = docopy(ui, repo, pats, opts)
- names = []
- for abs, rel, exact in copied:
- if ui.verbose or not exact:
- ui.status(_('removing %s\n') % rel)
- names.append(abs)
- if not opts.get('dry_run'):
- repo.remove(names, True)
- return errs
+ return cmdutil.copy(ui, repo, pats, opts, rename=True)
finally:
del wlock
def revert(ui, repo, *pats, **opts):
- """revert files or dirs to their states as of some revision
+ """restore individual files or dirs to an earlier state
+
+ (use update -r to check out earlier revisions, revert does not
+ change the working dir parents)
With no revision specified, revert the named files or directories
to the contents they had in the parent of the working directory.
@@ -2282,12 +2149,9 @@
working directory has two parents, you must explicitly specify the
revision to revert to.
- Modified files are saved with a .orig suffix before reverting.
- To disable these backups, use --no-backup.
-
Using the -r option, revert the given files or directories to their
contents as of a specific revision. This can be helpful to "roll
- back" some or all of a change that should not have been committed.
+ back" some or all of an earlier change.
Revert modifies the working directory. It does not commit any
changes, or change the parent of the working directory. If you
@@ -2301,6 +2165,9 @@
If names are given, all files matching the names are reverted.
If no arguments are given, no files are reverted.
+
+ Modified files are saved with a .orig suffix before reverting.
+ To disable these backups, use --no-backup.
"""
if opts["date"]:
@@ -2361,6 +2228,14 @@
changes = repo.status(match=names.has_key)[:5]
modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
+ # if f is a rename, also revert the source
+ cwd = repo.getcwd()
+ for f in added:
+ src = repo.dirstate.copied(f)
+ if src and src not in names and repo.dirstate[src] == 'r':
+ removed[src] = None
+ names[src] = (repo.pathto(src, cwd), True)
+
revert = ([], _('reverting %s\n'))
add = ([], _('adding %s\n'))
remove = ([], _('removing %s\n'))
@@ -2443,10 +2318,12 @@
del wlock
def rollback(ui, repo):
- """roll back the last transaction in this repository
-
- Roll back the last transaction in this repository, restoring the
- project to its state prior to the transaction.
+ """roll back the last transaction
+
+ This command should be used with care. There is only one level of
+ rollback, and there is no way to undo a rollback. It will also
+ restore the dirstate at the time of the last transaction, losing
+ any dirstate changes since that time.
Transactions are used to encapsulate the effects of all commands
that create new changesets or propagate existing changesets into a
@@ -2459,11 +2336,6 @@
push (with this repository as destination)
unbundle
- This command should be used with care. There is only one level of
- rollback, and there is no way to undo a rollback. It will also
- restore the dirstate at the time of the last transaction, which
- may lose subsequent dirstate changes.
-
This command is not intended for use on public repositories. Once
changes are visible for pull by other users, rolling a transaction
back locally is ineffective (someone else may already have pulled
@@ -2497,12 +2369,12 @@
s.serve_forever()
parentui = ui.parentui or ui
- optlist = ("name templates style address port ipv6"
+ optlist = ("name templates style address port prefix ipv6"
" accesslog errorlog webdir_conf certificate")
for o in optlist.split():
if opts[o]:
parentui.setconfig("web", o, str(opts[o]))
- if repo.ui != parentui:
+ if (repo is not None) and (repo.ui != parentui):
repo.ui.setconfig("web", o, str(opts[o]))
if repo is None and not ui.config("web", "webdir_conf"):
@@ -2519,11 +2391,17 @@
if not ui.verbose: return
+ if self.httpd.prefix:
+ prefix = self.httpd.prefix.strip('/') + '/'
+ else:
+ prefix = ''
+
if self.httpd.port != 80:
- ui.status(_('listening at http://%s:%d/\n') %
- (self.httpd.addr, self.httpd.port))
+ ui.status(_('listening at http://%s:%d/%s\n') %
+ (self.httpd.addr, self.httpd.port, prefix))
else:
- ui.status(_('listening at http://%s/\n') % self.httpd.addr)
+ ui.status(_('listening at http://%s/%s\n') %
+ (self.httpd.addr, prefix))
def run(self):
self.httpd.serve_forever()
@@ -2536,8 +2414,10 @@
"""show changed files in the working directory
Show status of files in the repository. If names are given, only
- files that match are shown. Files that are clean or ignored, are
- not listed unless -c (clean), -i (ignored) or -A is given.
+ files that match are shown. Files that are clean or ignored or
+ source of a copy/move operation, are not listed unless -c (clean),
+ -i (ignored), -C (copies) or -A is given. Unless options described
+ with "show only ..." are given, the options -mardu are used.
NOTE: status may appear to disagree with diff if permissions have
changed or a merge has occurred. The standard diff format does not
@@ -2554,7 +2434,7 @@
C = clean
! = deleted, but still tracked
? = not tracked
- I = ignored (not shown by default)
+ I = ignored
= the previous added file was copied from here
"""
@@ -2626,8 +2506,15 @@
rev_ = opts['rev']
message = opts['message']
if opts['remove']:
- if not name in repo.tags():
+ tagtype = repo.tagtype(name)
+
+ if not tagtype:
raise util.Abort(_('tag %s does not exist') % name)
+ if opts['local'] and tagtype == 'global':
+ raise util.Abort(_('%s tag is global') % name)
+ if not opts['local'] and tagtype == 'local':
+ raise util.Abort(_('%s tag is local') % name)
+
rev_ = nullid
if not message:
message = _('Removed tag %s') % name
@@ -2649,23 +2536,33 @@
List the repository tags.
- This lists both regular and local tags.
+ This lists both regular and local tags. When the -v/--verbose switch
+ is used, a third column "local" is printed for local tags.
"""
l = repo.tagslist()
l.reverse()
hexfunc = ui.debugflag and hex or short
+ tagtype = ""
+
for t, n in l:
+ if ui.quiet:
+ ui.write("%s\n" % t)
+ continue
+
try:
hn = hexfunc(n)
- r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n))
+ r = "%5d:%s" % (repo.changelog.rev(n), hn)
except revlog.LookupError:
r = " ?:%s" % hn
- if ui.quiet:
- ui.write("%s\n" % t)
else:
spaces = " " * (30 - util.locallen(t))
- ui.write("%s%s %s\n" % (t, spaces, r))
+ if ui.verbose:
+ if repo.tagtype(t) == 'local':
+ tagtype = " local"
+ else:
+ tagtype = ""
+ ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
def tip(ui, repo, **opts):
"""show the tip revision
@@ -2689,7 +2586,7 @@
gen = changegroup.readbundle(f, fname)
modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
- return postincoming(ui, repo, modheads, opts['update'])
+ return postincoming(ui, repo, modheads, opts['update'], None)
def update(ui, repo, node=None, rev=None, clean=False, date=None):
"""update working directory
@@ -2740,7 +2637,7 @@
ui.write(_("Mercurial Distributed SCM (version %s)\n")
% version.get_version())
ui.status(_(
- "\nCopyright (C) 2005-2007 Matt Mackall <mpm@selenic.com> and others\n"
+ "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
"This is free software; see the source for copying conditions. "
"There is NO\nwarranty; "
"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
@@ -2787,6 +2684,11 @@
('l', 'logfile', '', _('read commit message from <file>')),
]
+commitopts2 = [
+ ('d', 'date', '', _('record datecode as commit date')),
+ ('u', 'user', '', _('record user as committer')),
+]
+
table = {
"^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
"addremove":
@@ -2820,17 +2722,23 @@
(backout,
[('', 'merge', None,
_('merge with old dirstate parent after backout')),
- ('d', 'date', '', _('record datecode as commit date')),
('', 'parent', '', _('parent to choose when backing out merge')),
- ('u', 'user', '', _('record user as committer')),
('r', 'rev', '', _('revision to backout')),
- ] + walkopts + commitopts,
+ ] + walkopts + commitopts + commitopts2,
_('hg backout [OPTION]... [-r] REV')),
+ "bisect":
+ (bisect,
+ [('r', 'reset', False, _('reset bisect state')),
+ ('g', 'good', False, _('mark changeset good')),
+ ('b', 'bad', False, _('mark changeset bad')),
+ ('s', 'skip', False, _('skip testing changeset')),
+ ('U', 'noupdate', False, _('do not update to target'))],
+ _("hg bisect [-gbsr] [REV]")),
"branch":
(branch,
[('f', 'force', None,
_('set branch name even if it shadows an existing branch'))],
- _('hg branch [NAME]')),
+ _('hg branch [-f] [NAME]')),
"branches":
(branches,
[('a', 'active', False,
@@ -2866,9 +2774,7 @@
(commit,
[('A', 'addremove', None,
_('mark new/missing files as added/removed before committing')),
- ('d', 'date', '', _('record datecode as commit date')),
- ('u', 'user', '', _('record user as commiter')),
- ] + walkopts + commitopts,
+ ] + walkopts + commitopts + commitopts2,
_('hg commit [OPTION]... [FILE]...')),
"copy|cp":
(copy,
@@ -2877,31 +2783,41 @@
_('forcibly copy over an existing managed file')),
] + walkopts + dryrunopts,
_('hg copy [OPTION]... [SOURCE]... DEST')),
- "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
+ "debugancestor": (debugancestor, [], _('hg debugancestor INDEX REV1 REV2')),
+ "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
"debugcomplete":
(debugcomplete,
[('o', 'options', None, _('show the command options'))],
- _('debugcomplete [-o] CMD')),
- "debuginstall": (debuginstall, [], _('debuginstall')),
+ _('hg debugcomplete [-o] CMD')),
+ "debugdate":
+ (debugdate,
+ [('e', 'extended', None, _('try extended date formats'))],
+ _('hg debugdate [-e] DATE [RANGE]')),
+ "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
+ "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
+ "debugindex": (debugindex, [], _('hg debugindex FILE')),
+ "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
+ "debuginstall": (debuginstall, [], _('hg debuginstall')),
+ "debugrawcommit|rawcommit":
+ (rawcommit,
+ [('p', 'parent', [], _('parent')),
+ ('F', 'files', '', _('file list'))
+ ] + commitopts + commitopts2,
+ _('hg debugrawcommit [OPTION]... [FILE]...')),
"debugrebuildstate":
(debugrebuildstate,
[('r', 'rev', '', _('revision to rebuild to'))],
- _('debugrebuildstate [-r REV] [REV]')),
- "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
- "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
- "debugstate": (debugstate, [], _('debugstate')),
- "debugdate":
- (debugdate,
- [('e', 'extended', None, _('try extended date formats'))],
- _('debugdate [-e] DATE [RANGE]')),
- "debugdata": (debugdata, [], _('debugdata FILE REV')),
- "debugindex": (debugindex, [], _('debugindex FILE')),
- "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
+ _('hg debugrebuildstate [-r REV] [REV]')),
"debugrename":
(debugrename,
[('r', 'rev', '', _('revision to debug'))],
- _('debugrename [-r REV] FILE')),
- "debugwalk": (debugwalk, walkopts, _('debugwalk [OPTION]... [FILE]...')),
+ _('hg debugrename [-r REV] FILE')),
+ "debugsetparents":
+ (debugsetparents,
+ [],
+ _('hg debugsetparents REV1 [REV2]')),
+ "debugstate": (debugstate, [], _('hg debugstate')),
+ "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
"^diff":
(diff,
[('r', 'rev', [], _('revision')),
@@ -2965,12 +2881,15 @@
('b', 'base', '', _('base path')),
('f', 'force', None,
_('skip check for outstanding uncommitted changes')),
+ ('', 'no-commit', None, _("don't commit, just update the working directory")),
('', 'exact', None,
_('apply patch to the nodes from which it was generated')),
('', 'import-branch', None,
- _('Use any branch information in patch (implied by --exact)'))] + commitopts,
- _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')),
- "incoming|in": (incoming,
+ _('Use any branch information in patch (implied by --exact)'))] +
+ commitopts + commitopts2,
+ _('hg import [OPTION]... PATCH...')),
+ "incoming|in":
+ (incoming,
[('M', 'no-merges', None, _('do not show merges')),
('f', 'force', None,
_('run even when remote repository is unrelated')),
@@ -3016,14 +2935,18 @@
('', 'template', '', _('display with template')),
] + walkopts,
_('hg log [OPTION]... [FILE]')),
- "manifest": (manifest, [], _('hg manifest [REV]')),
+ "manifest":
+ (manifest,
+ [('r', 'rev', '', _('revision to display'))],
+ _('hg manifest [-r REV]')),
"^merge":
(merge,
[('f', 'force', None, _('force a merge with outstanding changes')),
('r', 'rev', '', _('revision to merge')),
],
_('hg merge [-f] [[-r] REV]')),
- "outgoing|out": (outgoing,
+ "outgoing|out":
+ (outgoing,
[('M', 'no-merges', None, _('do not show merges')),
('f', 'force', None,
_('run even when remote repository is unrelated')),
@@ -3057,18 +2980,10 @@
('r', 'rev', [], _('a specific revision you would like to push')),
] + remoteopts,
_('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
- "debugrawcommit|rawcommit":
- (rawcommit,
- [('p', 'parent', [], _('parent')),
- ('d', 'date', '', _('date code')),
- ('u', 'user', '', _('user')),
- ('F', 'files', '', _('file list'))
- ] + commitopts,
- _('hg debugrawcommit [OPTION]... [FILE]...')),
"recover": (recover, [], _('hg recover')),
"^remove|rm":
(remove,
- [('A', 'after', None, _('record remove that has already occurred')),
+ [('A', 'after', None, _('record remove without deleting')),
('f', 'force', None, _('remove file even if modified')),
] + walkopts,
_('hg remove [OPTION]... FILE...')),
@@ -3079,7 +2994,7 @@
_('forcibly copy over an existing managed file')),
] + walkopts + dryrunopts,
_('hg rename [OPTION]... SOURCE... DEST')),
- "^revert":
+ "revert":
(revert,
[('a', 'all', None, _('revert all changes when no arguments given')),
('d', 'date', '', _('tipmost revision matching date')),
@@ -3089,10 +3004,6 @@
_('hg revert [OPTION]... [-r REV] [NAME]...')),
"rollback": (rollback, [], _('hg rollback')),
"root": (root, [], _('hg root')),
- "showconfig|debugconfig":
- (showconfig,
- [('u', 'untrusted', None, _('show untrusted configuration options'))],
- _('showconfig [-u] [NAME]...')),
"^serve":
(serve,
[('A', 'accesslog', '', _('name of access log file to write to')),
@@ -3101,6 +3012,7 @@
('E', 'errorlog', '', _('name of error log file to write to')),
('p', 'port', 0, _('port to use (default: 8000)')),
('a', 'address', '', _('address to use')),
+ ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
('n', 'name', '',
_('name to show in web pages (default: working dir)')),
('', 'webdir-conf', '', _('name of the webdir config file'
@@ -3112,6 +3024,10 @@
('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
('', 'certificate', '', _('SSL certificate file'))],
_('hg serve [OPTION]...')),
+ "showconfig|debugconfig":
+ (showconfig,
+ [('u', 'untrusted', None, _('show untrusted configuration options'))],
+ _('hg showconfig [-u] [NAME]...')),
"^status|st":
(status,
[('A', 'all', None, _('show status of all files')),
@@ -3133,11 +3049,11 @@
(tag,
[('f', 'force', None, _('replace existing tag')),
('l', 'local', None, _('make the tag local')),
- ('m', 'message', '', _('message for tag commit log entry')),
- ('d', 'date', '', _('record datecode as commit date')),
- ('u', 'user', '', _('record user as commiter')),
('r', 'rev', '', _('revision to tag')),
- ('', 'remove', None, _('remove a tag'))],
+ ('', 'remove', None, _('remove a tag')),
+ # -l/--local is already there, commitopts cannot be used
+ ('m', 'message', '', _('use <text> as commit message')),
+ ] + commitopts2,
_('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
"tags": (tags, [], _('hg tags')),
"tip":
@@ -3161,19 +3077,6 @@
"version": (version_, [], _('hg version')),
}
-extensions.commandtable = table
-
norepo = ("clone init version help debugancestor debugcomplete debugdata"
- " debugindex debugindexdot debugdate debuginstall")
-optionalrepo = ("paths serve showconfig")
-
-def dispatch(args, argv0=None):
- try:
- u = ui.ui(traceback='--traceback' in args)
- except util.Abort, inst:
- sys.stderr.write(_("abort: %s\n") % inst)
- return -1
- return cmdutil.runcatch(u, args, argv0=argv0)
-
-def run():
- sys.exit(dispatch(sys.argv[1:], argv0=sys.argv[0]))
+ " debugindex debugindexdot debugdate debuginstall debugfsinfo")
+optionalrepo = ("identify paths serve showconfig")