--- a/contrib/check-code.py Thu Mar 18 19:26:56 2010 +0100
+++ b/contrib/check-code.py Thu Mar 18 14:36:24 2010 -0700
@@ -10,9 +10,15 @@
import sys, re, glob
def repquote(m):
- t = re.sub(r"\w", "x", m.group(2))
+ t = re.sub(r"\w", "x", m.group('text'))
t = re.sub(r"[^\sx]", "o", t)
- return m.group(1) + t + m.group(1)
+ return m.group('quote') + t + m.group('quote')
+
+def reppython(m):
+ comment = m.group('comment')
+ if comment:
+ return "#" * len(comment)
+ return repquote(m)
def repcomment(m):
return m.group(1) + "#" * len(m.group(2))
@@ -83,6 +89,7 @@
(r'[\x80-\xff]', "non-ASCII character literal"),
(r'("\')\.format\(', "str.format() not available in Python 2.4"),
(r'^\s*with\s+', "with not available in Python 2.4"),
+ (r'^\s*(any|all)\(', "any/all not available in Python 2.4"),
(r'if\s.*\selse', "if ... else form not available in Python 2.4"),
(r'([\(\[]\s\S)|(\S\s[\)\]])', "gratuitous whitespace in () or []"),
# (r'\s\s=', "gratuitous whitespace before ="),
@@ -95,11 +102,10 @@
]
pyfilters = [
- (r"""(''')(([^']|\\'|'{1,2}(?!'))*)'''""", repquote),
- (r'''(""")(([^"]|\\"|"{1,2}(?!"))*)"""''', repquote),
- (r'''(?<!")(")(([^"\n]|\\")+)"(?!")''', repquote),
- (r"""(?<!')(')(([^'\n]|\\')+)'(?!')""", repquote),
- (r"( *)(#([^\n]*\S)?)", repcomment),
+ (r"""(?msx)(?P<comment>\#.*?$)|
+ ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
+ (?P<text>(([^\\]|\\.)*?))
+ (?P=quote))""", reppython),
]
cpats = [
@@ -122,7 +128,7 @@
cfilters = [
(r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
- (r'''(?<!")(")(([^"]|\\")+"(?!"))''', repquote),
+ (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
(r'''(#\s*include\s+<)([^>]+)>''', repinclude),
(r'(\()([^)]+\))', repcallspaces),
]
@@ -133,12 +139,42 @@
('c', r'.*\.c$', cfilters, cpats),
]
-if len(sys.argv) == 1:
- check = glob.glob("*")
-else:
- check = sys.argv[1:]
+class norepeatlogger(object):
+ def __init__(self):
+ self._lastseen = None
+
+ def log(self, fname, lineno, line, msg):
+ """print error related a to given line of a given file.
+
+ The faulty line will also be printed but only once in the case
+ of multiple errors.
-for f in check:
+ :fname: filename
+ :lineno: line number
+ :line: actual content of the line
+ :msg: error message
+ """
+ msgid = fname, lineno, line
+ if msgid != self._lastseen:
+ print "%s:%d:" % (fname, lineno)
+ print " > %s" % line
+ self._lastseen = msgid
+ print " " + msg
+
+_defaultlogger = norepeatlogger()
+
+def checkfile(f, logfunc=_defaultlogger.log, maxerr=None):
+ """checks style and portability of a given file
+
+ :f: filepath
+ :logfunc: function used to report error
+ logfunc(filename, linenumber, linecontent, errormessage)
+ :maxerr: number of error to display before arborting.
+ Set to None (default) to report all errors
+
+ return True if no error is found, False otherwise.
+ """
+ result = True
for name, match, filters, pats in checks:
fc = 0
if not re.match(match, f):
@@ -153,16 +189,23 @@
for n, l in z:
if "check-code" + "-ignore" in l[0]:
continue
- lc = 0
for p, msg in pats:
if re.search(p, l[1]):
- if not lc:
- print "%s:%d:" % (f, n + 1)
- print " > %s" % l[0]
- print " %s" % msg
- lc += 1
+ logfunc(f, n + 1, l[0], msg)
fc += 1
- if fc == 15:
+ result = False
+ if maxerr is not None and fc >= maxerr:
print " (too many errors, giving up)"
break
break
+ return result
+
+
+if __name__ == "__main__":
+ if len(sys.argv) == 1:
+ check = glob.glob("*")
+ else:
+ check = sys.argv[1:]
+
+ for f in check:
+ checkfile(f, maxerr=15)
--- a/contrib/hgdiff Thu Mar 18 19:26:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-#!/usr/bin/env python
-
-import os, sys, struct, stat
-import difflib
-import re
-from optparse import OptionParser
-from mercurial.bdiff import bdiff, blocks
-from mercurial.mdiff import bunidiff, diffopts
-
-VERSION="0.3"
-usage = "usage: %prog [options] file1 file2"
-parser = OptionParser(usage=usage)
-
-parser.add_option("-d", "--difflib", action="store_true", default=False)
-parser.add_option('-x', '--count', default=1)
-parser.add_option('-c', '--context', type="int", default=3)
-parser.add_option('-p', '--show-c-function', action="store_true", default=False)
-parser.add_option('-w', '--ignore-all-space', action="store_true",
- default=False)
-
-(options, args) = parser.parse_args()
-
-if not args:
- parser.print_help()
- sys.exit(1)
-
-# simple utility function to put all the
-# files from a directory tree into a dict
-def buildlist(names, top):
- tlen = len(top)
- for root, dirs, files in os.walk(top):
- l = root[tlen + 1:]
- for x in files:
- p = os.path.join(root, x)
- st = os.lstat(p)
- if stat.S_ISREG(st.st_mode):
- names[os.path.join(l, x)] = (st.st_dev, st.st_ino)
-
-def diff_files(file1, file2):
- if file1 is None:
- b = file(file2).read().splitlines(True)
- l1 = "--- %s\n" % (file2)
- l2 = "+++ %s\n" % (file2)
- l3 = "@@ -0,0 +1,%d @@\n" % len(b)
- l = [l1, l2, l3] + ["+" + e for e in b]
- elif file2 is None:
- a = file(file1).read().splitlines(True)
- l1 = "--- %s\n" % (file1)
- l2 = "+++ %s\n" % (file1)
- l3 = "@@ -1,%d +0,0 @@\n" % len(a)
- l = [l1, l2, l3] + ["-" + e for e in a]
- else:
- t1 = file(file1).read()
- t2 = file(file2).read()
- l1 = t1.splitlines(True)
- l2 = t2.splitlines(True)
- if options.difflib:
- l = difflib.unified_diff(l1, l2, file1, file2)
- else:
- l = bunidiff(t1, t2, l1, l2, file1, file2,
- diffopts(context=options.context,
- showfunc=options.show_c_function,
- ignorews=options.ignore_all_space))
- for x in l:
- if x[-1] != '\n':
- x += "\n\ No newline at end of file\n"
- print x,
-
-file1 = args[0]
-file2 = args[1]
-
-if os.path.isfile(file1) and os.path.isfile(file2):
- diff_files(file1, file2)
-elif os.path.isdir(file1):
- if not os.path.isdir(file2):
- sys.stderr.write("file types don't match\n")
- sys.exit(1)
-
- d1 = {}
- d2 = {}
-
- buildlist(d1, file1)
- buildlist(d2, file2)
- keys = d1.keys()
- keys.sort()
- for x in keys:
- if x not in d2:
- f2 = None
- else:
- f2 = os.path.join(file2, x)
- st1 = d1[x]
- st2 = d2[x]
- del d2[x]
- if st1[0] == st2[0] and st1[1] == st2[1]:
- sys.stderr.write("%s is a hard link\n" % x)
- continue
- x = os.path.join(file1, x)
- diff_files(x, f2)
- keys = d2.keys()
- keys.sort()
- for x in keys:
- f1 = None
- x = os.path.join(file2, x)
- diff_files(f1, x)
-
--- a/contrib/shrink-revlog.py Thu Mar 18 19:26:56 2010 +0100
+++ b/contrib/shrink-revlog.py Thu Mar 18 14:36:24 2010 -0700
@@ -24,50 +24,81 @@
from mercurial import changegroup
from mercurial.i18n import _
-def toposort(ui, rl):
+
+def postorder(start, edges):
+ result = []
+ visit = list(start)
+ finished = set()
- children = {}
- root = []
- # build children and roots
+ while visit:
+ cur = visit[-1]
+ for p in edges[cur]:
+ if p not in finished:
+ visit.append(p)
+ break
+ else:
+ result.append(cur)
+ finished.add(cur)
+ visit.pop()
+
+ return result
+
+def toposort_reversepostorder(ui, rl):
+ # postorder of the reverse directed graph
+
+ # map rev to list of parent revs (p2 first)
+ parents = {}
+ heads = set()
ui.status(_('reading revs\n'))
try:
- for i in rl:
- ui.progress(_('reading'), i, total=len(rl))
- children[i] = []
- parents = [p for p in rl.parentrevs(i) if p != node.nullrev]
- # in case of duplicate parents
- if len(parents) == 2 and parents[0] == parents[1]:
- del parents[1]
- for p in parents:
- assert p in children
- children[p].append(i)
+ for rev in rl:
+ ui.progress(_('reading'), rev, total=len(rl))
+ (p1, p2) = rl.parentrevs(rev)
+ if p1 == p2 == node.nullrev:
+ parents[rev] = () # root node
+ elif p1 == p2 or p2 == node.nullrev:
+ parents[rev] = (p1,) # normal node
+ else:
+ parents[rev] = (p2, p1) # merge node
+ heads.add(rev)
+ for p in parents[rev]:
+ heads.discard(p)
+ finally:
+ ui.progress(_('reading'), None)
- if len(parents) == 0:
- root.append(i)
- finally:
- ui.progress(_('reading'), None, total=len(rl))
+ heads = list(heads)
+ heads.sort(reverse=True)
+
+ ui.status(_('sorting revs\n'))
+ return postorder(heads, parents)
+
+def toposort_postorderreverse(ui, rl):
+ # reverse-postorder of the reverse directed graph
- # XXX this is a reimplementation of the 'branchsort' topo sort
- # algorithm in hgext.convert.convcmd... would be nice not to duplicate
- # the algorithm
+ children = {}
+ roots = set()
+ ui.status(_('reading revs\n'))
+ try:
+ for rev in rl:
+ ui.progress(_('reading'), rev, total=len(rl))
+ (p1, p2) = rl.parentrevs(rev)
+ if p1 == p2 == node.nullrev:
+ roots.add(rev)
+ children[rev] = []
+ if p1 != node.nullrev:
+ children[p1].append(rev)
+ if p2 != node.nullrev:
+ children[p2].append(rev)
+ finally:
+ ui.progress(_('reading'), None)
+
+ root = list(roots)
+ roots.sort()
+
ui.status(_('sorting revs\n'))
- visit = root
- ret = []
- while visit:
- i = visit.pop(0)
- ret.append(i)
- if i not in children:
- # This only happens if some node's p1 == p2, which can
- # happen in the manifest in certain circumstances.
- continue
- next = []
- for c in children.pop(i):
- parents_unseen = [p for p in rl.parentrevs(c)
- if p != node.nullrev and p in children]
- if len(parents_unseen) == 0:
- next.append(c)
- visit = next + visit
- return ret
+ result = postorder(roots, children)
+ result.reverse()
+ return result
def writerevs(ui, r1, r2, order, tr):
@@ -89,7 +120,7 @@
chunkiter = changegroup.chunkiter(group)
r2.addgroup(chunkiter, unlookup, tr)
finally:
- ui.progress(_('writing'), None, len(order))
+ ui.progress(_('writing'), None)
def report(ui, r1, r2):
def getsize(r):
@@ -118,9 +149,15 @@
% (shrink_percent, shrink_factor))
def shrink(ui, repo, **opts):
+ """shrink a revlog by reordering revisions
+
+ Rewrites all the entries in some revlog of the current repository
+ (by default, the manifest log) to save space.
+
+ Different sort algorithms have different performance
+ characteristics. Use ``--sort`` to select a sort algorithm so you
+ can determine which works best for your data.
"""
- Shrink revlog by re-ordering revisions. Will operate on manifest for
- the given repository if no other revlog is specified."""
if not repo.local():
raise util.Abort(_('not a local repository: %s') % repo.root)
@@ -139,6 +176,12 @@
raise util.Abort(_('--revlog option must specify a revlog in %s, '
'not %s') % (store, indexfn))
+ sortname = opts['sort']
+ try:
+ toposort = globals()['toposort_' + sortname]
+ except KeyError:
+ raise util.Abort(_('no such toposort algorithm: %s') % sortname)
+
if not os.path.exists(indexfn):
raise util.Abort(_('no such file: %s') % indexfn)
if '00changelog' in indexfn:
@@ -187,6 +230,15 @@
try:
try:
order = toposort(ui, r1)
+
+ suboptimal = 0
+ for i in xrange(1, len(order)):
+ parents = [p for p in r1.parentrevs(order[i])
+ if p != node.nullrev]
+ if parents and order[i - 1] not in parents:
+ suboptimal += 1
+ ui.note(_('%d suboptimal nodes\n') % suboptimal)
+
writerevs(ui, r1, r2, order, tr)
report(ui, r1, r2)
tr.close()
@@ -229,6 +281,7 @@
'shrink': (shrink,
[('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
('n', 'dry-run', None, _('do not shrink, simulate only')),
+ ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
],
_('hg shrink [--revlog PATH]'))
}
--- a/contrib/wix/mercurial.wxs Thu Mar 18 19:26:56 2010 +0100
+++ b/contrib/wix/mercurial.wxs Thu Mar 18 14:36:24 2010 -0700
@@ -37,6 +37,9 @@
<Property Id='INSTALLEDMERCURIALPRODUCTS' Secure='yes'></Property>
<Property Id='REINSTALLMODE'>amus</Property>
+ <!--Auto-accept the license page-->
+ <Property Id='LicenseAccepted'>1</Property>
+
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='INSTALLDIR' Name='Mercurial'>
--- a/hgext/churn.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/churn.py Thu Mar 18 14:36:24 2010 -0700
@@ -48,7 +48,7 @@
tmpl.show(ctx)
return ui.popbuffer()
- state = {'count': 0, 'pct': 0}
+ state = {'count': 0}
rate = {}
df = False
if opts.get('date'):
@@ -74,20 +74,13 @@
lines = changedlines(ui, repo, ctx1, ctx, fns)
rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
- if opts.get('progress'):
- state['count'] += 1
- newpct = int(100.0 * state['count'] / max(len(repo), 1))
- if state['pct'] < newpct:
- state['pct'] = newpct
- ui.write("\r" + _("generating stats: %d%%") % state['pct'])
- sys.stdout.flush()
+ state['count'] += 1
+ ui.progress(_('analyzing'), state['count'], total=len(repo))
for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
continue
- if opts.get('progress'):
- ui.write("\r")
- sys.stdout.flush()
+ ui.progress(_('analyzing'), None)
return rate
@@ -188,6 +181,6 @@
('s', 'sort', False, _('sort by key (default: sort by count)')),
('', 'diffstat', False, _('display added/removed lines separately')),
('', 'aliases', '', _('file with email aliases')),
- ('', 'progress', None, _('show progress'))],
- _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
+ ],
+ _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]")),
}
--- a/hgext/hgcia.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/hgcia.py Thu Mar 18 14:36:24 2010 -0700
@@ -113,7 +113,7 @@
n = self.ctx.node()
pbuf = patchbuf()
- patch.export(self.cia.repo, [n], fp=pbuf)
+ cmdutil.export(self.cia.repo, [n], fp=pbuf)
return patch.diffstat(pbuf.lines) or ''
def logmsg(self):
--- a/hgext/inotify/__init__.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/inotify/__init__.py Thu Mar 18 14:36:24 2010 -0700
@@ -41,7 +41,7 @@
# to start an inotify server if it won't start.
_inotifyon = True
- def status(self, match, subrepos, ignored, clean, unknown=True):
+ def status(self, match, subrepos, ignored, clean, unknown):
files = match.files()
if '.' in files:
files = []
--- a/hgext/keyword.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/keyword.py Thu Mar 18 14:36:24 2010 -0700
@@ -1,6 +1,6 @@
# keyword.py - $Keyword$ expansion for Mercurial
#
-# Copyright 2007-2009 Christian Ebert <blacktrash@gmx.net>
+# Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
@@ -79,7 +79,6 @@
from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
from mercurial import patch, localrepo, templater, templatefilters, util, match
from mercurial.hgweb import webcommands
-from mercurial.lock import release
from mercurial.node import nullid
from mercurial.i18n import _
import re, shutil, tempfile
@@ -163,16 +162,13 @@
Caveat: localrepository._link fails on Windows.'''
return self.match(path) and not 'l' in flagfunc(path)
- def overwrite(self, node, expand, files):
+ def overwrite(self, node, expand, candidates):
'''Overwrites selected files expanding/shrinking keywords.'''
ctx = self.repo[node]
mf = ctx.manifest()
if node is not None: # commit
- files = [f for f in ctx.files() if f in mf]
- notify = self.ui.debug
- else: # kwexpand/kwshrink
- notify = self.ui.note
- candidates = [f for f in files if self.iskwfile(f, ctx.flags)]
+ candidates = [f for f in ctx.files() if f in mf]
+ candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
if candidates:
self.restrict = True # do not expand when reading
msg = (expand and _('overwriting %s expanding keywords\n')
@@ -190,7 +186,7 @@
else:
found = self.re_kw.search(data)
if found:
- notify(msg % f)
+ self.ui.note(msg % f)
self.repo.wwrite(f, data, mf.flags(f))
if node is None:
self.repo.dirstate.normal(f)
@@ -251,10 +247,8 @@
'''Bails out if [keyword] configuration is not active.
Returns status of working directory.'''
if kwt:
- unknown = (opts.get('unknown') or opts.get('all')
- or opts.get('untracked'))
return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
- unknown=unknown)
+ unknown=opts.get('unknown') or opts.get('all'))
if ui.configitems('keyword'):
raise util.Abort(_('[keyword] patterns cannot match'))
raise util.Abort(_('no [keyword] patterns configured'))
@@ -264,17 +258,15 @@
if repo.dirstate.parents()[1] != nullid:
raise util.Abort(_('outstanding uncommitted merge'))
kwt = kwtools['templater']
- status = _status(ui, repo, kwt, *pats, **opts)
- modified, added, removed, deleted = status[:4]
- if modified or added or removed or deleted:
- raise util.Abort(_('outstanding uncommitted changes'))
- wlock = lock = None
+ wlock = repo.wlock()
try:
- wlock = repo.wlock()
- lock = repo.lock()
- kwt.overwrite(None, expand, status[6])
+ status = _status(ui, repo, kwt, *pats, **opts)
+ modified, added, removed, deleted, unknown, ignored, clean = status
+ if modified or added or removed or deleted:
+ raise util.Abort(_('outstanding uncommitted changes'))
+ kwt.overwrite(None, expand, clean)
finally:
- release(lock, wlock)
+ wlock.release()
def demo(ui, repo, *args, **opts):
'''print [keywordmaps] configuration and an expansion example
@@ -295,7 +287,6 @@
ui.write('%s = %s\n' % (k, v))
fn = 'demo.txt'
- branchname = 'demobranch'
tmpdir = tempfile.mkdtemp('', 'kwdemo.')
ui.note(_('creating temporary repository at %s\n') % tmpdir)
repo = localrepo.localrepository(ui, tmpdir, True)
@@ -331,35 +322,23 @@
uisetup(ui)
reposetup(ui, repo)
- for k, v in ui.configitems('extensions'):
- if k.endswith('keyword'):
- extension = '%s = %s' % (k, v)
- break
- ui.write('[extensions]\n%s\n' % extension)
+ ui.write('[extensions]\nkeyword =\n')
demoitems('keyword', ui.configitems('keyword'))
demoitems('keywordmaps', kwmaps.iteritems())
keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
repo.wopener(fn, 'w').write(keywords)
repo.add([fn])
- path = repo.wjoin(fn)
- ui.note(_('\nkeywords written to %s:\n') % path)
+ ui.note(_('\nkeywords written to %s:\n') % fn)
ui.note(keywords)
- ui.note('\nhg -R "%s" branch "%s"\n' % (tmpdir, branchname))
- # silence branch command if not verbose
- quiet = ui.quiet
- ui.quiet = not ui.verbose
- commands.branch(ui, repo, branchname)
- ui.quiet = quiet
+ repo.dirstate.setbranch('demobranch')
for name, cmd in ui.configitems('hooks'):
if name.split('.', 1)[0].find('commit') > -1:
repo.ui.setconfig('hooks', name, '')
- ui.note(_('unhooked all commit hooks\n'))
msg = _('hg keyword configuration and expansion example')
- ui.note("hg -R '%s' ci -m '%s'\n" % (tmpdir, msg))
+ ui.note("hg ci -m '%s'\n" % msg)
repo.commit(text=msg)
ui.status(_('\n\tkeywords expanded\n'))
ui.write(repo.wread(fn))
- ui.debug('\nremoving temporary repository %s\n' % tmpdir)
shutil.rmtree(tmpdir, ignore_errors=True)
def expand(ui, repo, *pats, **opts):
@@ -398,7 +377,7 @@
cwd = pats and repo.getcwd() or ''
modified, added, removed, deleted, unknown, ignored, clean = status
files = []
- if not (opts.get('unknown') or opts.get('untracked')) or opts.get('all'):
+ if not opts.get('unknown') or opts.get('all'):
files = sorted(modified + added + clean)
wctx = repo[None]
kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
@@ -485,15 +464,10 @@
del self.commitctx
def kwcommitctx(self, ctx, error=False):
- wlock = lock = None
- try:
- wlock = self.wlock()
- lock = self.lock()
- n = super(kwrepo, self).commitctx(ctx, error)
- kwt.overwrite(n, True, None)
- return n
- finally:
- release(lock, wlock)
+ n = super(kwrepo, self).commitctx(ctx, error)
+ # no lock needed, only called from repo.commit() which already locks
+ kwt.overwrite(n, True, None)
+ return n
# monkeypatches
def kwpatchfile_init(orig, self, ui, fname, opener,
@@ -540,9 +514,6 @@
[('A', 'all', None, _('show keyword status flags of all files')),
('i', 'ignore', None, _('show files excluded from expansion')),
('u', 'unknown', None, _('only show unknown (not tracked) files')),
- ('a', 'all', None,
- _('show keyword status flags of all files (DEPRECATED)')),
- ('u', 'untracked', None, _('only show untracked files (DEPRECATED)')),
] + commands.walkopts,
_('hg kwfiles [OPTION]... [FILE]...')),
'kwshrink': (shrink, commands.walkopts,
--- a/hgext/mq.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/mq.py Thu Mar 18 14:36:24 2010 -0700
@@ -53,18 +53,11 @@
normname = util.normpath
class statusentry(object):
- def __init__(self, rev, name=None):
- if not name:
- fields = rev.split(':', 1)
- if len(fields) == 2:
- self.rev, self.name = fields
- else:
- self.rev, self.name = None, None
- else:
- self.rev, self.name = rev, name
+ def __init__(self, node, name):
+ self.node, self.name = node, name
def __str__(self):
- return self.rev + ':' + self.name
+ return hex(self.node) + ':' + self.name
class patchheader(object):
def __init__(self, pf, plainmode=False):
@@ -79,8 +72,7 @@
break
def eatempty(lines):
while lines:
- l = lines[-1]
- if re.match('\s*$', l):
+ if not lines[-1].strip():
del lines[-1]
else:
break
@@ -265,8 +257,11 @@
@util.propertycache
def applied(self):
if os.path.exists(self.join(self.status_path)):
+ def parse(l):
+ n, name = l.split(':', 1)
+ return statusentry(bin(n), name)
lines = self.opener(self.status_path).read().splitlines()
- return [statusentry(l) for l in lines]
+ return [parse(l) for l in lines]
return []
@util.propertycache
@@ -329,16 +324,12 @@
return os.path.join(self.path, *p)
def find_series(self, patch):
- pre = re.compile("(\s*)([^#]+)")
- index = 0
- for l in self.full_series:
- m = pre.match(l)
- if m:
- s = m.group(2)
- s = s.rstrip()
- if s == patch:
- return index
- index += 1
+ def matchpatch(l):
+ l = l.split('#', 1)[0]
+ return l.strip() == patch
+ for index, l in enumerate(self.full_series):
+ if matchpatch(l):
+ return index
return None
guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
@@ -544,22 +535,16 @@
(p1, p2) = repo.dirstate.parents()
if p2 == nullid:
return p1
- if len(self.applied) == 0:
+ if not self.applied:
return None
- return bin(self.applied[-1].rev)
- pp = repo.changelog.parents(rev)
- if pp[1] != nullid:
- arevs = [x.rev for x in self.applied]
- p0 = hex(pp[0])
- p1 = hex(pp[1])
- if p0 in arevs:
- return pp[0]
- if p1 in arevs:
- return pp[1]
- return pp[0]
+ return self.applied[-1].node
+ p1, p2 = repo.changelog.parents(rev)
+ if p2 != nullid and p2 in [x.node for x in self.applied]:
+ return p2
+ return p1
def mergepatch(self, repo, mergeq, series, diffopts):
- if len(self.applied) == 0:
+ if not self.applied:
# each of the patches merged in will have two parents. This
# can confuse the qrefresh, qdiff, and strip code because it
# needs to know which parent is actually in the patch queue.
@@ -569,7 +554,7 @@
pname = ".hg.patches.merge.marker"
n = repo.commit('[mq]: merge marker', force=True)
self.removeundo(repo)
- self.applied.append(statusentry(hex(n), pname))
+ self.applied.append(statusentry(n, pname))
self.applied_dirty = 1
head = self.qparents(repo)
@@ -587,10 +572,10 @@
if not info:
self.ui.warn(_("patch %s is not applied\n") % patch)
return (1, None)
- rev = bin(info[1])
+ rev = info[1]
err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
if head:
- self.applied.append(statusentry(hex(head), patch))
+ self.applied.append(statusentry(head, patch))
self.applied_dirty = 1
if err:
return (err, head)
@@ -613,7 +598,7 @@
return (True, files, fuzz)
def apply(self, repo, series, list=False, update_status=True,
- strict=False, patchdir=None, merge=None, all_files={}):
+ strict=False, patchdir=None, merge=None, all_files=None):
wlock = lock = tr = None
try:
wlock = repo.wlock()
@@ -638,7 +623,7 @@
self.removeundo(repo)
def _apply(self, repo, series, list=False, update_status=True,
- strict=False, patchdir=None, merge=None, all_files={}):
+ strict=False, patchdir=None, merge=None, all_files=None):
'''returns (error, hash)
error = 1 for unable to read, 2 for patch failed, 3 for patch fuzz'''
# TODO unify with commands.py
@@ -671,7 +656,8 @@
if ph.haspatch:
(patcherr, files, fuzz) = self.patch(repo, pf)
- all_files.update(files)
+ if all_files is not None:
+ all_files.update(files)
patcherr = not patcherr
else:
self.ui.warn(_("patch %s is empty\n") % patchname)
@@ -701,7 +687,7 @@
raise util.Abort(_("repo commit failed"))
if update_status:
- self.applied.append(statusentry(hex(n), patchname))
+ self.applied.append(statusentry(n, patchname))
if patcherr:
self.ui.warn(_("patch failed, rejects left in working dir\n"))
@@ -733,7 +719,7 @@
self.series_dirty = 1
def _revpatches(self, repo, revs):
- firstrev = repo[self.applied[0].rev].rev()
+ firstrev = repo[self.applied[0].node].rev()
patches = []
for i, rev in enumerate(revs):
@@ -741,7 +727,7 @@
raise util.Abort(_('revision %d is not managed') % rev)
ctx = repo[rev]
- base = bin(self.applied[i].rev)
+ base = self.applied[i].node
if ctx.node() != base:
msg = _('cannot delete revision %d above applied patches')
raise util.Abort(msg % rev)
@@ -789,8 +775,8 @@
self._cleanup(realpatches, numrevs, opts.get('keep'))
def check_toppatch(self, repo):
- if len(self.applied) > 0:
- top = bin(self.applied[-1].rev)
+ if self.applied:
+ top = self.applied[-1].node
patch = self.applied[-1].name
pp = repo.dirstate.parents()
if top not in pp:
@@ -870,7 +856,7 @@
raise util.Abort(_("repo commit failed"))
try:
self.full_series[insert:insert] = [patchfn]
- self.applied.append(statusentry(hex(n), patchfn))
+ self.applied.append(statusentry(n, patchfn))
self.parse_series()
self.series_dirty = 1
self.applied_dirty = 1
@@ -927,7 +913,7 @@
"""returns (index, rev, patch)"""
for i, a in enumerate(self.applied):
if a.name == patch:
- return (i, a.rev, a.name)
+ return (i, a.node, a.name)
return None
# if the exact patch name does not exist, we try a few
@@ -950,7 +936,7 @@
return None
if matches:
return matches[0]
- if len(self.series) > 0 and len(self.applied) > 0:
+ if self.series and self.applied:
if s == 'qtip':
return self.series[self.series_end(True)-1]
if s == 'qbase':
@@ -1068,7 +1054,7 @@
end = self.series.index(patch, start) + 1
s = self.series[start:end]
- all_files = {}
+ all_files = set()
try:
if mergeq:
ret = self.mergepatch(repo, mergeq, s, diffopts)
@@ -1078,12 +1064,15 @@
self.ui.warn(_('cleaning up working directory...'))
node = repo.dirstate.parents()[0]
hg.revert(repo, node, None)
- unknown = repo.status(unknown=True)[4]
# only remove unknown files that we know we touched or
# created while patching
- for f in unknown:
- if f in all_files:
- util.unlink(repo.wjoin(f))
+ for f in all_files:
+ if f not in repo.dirstate:
+ try:
+ util.unlink(repo.wjoin(f))
+ except OSError, inst:
+ if inst.errno != errno.ENOENT:
+ raise
self.ui.warn(_('done\n'))
raise
@@ -1101,10 +1090,6 @@
wlock.release()
def pop(self, repo, patch=None, force=False, update=True, all=False):
- def getfile(f, rev, flags):
- t = repo.file(f).read(rev)
- repo.wwrite(f, t, flags)
-
wlock = repo.wlock()
try:
if patch:
@@ -1116,7 +1101,7 @@
if not info:
raise util.Abort(_("patch %s is not applied") % patch)
- if len(self.applied) == 0:
+ if not self.applied:
# Allow qpop -a to work repeatedly,
# but not qpop without an argument
self.ui.warn(_("no patches applied\n"))
@@ -1135,16 +1120,16 @@
if not update:
parents = repo.dirstate.parents()
- rr = [bin(x.rev) for x in self.applied]
+ rr = [x.node for x in self.applied]
for p in parents:
if p in rr:
self.ui.warn(_("qpop: forcing dirstate update\n"))
update = True
else:
- parents = [p.hex() for p in repo[None].parents()]
+ parents = [p.node() for p in repo[None].parents()]
needupdate = False
for entry in self.applied[start:]:
- if entry.rev in parents:
+ if entry.node in parents:
needupdate = True
break
update = needupdate
@@ -1154,7 +1139,7 @@
self.applied_dirty = 1
end = len(self.applied)
- rev = bin(self.applied[start].rev)
+ rev = self.applied[start].node
if update:
top = self.check_toppatch(repo)[0]
@@ -1164,7 +1149,7 @@
node = short(rev)
raise util.Abort(_('trying to pop unknown node %s') % node)
- if heads != [bin(self.applied[-1].rev)]:
+ if heads != [self.applied[-1].node]:
raise util.Abort(_("popping would remove a revision not "
"managed by this patch queue"))
@@ -1172,8 +1157,7 @@
# form of hg.update.
if update:
qp = self.qparents(repo, rev)
- changes = repo.changelog.read(qp)
- mmap = repo.manifest.read(changes[0])
+ ctx = repo[qp]
m, a, r, d = repo.status(qp, top)[:4]
if d:
raise util.Abort(_("deletions found between repo revs"))
@@ -1186,18 +1170,16 @@
try: os.removedirs(os.path.dirname(repo.wjoin(f)))
except: pass
repo.dirstate.forget(f)
- for f in m:
- getfile(f, mmap[f], mmap.flags(f))
- for f in r:
- getfile(f, mmap[f], mmap.flags(f))
for f in m + r:
+ fctx = ctx[f]
+ repo.wwrite(f, fctx.data(), fctx.flags())
repo.dirstate.normal(f)
repo.dirstate.setparents(qp, nullid)
for patch in reversed(self.applied[start:end]):
self.ui.status(_("popping %s\n") % patch.name)
del self.applied[start:end]
self.strip(repo, rev, update=False, backup='strip')
- if len(self.applied):
+ if self.applied:
self.ui.write(_("now at: %s\n") % self.applied[-1].name)
else:
self.ui.write(_("patch queue now empty\n"))
@@ -1218,7 +1200,7 @@
self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
def refresh(self, repo, pats=None, **opts):
- if len(self.applied) == 0:
+ if not self.applied:
self.ui.write(_("no patches applied\n"))
return 1
msg = opts.get('msg', '').rstrip()
@@ -1230,8 +1212,7 @@
try:
self.check_toppatch(repo)
- (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
- top = bin(top)
+ (top, patchfn) = (self.applied[-1].node, self.applied[-1].name)
if repo.changelog.heads(top) != [top]:
raise util.Abort(_("cannot refresh a revision with children"))
@@ -1388,7 +1369,7 @@
patchf.rename()
n = repo.commit(message, user, ph.date, match=match,
force=True)
- self.applied.append(statusentry(hex(n), patchfn))
+ self.applied.append(statusentry(n, patchfn))
except:
ctx = repo[cparents[0]]
repo.dirstate.rebuild(ctx.node(), ctx.manifest())
@@ -1487,8 +1468,7 @@
return hg.repository(self.ui, path=self.path, create=create)
def restore(self, repo, rev, delete=None, qupdate=None):
- c = repo.changelog.read(rev)
- desc = c[4].strip()
+ desc = repo[rev].description().strip()
lines = desc.splitlines()
i = 0
datastart = None
@@ -1504,12 +1484,11 @@
qpp = [bin(x) for x in l]
elif datastart != None:
l = line.rstrip()
- se = statusentry(l)
- file_ = se.name
- if se.rev:
- applied.append(se)
+ n, name = l.split(':', 1)
+ if n:
+ applied.append(statusentry(bin(n), name))
else:
- series.append(file_)
+ series.append(l)
if datastart is None:
self.ui.warn(_("No saved patch data found\n"))
return 1
@@ -1543,14 +1522,13 @@
hg.clean(r, qpp[0])
def save(self, repo, msg=None):
- if len(self.applied) == 0:
+ if not self.applied:
self.ui.warn(_("save: no patches applied, exiting\n"))
return 1
if self.issaveline(self.applied[-1]):
self.ui.warn(_("status is already saved\n"))
return 1
- ar = [':' + x for x in self.full_series]
if not msg:
msg = _("hg patches saved state")
else:
@@ -1560,18 +1538,18 @@
pp = r.dirstate.parents()
msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1]))
msg += "\n\nPatch Data:\n"
- text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and
- "\n".join(ar) + '\n' or "")
- n = repo.commit(text, force=True)
+ msg += ''.join('%s\n' % x for x in self.applied)
+ msg += ''.join(':%s\n' % x for x in self.full_series)
+ n = repo.commit(msg, force=True)
if not n:
self.ui.warn(_("repo commit failed\n"))
return 1
- self.applied.append(statusentry(hex(n),'.hg.patches.save.line'))
+ self.applied.append(statusentry(n, '.hg.patches.save.line'))
self.applied_dirty = 1
self.removeundo(repo)
def full_series_end(self):
- if len(self.applied) > 0:
+ if self.applied:
p = self.applied[-1].name
end = self.find_series(p)
if end is None:
@@ -1586,17 +1564,15 @@
"""
end = 0
def next(start):
- if all_patches:
+ if all_patches or start >= len(self.series):
return start
- i = start
- while i < len(self.series):
+ for i in xrange(start, len(self.series)):
p, reason = self.pushable(i)
if p:
break
self.explain_pushable(i)
- i += 1
return i
- if len(self.applied) > 0:
+ if self.applied:
p = self.applied[-1].name
try:
end = self.series.index(p)
@@ -1633,7 +1609,6 @@
if (len(files) > 1 or len(rev) > 1) and patchname:
raise util.Abort(_('option "-n" not valid when importing multiple '
'patches'))
- i = 0
added = []
if rev:
# If mq patches are applied, we can only import revisions
@@ -1644,14 +1619,14 @@
raise util.Abort(_('revision %d is the root of more than one '
'branch') % rev[-1])
if self.applied:
- base = hex(repo.changelog.node(rev[0]))
- if base in [n.rev for n in self.applied]:
+ base = repo.changelog.node(rev[0])
+ if base in [n.node for n in self.applied]:
raise util.Abort(_('revision %d is already managed')
% rev[0])
- if heads != [bin(self.applied[-1].rev)]:
+ if heads != [self.applied[-1].node]:
raise util.Abort(_('revision %d is not the parent of '
'the queue') % rev[0])
- base = repo.changelog.rev(bin(self.applied[0].rev))
+ base = repo.changelog.rev(self.applied[0].node)
lastparent = repo.changelog.parentrevs(base)[0]
else:
if heads != [repo.changelog.node(rev[0])]:
@@ -1678,10 +1653,10 @@
self.full_series.insert(0, patchname)
patchf = self.opener(patchname, "w")
- patch.export(repo, [n], fp=patchf, opts=diffopts)
+ cmdutil.export(repo, [n], fp=patchf, opts=diffopts)
patchf.close()
- se = statusentry(hex(n), patchname)
+ se = statusentry(n, patchname)
self.applied.insert(0, se)
added.append(patchname)
@@ -1689,7 +1664,7 @@
self.parse_series()
self.applied_dirty = 1
- for filename in files:
+ for i, filename in enumerate(files):
if existing:
if filename == '-':
raise util.Abort(_('-e is incompatible with import from -'))
@@ -1722,7 +1697,6 @@
self.full_series[index:index] = [patchname]
self.parse_series()
self.ui.warn(_("adding %s to series file\n") % patchname)
- i += 1
added.append(patchname)
patchname = None
self.series_dirty = 1
@@ -1899,7 +1873,7 @@
qbase, destrev = None, None
if sr.local():
if sr.mq.applied:
- qbase = bin(sr.mq.applied[0].rev)
+ qbase = sr.mq.applied[0].node
if not hg.islocal(dest):
heads = set(sr.heads())
destrev = list(heads.difference(sr.heads(qbase)))
@@ -2541,8 +2515,8 @@
def abort_if_wdir_patched(self, errmsg, force=False):
if self.mq.applied and not force:
- parent = hex(self.dirstate.parents()[0])
- if parent in [s.rev for s in self.mq.applied]:
+ parent = self.dirstate.parents()[0]
+ if parent in [s.node for s in self.mq.applied]:
raise util.Abort(errmsg)
def commit(self, text="", user=None, date=None, match=None,
@@ -2567,7 +2541,7 @@
if not q.applied:
return result
- mqtags = [(bin(patch.rev), patch.name) for patch in q.applied]
+ mqtags = [(patch.node, patch.name) for patch in q.applied]
if mqtags[-1][0] not in self.changelog.nodemap:
self.ui.warn(_('mq status file refers to unknown node %s\n')
@@ -2593,7 +2567,7 @@
return super(mqrepo, self)._branchtags(partial, lrev)
cl = self.changelog
- qbasenode = bin(q.applied[0].rev)
+ qbasenode = q.applied[0].node
if qbasenode not in cl.nodemap:
self.ui.warn(_('mq status file refers to unknown node %s\n')
% short(qbasenode))
--- a/hgext/patchbomb.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/patchbomb.py Thu Mar 18 14:36:24 2010 -0700
@@ -249,7 +249,7 @@
def getpatches(revs):
for r in cmdutil.revrange(repo, revs):
output = cStringIO.StringIO()
- patch.export(repo, [r], fp=output,
+ cmdutil.export(repo, [r], fp=output,
opts=patch.diffopts(ui, opts))
yield output.getvalue().split('\n')
--- a/hgext/rebase.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/rebase.py Thu Mar 18 14:36:24 2010 -0700
@@ -14,7 +14,7 @@
http://mercurial.selenic.com/wiki/RebaseExtension
'''
-from mercurial import util, repair, merge, cmdutil, commands, error
+from mercurial import hg, util, repair, merge, cmdutil, commands, error
from mercurial import extensions, ancestor, copies, patch
from mercurial.commands import templateopts
from mercurial.node import nullrev
@@ -87,6 +87,9 @@
keepf = opts.get('keep', False)
keepbranchesf = opts.get('keepbranches', False)
detachf = opts.get('detach', False)
+ # keepopen is not meant for use on the command line, but by
+ # other extensions
+ keepopen = opts.get('keepopen', False)
if contf or abortf:
if contf and abortf:
@@ -181,7 +184,7 @@
ui.note(_('rebase merging completed\n'))
- if collapsef:
+ if collapsef and not keepopen:
p1, p2 = defineparents(repo, min(state), target,
state, targetancestors)
commitmsg = 'Collapsed revision'
@@ -345,10 +348,10 @@
'Update rebased mq patches - finalize and then import them'
mqrebase = {}
for p in repo.mq.applied:
- if repo[p.rev].rev() in state:
+ if repo[p.node].rev() in state:
repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
- (repo[p.rev].rev(), p.name))
- mqrebase[repo[p.rev].rev()] = (p.name, isagitpatch(repo, p.name))
+ (repo[p.node].rev(), p.name))
+ mqrebase[repo[p.node].rev()] = (p.name, isagitpatch(repo, p.name))
if mqrebase:
repo.mq.finish(repo, mqrebase.keys())
@@ -445,8 +448,8 @@
# This check isn't strictly necessary, since mq detects commits over an
# applied patch. But it prevents messing up the working directory when
# a partially completed rebase is blocked by mq.
- if 'qtip' in repo.tags() and (repo[dest].hex() in
- [s.rev for s in repo.mq.applied]):
+ if 'qtip' in repo.tags() and (repo[dest].node() in
+ [s.node for s in repo.mq.applied]):
raise util.Abort(_('cannot rebase onto an applied mq patch'))
if src:
@@ -502,7 +505,14 @@
cmdutil.bail_if_changed(repo)
revsprepull = len(repo)
- orig(ui, repo, *args, **opts)
+ origpostincoming = commands.postincoming
+ def _dummy(*args, **kwargs):
+ pass
+ commands.postincoming = _dummy
+ try:
+ orig(ui, repo, *args, **opts)
+ finally:
+ commands.postincoming = origpostincoming
revspostpull = len(repo)
if revspostpull > revsprepull:
rebase(ui, repo, **opts)
@@ -510,7 +520,7 @@
dest = repo[branch].rev()
if dest != repo['.'].rev():
# there was nothing to rebase we force an update
- merge.update(repo, dest, False, False, False)
+ hg.update(repo, dest)
else:
orig(ui, repo, *args, **opts)
--- a/hgext/record.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/record.py Thu Mar 18 14:36:24 2010 -0700
@@ -293,6 +293,7 @@
_('&Quit, recording no changes'),
_('&?'))
r = ui.promptchoice("%s %s" % (query, resps), choices)
+ ui.write("\n")
if r == 7: # ?
doc = gettext(record.__doc__)
c = doc.find(_('y - record this change'))
--- a/hgext/relink.py Thu Mar 18 19:26:56 2010 +0100
+++ b/hgext/relink.py Thu Mar 18 14:36:24 2010 -0700
@@ -116,6 +116,7 @@
CHUNKLEN = 65536
relinked = 0
savedbytes = 0
+ f = ''
pos = 0
total = len(files)
@@ -145,7 +146,7 @@
except OSError, inst:
ui.warn('%s: %s\n' % (tgt, str(inst)))
- ui.progress(_('relinking'), None, f, _(' files'), total)
+ ui.progress(_('relinking'), None)
ui.status(_('relinked %d files (%d bytes reclaimed)\n') %
(relinked, savedbytes))
--- a/mercurial/cmdutil.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/cmdutil.py Thu Mar 18 14:36:24 2010 -0700
@@ -289,11 +289,18 @@
'''find renamed files -- yields (before, after, score) tuples'''
copies = {}
ctx = repo['.']
- for r in removed:
+ for i, r in enumerate(removed):
+ repo.ui.progress(_('searching'), i, total=len(removed))
if r not in ctx:
continue
fctx = ctx.filectx(r)
+ # lazily load text
+ @util.cachefunc
+ def data():
+ orig = fctx.data()
+ return orig, mdiff.splitnewlines(orig)
+
def score(text):
if not len(text):
return 0.0
@@ -301,14 +308,13 @@
return 1.0
if threshold == 1.0:
return 0.0
- orig = fctx.data()
+ orig, lines = data()
# bdiff.blocks() returns blocks of matching lines
# count the number of bytes in each
equal = 0
- alines = mdiff.splitnewlines(text)
matches = bdiff.blocks(text, orig)
for x1, x2, y1, y2 in matches:
- for line in alines[x1:x2]:
+ for line in lines[y1:y2]:
equal += len(line)
lengths = len(text) + len(orig)
@@ -319,6 +325,7 @@
myscore = score(repo.wread(a))
if myscore >= bestscore:
copies[a] = (r, myscore)
+ repo.ui.progress(_('searching'), None)
for dest, v in copies.iteritems():
source, score = v
@@ -356,9 +363,7 @@
removed.append(abs)
elif repo.dirstate[abs] == 'a':
added.append(abs)
- if not dry_run:
- repo.remove(deleted)
- repo.add(unknown)
+ copies = {}
if similarity > 0:
for old, new, score in findrenames(repo, added + unknown,
removed + deleted, similarity):
@@ -366,8 +371,17 @@
repo.ui.status(_('recording removal of %s as rename to %s '
'(%d%% similar)\n') %
(m.rel(old), m.rel(new), score * 100))
- if not dry_run:
+ copies[new] = old
+
+ if not dry_run:
+ wlock = repo.wlock()
+ try:
+ repo.remove(deleted)
+ repo.add(unknown)
+ for new, old in copies.iteritems():
repo.copy(old, new)
+ finally:
+ wlock.release()
def copy(ui, repo, pats, opts, rename=False):
# called with the repo lock held
@@ -646,6 +660,46 @@
if runfn:
return runfn()
+def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
+ opts=None):
+ '''export changesets as hg patches.'''
+
+ total = len(revs)
+ revwidth = max([len(str(rev)) for rev in revs])
+
+ def single(rev, seqno, fp):
+ ctx = repo[rev]
+ node = ctx.node()
+ parents = [p.node() for p in ctx.parents() if p]
+ branch = ctx.branch()
+ if switch_parent:
+ parents.reverse()
+ prev = (parents and parents[0]) or nullid
+
+ if not fp:
+ fp = make_file(repo, template, node, total=total, seqno=seqno,
+ revwidth=revwidth, mode='ab')
+ if fp != sys.stdout and hasattr(fp, 'name'):
+ repo.ui.note("%s\n" % fp.name)
+
+ fp.write("# HG changeset patch\n")
+ fp.write("# User %s\n" % ctx.user())
+ fp.write("# Date %d %d\n" % ctx.date())
+ if branch and (branch != 'default'):
+ fp.write("# Branch %s\n" % branch)
+ fp.write("# Node ID %s\n" % hex(node))
+ fp.write("# Parent %s\n" % hex(prev))
+ if len(parents) > 1:
+ fp.write("# Parent %s\n" % hex(parents[1]))
+ fp.write(ctx.description().rstrip())
+ fp.write("\n\n")
+
+ for chunk in patch.diff(repo, prev, node, opts=opts):
+ fp.write(chunk)
+
+ for seqno, rev in enumerate(revs):
+ single(rev, seqno + 1, fp)
+
class changeset_printer(object):
'''show changeset information when templating not requested.'''
--- a/mercurial/commands.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/commands.py Thu Mar 18 14:36:24 2010 -0700
@@ -12,8 +12,8 @@
import hg, util, revlog, bundlerepo, extensions, copies, error
import patch, help, mdiff, url, encoding, templatekw
import archival, changegroup, cmdutil, sshserver, hbisect
-from hgweb import server
-import merge as merge_
+from hgweb import server, hgweb_mod, hgwebdir_mod
+import merge as mergemod
import minirst
# Commands start here, listed alphabetically
@@ -158,8 +158,10 @@
By default, the revision used is the parent of the working
directory; use -r/--rev to specify a different revision.
- To specify the type of archive to create, use -t/--type. Valid
- types are:
+ The archive type is automatically detected based on file
+ extension (or override using -t/--type).
+
+ Valid types are:
:``files``: a directory full of files (default)
:``tar``: tar archive, uncompressed
@@ -184,16 +186,32 @@
dest = cmdutil.make_filename(repo, dest, node)
if os.path.realpath(dest) == repo.root:
raise util.Abort(_('repository root cannot be destination'))
- matchfn = cmdutil.match(repo, [], opts)
- kind = opts.get('type') or 'files'
+
+ def guess_type():
+ exttypes = {
+ 'tar': ['.tar'],
+ 'tbz2': ['.tbz2', '.tar.bz2'],
+ 'tgz': ['.tgz', '.tar.gz'],
+ 'zip': ['.zip'],
+ }
+
+ for type, extensions in exttypes.items():
+ if util.any(dest.endswith(ext) for ext in extensions):
+ return type
+ return None
+
+ kind = opts.get('type') or guess_type() or 'files'
prefix = opts.get('prefix')
+
if dest == '-':
if kind == 'files':
raise util.Abort(_('cannot archive plain files to stdout'))
dest = sys.stdout
if not prefix:
prefix = os.path.basename(repo.root) + '-%h'
+
prefix = cmdutil.make_filename(repo, prefix, node)
+ matchfn = cmdutil.match(repo, [], opts)
archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
matchfn, prefix)
@@ -1208,7 +1226,7 @@
ui.note(_('exporting patches:\n'))
else:
ui.note(_('exporting patch:\n'))
- patch.export(repo, revs, template=opts.get('output'),
+ cmdutil.export(repo, revs, template=opts.get('output'),
switch_parent=opts.get('switch_parent'),
opts=patch.diffopts(ui, opts))
@@ -2578,7 +2596,7 @@
raise util.Abort(_('no files or directories specified; '
'use --all to remerge all files'))
- ms = merge_.mergestate(repo)
+ ms = mergemod.mergestate(repo)
m = cmdutil.match(repo, pats, opts)
for f in ms:
@@ -2868,6 +2886,10 @@
By default, the server logs accesses to stdout and errors to
stderr. Use the -A/--accesslog and -E/--errorlog options to log to
files.
+
+ To have the server choose a free port number to listen on, specify
+ a port number of 0; in this case, the server will print the port
+ number it uses.
"""
if opts["stdio"]:
@@ -2877,25 +2899,35 @@
s = sshserver.sshserver(ui, repo)
s.serve_forever()
+ # this way we can check if something was given in the command-line
+ if opts.get('port'):
+ opts['port'] = int(opts.get('port'))
+
baseui = repo and repo.baseui or ui
optlist = ("name templates style address port prefix ipv6"
- " accesslog errorlog webdir_conf certificate encoding")
+ " accesslog errorlog certificate encoding")
for o in optlist.split():
- if opts.get(o, None):
- baseui.setconfig("web", o, str(opts[o]))
- if (repo is not None) and (repo.ui != baseui):
- repo.ui.setconfig("web", o, str(opts[o]))
-
- if repo is None and not ui.config("web", "webdir_conf"):
- raise error.RepoError(_("There is no Mercurial repository here"
- " (.hg not found)"))
+ val = opts.get(o, '')
+ if val in (None, ''): # should check against default options instead
+ continue
+ baseui.setconfig("web", o, val)
+ if repo and repo.ui != baseui:
+ repo.ui.setconfig("web", o, val)
+
+ if opts.get('webdir_conf'):
+ app = hgwebdir_mod.hgwebdir(opts['webdir_conf'], ui)
+ elif repo is not None:
+ app = hgweb_mod.hgweb(hg.repository(repo.ui, repo.root))
+ else:
+ raise error.RepoError(_("There is no Mercurial repository"
+ " here (.hg not found)"))
class service(object):
def init(self):
util.set_signal_handler()
- self.httpd = server.create_server(baseui, repo)
-
- if not ui.verbose:
+ self.httpd = server.create_server(ui, app)
+
+ if opts['port'] and not ui.verbose:
return
if self.httpd.prefix:
@@ -2916,8 +2948,12 @@
fqaddr = self.httpd.fqaddr
if ':' in fqaddr:
fqaddr = '[%s]' % fqaddr
- ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
- (fqaddr, port, prefix, bindaddr, self.httpd.port))
+ if opts['port']:
+ write = ui.status
+ else:
+ write = ui.write
+ write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
+ (fqaddr, port, prefix, bindaddr, self.httpd.port))
def run(self):
self.httpd.serve_forever()
@@ -3047,7 +3083,7 @@
ui.status(m)
st = list(repo.status(unknown=True))[:6]
- ms = merge_.mergestate(repo)
+ ms = mergemod.mergestate(repo)
st.append([f for f in ms if ms[f] == 'u'])
labels = [_('%d modified'), _('%d added'), _('%d removed'),
_('%d deleted'), _('%d unknown'), _('%d ignored'),
@@ -3771,7 +3807,8 @@
('d', 'daemon', None, _('run server in background')),
('', 'daemon-pipefds', '', _('used internally by daemon mode')),
('E', 'errorlog', '', _('name of error log file to write to')),
- ('p', 'port', 0, _('port to listen on (default: 8000)')),
+ # use string type, then we can check if something was passed
+ ('p', 'port', '', _('port to listen on (default: 8000')),
('a', 'address', '',
_('address to listen on (default: all interfaces)')),
('', 'prefix', '',
--- a/mercurial/dispatch.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/dispatch.py Thu Mar 18 14:36:24 2010 -0700
@@ -9,7 +9,7 @@
import os, sys, atexit, signal, pdb, socket, errno, shlex, time
import util, commands, hg, fancyopts, extensions, hook, error
import cmdutil, encoding
-import ui as _ui
+import ui as uimod
def run():
"run the command in sys.argv"
@@ -18,7 +18,7 @@
def dispatch(args):
"run the command specified in args"
try:
- u = _ui.ui()
+ u = uimod.ui()
if '--traceback' in args:
u.setconfig('ui', 'traceback', 'on')
except util.Abort, inst:
--- a/mercurial/filelog.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/filelog.py Thu Mar 18 14:36:24 2010 -0700
@@ -33,9 +33,7 @@
def add(self, text, meta, transaction, link, p1=None, p2=None):
if meta or text.startswith('\1\n'):
- mt = ""
- if meta:
- mt = ["%s: %s\n" % (k, v) for k, v in sorted(meta.iteritems())]
+ mt = ["%s: %s\n" % (k, v) for k, v in sorted(meta.iteritems())]
text = "\1\n%s\1\n%s" % ("".join(mt), text)
return self.addrevision(text, transaction, link, p1, p2)
--- a/mercurial/graphmod.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/graphmod.py Thu Mar 18 14:36:24 2010 -0700
@@ -115,7 +115,7 @@
edges.append((ecol, next.index(eid), colors[eid]))
elif eid == cur:
for p in parents:
- edges.append((ecol, next.index(p), colors[p]))
+ edges.append((ecol, next.index(p), color))
# Yield and move on
yield (cur, type, data, (col, color), edges)
--- a/mercurial/help.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/help.py Thu Mar 18 14:36:24 2010 -0700
@@ -25,7 +25,7 @@
break
start = line[:3]
- if start == '\"\"\"' or start == "\'\'\'":
+ if start == '"""' or start == "'''":
line = line[3:]
while line:
if line.rstrip().endswith(start):
--- a/mercurial/hg.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/hg.py Thu Mar 18 14:36:24 2010 -0700
@@ -10,8 +10,8 @@
from lock import release
import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
import lock, util, extensions, error, encoding, node
-import merge as _merge
-import verify as _verify
+import merge as mergemod
+import verify as verifymod
import errno, os, shutil
def _local(path):
@@ -359,7 +359,7 @@
def update(repo, node):
"""update the working directory to node, merging linear changes"""
- stats = _merge.update(repo, node, False, False, None)
+ stats = mergemod.update(repo, node, False, False, None)
_showstats(repo, stats)
if stats[3]:
repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
@@ -370,14 +370,14 @@
def clean(repo, node, show_stats=True):
"""forcibly switch the working directory to node, clobbering changes"""
- stats = _merge.update(repo, node, False, True, None)
+ stats = mergemod.update(repo, node, False, True, None)
if show_stats:
_showstats(repo, stats)
return stats[3] > 0
def merge(repo, node, force=None, remind=True):
"""branch merge with node, resolving changes"""
- stats = _merge.update(repo, node, True, force, False)
+ stats = mergemod.update(repo, node, True, force, False)
_showstats(repo, stats)
if stats[3]:
repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
@@ -388,8 +388,8 @@
def revert(repo, node, choose):
"""revert changes to revision in node without updating dirstate"""
- return _merge.update(repo, node, False, True, choose)[3] > 0
+ return mergemod.update(repo, node, False, True, choose)[3] > 0
def verify(repo):
"""verify the consistency of a repository"""
- return _verify.verify(repo)
+ return verifymod.verify(repo)
--- a/mercurial/hgweb/hgwebdir_mod.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/hgweb/hgwebdir_mod.py Thu Mar 18 14:36:24 2010 -0700
@@ -195,11 +195,8 @@
yield {"type" : i[0], "extension": i[1],
"node": nodeid, "url": url}
- sortdefault = None, False
- def entries(sortcolumn="", descending=False, subdir="", **map):
+ def rawentries(subdir="", **map):
- rows = []
- parity = paritygen(self.stripecount)
descend = self.ui.configbool('web', 'descend', True)
for name, path in self.repos:
@@ -251,19 +248,19 @@
lastchange=d,
lastchange_sort=d[1]-d[0],
archives=archivelist(u, "tip", url))
- if (not sortcolumn or (sortcolumn, descending) == sortdefault):
- # fast path for unsorted output
- row['parity'] = parity.next()
- yield row
- else:
- rows.append((row["%s_sort" % sortcolumn], row))
- if rows:
- rows.sort()
- if descending:
- rows.reverse()
- for key, row in rows:
- row['parity'] = parity.next()
- yield row
+ yield row
+
+ sortdefault = None, False
+ def entries(sortcolumn="", descending=False, subdir="", **map):
+ rows = rawentries(subdir=subdir, **map)
+
+ if sortcolumn and sortdefault != (sortcolumn, descending):
+ sortkey = '%s_sort' % sortcolumn
+ rows = sorted(rows, key=lambda x: x[sortkey],
+ reverse=descending)
+ for row, parity in zip(rows, paritygen(self.stripecount)):
+ row['parity'] = parity
+ yield row
self.refresh()
sortable = ["name", "description", "contact", "lastchange"]
--- a/mercurial/hgweb/server.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/hgweb/server.py Thu Mar 18 14:36:24 2010 -0700
@@ -8,8 +8,6 @@
import os, sys, errno, urllib, BaseHTTPServer, socket, SocketServer, traceback
from mercurial import hg, util, error
-from hgweb_mod import hgweb
-from hgwebdir_mod import hgwebdir
from mercurial.i18n import _
def _splitURI(uri):
@@ -195,104 +193,85 @@
self.close_connection = True
pass
-def create_server(ui, repo):
- use_threads = True
-
- def openlog(opt, default):
- if opt and opt != '-':
- return open(opt, 'a')
- return default
-
- if repo is None:
- myui = ui
+try:
+ from threading import activeCount
+ _mixin = SocketServer.ThreadingMixIn
+except ImportError:
+ if hasattr(os, "fork"):
+ _mixin = SocketServer.ForkingMixIn
else:
- myui = repo.ui
- address = myui.config("web", "address", "")
- port = int(myui.config("web", "port", 8000))
- prefix = myui.config("web", "prefix", "")
- if prefix:
- prefix = "/" + prefix.strip("/")
- use_ipv6 = myui.configbool("web", "ipv6")
- webdir_conf = myui.config("web", "webdir_conf")
- ssl_cert = myui.config("web", "certificate")
- accesslog = openlog(myui.config("web", "accesslog", "-"), sys.stdout)
- errorlog = openlog(myui.config("web", "errorlog", "-"), sys.stderr)
+ class _mixin:
+ pass
+
+def openlog(opt, default):
+ if opt and opt != '-':
+ return open(opt, 'a')
+ return default
- if use_threads:
- try:
- from threading import activeCount
- except ImportError:
- use_threads = False
+class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
- if use_threads:
- _mixin = SocketServer.ThreadingMixIn
- else:
- if hasattr(os, "fork"):
- _mixin = SocketServer.ForkingMixIn
- else:
- class _mixin:
- pass
+ # SO_REUSEADDR has broken semantics on windows
+ if os.name == 'nt':
+ allow_reuse_address = 0
- class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
+ def __init__(self, ui, app, addr, handler, **kwargs):
+ BaseHTTPServer.HTTPServer.__init__(self, addr, handler, **kwargs)
+ self.daemon_threads = True
+ self.application = app
- # SO_REUSEADDR has broken semantics on windows
- if os.name == 'nt':
- allow_reuse_address = 0
+ ssl_cert = ui.config('web', 'certificate')
+ if ssl_cert:
+ try:
+ from OpenSSL import SSL
+ ctx = SSL.Context(SSL.SSLv23_METHOD)
+ except ImportError:
+ raise util.Abort(_("SSL support is unavailable"))
+ ctx.use_privatekey_file(ssl_cert)
+ ctx.use_certificate_file(ssl_cert)
+ sock = socket.socket(self.address_family, self.socket_type)
+ self.socket = SSL.Connection(ctx, sock)
+ self.server_bind()
+ self.server_activate()
- def __init__(self, *args, **kargs):
- BaseHTTPServer.HTTPServer.__init__(self, *args, **kargs)
- self.accesslog = accesslog
- self.errorlog = errorlog
- self.daemon_threads = True
- def make_handler():
- if webdir_conf:
- hgwebobj = hgwebdir(webdir_conf, ui)
- elif repo is not None:
- hgwebobj = hgweb(hg.repository(repo.ui, repo.root))
- else:
- raise error.RepoError(_("There is no Mercurial repository"
- " here (.hg not found)"))
- return hgwebobj
- self.application = make_handler()
+ prefix = ui.config('web', 'prefix', '')
+ if prefix:
+ prefix = '/' + prefix.strip('/')
+ self.prefix = prefix
- if ssl_cert:
- try:
- from OpenSSL import SSL
- ctx = SSL.Context(SSL.SSLv23_METHOD)
- except ImportError:
- raise util.Abort(_("SSL support is unavailable"))
- ctx.use_privatekey_file(ssl_cert)
- ctx.use_certificate_file(ssl_cert)
- sock = socket.socket(self.address_family, self.socket_type)
- self.socket = SSL.Connection(ctx, sock)
- self.server_bind()
- self.server_activate()
+ alog = openlog(ui.config('web', 'accesslog', '-'), sys.stdout)
+ elog = openlog(ui.config('web', 'errorlog', '-'), sys.stderr)
+ self.accesslog = alog
+ self.errorlog = elog
+
+ self.addr, self.port = self.socket.getsockname()[0:2]
+ self.fqaddr = socket.getfqdn(addr[0])
- self.addr, self.port = self.socket.getsockname()[0:2]
- self.prefix = prefix
- self.fqaddr = socket.getfqdn(address)
-
- class IPv6HTTPServer(MercurialHTTPServer):
- address_family = getattr(socket, 'AF_INET6', None)
+class IPv6HTTPServer(MercurialHTTPServer):
+ address_family = getattr(socket, 'AF_INET6', None)
+ def __init__(self, *args, **kwargs):
+ if self.address_family is None:
+ raise error.RepoError(_('IPv6 is not available on this system'))
+ super(IPv6HTTPServer, self).__init__(*args, **kwargs)
- def __init__(self, *args, **kwargs):
- if self.address_family is None:
- raise error.RepoError(_('IPv6 is not available on this system'))
- super(IPv6HTTPServer, self).__init__(*args, **kwargs)
+def create_server(ui, app):
- if ssl_cert:
+ if ui.config('web', 'certificate'):
handler = _shgwebhandler
else:
handler = _hgwebhandler
+ if ui.configbool('web', 'ipv6'):
+ cls = IPv6HTTPServer
+ else:
+ cls = MercurialHTTPServer
+
# ugly hack due to python issue5853 (for threaded use)
import mimetypes; mimetypes.init()
+ address = ui.config('web', 'address', '')
+ port = int(ui.config('web', 'port', 8000))
try:
- if use_ipv6:
- return IPv6HTTPServer((address, port), handler)
- else:
- return MercurialHTTPServer((address, port), handler)
+ return cls(ui, app, (address, port), handler)
except socket.error, inst:
raise util.Abort(_("cannot start server at '%s:%d': %s")
% (address, port, inst.args[1]))
--- a/mercurial/localrepo.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/localrepo.py Thu Mar 18 14:36:24 2010 -0700
@@ -11,9 +11,9 @@
import changelog, dirstate, filelog, manifest, context
import lock, transaction, store, encoding
import util, extensions, hook, error
-import match as match_
-import merge as merge_
-import tags as tags_
+import match as matchmod
+import merge as mergemod
+import tags as tagsmod
from lock import release
import weakref, stat, errno, os, time, inspect
propertycache = util.propertycache
@@ -207,7 +207,7 @@
if '.hgtags' not in self.dirstate:
self.add(['.hgtags'])
- m = match_.exact(self.root, '', ['.hgtags'])
+ m = matchmod.exact(self.root, '', ['.hgtags'])
tagnode = self.commit(message, user, date, extra=extra, match=m)
for name in names:
@@ -268,8 +268,8 @@
alltags = {} # map tag name to (node, hist)
tagtypes = {}
- tags_.findglobaltags(self.ui, self, alltags, tagtypes)
- tags_.readlocaltags(self.ui, self, alltags, tagtypes)
+ tagsmod.findglobaltags(self.ui, self, alltags, tagtypes)
+ tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
# Build the return dicts. Have to re-encode tag names because
# the tags module always uses UTF-8 (in order not to lose info
@@ -503,7 +503,7 @@
for pat, cmd in self.ui.configitems(filter):
if cmd == '!':
continue
- mf = match_.match(self.root, '', [pat])
+ mf = matchmod.match(self.root, '', [pat])
fn = None
params = cmd
for name, filterfn in self._datafilters.iteritems():
@@ -767,7 +767,7 @@
raise util.Abort('%s: %s' % (f, msg))
if not match:
- match = match_.always(self.root, '')
+ match = matchmod.always(self.root, '')
if not force:
vdirs = []
@@ -824,7 +824,7 @@
and self[None].branch() == self['.'].branch()):
return None
- ms = merge_.mergestate(self)
+ ms = mergemod.mergestate(self)
for f in changes[0]:
if f in ms and ms[f] == 'u':
raise util.Abort(_("unresolved merge conflicts "
@@ -996,7 +996,7 @@
working = ctx2.rev() is None
parentworking = working and ctx1 == self['.']
- match = match or match_.always(self.root, self.getcwd())
+ match = match or matchmod.always(self.root, self.getcwd())
listignored, listclean, listunknown = ignored, clean, unknown
# load earliest manifest first for caching reasons
@@ -1396,7 +1396,7 @@
self.ui.debug("found new changesets starting at " +
" ".join([short(f) for f in fetch]) + "\n")
- self.ui.progress(_('searching'), None, unit=_('queries'))
+ self.ui.progress(_('searching'), None)
self.ui.debug("%d total queries\n" % reqcnt)
return base.keys(), list(fetch), heads
@@ -1829,7 +1829,7 @@
yield chnk
self.ui.progress(_('bundling changes'), cnt, unit=_('chunks'))
cnt += 1
- self.ui.progress(_('bundling changes'), None, unit=_('chunks'))
+ self.ui.progress(_('bundling changes'), None)
# Figure out which manifest nodes (of the ones we think might be
@@ -1857,7 +1857,7 @@
yield chnk
self.ui.progress(_('bundling manifests'), cnt, unit=_('chunks'))
cnt += 1
- self.ui.progress(_('bundling manifests'), None, unit=_('chunks'))
+ self.ui.progress(_('bundling manifests'), None)
# These are no longer needed, dereference and toss the memory for
# them.
@@ -1906,7 +1906,7 @@
del msng_filenode_set[fname]
# Signal that no more groups are left.
yield changegroup.closechunk()
- self.ui.progress(_('bundling files'), None, unit=_('chunks'))
+ self.ui.progress(_('bundling files'), None)
if msng_cl_lst:
self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
@@ -1958,7 +1958,7 @@
self.ui.progress(_('bundling changes'), cnt, unit=_('chunks'))
cnt += 1
yield chnk
- self.ui.progress(_('bundling changes'), None, unit=_('chunks'))
+ self.ui.progress(_('bundling changes'), None)
mnfst = self.manifest
nodeiter = gennodelst(mnfst)
@@ -1967,7 +1967,7 @@
self.ui.progress(_('bundling manifests'), cnt, unit=_('chunks'))
cnt += 1
yield chnk
- self.ui.progress(_('bundling manifests'), None, unit=_('chunks'))
+ self.ui.progress(_('bundling manifests'), None)
cnt = 0
for fname in sorted(changedfiles):
@@ -1985,7 +1985,7 @@
_('bundling files'), cnt, item=fname, unit=_('chunks'))
cnt += 1
yield chnk
- self.ui.progress(_('bundling files'), None, unit=_('chunks'))
+ self.ui.progress(_('bundling files'), None)
yield changegroup.closechunk()
--- a/mercurial/mdiff.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/mdiff.py Thu Mar 18 14:36:24 2010 -0700
@@ -125,12 +125,12 @@
else:
al = splitnewlines(a)
bl = splitnewlines(b)
- l = list(bunidiff(a, b, al, bl, "a/" + fn1, "b/" + fn2, opts=opts))
+ l = list(_unidiff(a, b, al, bl, opts=opts))
if not l:
return ""
- # difflib uses a space, rather than a tab
- l[0] = "%s%s" % (l[0][:-2], datetag(ad))
- l[1] = "%s%s" % (l[1][:-2], datetag(bd))
+
+ l.insert(0, "--- a/%s%s" % (fn1, datetag(ad)))
+ l.insert(1, "+++ b/%s%s" % (fn2, datetag(bd)))
for ln in xrange(len(l)):
if l[ln][-1] != '\n':
@@ -141,11 +141,10 @@
return "".join(l)
-# somewhat self contained replacement for difflib.unified_diff
+# creates a headerless unified diff
# t1 and t2 are the text to be diffed
# l1 and l2 are the text broken up into lines
-# header1 and header2 are the filenames for the diff output
-def bunidiff(t1, t2, l1, l2, header1, header2, opts=defaultopts):
+def _unidiff(t1, t2, l1, l2, opts=defaultopts):
def contextend(l, len):
ret = l + opts.context
if ret > len:
@@ -158,10 +157,7 @@
return 0
return ret
- def yieldhunk(hunk, header):
- if header:
- for x in header:
- yield x
+ def yieldhunk(hunk):
(astart, a2, bstart, b2, delta) = hunk
aend = contextend(a2, len(l1))
alen = aend - astart
@@ -184,8 +180,6 @@
for x in xrange(a2, aend):
yield ' ' + l1[x]
- header = ["--- %s\t\n" % header1, "+++ %s\t\n" % header2]
-
if opts.showfunc:
funcre = re.compile('\w')
@@ -236,11 +230,8 @@
astart = hunk[1]
bstart = hunk[3]
else:
- for x in yieldhunk(hunk, header):
+ for x in yieldhunk(hunk):
yield x
- # we only want to yield the header if the files differ, and
- # we only want to yield it once.
- header = None
if prev:
# we've joined the previous hunk, record the new ending points.
hunk[1] = a2
@@ -255,7 +246,7 @@
delta[len(delta):] = ['+' + x for x in new]
if hunk:
- for x in yieldhunk(hunk, header):
+ for x in yieldhunk(hunk):
yield x
def patchtext(bin):
--- a/mercurial/patch.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/patch.py Thu Mar 18 14:36:24 2010 -0700
@@ -1176,20 +1176,6 @@
return -1
return err
-def diffopts(ui, opts=None, untrusted=False):
- def get(key, name=None, getter=ui.configbool):
- return ((opts and opts.get(key)) or
- getter('diff', name or key, None, untrusted=untrusted))
- return mdiff.diffopts(
- text=opts and opts.get('text'),
- git=get('git'),
- nodates=get('nodates'),
- showfunc=get('show_function', 'showfunc'),
- ignorews=get('ignore_all_space', 'ignorews'),
- ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
- ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
- context=get('unified', getter=ui.config))
-
def updatedir(ui, repo, patches, similarity=0):
'''Update dirstate after patch application according to metadata'''
if not patches:
@@ -1377,6 +1363,20 @@
class GitDiffRequired(Exception):
pass
+def diffopts(ui, opts=None, untrusted=False):
+ def get(key, name=None, getter=ui.configbool):
+ return ((opts and opts.get(key)) or
+ getter('diff', name or key, None, untrusted=untrusted))
+ return mdiff.diffopts(
+ text=opts and opts.get('text'),
+ git=get('git'),
+ nodates=get('nodates'),
+ showfunc=get('show_function', 'showfunc'),
+ ignorews=get('ignore_all_space', 'ignorews'),
+ ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
+ ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
+ context=get('unified', getter=ui.config))
+
def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None,
losedatafn=None):
'''yields diff of changes to files between two nodes, or node and
@@ -1552,47 +1552,6 @@
if text:
yield text
-def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
- opts=None):
- '''export changesets as hg patches.'''
-
- total = len(revs)
- revwidth = max([len(str(rev)) for rev in revs])
-
- def single(rev, seqno, fp):
- ctx = repo[rev]
- node = ctx.node()
- parents = [p.node() for p in ctx.parents() if p]
- branch = ctx.branch()
- if switch_parent:
- parents.reverse()
- prev = (parents and parents[0]) or nullid
-
- if not fp:
- fp = cmdutil.make_file(repo, template, node, total=total,
- seqno=seqno, revwidth=revwidth,
- mode='ab')
- if fp != sys.stdout and hasattr(fp, 'name'):
- repo.ui.note("%s\n" % fp.name)
-
- fp.write("# HG changeset patch\n")
- fp.write("# User %s\n" % ctx.user())
- fp.write("# Date %d %d\n" % ctx.date())
- if branch and (branch != 'default'):
- fp.write("# Branch %s\n" % branch)
- fp.write("# Node ID %s\n" % hex(node))
- fp.write("# Parent %s\n" % hex(prev))
- if len(parents) > 1:
- fp.write("# Parent %s\n" % hex(parents[1]))
- fp.write(ctx.description().rstrip())
- fp.write("\n\n")
-
- for chunk in diff(repo, prev, node, opts=opts):
- fp.write(chunk)
-
- for seqno, rev in enumerate(revs):
- single(rev, seqno + 1, fp)
-
def diffstatdata(lines):
filename, adds, removes = None, 0, 0
for line in lines:
--- a/mercurial/pure/osutil.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/pure/osutil.py Thu Mar 18 14:36:24 2010 -0700
@@ -6,25 +6,25 @@
# GNU General Public License version 2 or any later version.
import os
-import stat as _stat
+import stat as statmod
posixfile = open
def _mode_to_kind(mode):
- if _stat.S_ISREG(mode):
- return _stat.S_IFREG
- if _stat.S_ISDIR(mode):
- return _stat.S_IFDIR
- if _stat.S_ISLNK(mode):
- return _stat.S_IFLNK
- if _stat.S_ISBLK(mode):
- return _stat.S_IFBLK
- if _stat.S_ISCHR(mode):
- return _stat.S_IFCHR
- if _stat.S_ISFIFO(mode):
- return _stat.S_IFIFO
- if _stat.S_ISSOCK(mode):
- return _stat.S_IFSOCK
+ if statmod.S_ISREG(mode):
+ return statmod.S_IFREG
+ if statmod.S_ISDIR(mode):
+ return statmod.S_IFDIR
+ if statmod.S_ISLNK(mode):
+ return statmod.S_IFLNK
+ if statmod.S_ISBLK(mode):
+ return statmod.S_IFBLK
+ if statmod.S_ISCHR(mode):
+ return statmod.S_IFCHR
+ if statmod.S_ISFIFO(mode):
+ return statmod.S_IFIFO
+ if statmod.S_ISSOCK(mode):
+ return statmod.S_IFSOCK
return mode
def listdir(path, stat=False, skip=None):
@@ -49,7 +49,7 @@
names.sort()
for fn in names:
st = os.lstat(prefix + fn)
- if fn == skip and _stat.S_ISDIR(st.st_mode):
+ if fn == skip and statmod.S_ISDIR(st.st_mode):
return []
if stat:
result.append((fn, _mode_to_kind(st.st_mode), st))
--- a/mercurial/subrepo.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/subrepo.py Thu Mar 18 14:36:24 2010 -0700
@@ -228,8 +228,9 @@
self._repo.lookup(revision)
except error.RepoError:
self._repo._subsource = source
- self._repo.ui.status(_('pulling subrepo %s\n') % self._path)
srcurl = _abssource(self._repo)
+ self._repo.ui.status(_('pulling subrepo %s from %s\n')
+ % (self._path, srcurl))
other = hg.repository(self._repo.ui, srcurl)
self._repo.pull(other)
--- a/mercurial/templatefilters.py Thu Mar 18 19:26:56 2010 +0100
+++ b/mercurial/templatefilters.py Thu Mar 18 14:36:24 2010 -0700
@@ -14,15 +14,13 @@
return "".join([stringify(t) for t in thing if t is not None])
return str(thing)
-agescales = [("second", 1),
- ("minute", 60),
- ("hour", 3600),
- ("day", 3600 * 24),
+agescales = [("year", 3600 * 24 * 365),
+ ("month", 3600 * 24 * 30),
("week", 3600 * 24 * 7),
- ("month", 3600 * 24 * 30),
- ("year", 3600 * 24 * 365)]
-
-agescales.reverse()
+ ("day", 3600 * 24),
+ ("hour", 3600),
+ ("minute", 60),
+ ("second", 1),]
def age(date):
'''turn a (timestamp, tzoff) tuple into an age string.'''
--- a/tests/test-archive Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-archive Thu Mar 18 14:36:24 2010 -0700
@@ -74,6 +74,20 @@
hg archive -t tgz -p %b-%h test-%h.tar.gz
gzip -dc test-$QTIP.tar.gz | tar tf - 2>/dev/null | sed "s/$QTIP/TIP/"
+hg archive autodetected_test.tar
+tar tf autodetected_test.tar
+
+# The '-t' should override autodetection
+hg archive -t tar autodetect_override_test.zip
+tar tf autodetect_override_test.zip
+
+for ext in tar tar.gz tgz tar.bz2 tbz2 zip; do
+ hg archive auto_test.$ext
+ if [ -d auto_test.$ext ]; then
+ echo "extension $ext was not autodetected."
+ fi
+done
+
cat > md5comp.py <<EOF
try:
from hashlib import md5
--- a/tests/test-archive.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-archive.out Thu Mar 18 14:36:24 2010 -0700
@@ -45,6 +45,14 @@
test-TIP/bar
test-TIP/baz/bletch
test-TIP/foo
+autodetected_test/.hg_archival.txt
+autodetected_test/bar
+autodetected_test/baz/bletch
+autodetected_test/foo
+autodetect_override_test.zip/.hg_archival.txt
+autodetect_override_test.zip/bar
+autodetect_override_test.zip/baz/bletch
+autodetect_override_test.zip/foo
True
abort: archive prefix contains illegal components
Archive: test.zip
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-check-code Thu Mar 18 14:36:24 2010 -0700
@@ -0,0 +1,26 @@
+#!/bin/sh
+#cd `dirname $0`
+cat > correct.py <<EOF
+def toto(arg1, arg2):
+ del arg2
+ return (5 + 6, 9)
+EOF
+
+cat > wrong.py <<EOF
+def toto( arg1, arg2):
+ del(arg2)
+ return ( 5+6, 9)
+EOF
+
+cat > quote.py <<EOF
+# let's use quote in comments
+(''' ( 4x5 )
+but """\\''' and finally''',
+"""let's fool checkpatch""", '1+2',
+'"""', 42+1, """and
+( 4-1 ) """, "( 1+1 )\" and ")
+a, '\\\\\\\\', "\\\\\\" x-2", "c-1"
+EOF
+
+check_code=`dirname $0`/../contrib/check-code.py
+${check_code} ./wrong.py ./correct.py ./quote.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-check-code.out Thu Mar 18 14:36:24 2010 -0700
@@ -0,0 +1,13 @@
+./wrong.py:1:
+ > def toto( arg1, arg2):
+ gratuitous whitespace in () or []
+./wrong.py:2:
+ > del(arg2)
+ del isn't a function
+./wrong.py:3:
+ > return ( 5+6, 9)
+ missing whitespace in expression
+ gratuitous whitespace in () or []
+./quote.py:5:
+ > '"""', 42+1, """and
+ missing whitespace in expression
--- a/tests/test-diff-color.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-diff-color.out Thu Mar 18 14:36:24 2010 -0700
@@ -31,7 +31,8 @@
[0;36;1mold mode 100644[0m
[0;36;1mnew mode 100755[0m
1 hunks, 2 lines changed
-examine changes to 'a'? [Ynsfdaq?] [0;35m@@ -2,7 +2,7 @@[0m
+examine changes to 'a'? [Ynsfdaq?]
+[0;35m@@ -2,7 +2,7 @@[0m
c
a
a
@@ -41,13 +42,15 @@
a
c
record this change to 'a'? [Ynsfdaq?]
+
rolling back last transaction
% qrecord
[0;1mdiff --git a/a b/a[0m
[0;36;1mold mode 100644[0m
[0;36;1mnew mode 100755[0m
1 hunks, 2 lines changed
-examine changes to 'a'? [Ynsfdaq?] [0;35m@@ -2,7 +2,7 @@[0m
+examine changes to 'a'? [Ynsfdaq?]
+[0;35m@@ -2,7 +2,7 @@[0m
c
a
a
@@ -57,3 +60,4 @@
a
c
record this change to 'a'? [Ynsfdaq?]
+
--- a/tests/test-keyword.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-keyword.out Thu Mar 18 14:36:24 2010 -0700
@@ -1,6 +1,6 @@
% hg kwdemo
[extensions]
-keyword =
+keyword =
[keyword]
demo.txt =
[keywordmaps]
@@ -21,7 +21,7 @@
$Revision: xxxxxxxxxxxx $
$Source: /TMP/demo.txt,v $
[extensions]
-keyword =
+keyword =
[keyword]
demo.txt =
[keywordmaps]
@@ -206,7 +206,7 @@
% custom keyword expansion
% try with kwdemo
[extensions]
-keyword =
+keyword =
[keyword]
* =
b = ignore
--- a/tests/test-qrecord.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-qrecord.out Thu Mar 18 14:36:24 2010 -0700
@@ -80,28 +80,34 @@
% qrecord a.patch
diff --git a/1.txt b/1.txt
2 hunks, 4 lines changed
-examine changes to '1.txt'? [Ynsfdaq?] @@ -1,3 +1,3 @@
+examine changes to '1.txt'? [Ynsfdaq?]
+@@ -1,3 +1,3 @@
1
-2
+2 2
3
-record change 1/6 to '1.txt'? [Ynsfdaq?] @@ -3,3 +3,3 @@
+record change 1/6 to '1.txt'? [Ynsfdaq?]
+@@ -3,3 +3,3 @@
3
-4
+4 4
5
-record change 2/6 to '1.txt'? [Ynsfdaq?] diff --git a/2.txt b/2.txt
+record change 2/6 to '1.txt'? [Ynsfdaq?]
+diff --git a/2.txt b/2.txt
1 hunks, 2 lines changed
-examine changes to '2.txt'? [Ynsfdaq?] @@ -1,5 +1,5 @@
+examine changes to '2.txt'? [Ynsfdaq?]
+@@ -1,5 +1,5 @@
a
-b
+b b
c
d
e
-record change 4/6 to '2.txt'? [Ynsfdaq?] diff --git a/dir/a.txt b/dir/a.txt
+record change 4/6 to '2.txt'? [Ynsfdaq?]
+diff --git a/dir/a.txt b/dir/a.txt
1 hunks, 2 lines changed
examine changes to 'dir/a.txt'? [Ynsfdaq?]
+
% after qrecord a.patch 'tip'
changeset: 1:5d1ca63427ee
tag: qtip
@@ -157,22 +163,26 @@
% qrecord b.patch
diff --git a/1.txt b/1.txt
1 hunks, 2 lines changed
-examine changes to '1.txt'? [Ynsfdaq?] @@ -1,5 +1,5 @@
+examine changes to '1.txt'? [Ynsfdaq?]
+@@ -1,5 +1,5 @@
1
2 2
3
-4
+4 4
5
-record change 1/3 to '1.txt'? [Ynsfdaq?] diff --git a/dir/a.txt b/dir/a.txt
+record change 1/3 to '1.txt'? [Ynsfdaq?]
+diff --git a/dir/a.txt b/dir/a.txt
1 hunks, 2 lines changed
-examine changes to 'dir/a.txt'? [Ynsfdaq?] @@ -1,4 +1,4 @@
+examine changes to 'dir/a.txt'? [Ynsfdaq?]
+@@ -1,4 +1,4 @@
-hello world
+hello world!
someone
up
record change 3/3 to 'dir/a.txt'? [Ynsfdaq?]
+
% after qrecord b.patch 'tip'
changeset: 2:b056198bf878
tag: qtip
--- a/tests/test-rebase-pull.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-rebase-pull.out Thu Mar 18 14:36:24 2010 -0700
@@ -10,7 +10,6 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
-(run 'hg heads' to see heads, 'hg merge' to merge)
saving bundle to
adding branch
adding changesets
@@ -39,8 +38,8 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
-(run 'hg update' to get a working copy)
nothing to rebase
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@ 2
|
--- a/tests/test-record.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-record.out Thu Mar 18 14:36:24 2010 -0700
@@ -39,7 +39,8 @@
% select no files
diff --git a/empty-rw b/empty-rw
new file mode 100644
-examine changes to 'empty-rw'? [Ynsfdaq?] no changes to record
+examine changes to 'empty-rw'? [Ynsfdaq?]
+no changes to record
changeset: -1:000000000000
tag: tip
@@ -50,7 +51,8 @@
% select files but no hunks
diff --git a/empty-rw b/empty-rw
new file mode 100644
-examine changes to 'empty-rw'? [Ynsfdaq?] abort: empty commit message
+examine changes to 'empty-rw'? [Ynsfdaq?]
+abort: empty commit message
changeset: -1:000000000000
tag: tip
@@ -62,6 +64,7 @@
diff --git a/empty-rw b/empty-rw
new file mode 100644
examine changes to 'empty-rw'? [Ynsfdaq?]
+
changeset: 0:c0708cf4e46e
tag: tip
user: test
@@ -74,6 +77,7 @@
rename from empty-rw
rename to empty-rename
examine changes to 'empty-rw' and 'empty-rename'? [Ynsfdaq?]
+
changeset: 1:d695e8dcb197
tag: tip
user: test
@@ -86,6 +90,7 @@
copy from empty-rename
copy to empty-copy
examine changes to 'empty-rename' and 'empty-copy'? [Ynsfdaq?]
+
changeset: 2:1d4b90bea524
tag: tip
user: test
@@ -97,6 +102,7 @@
diff --git a/empty-copy b/empty-copy
deleted file mode 100644
examine changes to 'empty-copy'? [Ynsfdaq?]
+
changeset: 3:b39a238f01a1
tag: tip
user: test
@@ -110,6 +116,7 @@
new file mode 100644
this is a binary file
examine changes to 'tip.bundle'? [Ynsfdaq?]
+
changeset: 4:ad816da3711e
tag: tip
user: test
@@ -124,6 +131,7 @@
diff --git a/tip.bundle b/tip.bundle
this modifies a binary file (all or nothing)
examine changes to 'tip.bundle'? [Ynsfdaq?]
+
changeset: 5:dccd6f3eb485
tag: tip
user: test
@@ -140,6 +148,7 @@
rename to top.bundle
this modifies a binary file (all or nothing)
examine changes to 'tip.bundle' and 'top.bundle'? [Ynsfdaq?]
+
changeset: 6:7fa44105f5b3
tag: tip
user: test
@@ -155,6 +164,7 @@
diff --git a/plain b/plain
new file mode 100644
examine changes to 'plain'? [Ynsfdaq?]
+
changeset: 7:11fb457c1be4
tag: tip
user: test
@@ -179,46 +189,55 @@
% modify end of plain file
diff --git a/plain b/plain
1 hunks, 1 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -8,3 +8,4 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -8,3 +8,4 @@
8
9
10
+11
-record this change to 'plain'? [Ynsfdaq?] % modify end of plain file, no EOL
+record this change to 'plain'? [Ynsfdaq?]
+% modify end of plain file, no EOL
diff --git a/plain b/plain
1 hunks, 1 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -9,3 +9,4 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -9,3 +9,4 @@
9
10
11
+7264f99c5f5ff3261504828afa4fb4d406c3af54
\ No newline at end of file
-record this change to 'plain'? [Ynsfdaq?] % modify end of plain file, add EOL
+record this change to 'plain'? [Ynsfdaq?]
+% modify end of plain file, add EOL
diff --git a/plain b/plain
1 hunks, 2 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -9,4 +9,4 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -9,4 +9,4 @@
9
10
11
-7264f99c5f5ff3261504828afa4fb4d406c3af54
\ No newline at end of file
+7264f99c5f5ff3261504828afa4fb4d406c3af54
-record this change to 'plain'? [Ynsfdaq?] % modify beginning, trim end, record both
+record this change to 'plain'? [Ynsfdaq?]
+% modify beginning, trim end, record both
diff --git a/plain b/plain
2 hunks, 4 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,4 +1,4 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -1,4 +1,4 @@
-1
+2
2
3
4
-record change 1/2 to 'plain'? [Ynsfdaq?] @@ -8,5 +8,3 @@
+record change 1/2 to 'plain'? [Ynsfdaq?]
+@@ -8,5 +8,3 @@
8
9
10
-11
-7264f99c5f5ff3261504828afa4fb4d406c3af54
record change 2/2 to 'plain'? [Ynsfdaq?]
+
changeset: 11:efca65c9b09e
tag: tip
user: test
@@ -245,7 +264,8 @@
% record end
diff --git a/plain b/plain
2 hunks, 5 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,9 +1,6 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -1,9 +1,6 @@
-2
-2
-3
@@ -255,7 +275,8 @@
7
8
9
-record change 1/2 to 'plain'? [Ynsfdaq?] @@ -4,7 +1,7 @@
+record change 1/2 to 'plain'? [Ynsfdaq?]
+@@ -4,7 +1,7 @@
4
5
6
@@ -265,6 +286,7 @@
-10
+10.new
record change 2/2 to 'plain'? [Ynsfdaq?]
+
changeset: 12:7d1e66983c15
tag: tip
user: test
@@ -284,7 +306,8 @@
% record beginning
diff --git a/plain b/plain
1 hunks, 3 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,6 +1,3 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -1,6 +1,3 @@
-2
-2
-3
@@ -292,6 +315,7 @@
5
6
record this change to 'plain'? [Ynsfdaq?]
+
changeset: 13:a09fc62a0e61
tag: tip
user: test
@@ -313,7 +337,8 @@
% record end
diff --git a/plain b/plain
2 hunks, 4 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,6 +1,9 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -1,6 +1,9 @@
+1
+2
+3
@@ -323,7 +348,8 @@
7
8
9
-record change 1/2 to 'plain'? [Ynsfdaq?] @@ -1,7 +4,6 @@
+record change 1/2 to 'plain'? [Ynsfdaq?]
+@@ -1,7 +4,6 @@
4
5
6
@@ -331,17 +357,20 @@
8
9
-10.new
-record change 2/2 to 'plain'? [Ynsfdaq?] % add to beginning, middle, end
+record change 2/2 to 'plain'? [Ynsfdaq?]
+% add to beginning, middle, end
% record beginning, middle
diff --git a/plain b/plain
3 hunks, 7 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,2 +1,5 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -1,2 +1,5 @@
+1
+2
+3
4
5
-record change 1/3 to 'plain'? [Ynsfdaq?] @@ -1,6 +4,8 @@
+record change 1/3 to 'plain'? [Ynsfdaq?]
+@@ -1,6 +4,8 @@
4
5
+5.new
@@ -350,7 +379,8 @@
7
8
9
-record change 2/3 to 'plain'? [Ynsfdaq?] @@ -3,4 +8,6 @@
+record change 2/3 to 'plain'? [Ynsfdaq?]
+@@ -3,4 +8,6 @@
6
7
8
@@ -358,6 +388,7 @@
+10
+11
record change 3/3 to 'plain'? [Ynsfdaq?]
+
changeset: 15:7d137997f3a6
tag: tip
user: test
@@ -382,13 +413,15 @@
% record end
diff --git a/plain b/plain
1 hunks, 2 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -9,3 +9,5 @@
+examine changes to 'plain'? [Ynsfdaq?]
+@@ -9,3 +9,5 @@
7
8
9
+10
+11
record this change to 'plain'? [Ynsfdaq?]
+
changeset: 16:4959e3ff13eb
tag: tip
user: test
@@ -408,10 +441,12 @@
adding subdir/a
diff --git a/subdir/a b/subdir/a
1 hunks, 1 lines changed
-examine changes to 'subdir/a'? [Ynsfdaq?] @@ -1,1 +1,2 @@
+examine changes to 'subdir/a'? [Ynsfdaq?]
+@@ -1,1 +1,2 @@
a
+a
record this change to 'subdir/a'? [Ynsfdaq?]
+
changeset: 18:40698cd490b2
tag: tip
user: test
@@ -428,7 +463,8 @@
% help, quit
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] y - record this change
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+y - record this change
n - skip this change
s - skip remaining changes to this file
f - record remaining changes to this file
@@ -436,31 +472,38 @@
a - record all changes to all remaining files
q - quit, recording no changes
? - display help
-examine changes to 'subdir/f1'? [Ynsfdaq?] abort: user quit
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+abort: user quit
% skip
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+diff --git a/subdir/f2 b/subdir/f2
1 hunks, 1 lines changed
examine changes to 'subdir/f2'? [Ynsfdaq?] abort: response expected
% no
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+diff --git a/subdir/f2 b/subdir/f2
1 hunks, 1 lines changed
examine changes to 'subdir/f2'? [Ynsfdaq?] abort: response expected
% f, quit
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+diff --git a/subdir/f2 b/subdir/f2
1 hunks, 1 lines changed
-examine changes to 'subdir/f2'? [Ynsfdaq?] abort: user quit
+examine changes to 'subdir/f2'? [Ynsfdaq?]
+abort: user quit
% s, all
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+diff --git a/subdir/f2 b/subdir/f2
1 hunks, 1 lines changed
examine changes to 'subdir/f2'? [Ynsfdaq?]
+
changeset: 20:d2d8c25276a8
tag: tip
user: test
@@ -478,6 +521,7 @@
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
examine changes to 'subdir/f1'? [Ynsfdaq?]
+
changeset: 21:1013f51ce32f
tag: tip
user: test
@@ -496,11 +540,13 @@
old mode 100644
new mode 100755
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -1,2 +1,3 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+@@ -1,2 +1,3 @@
a
a
+a
record this change to 'subdir/f1'? [Ynsfdaq?]
+
changeset: 22:5df857735621
tag: tip
user: test
@@ -520,12 +566,14 @@
% preserve execute permission on original
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -1,3 +1,4 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+@@ -1,3 +1,4 @@
a
a
a
+b
record this change to 'subdir/f1'? [Ynsfdaq?]
+
changeset: 23:a4ae36a78715
tag: tip
user: test
@@ -546,12 +594,14 @@
old mode 100755
new mode 100644
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -2,3 +2,4 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+@@ -2,3 +2,4 @@
a
a
b
+c
record this change to 'subdir/f1'? [Ynsfdaq?]
+
changeset: 24:1460f6e47966
tag: tip
user: test
@@ -572,12 +622,14 @@
% with win32ext
diff --git a/subdir/f1 b/subdir/f1
1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -3,3 +3,4 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?]
+@@ -3,3 +3,4 @@
a
b
c
+d
record this change to 'subdir/f1'? [Ynsfdaq?]
+
changeset: 25:5bacc1f6e9cf
tag: tip
user: test
--- a/tests/test-serve Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-serve Thu Mar 18 14:36:24 2010 -0700
@@ -2,8 +2,10 @@
hgserve()
{
- hg serve -a localhost -p $HGPORT1 -d --pid-file=hg.pid -E errors.log -v $@ \
- | sed -e 's/:[0-9][0-9]*//g' -e 's/http:\/\/[^/]*\//http:\/\/localhost\//'
+ hg serve -a localhost -d --pid-file=hg.pid -E errors.log -v $@ \
+ | sed -e "s/:$HGPORT1\\([^0-9]\\)/:HGPORT1\1/g" \
+ -e "s/:$HGPORT2\\([^0-9]\\)/:HGPORT2\1/g" \
+ -e 's/http:\/\/[^/]*\//http:\/\/localhost\//'
cat hg.pid >> "$DAEMON_PIDS"
echo % errors
cat errors.log
@@ -17,6 +19,7 @@
echo '[web]' > .hg/hgrc
echo 'accesslog = access.log' >> .hg/hgrc
+echo "port = $HGPORT1" >> .hg/hgrc
echo % Without -v
hg serve -a localhost -p $HGPORT -d --pid-file=hg.pid -E errors.log
@@ -30,6 +33,9 @@
echo % With -v
hgserve
+echo % With -v and -p HGPORT2
+hgserve -p "$HGPORT2"
+
echo % With --prefix foo
hgserve --prefix foo
--- a/tests/test-serve.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-serve.out Thu Mar 18 14:36:24 2010 -0700
@@ -2,17 +2,20 @@
access log created - .hg/hgrc respected
% errors
% With -v
-listening at http://localhost/ (bound to 127.0.0.1)
+listening at http://localhost/ (bound to 127.0.0.1:HGPORT1)
+% errors
+% With -v and -p HGPORT2
+listening at http://localhost/ (bound to 127.0.0.1:HGPORT2)
% errors
% With --prefix foo
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
% errors
% With --prefix /foo
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
% errors
% With --prefix foo/
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
% errors
% With --prefix /foo/
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
% errors
--- a/tests/test-subrepo Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-subrepo Thu Mar 18 14:36:24 2010 -0700
@@ -78,7 +78,7 @@
echo % clone
cd ..
-hg clone t tc
+hg clone t tc | sed 's|from .*/sub|from .../sub|g'
cd tc
hg debugsub
@@ -102,7 +102,8 @@
echo % pull
cd ../tc
hg pull | sed 's/ .*sub/ ...sub/g'
-hg up # should pull t
+# should pull t
+hg up | sed 's|from .*/sub|from .../sub|g'
cat t/t
echo % bogus subrepo path aborts
--- a/tests/test-subrepo.out Thu Mar 18 19:26:56 2010 +0100
+++ b/tests/test-subrepo.out Thu Mar 18 14:36:24 2010 -0700
@@ -108,19 +108,19 @@
>>>>>>> other
% clone
updating to branch default
-pulling subrepo s
+pulling subrepo s from .../sub/t/s
requesting all changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 5 changes to 3 files
-pulling subrepo ss
+pulling subrepo ss from .../sub/t/s/ss
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
-pulling subrepo t
+pulling subrepo t from .../sub/t/t
requesting all changes
adding changesets
adding manifests
@@ -197,7 +197,7 @@
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
-pulling subrepo t
+pulling subrepo t from .../sub/t/t
searching for changes
adding changesets
adding manifests