# HG changeset patch # User Matt Mackall # Date 1269122244 18000 # Node ID 03225f14c4956cd86b07c45838548877382745bd # Parent 16b9aa398c28e06028526287cb63979aaacd9313# Parent fb06e357e6982d878b1cc083a0a22d080527eb41 Merge with stable diff -r fb06e357e698 -r 03225f14c495 contrib/check-code.py --- a/contrib/check-code.py Sat Mar 20 14:47:05 2010 +0100 +++ b/contrib/check-code.py Sat Mar 20 16:57:24 2010 -0500 @@ -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'''(?\#.*?$)| + ((?P('''|\"\"\"|(?(([^\\]|\\.)*?)) + (?P=quote))""", reppython), ] cpats = [ @@ -122,7 +128,7 @@ cfilters = [ (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), - (r'''(?(?([^"]|\\")+)"(?!")''', 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) diff -r fb06e357e698 -r 03225f14c495 contrib/hgdiff --- a/contrib/hgdiff Sat Mar 20 14:47:05 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) - diff -r fb06e357e698 -r 03225f14c495 contrib/shrink-revlog.py --- a/contrib/shrink-revlog.py Sat Mar 20 14:47:05 2010 +0100 +++ b/contrib/shrink-revlog.py Sat Mar 20 16:57:24 2010 -0500 @@ -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]')) } diff -r fb06e357e698 -r 03225f14c495 contrib/wix/mercurial.wxs --- a/contrib/wix/mercurial.wxs Sat Mar 20 14:47:05 2010 +0100 +++ b/contrib/wix/mercurial.wxs Sat Mar 20 16:57:24 2010 -0500 @@ -37,6 +37,9 @@ amus + + 1 + diff -r fb06e357e698 -r 03225f14c495 hgext/churn.py --- a/hgext/churn.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/churn.py Sat Mar 20 16:57:24 2010 -0500 @@ -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]")), } diff -r fb06e357e698 -r 03225f14c495 hgext/hgcia.py --- a/hgext/hgcia.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/hgcia.py Sat Mar 20 16:57:24 2010 -0500 @@ -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): diff -r fb06e357e698 -r 03225f14c495 hgext/inotify/__init__.py --- a/hgext/inotify/__init__.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/inotify/__init__.py Sat Mar 20 16:57:24 2010 -0500 @@ -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 = [] diff -r fb06e357e698 -r 03225f14c495 hgext/keyword.py --- a/hgext/keyword.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/keyword.py Sat Mar 20 16:57:24 2010 -0500 @@ -1,6 +1,6 @@ # keyword.py - $Keyword$ expansion for Mercurial # -# Copyright 2007-2009 Christian Ebert +# Copyright 2007-2010 Christian Ebert # # 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, diff -r fb06e357e698 -r 03225f14c495 hgext/mq.py --- a/hgext/mq.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/mq.py Sat Mar 20 16:57:24 2010 -0500 @@ -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)) diff -r fb06e357e698 -r 03225f14c495 hgext/patchbomb.py --- a/hgext/patchbomb.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/patchbomb.py Sat Mar 20 16:57:24 2010 -0500 @@ -105,6 +105,10 @@ raise util.Abort(_('diffstat rejected')) return s +def introneeded(opts, number): + '''is an introductory message required?''' + return number > 1 or opts.get('intro') or opts.get('desc') + def makepatch(ui, repo, patch, opts, _charsets, idx, total, patchname=None): desc = [] @@ -170,7 +174,7 @@ flag = ' ' + flag subj = desc[0].strip().rstrip('. ') - if total == 1 and not opts.get('intro'): + if not introneeded(opts, total): subj = '[PATCH%s] %s' % (flag, opts.get('subject') or subj) else: tlen = len(str(total)) @@ -249,7 +253,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') @@ -329,7 +333,7 @@ len(patches), name) msgs.append(msg) - if len(patches) > 1 or opts.get('intro'): + if introneeded(opts, len(patches)): tlen = len(str(len(patches))) flag = ' '.join(opts.get('flag')) diff -r fb06e357e698 -r 03225f14c495 hgext/rebase.py --- a/hgext/rebase.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/rebase.py Sat Mar 20 16:57:24 2010 -0500 @@ -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) diff -r fb06e357e698 -r 03225f14c495 hgext/record.py --- a/hgext/record.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/record.py Sat Mar 20 16:57:24 2010 -0500 @@ -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')) diff -r fb06e357e698 -r 03225f14c495 hgext/relink.py --- a/hgext/relink.py Sat Mar 20 14:47:05 2010 +0100 +++ b/hgext/relink.py Sat Mar 20 16:57:24 2010 -0500 @@ -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)) diff -r fb06e357e698 -r 03225f14c495 i18n/da.po --- a/i18n/da.po Sat Mar 20 14:47:05 2010 +0100 +++ b/i18n/da.po Sat Mar 20 16:57:24 2010 -0500 @@ -1,9 +1,9 @@ # Danish translations for Mercurial # Danske oversættelser for Mercurial # Copyright (C) 2009, 2010 Matt Mackall and others -# +# # Translation dictionary: -# +# # changeset ændring # commit deponere # merge sammenføje @@ -12,14 +12,14 @@ # revision revision # tag mærkat # working directory arbejdskatalog -# +# msgid "" msgstr "" "Project-Id-Version: Mercurial\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-02-28 17:12+0100\n" "PO-Revision-Date: 2010-02-28 18:06+0100\n" -"Last-Translator: \n" +"Last-Translator: \n" "Language-Team: Danish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -101,8 +101,7 @@ #, python-format msgid "config error - hook type \"%s\" cannot stop incoming changesets" -msgstr "" -"konfigurationsfejl - hook type \"%s\" kan ikke stoppe indgående ændringer" +msgstr "konfigurationsfejl - hook type \"%s\" kan ikke stoppe indgående ændringer" #, python-format msgid "acl: access denied for changeset %s" @@ -166,7 +165,7 @@ msgstr "et bogmærke kan ikke hedde det samme som en eksisterende gren" msgid "no bookmarks set\n" -msgstr "" +msgstr "ingen bogmærker\r\n" msgid "force" msgstr "gennemtving" @@ -258,8 +257,7 @@ " {hgweb} Base URL for browsing Mercurial repositories.\n" "\n" " Default 'changeset {node|short} in repo {root} refers '\n" -" 'to bug {bug}.\\ndetails:\\n\\t{desc|tabindent}'\n" -"\n" +" 'to bug {bug}.\\ndetails:\\n\\t{desc|tabindent}'\\n\n" "strip\n" " The number of slashes to strip from the front of {root} to produce\n" " {webroot}. Default 0.\n" @@ -301,9 +299,7 @@ " bzuser=unknown@domain.com\n" " bzdir=/opt/bugzilla-3.2\n" " template=Changeset {node|short} in {root|basename}.\n" -" {hgweb}/{webroot}/rev/{node|short}\\n\n" -" {desc}\\n\n" -" strip=5\n" +" {hgweb}/{webroot}/rev/{node|short}\\n\\n {desc}\\n\\n strip=5\n" "\n" " [web]\n" " baseurl=http://dev.domain.com/hg\n" @@ -533,8 +529,7 @@ msgid "" "colorize output from some commands\n" "\n" -"This extension modifies the status and resolve commands to add color to " -"their\n" +"This extension modifies the status and resolve commands to add color to their\n" "output to reflect file status, the qseries command to add color to reflect\n" "patch status (applied, unapplied, missing), and to diff-related\n" "commands to highlight additions, removals, diff headers, and trailing\n" @@ -621,9 +616,7 @@ " diff.changed = white\n" " diff.trailingwhitespace = bold red_background\n" "\n" -" resolve.unresolved = red bold\\n\"\n" -" resolve.resolved = green bold\\n\"\n" -"\n" +" resolve.unresolved = red bold\\n\"\\n resolve.resolved = green bold\\n\"\\n\n" " bookmarks.current = green\n" msgid "when to colorize (always, auto, or never)" @@ -940,9 +933,7 @@ msgid "hg debugcvsps [OPTION]... [PATH]..." msgstr "hg debugcvsps [TILVALG]... [STI]..." -msgid "" -"warning: lightweight checkouts may cause conversion failures, try with a " -"regular branch instead.\n" +msgid "warning: lightweight checkouts may cause conversion failures, try with a regular branch instead.\n" msgstr "" msgid "bzr source type could not be determined\n" @@ -1062,10 +1053,8 @@ msgstr "CVS pserver godkendelse fejlede" #, python-format -msgid "" -"unexpected response from CVS server (expected \"Valid-requests\", but got %r)" -msgstr "" -"uventet svar fra CVS serveren (forventede \"Valid-requests\", men fik %r)" +msgid "unexpected response from CVS server (expected \"Valid-requests\", but got %r)" +msgstr "uventet svar fra CVS serveren (forventede \"Valid-requests\", men fik %r)" #, python-format msgid "%d bytes missing from remote file" @@ -1172,8 +1161,7 @@ msgstr "analyserer træ version %s...\n" #, python-format -msgid "" -"tree analysis stopped because it points to an unregistered archive %s...\n" +msgid "tree analysis stopped because it points to an unregistered archive %s...\n" msgstr "" #, python-format @@ -1223,9 +1211,7 @@ msgid "Mercurial failed to run itself, check hg executable is in PATH" msgstr "Mercurial kunne ikke køre sig selv, kontroller om hg er i PATH" -msgid "" -"svn: cannot probe remote repository, assume it could be a subversion " -"repository. Use --source-type if you know better.\n" +msgid "svn: cannot probe remote repository, assume it could be a subversion repository. Use --source-type if you know better.\n" msgstr "" msgid "Subversion python bindings could not be loaded" @@ -1433,11 +1419,8 @@ " " msgstr "" -msgid "" -"working dir not at branch tip (use \"hg update\" to check out branch tip)" -msgstr "" -"arbejdskataloget er ikke ved gren-spidsen (brug \"hg update\" for at hente " -"gren-spidsen)" +msgid "working dir not at branch tip (use \"hg update\" to check out branch tip)" +msgstr "arbejdskataloget er ikke ved gren-spidsen (brug \"hg update\" for at hente gren-spidsen)" msgid "outstanding uncommitted merge" msgstr "udestående udeponeret sammenføjning" @@ -1448,30 +1431,19 @@ msgid "working directory is missing some files" msgstr "arbejdskataloget mangler nogle filer" -msgid "" -"multiple heads in this branch (use \"hg heads .\" and \"hg merge\" to merge)" -msgstr "" -"flere hoveder i denne gren (brug \"hg heads .\" og \"hg merge\" for at " -"sammenføje)" +msgid "multiple heads in this branch (use \"hg heads .\" and \"hg merge\" to merge)" +msgstr "flere hoveder i denne gren (brug \"hg heads .\" og \"hg merge\" for at sammenføje)" #, python-format msgid "pulling from %s\n" msgstr "hiver fra %s\n" -msgid "" -"Other repository doesn't support revision lookup, so a rev cannot be " -"specified." -msgstr "" -"Det andet depot understøtter ikke revisionsopslag, så en revision kan ikke " -"angives." - -#, python-format -msgid "" -"not merging with %d other new branch heads (use \"hg heads .\" and \"hg merge" -"\" to merge them)\n" -msgstr "" -"sammenføjer ikke med %d andre nye gren-hoveder (brug \"hg heads .\" og \"hg " -"merge\" for at sammenføje dem)\n" +msgid "Other repository doesn't support revision lookup, so a rev cannot be specified." +msgstr "Det andet depot understøtter ikke revisionsopslag, så en revision kan ikke angives." + +#, python-format +msgid "not merging with %d other new branch heads (use \"hg heads .\" and \"hg merge\" to merge them)\n" +msgstr "sammenføjer ikke med %d andre nye gren-hoveder (brug \"hg heads .\" og \"hg merge\" for at sammenføje dem)\n" #, python-format msgid "updating to %d:%s\n" @@ -1559,12 +1531,8 @@ msgid "Error while signing" msgstr "Fejl ved underskrivning" -msgid "" -"working copy of .hgsigs is changed (please commit .hgsigs manually or use --" -"force)" -msgstr "" -"arbejdskopien af .hgsigs er ændret (deponer venligst .hgsigs manuelt eller " -"brug --force)" +msgid "working copy of .hgsigs is changed (please commit .hgsigs manually or use --force)" +msgstr "arbejdskopien af .hgsigs er ændret (deponer venligst .hgsigs manuelt eller brug --force)" msgid "unknown signature version" msgstr "ukendt underskrift-version" @@ -1666,8 +1634,7 @@ " # Append a diffstat to the log message (optional)\n" " #diffstat = False\n" " # Template to use for log messages (optional)\n" -" #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat}\n" -" # Style to use (optional)\n" +" #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat}\\n # Style to use (optional)\n" " #style = foo\n" " # The URL of the CIA notification service (optional)\n" " # You can use mailto: URLs to send by email, eg\n" @@ -1902,14 +1869,10 @@ #, python-format msgid "*** the current per-user limit on the number of inotify watches is %s\n" -msgstr "" -"*** den nuværende grænse pr bruger for antallet af inotify overvågninger er %" -"s\n" +msgstr "*** den nuværende grænse pr bruger for antallet af inotify overvågninger er %s\n" msgid "*** this limit is too low to watch every directory in this repository\n" -msgstr "" -"*** denne grænse er for lille til at overvåge alle biblioteker i dette " -"depot\n" +msgstr "*** denne grænse er for lille til at overvåge alle biblioteker i dette depot\n" msgid "*** counting directories: " msgstr "*** tæller kataloger: " @@ -1987,9 +1950,7 @@ msgid "cannot start: socket is already bound" msgstr "" -msgid "" -"cannot start: tried linking .hg/inotify.sock to a temporary socket but .hg/" -"inotify.sock already exists" +msgid "cannot start: tried linking .hg/inotify.sock to a temporary socket but .hg/inotify.sock already exists" msgstr "" #, python-format @@ -2016,8 +1977,7 @@ "\n" " [interhg]\n" " issues = s!issue(\\d+)!issue\\1!\n" -" bugzilla = s!((?:bug|b=|(?=#?\\d{4,}))(?:\\s*#?)(\\d+))!\\1!" -"i\n" +" bugzilla = s!((?:bug|b=|(?=#?\\d{4,}))(?:\\s*#?)(\\d+))!\\1!i\n" " boldify = s!(^|\\s)#(\\d+)\\b! #\\2!\n" msgstr "" "ekspander udtryk i historikken og sammendrag\n" @@ -2031,8 +1991,7 @@ "\n" " [interhg]\n" " issues = s!issue(\\d+)!issue\\1!\n" -" bugzilla = s!((?:bug|b=|(?=#?\\d{4,}))(?:\\s*#?)(\\d+))!\\1!" -"i\n" +" bugzilla = s!((?:bug|b=|(?=#?\\d{4,}))(?:\\s*#?)(\\d+))!\\1!i\n" " boldify = s!(^|\\s)#(\\d+)\\b! #\\2!\n" #, python-format @@ -2190,8 +2149,7 @@ "\n" " Kør efter at at keyword-udvidelsen er blevet (gen)aktiveret.\n" "\n" -" kwexpand nægter at køre hvis de angivne filer indeholder lokale " -"ændringer.\n" +" kwexpand nægter at køre hvis de angivne filer indeholder lokale ændringer.\n" " " msgid "" @@ -2574,9 +2532,7 @@ msgid "cannot refresh a revision with children" msgstr "kan ikke genopfriske en revision som har børn" -msgid "" -"refresh interrupted while patch was popped! (revert --all, qpush to " -"recover)\n" +msgid "refresh interrupted while patch was popped! (revert --all, qpush to recover)\n" msgstr "" msgid "patch queue directory already exists" @@ -2673,8 +2629,7 @@ msgid "" "remove patches from queue\n" "\n" -" The patches must not be applied, and at least one patch is required. " -"With\n" +" The patches must not be applied, and at least one patch is required. With\n" " -k/--keep, the patch files are preserved in the patch directory.\n" "\n" " To stop managing a patch and move it into permanent history,\n" @@ -2941,9 +2896,7 @@ msgstr "Fejl ved foldning af rettelse %s" msgid "push or pop patches until named patch is at top of stack" -msgstr "" -"tilføj eller fjern rettelser indtil den navngivne rettelser er på toppen af " -"stakken" +msgstr "tilføj eller fjern rettelser indtil den navngivne rettelser er på toppen af stakken" msgid "" "set or print guards for a patch\n" @@ -3170,14 +3123,11 @@ #, python-format msgid "number of unguarded, unapplied patches has changed from %d to %d\n" -msgstr "" -"antallet af ufiltrerede og ikke-anvendte rettelser har ændret sig fra %d til " -"%d\n" +msgstr "antallet af ufiltrerede og ikke-anvendte rettelser har ændret sig fra %d til %d\n" #, python-format msgid "number of guarded, applied patches has changed from %d to %d\n" -msgstr "" -"antallet af filtrerede og anvendte rettelser har ændret sig fra %d til %d\n" +msgstr "antallet af filtrerede og anvendte rettelser har ændret sig fra %d til %d\n" msgid "guards in series file:\n" msgstr "filtre i seriefilen:\n" @@ -3515,8 +3465,7 @@ " maxdiff = 300 # max lines of diffs to include (0=none, -1=all)\n" " maxsubject = 67 # truncate subject line longer than this\n" " diffstat = True # add a diffstat before the diff content\n" -" sources = serve # notify if source of incoming changes in this " -"list\n" +" sources = serve # notify if source of incoming changes in this list\n" " # (serve == ssh or http, push, pull, bundle)\n" " merge = False # send notification for merges (default True)\n" " [email]\n" @@ -3774,10 +3723,8 @@ "\n" " hg email -b # send bundle of all patches not in default\n" " hg email -b DEST # send bundle of all patches not in DEST\n" -" hg email -b -r 3000 # bundle of all ancestors of 3000 not in " -"default\n" -" hg email -b -r 3000 DEST # bundle of all ancestors of 3000 not in " -"DEST\n" +" hg email -b -r 3000 # bundle of all ancestors of 3000 not in default\n" +" hg email -b -r 3000 DEST # bundle of all ancestors of 3000 not in DEST\n" "\n" " Before using this command, you will need to enable email in your\n" " hgrc. See the [email] section in hgrc(5) for details.\n" @@ -4111,9 +4058,7 @@ msgid "abort an interrupted rebase" msgstr "" -msgid "" -"hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--" -"keepbranches] | [-c] | [-a]" +msgid "hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--keepbranches] | [-c] | [-a]" msgstr "hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--keepbranches] | [-c] | [-a]" msgid "commands to interactively select changes for commit/qrefresh" @@ -4527,8 +4472,7 @@ msgid "filter changesets through FILTER" msgstr "filtrer ændringer igennem FILTER" -msgid "" -"hg transplant [-s REPOSITORY] [-b BRANCH [-a]] [-p REV] [-m REV] [REV]..." +msgid "hg transplant [-s REPOSITORY] [-b BRANCH [-a]] [-p REV] [-m REV] [REV]..." msgstr "hg transplant [-s DEPOT] [-b GREN [-a]] [-p REV] [-m REV] [REV]..." msgid "" @@ -4589,8 +4533,7 @@ " ** = cleverdecode:\n" " # or ** = macdecode:\n" "\n" -"If not doing conversion, to make sure you do not commit CRLF/CR by " -"accident::\n" +"If not doing conversion, to make sure you do not commit CRLF/CR by accident::\n" "\n" " [hooks]\n" " pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n" @@ -4774,9 +4717,7 @@ #, python-format msgid "%s has not been committed yet, so no copy data will be stored for %s.\n" -msgstr "" -"%s er endnu ikke comitted, så der vil ikke blive gemt kopieringsdata for %" -"s.\n" +msgstr "%s er endnu ikke comitted, så der vil ikke blive gemt kopieringsdata for %s.\n" msgid "no source or destination specified" msgstr "ingen kilde eller destination angivet" @@ -4785,8 +4726,7 @@ msgstr "ingen destination angivet" msgid "with multiple sources, destination must be an existing directory" -msgstr "" -"destinationen skal være en eksisterende mappe når der angivet flere kilder" +msgstr "destinationen skal være en eksisterende mappe når der angivet flere kilder" #, python-format msgid "destination %s is not a directory" @@ -4880,8 +4820,7 @@ msgstr "" msgid "HG: Enter commit message. Lines beginning with 'HG:' are removed." -msgstr "" -"HG: Skriv deponeringsbesked. Linier som starter med 'HG:' bliver fjernet." +msgstr "HG: Skriv deponeringsbesked. Linier som starter med 'HG:' bliver fjernet." msgid "HG: Leave message empty to abort commit." msgstr "HG: Efterlad beskeden tom for at afbryde deponeringen." @@ -5187,14 +5126,10 @@ msgstr "Den første dårlige revision er:\n" msgid "Due to skipped revisions, the first good revision could be any of:\n" -msgstr "" -"På grund af oversprungne revisioner kan den første gode revision være en " -"hvilken som helst af:\n" +msgstr "På grund af oversprungne revisioner kan den første gode revision være en hvilken som helst af:\n" msgid "Due to skipped revisions, the first bad revision could be any of:\n" -msgstr "" -"På grund af oversprungne revisioner kan den første dårlige revision være en " -"hvilken som helst af:\n" +msgstr "På grund af oversprungne revisioner kan den første dårlige revision være en hvilken som helst af:\n" msgid "cannot bisect (no known good revisions)" msgstr "" @@ -5267,8 +5202,7 @@ msgstr "nulstil arbejdskataloget til gren %s\n" msgid "a branch of the same name already exists (use --force to override)" -msgstr "" -"en gren ved samme navn eksisterer allerede (brug --force for at gennemtvinge)" +msgstr "en gren ved samme navn eksisterer allerede (brug --force for at gennemtvinge)" #, python-format msgid "marked working directory as branch %s\n" @@ -5688,14 +5622,10 @@ msgid " patch test failed!\n" msgstr "" -msgid "" -" (Current patch tool may be incompatible with patch, or misconfigured. " -"Please check your .hgrc file)\n" -msgstr "" - -msgid "" -" Internal patcher failure, please report this error to http://mercurial." -"selenic.com/bts/\n" +msgid " (Current patch tool may be incompatible with patch, or misconfigured. Please check your .hgrc file)\n" +msgstr "" + +msgid " Internal patcher failure, please report this error to http://mercurial.selenic.com/bts/\n" msgstr "" msgid "Checking commit editor...\n" @@ -5948,8 +5878,7 @@ " If STARTREV is specified, only those heads that are descendants of\n" " STARTREV will be displayed.\n" "\n" -" If -t/--topo is specified, named branch mechanics will be ignored and " -"only\n" +" If -t/--topo is specified, named branch mechanics will be ignored and only\n" " changesets without children will be shown.\n" " " msgstr "" @@ -5978,9 +5907,7 @@ msgstr "brug \"hg help\" for den fulde liste af kommandoer" msgid "use \"hg help\" for the full list of commands or \"hg -v\" for details" -msgstr "" -"brug \"hg help\" for den fulde liste af kommandoer eller \"hg -v\" for " -"detaljer" +msgstr "brug \"hg help\" for den fulde liste af kommandoer eller \"hg -v\" for detaljer" #, python-format msgid "use \"hg -v help%s\" to show aliases and global options" @@ -6012,7 +5939,9 @@ msgid "" "\n" "use \"hg -v help %s\" to show verbose help\n" -msgstr "\nbrug \"hg -v help %s\" for at se udførlig hjælp\n" +msgstr "" +"\n" +"brug \"hg -v help %s\" for at se udførlig hjælp\n" msgid "options:\n" msgstr "valgmuligheder:\n" @@ -6315,12 +6244,8 @@ msgid "%s - use \"hg update\" instead" msgstr "%s - brug \"hg update\" istedet" -msgid "" -"working dir not at a head rev - use \"hg update\" or merge with an explicit " -"rev" -msgstr "" -"arbejdskataloget er ikke ved en hovedrevision - brug \"hg update\" eller " -"sammenføj med en eksplicit revision" +msgid "working dir not at a head rev - use \"hg update\" or merge with an explicit rev" +msgstr "arbejdskataloget er ikke ved en hovedrevision - brug \"hg update\" eller sammenføj med en eksplicit revision" msgid "" "show changesets not found in the destination\n" @@ -6596,9 +6521,7 @@ msgstr "kan ikke angive --all og mønstre" msgid "no files or directories specified; use --all to remerge all files" -msgstr "" -"ingen filer eller mapper specificeret; brug --all for at gen-sammenføje alle " -"filerne" +msgstr "ingen filer eller mapper specificeret; brug --all for at gen-sammenføje alle filerne" msgid "" "restore individual files or directories to an earlier state\n" @@ -6639,9 +6562,7 @@ msgstr "du kan ikke specificeret en revision og en dato" msgid "no files or directories specified; use --all to revert the whole repo" -msgstr "" -"ingen filer eller mapper specificeret; brug --all for at føre hele repo'et " -"tilbage" +msgstr "ingen filer eller mapper specificeret; brug --all for at føre hele repo'et tilbage" #, python-format msgid "forgetting %s\n" @@ -7001,8 +6922,7 @@ " Use null as the changeset to remove the working directory (like 'hg\n" " clone -U').\n" "\n" -" If you want to update just one file to an older changeset, use 'hg " -"revert'.\n" +" If you want to update just one file to an older changeset, use 'hg revert'.\n" "\n" " See 'hg help dates' for a list of formats valid for -d/--date.\n" " " @@ -7484,9 +7404,7 @@ msgid "[-nibt] [-r REV] [SOURCE]" msgstr "[-nibt] [-r REV] [KILDE]" -msgid "" -"directory strip option for patch. This has the same meaning as the " -"corresponding patch option" +msgid "directory strip option for patch. This has the same meaning as the corresponding patch option" msgstr "" msgid "base path" @@ -7966,12 +7884,8 @@ msgid "Option --cwd may not be abbreviated!" msgstr "Tilvalget --cwd må ikke forkortes!" -msgid "" -"Option -R has to be separated from other options (e.g. not -qR) and --" -"repository may only be abbreviated as --repo!" -msgstr "" -"Tilvalget -R skal adskilles fra andre tilvalg (fx ikke -qR) og --repository " -"må kun forkortes som --repo!" +msgid "Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!" +msgstr "Tilvalget -R skal adskilles fra andre tilvalg (fx ikke -qR) og --repository må kun forkortes som --repo!" #, python-format msgid "Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n" @@ -7988,12 +7902,8 @@ msgid "unrecognized profiling format '%s' - Ignored\n" msgstr "profileringsformat '%s' ikke genkendt - Ignoreret\n" -msgid "" -"lsprof not available - install from http://codespeak.net/svn/user/arigo/hack/" -"misc/lsprof/" -msgstr "" -"lsprof er ikke tilgængelig - installer fra http://codespeak.net/svn/user/" -"arigo/hack/misc/lsprof/" +msgid "lsprof not available - install from http://codespeak.net/svn/user/arigo/hack/misc/lsprof/" +msgstr "lsprof er ikke tilgængelig - installer fra http://codespeak.net/svn/user/arigo/hack/misc/lsprof/" #, python-format msgid "*** failed to import extension %s from %s: %s\n" @@ -8563,8 +8473,7 @@ "A template is a piece of text, with markup to invoke variable\n" "expansion::\n" "\n" -" $ hg log -r1 --template \"{node}\\n\"\n" -" b56ce7b07c52de7d5fd79fb89701ea538af65746\n" +" $ hg log -r1 --template \"{node}\\n\"\\n b56ce7b07c52de7d5fd79fb89701ea538af65746\n" "\n" "Strings in curly braces are called keywords. The availability of\n" "keywords depends on the exact context of the templater. These\n" @@ -8617,8 +8526,7 @@ "variable. You can also use a chain of filters to get the desired\n" "output::\n" "\n" -" $ hg tip --template \"{date|isodate}\\n\"\n" -" 2008-08-21 18:22 +0000\n" +" $ hg tip --template \"{date|isodate}\\n\"\\n 2008-08-21 18:22 +0000\n" "\n" "List of filters:\n" "\n" @@ -8787,9 +8695,7 @@ msgid "destination '%s' is not empty" msgstr "målet '%s' er ikke tomt" -msgid "" -"src repository does not support revision lookup and so doesn't support clone " -"by revision" +msgid "src repository does not support revision lookup and so doesn't support clone by revision" msgstr "" msgid "clone from remote to remote not supported" @@ -8800,19 +8706,14 @@ msgstr "opdaterer til gren %s\n" #, python-format -msgid "" -"%d files updated, %d files merged, %d files removed, %d files unresolved\n" +msgid "%d files updated, %d files merged, %d files removed, %d files unresolved\n" msgstr "" msgid "use 'hg resolve' to retry unresolved file merges\n" msgstr "brug 'hg resolve' for at prøve at sammenføje uløste filer igen\n" -msgid "" -"use 'hg resolve' to retry unresolved file merges or 'hg update -C' to " -"abandon\n" -msgstr "" -"brug 'hg resolve' for at prøve at sammenføje uløste filer igen eller 'hg up -" -"C' for at opgive\n" +msgid "use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon\n" +msgstr "brug 'hg resolve' for at prøve at sammenføje uløste filer igen eller 'hg up -C' for at opgive\n" msgid "(branch merge, don't forget to commit)\n" msgstr "(grensammenføjning, glem ikke at deponere)\n" @@ -9003,8 +8904,7 @@ #, python-format msgid "Named branch could not be reset, current branch still is: %s\n" -msgstr "" -"Navngiven gren kunne ikke nulstilles, den nuværende gren er stadig: %s\n" +msgstr "Navngiven gren kunne ikke nulstilles, den nuværende gren er stadig: %s\n" msgid "no rollback information available\n" msgstr "ingen tilbagerulningsinformation til stede\n" @@ -9022,9 +8922,7 @@ msgstr "arbejdskatalog for %s" msgid "cannot partially commit a merge (do not specify files or patterns)" -msgstr "" -"kan ikke deponere en sammenføjning partielt (undgå at specificere filer " -"eller mønstre)" +msgstr "kan ikke deponere en sammenføjning partielt (undgå at specificere filer eller mønstre)" msgid "file not found!" msgstr "filen blev ikke fundet!" @@ -9064,8 +8962,7 @@ #, python-format msgid "%s not added: only files and symlinks supported currently\n" -msgstr "" -"%s ikke tilføjet: i øjeblikket understøttes kun filer og symbolske lænker\n" +msgstr "%s ikke tilføjet: i øjeblikket understøttes kun filer og symbolske lænker\n" #, python-format msgid "%s already tracked!\n" @@ -9112,9 +9009,7 @@ msgid "requesting all changes\n" msgstr "anmoder om alle ændringer\n" -msgid "" -"Partial pull cannot be done because other repository doesn't support " -"changegroupsubset." +msgid "Partial pull cannot be done because other repository doesn't support changegroupsubset." msgstr "" #, python-format @@ -9268,9 +9163,7 @@ msgstr "" #, python-format -msgid "" -"untracked file in working directory differs from file in requested revision: " -"'%s'" +msgid "untracked file in working directory differs from file in requested revision: '%s'" msgstr "" #, python-format @@ -9343,15 +9236,10 @@ msgstr "intet at sammenføje (brug 'hg update' eller kontroller 'hg heads')" msgid "outstanding uncommitted changes (use 'hg status' to list changes)" -msgstr "" -"udestående ikke-deponerede ændringer (brug 'hg status' for at se ændringer)" - -msgid "" -"crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard " -"changes)" -msgstr "" -"krydser grene (brug 'hg merge' for at sammenføje eller 'hg update -C' for at " -"kassere ændringerne)" +msgstr "udestående ikke-deponerede ændringer (brug 'hg status' for at se ændringer)" + +msgid "crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard changes)" +msgstr "krydser grene (brug 'hg merge' for at sammenføje eller 'hg update -C' for at kassere ændringerne)" msgid "crosses branches (use 'hg merge' or use 'hg update -c')" msgstr "krydser grene (brug 'hg merge' eller 'hg update -c')" diff -r fb06e357e698 -r 03225f14c495 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/cmdutil.py Sat Mar 20 16:57:24 2010 -0500 @@ -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.''' diff -r fb06e357e698 -r 03225f14c495 mercurial/commands.py --- a/mercurial/commands.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/commands.py Sat Mar 20 16:57:24 2010 -0500 @@ -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', '', diff -r fb06e357e698 -r 03225f14c495 mercurial/dispatch.py --- a/mercurial/dispatch.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/dispatch.py Sat Mar 20 16:57:24 2010 -0500 @@ -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: diff -r fb06e357e698 -r 03225f14c495 mercurial/filelog.py --- a/mercurial/filelog.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/filelog.py Sat Mar 20 16:57:24 2010 -0500 @@ -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) diff -r fb06e357e698 -r 03225f14c495 mercurial/graphmod.py --- a/mercurial/graphmod.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/graphmod.py Sat Mar 20 16:57:24 2010 -0500 @@ -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) diff -r fb06e357e698 -r 03225f14c495 mercurial/help.py --- a/mercurial/help.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/help.py Sat Mar 20 16:57:24 2010 -0500 @@ -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): diff -r fb06e357e698 -r 03225f14c495 mercurial/hg.py --- a/mercurial/hg.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/hg.py Sat Mar 20 16:57:24 2010 -0500 @@ -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) diff -r fb06e357e698 -r 03225f14c495 mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/hgweb/hgwebdir_mod.py Sat Mar 20 16:57:24 2010 -0500 @@ -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"] diff -r fb06e357e698 -r 03225f14c495 mercurial/hgweb/server.py --- a/mercurial/hgweb/server.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/hgweb/server.py Sat Mar 20 16:57:24 2010 -0500 @@ -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])) diff -r fb06e357e698 -r 03225f14c495 mercurial/localrepo.py --- a/mercurial/localrepo.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/localrepo.py Sat Mar 20 16:57:24 2010 -0500 @@ -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() diff -r fb06e357e698 -r 03225f14c495 mercurial/mdiff.py --- a/mercurial/mdiff.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/mdiff.py Sat Mar 20 16:57:24 2010 -0500 @@ -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): diff -r fb06e357e698 -r 03225f14c495 mercurial/patch.py --- a/mercurial/patch.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/patch.py Sat Mar 20 16:57:24 2010 -0500 @@ -1189,20 +1189,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: @@ -1390,6 +1376,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 @@ -1565,47 +1565,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: diff -r fb06e357e698 -r 03225f14c495 mercurial/pure/osutil.py --- a/mercurial/pure/osutil.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/pure/osutil.py Sat Mar 20 16:57:24 2010 -0500 @@ -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)) diff -r fb06e357e698 -r 03225f14c495 mercurial/subrepo.py --- a/mercurial/subrepo.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/subrepo.py Sat Mar 20 16:57:24 2010 -0500 @@ -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) diff -r fb06e357e698 -r 03225f14c495 mercurial/templatefilters.py --- a/mercurial/templatefilters.py Sat Mar 20 14:47:05 2010 +0100 +++ b/mercurial/templatefilters.py Sat Mar 20 16:57:24 2010 -0500 @@ -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.''' diff -r fb06e357e698 -r 03225f14c495 tests/test-archive --- a/tests/test-archive Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-archive Sat Mar 20 16:57:24 2010 -0500 @@ -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 < correct.py < wrong.py < quote.py < 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 diff -r fb06e357e698 -r 03225f14c495 tests/test-diff-color.out --- a/tests/test-diff-color.out Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-diff-color.out Sat Mar 20 16:57:24 2010 -0500 @@ -31,7 +31,8 @@ old mode 100644 new mode 100755 1 hunks, 2 lines changed -examine changes to 'a'? [Ynsfdaq?] @@ -2,7 +2,7 @@ +examine changes to 'a'? [Ynsfdaq?] +@@ -2,7 +2,7 @@ c a a @@ -41,13 +42,15 @@ a c record this change to 'a'? [Ynsfdaq?] + rolling back last transaction % qrecord diff --git a/a b/a old mode 100644 new mode 100755 1 hunks, 2 lines changed -examine changes to 'a'? [Ynsfdaq?] @@ -2,7 +2,7 @@ +examine changes to 'a'? [Ynsfdaq?] +@@ -2,7 +2,7 @@ c a a @@ -57,3 +60,4 @@ a c record this change to 'a'? [Ynsfdaq?] + diff -r fb06e357e698 -r 03225f14c495 tests/test-keyword.out --- a/tests/test-keyword.out Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-keyword.out Sat Mar 20 16:57:24 2010 -0500 @@ -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 diff -r fb06e357e698 -r 03225f14c495 tests/test-patchbomb --- a/tests/test-patchbomb Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-patchbomb Sat Mar 20 16:57:24 2010 -0500 @@ -126,6 +126,11 @@ hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test \ -r 2 | fixheaders +echo "% test --desc without --intro for a single patch" +echo foo > intro.text +hg email --date '1970-1-1 0:1' -n --desc intro.text -f quux -t foo -c bar \ + -s test -r 2 | fixheaders + echo "% test intro for multiple patches" hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test \ -r 0:1 | fixheaders diff -r fb06e357e698 -r 03225f14c495 tests/test-patchbomb.out --- a/tests/test-patchbomb.out Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-patchbomb.out Sat Mar 20 16:57:24 2010 -0500 @@ -940,6 +940,52 @@ @@ -0,0 +1,1 @@ +c +% test --desc without --intro for a single patch +This patch series consists of 1 patches. + + +Displaying [PATCH 0 of 1] test ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 0 of 1] test +Message-Id: > "$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 diff -r fb06e357e698 -r 03225f14c495 tests/test-serve.out --- a/tests/test-serve.out Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-serve.out Sat Mar 20 16:57:24 2010 -0500 @@ -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 diff -r fb06e357e698 -r 03225f14c495 tests/test-subrepo --- a/tests/test-subrepo Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-subrepo Sat Mar 20 16:57:24 2010 -0500 @@ -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 diff -r fb06e357e698 -r 03225f14c495 tests/test-subrepo.out --- a/tests/test-subrepo.out Sat Mar 20 14:47:05 2010 +0100 +++ b/tests/test-subrepo.out Sat Mar 20 16:57:24 2010 -0500 @@ -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