diff --git a/doc/gendoc.py b/doc/gendoc.py --- a/doc/gendoc.py +++ b/doc/gendoc.py @@ -92,11 +92,10 @@ def show_doc(ui): ui.write(_(" aliases: %s\n\n") % " ".join(d['aliases'])) # print topics - for t in helptable: + for t, doc in helptable: l = t.split("|") section = l[-1] underlined(_(section).upper()) - doc = helptable[t] if callable(doc): doc = doc() ui.write(_(doc)) diff --git a/doc/hg.1.txt b/doc/hg.1.txt --- a/doc/hg.1.txt +++ b/doc/hg.1.txt @@ -37,58 +37,6 @@ repository path:: include::hg.1.gendoc.txt[] -SPECIFYING SINGLE REVISIONS ---------------------------- - - Mercurial accepts several notations for identifying individual - revisions. - - A plain integer is treated as a revision number. Negative - integers are treated as offsets from the tip, with -1 denoting the - tip. - - A 40-digit hexadecimal string is treated as a unique revision - identifier. - - A hexadecimal string less than 40 characters long is treated as a - unique revision identifier, and referred to as a short-form - identifier. A short-form identifier is only valid if it is the - prefix of one full-length identifier. - - Any other string is treated as a tag name, which is a symbolic - name associated with a revision identifier. Tag names may not - contain the ":" character. - - The reserved name "tip" is a special tag that always identifies - the most recent revision. - - The reserved name "null" indicates the null revision. This is the - revision of an empty repository, and the parent of revision 0. - - The reserved name "." indicates the working directory parent. If - no working directory is checked out, it is equivalent to null. - If an uncommitted merge is in progress, "." is the revision of - the first parent. - -SPECIFYING MULTIPLE REVISIONS ------------------------------ - - When Mercurial accepts more than one revision, they may be - specified individually, or provided as a continuous range, - separated by the ":" character. - - The syntax of range notation is [BEGIN]:[END], where BEGIN and END - are revision identifiers. Both BEGIN and END are optional. If - BEGIN is not specified, it defaults to revision number 0. If END - is not specified, it defaults to the tip. The range ":" thus - means "all revisions". - - If BEGIN is greater than END, revisions are treated in reverse - order. - - A range acts as a closed interval. This means that a range of 3:5 - gives 3, 4 and 5. Similarly, a range of 4:2 gives 4, 3, and 2. - FILES ----- .hgignore:: diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -2038,10 +2038,14 @@ def rename(ui, repo, patch, name=None, * if r: wlock = r.wlock() try: - if r.dirstate[name] == 'r': - r.undelete([name]) - r.copy(patch, name) - r.remove([patch], False) + if r.dirstate[patch] == 'a': + r.dirstate.forget(patch) + r.dirstate.add(name) + else: + if r.dirstate[name] == 'r': + r.undelete([name]) + r.copy(patch, name) + r.remove([patch], False) finally: del wlock diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -127,7 +127,7 @@ class bundlerevlog(revlog.revlog): def addrevision(self, text, transaction, link, p1=None, p2=None, d=None): raise NotImplementedError - def addgroup(self, revs, linkmapper, transaction, unique=0): + def addgroup(self, revs, linkmapper, transaction): raise NotImplementedError def strip(self, rev, minlink): raise NotImplementedError diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -276,17 +276,23 @@ def addremove(repo, pats=[], opts={}, dr similarity = float(opts.get('similarity') or 0) add, remove = [], [] mapping = {} + audit_path = util.path_auditor(repo.root) m = match(repo, pats, opts) for abs in repo.walk(m): target = repo.wjoin(abs) + good = True + try: + audit_path(abs) + except: + good = False rel = m.rel(abs) exact = m.exact(abs) - if abs not in repo.dirstate: + if good and abs not in repo.dirstate: add.append(abs) mapping[abs] = rel, m.exact(abs) if repo.ui.verbose or not exact: repo.ui.status(_('adding %s\n') % ((pats and rel) or abs)) - if repo.dirstate[abs] != 'r' and (not util.lexists(target) + if repo.dirstate[abs] != 'r' and (not good or not util.lexists(target) or (os.path.isdir(target) and not os.path.islink(target))): remove.append(abs) mapping[abs] = rel, exact diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1253,7 +1253,14 @@ def help_(ui, name=None, with_version=Fa if with_version: version_(ui) ui.write('\n') - aliases, i = cmdutil.findcmd(ui, name, table) + + try: + aliases, i = cmdutil.findcmd(ui, name, table) + except cmdutil.AmbiguousCommand, inst: + select = lambda c: c.lstrip('^').startswith(inst.args[0]) + helplist(_('list of commands:\n\n'), select) + return + # synopsis ui.write("%s\n" % i[2]) @@ -1314,16 +1321,16 @@ def help_(ui, name=None, with_version=Fa def helptopic(name): v = None - for i in help.helptable: + for i, d in help.helptable: l = i.split('|') if name in l: v = i header = l[-1] + doc = d if not v: raise cmdutil.UnknownCommand(name) # description - doc = help.helptable[v] if not doc: doc = _("(No help text available)") if callable(doc): @@ -1394,6 +1401,16 @@ def help_(ui, name=None, with_version=Fa and _(" (default: %s)") % default or ""))) + if ui.verbose: + ui.write(_("\nspecial help topics:\n")) + topics = [] + for i, d in help.helptable: + l = i.split('|') + topics.append((", ".join(l[:-1]), l[-1])) + topics_len = max([len(s[0]) for s in topics]) + for t, desc in topics: + ui.write(" %-*s %s\n" % (topics_len, t, desc)) + if opt_output: opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0]) for first, second in opt_output: diff --git a/mercurial/help.py b/mercurial/help.py --- a/mercurial/help.py +++ b/mercurial/help.py @@ -5,8 +5,8 @@ # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. -helptable = { - "dates|Date Formats": +helptable = ( + ("dates|Date Formats", r''' Some commands allow the user to specify a date: backout, commit, import, tag: Specify the commit date. @@ -43,9 +43,55 @@ helptable = { ">{date}" - on or after a given date "{date} to {date}" - a date range, inclusive "-{days}" - within a given number of days of today - ''', + '''), + + ("patterns|File Name Patterns", + r''' + Mercurial accepts several notations for identifying one or more + files at a time. + + By default, Mercurial treats filenames as shell-style extended + glob patterns. + + Alternate pattern notations must be specified explicitly. + + To use a plain path name without any pattern matching, start a + name with "path:". These path names must match completely, from + the root of the current repository. + + To use an extended glob, start a name with "glob:". Globs are + rooted at the current directory; a glob such as "*.c" will match + files ending in ".c" in the current directory only. + + The supported glob syntax extensions are "**" to match any string + across path separators, and "{a,b}" to mean "a or b". - 'environment|env|Environment Variables': + To use a Perl/Python regular expression, start a name with "re:". + Regexp pattern matching is anchored at the root of the repository. + + Plain examples: + + path:foo/bar a name bar in a directory named foo in the root of + the repository + path:path:name a file or directory named "path:name" + + Glob examples: + + glob:*.c any name ending in ".c" in the current directory + *.c any name ending in ".c" in the current directory + **.c any name ending in ".c" in the current directory, or + any subdirectory + foo/*.c any name ending in ".c" in the directory foo + foo/**.c any name ending in ".c" in the directory foo, or any + subdirectory + + Regexp examples: + + re:.*\.c$ any name ending in ".c", anywhere in the repository + + '''), + + ('environment|env|Environment Variables', r''' HG:: Path to the 'hg' executable, automatically passed when running hooks, @@ -114,51 +160,57 @@ EDITOR:: PYTHONPATH:: This is used by Python to find imported modules and may need to be set appropriately if Mercurial is not installed system-wide. - ''', + '''), - "patterns|File Name Patterns": r''' - Mercurial accepts several notations for identifying one or more - files at a time. + ('revs|revisions|Specifying Single Revisions', + r''' + Mercurial accepts several notations for identifying individual + revisions. - By default, Mercurial treats filenames as shell-style extended - glob patterns. - - Alternate pattern notations must be specified explicitly. + A plain integer is treated as a revision number. Negative + integers are treated as offsets from the tip, with -1 denoting the + tip. - To use a plain path name without any pattern matching, start a - name with "path:". These path names must match completely, from - the root of the current repository. + A 40-digit hexadecimal string is treated as a unique revision + identifier. - To use an extended glob, start a name with "glob:". Globs are - rooted at the current directory; a glob such as "*.c" will match - files ending in ".c" in the current directory only. + A hexadecimal string less than 40 characters long is treated as a + unique revision identifier, and referred to as a short-form + identifier. A short-form identifier is only valid if it is the + prefix of one full-length identifier. - The supported glob syntax extensions are "**" to match any string - across path separators, and "{a,b}" to mean "a or b". + Any other string is treated as a tag name, which is a symbolic + name associated with a revision identifier. Tag names may not + contain the ":" character. + + The reserved name "tip" is a special tag that always identifies + the most recent revision. - To use a Perl/Python regular expression, start a name with "re:". - Regexp pattern matching is anchored at the root of the repository. - - Plain examples: + The reserved name "null" indicates the null revision. This is the + revision of an empty repository, and the parent of revision 0. - path:foo/bar a name bar in a directory named foo in the root of - the repository - path:path:name a file or directory named "path:name" - - Glob examples: + The reserved name "." indicates the working directory parent. If + no working directory is checked out, it is equivalent to null. + If an uncommitted merge is in progress, "." is the revision of + the first parent. + '''), - glob:*.c any name ending in ".c" in the current directory - *.c any name ending in ".c" in the current directory - **.c any name ending in ".c" in the current directory, or - any subdirectory - foo/*.c any name ending in ".c" in the directory foo - foo/**.c any name ending in ".c" in the directory foo, or any - subdirectory + ('mrevs|multirevs|Specifying Multiple Revisions', + r''' + When Mercurial accepts more than one revision, they may be + specified individually, or provided as a continuous range, + separated by the ":" character. - Regexp examples: - - re:.*\.c$ any name ending in ".c", anywhere in the repository + The syntax of range notation is [BEGIN]:[END], where BEGIN and END + are revision identifiers. Both BEGIN and END are optional. If + BEGIN is not specified, it defaults to revision number 0. If END + is not specified, it defaults to the tip. The range ":" thus + means "all revisions". -''', -} + If BEGIN is greater than END, revisions are treated in reverse + order. + A range acts as a closed interval. This means that a range of 3:5 + gives 3, 4 and 5. Similarly, a range of 4:2 gives 4, 3, and 2. + '''), +) diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py --- a/mercurial/hgweb/webcommands.py +++ b/mercurial/hgweb/webcommands.py @@ -472,6 +472,7 @@ def annotate(web, req, tmpl): "node": hex(f.node()), "rev": f.rev(), "author": f.user(), + "desc": f.description(), "file": f.path(), "targetline": targetline, "line": l, diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1985,7 +1985,7 @@ class localrepository(repo.repository): self.ui.status(_("adding changesets\n")) cor = cl.count() - 1 chunkiter = changegroup.chunkiter(source) - if cl.addgroup(chunkiter, csmap, trp, 1) is None and not emptyok: + if cl.addgroup(chunkiter, csmap, trp) is None and not emptyok: raise util.Abort(_("received changelog group is empty")) cnr = cl.count() - 1 changesets = cnr - cor diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -1133,7 +1133,7 @@ class revlog(object): yield changegroup.closechunk() - def addgroup(self, revs, linkmapper, transaction, unique=0): + def addgroup(self, revs, linkmapper, transaction): """ add a delta group @@ -1170,8 +1170,6 @@ class revlog(object): link = linkmapper(cs) if node in self.nodemap: # this can happen if two branches make the same change - # if unique: - # raise RevlogError(_("already have %s") % hex(node[:4])) chain = node continue delta = buffer(chunk, 80) diff --git a/templates/coal/map b/templates/coal/map --- a/templates/coal/map +++ b/templates/coal/map @@ -30,7 +30,7 @@ filelog = filelog.tmpl fileline = '{linenumber}{line|escape}' filelogentry = filelogentry.tmpl -annotateline = '{author|user}@{rev}{linenumber}{line|escape}' +annotateline = '{author|user}@{rev}{linenumber}{line|escape}' diffblock = '{lines}
' difflineplus = '{linenumber}{line|escape}' diff --git a/templates/gitweb/map b/templates/gitweb/map --- a/templates/gitweb/map +++ b/templates/gitweb/map @@ -24,7 +24,7 @@ fileannotate = fileannotate.tmpl filediff = filediff.tmpl filelog = filelog.tmpl fileline = '
#linenumber# #line|escape#
' -annotateline = '#author|user#@#rev#
#linenumber#
#line|escape#
' +annotateline = '#author|user#@#rev#
#linenumber#
#line|escape#
' difflineplus = '#linenumber# #line|escape#' difflineminus = '#linenumber# #line|escape#' difflineat = '#linenumber# #line|escape#' diff --git a/templates/map b/templates/map --- a/templates/map +++ b/templates/map @@ -24,7 +24,7 @@ filediff = filediff.tmpl filelog = filelog.tmpl fileline = '
#linenumber##line|escape#
' filelogentry = filelogentry.tmpl -annotateline = '#author|user#@#rev##linenumber#
#line|escape#
' +annotateline = '#author|user#@#rev##linenumber#
#line|escape#
' difflineplus = '#linenumber##line|escape#' difflineminus = '#linenumber##line|escape#' difflineat = '#linenumber##line|escape#' diff --git a/tests/test-extension.out b/tests/test-extension.out --- a/tests/test-extension.out +++ b/tests/test-extension.out @@ -33,6 +33,13 @@ list of commands: debugfoobar: yet another debug command +special help topics: + dates Date Formats + patterns File Name Patterns + environment, env Environment Variables + revs, revisions Specifying Single Revisions + mrevs, multirevs Specifying Multiple Revisions + global options: -R --repository repository root directory or symbolic path name --cwd change working directory diff --git a/tests/test-highlight.out b/tests/test-highlight.out --- a/tests/test-highlight.out +++ b/tests/test-highlight.out @@ -114,7 +114,7 @@ 200 Script output follows
- +
test@0 1
#!/usr/bin/env python
test@0 2
test@0 3
__doc__ = """This does HTTP get requests given a host:port and path and returns
test@0 4
a subset of the headers plus the body of the result."""
test@0 5
test@0 6
import httplib, sys
test@0 7
headers = [h.lower() for h in sys.argv[3:]]
test@0 8
conn = httplib.HTTPConnection(sys.argv[1])
test@0 9
conn.request("GET", sys.argv[2])
test@0 10
response = conn.getresponse()
test@0 11
print response.status, response.reason
test@0 12
for h in headers:
test@0 13
    if response.getheader(h, None) is not None:
test@0 14
        print "%s: %s" % (h, response.getheader(h))
test@0 15
print
test@0 16
sys.stdout.write(response.read())
test@0 17
test@0 18
if 200 <= response.status <= 299:
test@0 19
    sys.exit(0)
test@0 20
sys.exit(1)
test@0 1
#!/usr/bin/env python
test@0 2
test@0 3
__doc__ = """This does HTTP get requests given a host:port and path and returns
test@0 4
a subset of the headers plus the body of the result."""
test@0 5
test@0 6
import httplib, sys
test@0 7
headers = [h.lower() for h in sys.argv[3:]]
test@0 8
conn = httplib.HTTPConnection(sys.argv[1])
test@0 9
conn.request("GET", sys.argv[2])
test@0 10
response = conn.getresponse()
test@0 11
print response.status, response.reason
test@0 12
for h in headers:
test@0 13
    if response.getheader(h, None) is not None:
test@0 14
        print "%s: %s" % (h, response.getheader(h))
test@0 15
print
test@0 16
sys.stdout.write(response.read())
test@0 17
test@0 18
if 200 <= response.status <= 299:
test@0 19
    sys.exit(0)
test@0 20
sys.exit(1)
diff --git a/tests/test-mq-qrename b/tests/test-mq-qrename --- a/tests/test-mq-qrename +++ b/tests/test-mq-qrename @@ -22,4 +22,15 @@ ls .hg/patches/bar hg qrename bar/renamed baz hg qseries ls .hg/patches/baz +cd .. +echo % test patch being renamed before committed +hg init b +cd b +hg qinit -c +hg qnew x +hg qrename y +hg qcommit -m rename +cd .. + + diff --git a/tests/test-mq-qrename.out b/tests/test-mq-qrename.out --- a/tests/test-mq-qrename.out +++ b/tests/test-mq-qrename.out @@ -5,3 +5,4 @@ bar/renamed renamed baz .hg/patches/baz +% test patch being renamed before committed diff --git a/tests/test-symlink-addremove b/tests/test-symlink-addremove new file mode 100755 --- /dev/null +++ b/tests/test-symlink-addremove @@ -0,0 +1,15 @@ +#!/bin/sh + +"$TESTDIR/hghave" symlink || exit 80 + +hg init a +cd a + +echo '% directory moved and symlinked' +mkdir foo +touch foo/a +hg ci -Ama +mv foo bar +ln -s bar foo +echo '% now addremove should remove old files' +hg addremove diff --git a/tests/test-symlink-addremove.out b/tests/test-symlink-addremove.out new file mode 100644 --- /dev/null +++ b/tests/test-symlink-addremove.out @@ -0,0 +1,6 @@ +% directory moved and symlinked +adding foo/a +% now addremove should remove old files +adding bar/a +adding foo +removing foo/a