Mercurial > hg
changeset 10617:da7662ea741f
merge with stable
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Tue, 09 Mar 2010 20:47:35 +0100 |
parents | 3bb438ce4458 (diff) 65b178f30eae (current diff) |
children | bcdf37680569 |
files | mercurial/commands.py |
diffstat | 14 files changed, 125 insertions(+), 236 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/hgdiff Tue Mar 09 20:38:23 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -#!/usr/bin/env python - -import os, sys, struct, stat -import difflib -import re -from optparse import OptionParser -from mercurial.bdiff import bdiff, blocks -from mercurial.mdiff import bunidiff, diffopts - -VERSION="0.3" -usage = "usage: %prog [options] file1 file2" -parser = OptionParser(usage=usage) - -parser.add_option("-d", "--difflib", action="store_true", default=False) -parser.add_option('-x', '--count', default=1) -parser.add_option('-c', '--context', type="int", default=3) -parser.add_option('-p', '--show-c-function', action="store_true", default=False) -parser.add_option('-w', '--ignore-all-space', action="store_true", - default=False) - -(options, args) = parser.parse_args() - -if not args: - parser.print_help() - sys.exit(1) - -# simple utility function to put all the -# files from a directory tree into a dict -def buildlist(names, top): - tlen = len(top) - for root, dirs, files in os.walk(top): - l = root[tlen + 1:] - for x in files: - p = os.path.join(root, x) - st = os.lstat(p) - if stat.S_ISREG(st.st_mode): - names[os.path.join(l, x)] = (st.st_dev, st.st_ino) - -def diff_files(file1, file2): - if file1 is None: - b = file(file2).read().splitlines(True) - l1 = "--- %s\n" % (file2) - l2 = "+++ %s\n" % (file2) - l3 = "@@ -0,0 +1,%d @@\n" % len(b) - l = [l1, l2, l3] + ["+" + e for e in b] - elif file2 is None: - a = file(file1).read().splitlines(True) - l1 = "--- %s\n" % (file1) - l2 = "+++ %s\n" % (file1) - l3 = "@@ -1,%d +0,0 @@\n" % len(a) - l = [l1, l2, l3] + ["-" + e for e in a] - else: - t1 = file(file1).read() - t2 = file(file2).read() - l1 = t1.splitlines(True) - l2 = t2.splitlines(True) - if options.difflib: - l = difflib.unified_diff(l1, l2, file1, file2) - else: - l = bunidiff(t1, t2, l1, l2, file1, file2, - diffopts(context=options.context, - showfunc=options.show_c_function, - ignorews=options.ignore_all_space)) - for x in l: - if x[-1] != '\n': - x += "\n\ No newline at end of file\n" - print x, - -file1 = args[0] -file2 = args[1] - -if os.path.isfile(file1) and os.path.isfile(file2): - diff_files(file1, file2) -elif os.path.isdir(file1): - if not os.path.isdir(file2): - sys.stderr.write("file types don't match\n") - sys.exit(1) - - d1 = {} - d2 = {} - - buildlist(d1, file1) - buildlist(d2, file2) - keys = d1.keys() - keys.sort() - for x in keys: - if x not in d2: - f2 = None - else: - f2 = os.path.join(file2, x) - st1 = d1[x] - st2 = d2[x] - del d2[x] - if st1[0] == st2[0] and st1[1] == st2[1]: - sys.stderr.write("%s is a hard link\n" % x) - continue - x = os.path.join(file1, x) - diff_files(x, f2) - keys = d2.keys() - keys.sort() - for x in keys: - f1 = None - x = os.path.join(file2, x) - diff_files(f1, x) -
--- a/contrib/wix/mercurial.wxs Tue Mar 09 20:38:23 2010 +0100 +++ b/contrib/wix/mercurial.wxs Tue Mar 09 20:47:35 2010 +0100 @@ -37,6 +37,9 @@ <Property Id='INSTALLEDMERCURIALPRODUCTS' Secure='yes'></Property> <Property Id='REINSTALLMODE'>amus</Property> + <!--Auto-accept the license page--> + <Property Id='LicenseAccepted'>1</Property> + <Directory Id='TARGETDIR' Name='SourceDir'> <Directory Id='ProgramFilesFolder' Name='PFiles'> <Directory Id='INSTALLDIR' Name='Mercurial'>
--- a/hgext/hgcia.py Tue Mar 09 20:38:23 2010 +0100 +++ b/hgext/hgcia.py Tue Mar 09 20:47:35 2010 +0100 @@ -113,7 +113,7 @@ n = self.ctx.node() pbuf = patchbuf() - patch.export(self.cia.repo, [n], fp=pbuf) + cmdutil.export(self.cia.repo, [n], fp=pbuf) return patch.diffstat(pbuf.lines) or '' def logmsg(self):
--- a/hgext/inotify/__init__.py Tue Mar 09 20:38:23 2010 +0100 +++ b/hgext/inotify/__init__.py Tue Mar 09 20:47:35 2010 +0100 @@ -41,7 +41,7 @@ # to start an inotify server if it won't start. _inotifyon = True - def status(self, match, subrepos, ignored, clean, unknown=True): + def status(self, match, subrepos, ignored, clean, unknown): files = match.files() if '.' in files: files = []
--- a/hgext/keyword.py Tue Mar 09 20:38:23 2010 +0100 +++ b/hgext/keyword.py Tue Mar 09 20:47:35 2010 +0100 @@ -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 @@ -264,17 +263,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 @@ -485,15 +482,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,
--- a/hgext/mq.py Tue Mar 09 20:38:23 2010 +0100 +++ b/hgext/mq.py Tue Mar 09 20:47:35 2010 +0100 @@ -1681,7 +1681,7 @@ 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)
--- a/hgext/patchbomb.py Tue Mar 09 20:38:23 2010 +0100 +++ b/hgext/patchbomb.py Tue Mar 09 20:47:35 2010 +0100 @@ -249,7 +249,7 @@ def getpatches(revs): for r in cmdutil.revrange(repo, revs): output = cStringIO.StringIO() - patch.export(repo, [r], fp=output, + cmdutil.export(repo, [r], fp=output, opts=patch.diffopts(ui, opts)) yield output.getvalue().split('\n')
--- a/mercurial/cmdutil.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/cmdutil.py Tue Mar 09 20:47:35 2010 +0100 @@ -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(_('looking for similarities'), 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(_('looking for similarities'), None, total=len(removed)) for dest, v in copies.iteritems(): source, score = v @@ -356,9 +363,7 @@ removed.append(abs) elif repo.dirstate[abs] == 'a': added.append(abs) - if not dry_run: - repo.remove(deleted) - repo.add(unknown) + copies = {} if similarity > 0: for old, new, score in findrenames(repo, added + unknown, removed + deleted, similarity): @@ -366,8 +371,17 @@ repo.ui.status(_('recording removal of %s as rename to %s ' '(%d%% similar)\n') % (m.rel(old), m.rel(new), score * 100)) - if not dry_run: + copies[new] = old + + if not dry_run: + wlock = repo.wlock() + try: + repo.remove(deleted) + repo.add(unknown) + for new, old in copies.iteritems(): repo.copy(old, new) + finally: + wlock.release() def copy(ui, repo, pats, opts, rename=False): # called with the repo lock held @@ -646,6 +660,46 @@ if runfn: return runfn() +def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False, + opts=None): + '''export changesets as hg patches.''' + + total = len(revs) + revwidth = max([len(str(rev)) for rev in revs]) + + def single(rev, seqno, fp): + ctx = repo[rev] + node = ctx.node() + parents = [p.node() for p in ctx.parents() if p] + branch = ctx.branch() + if switch_parent: + parents.reverse() + prev = (parents and parents[0]) or nullid + + if not fp: + fp = make_file(repo, template, node, total=total, seqno=seqno, + revwidth=revwidth, mode='ab') + if fp != sys.stdout and hasattr(fp, 'name'): + repo.ui.note("%s\n" % fp.name) + + fp.write("# HG changeset patch\n") + fp.write("# User %s\n" % ctx.user()) + fp.write("# Date %d %d\n" % ctx.date()) + if branch and (branch != 'default'): + fp.write("# Branch %s\n" % branch) + fp.write("# Node ID %s\n" % hex(node)) + fp.write("# Parent %s\n" % hex(prev)) + if len(parents) > 1: + fp.write("# Parent %s\n" % hex(parents[1])) + fp.write(ctx.description().rstrip()) + fp.write("\n\n") + + for chunk in patch.diff(repo, prev, node, opts=opts): + fp.write(chunk) + + for seqno, rev in enumerate(revs): + single(rev, seqno + 1, fp) + class changeset_printer(object): '''show changeset information when templating not requested.'''
--- a/mercurial/commands.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/commands.py Tue Mar 09 20:47:35 2010 +0100 @@ -1208,7 +1208,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))
--- a/mercurial/graphmod.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/graphmod.py Tue Mar 09 20:47:35 2010 +0100 @@ -115,7 +115,7 @@ edges.append((ecol, next.index(eid), colors[eid])) elif eid == cur: for p in parents: - edges.append((ecol, next.index(p), colors[p])) + edges.append((ecol, next.index(p), color)) # Yield and move on yield (cur, type, data, (col, color), edges)
--- a/mercurial/hgweb/hgwebdir_mod.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/hgweb/hgwebdir_mod.py Tue Mar 09 20:47:35 2010 +0100 @@ -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: @@ -253,19 +250,19 @@ lastchange=d, lastchange_sort=d[1]-d[0], archives=archivelist(u, "tip", url)) - if (not sortcolumn or (sortcolumn, descending) == sortdefault): - # fast path for unsorted output - row['parity'] = parity.next() - yield row - else: - rows.append((row["%s_sort" % sortcolumn], row)) - if rows: - rows.sort() - if descending: - rows.reverse() - for key, row in rows: - row['parity'] = parity.next() - yield row + yield row + + sortdefault = None, False + def entries(sortcolumn="", descending=False, subdir="", **map): + rows = rawentries(subdir=subdir, **map) + + if sortcolumn and sortdefault != (sortcolumn, descending): + sortkey = '%s_sort' % sortcolumn + rows = sorted(rows, key=lambda x: x[sortkey], + reverse=descending) + for row, parity in zip(rows, paritygen(self.stripecount)): + row['parity'] = parity + yield row self.refresh() sortable = ["name", "description", "contact", "lastchange"]
--- a/mercurial/mdiff.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/mdiff.py Tue Mar 09 20:47:35 2010 +0100 @@ -125,12 +125,12 @@ else: al = splitnewlines(a) bl = splitnewlines(b) - l = list(bunidiff(a, b, al, bl, "a/" + fn1, "b/" + fn2, opts=opts)) + l = list(_unidiff(a, b, al, bl, opts=opts)) if not l: return "" - # difflib uses a space, rather than a tab - l[0] = "%s%s" % (l[0][:-2], datetag(ad)) - l[1] = "%s%s" % (l[1][:-2], datetag(bd)) + + l.insert(0, "--- a/%s%s" % (fn1, datetag(ad))) + l.insert(1, "+++ b/%s%s" % (fn2, datetag(bd))) for ln in xrange(len(l)): if l[ln][-1] != '\n': @@ -141,11 +141,10 @@ return "".join(l) -# somewhat self contained replacement for difflib.unified_diff +# creates a headerless unified diff # t1 and t2 are the text to be diffed # l1 and l2 are the text broken up into lines -# header1 and header2 are the filenames for the diff output -def bunidiff(t1, t2, l1, l2, header1, header2, opts=defaultopts): +def _unidiff(t1, t2, l1, l2, opts=defaultopts): def contextend(l, len): ret = l + opts.context if ret > len: @@ -158,10 +157,7 @@ return 0 return ret - def yieldhunk(hunk, header): - if header: - for x in header: - yield x + def yieldhunk(hunk): (astart, a2, bstart, b2, delta) = hunk aend = contextend(a2, len(l1)) alen = aend - astart @@ -184,8 +180,6 @@ for x in xrange(a2, aend): yield ' ' + l1[x] - header = ["--- %s\t\n" % header1, "+++ %s\t\n" % header2] - if opts.showfunc: funcre = re.compile('\w') @@ -236,11 +230,8 @@ astart = hunk[1] bstart = hunk[3] else: - for x in yieldhunk(hunk, header): + for x in yieldhunk(hunk): yield x - # we only want to yield the header if the files differ, and - # we only want to yield it once. - header = None if prev: # we've joined the previous hunk, record the new ending points. hunk[1] = a2 @@ -255,7 +246,7 @@ delta[len(delta):] = ['+' + x for x in new] if hunk: - for x in yieldhunk(hunk, header): + for x in yieldhunk(hunk): yield x def patchtext(bin):
--- a/mercurial/patch.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/patch.py Tue Mar 09 20:47:35 2010 +0100 @@ -1175,20 +1175,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: @@ -1376,6 +1362,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 @@ -1551,47 +1551,6 @@ if text: yield text -def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False, - opts=None): - '''export changesets as hg patches.''' - - total = len(revs) - revwidth = max([len(str(rev)) for rev in revs]) - - def single(rev, seqno, fp): - ctx = repo[rev] - node = ctx.node() - parents = [p.node() for p in ctx.parents() if p] - branch = ctx.branch() - if switch_parent: - parents.reverse() - prev = (parents and parents[0]) or nullid - - if not fp: - fp = cmdutil.make_file(repo, template, node, total=total, - seqno=seqno, revwidth=revwidth, - mode='ab') - if fp != sys.stdout and hasattr(fp, 'name'): - repo.ui.note("%s\n" % fp.name) - - fp.write("# HG changeset patch\n") - fp.write("# User %s\n" % ctx.user()) - fp.write("# Date %d %d\n" % ctx.date()) - if branch and (branch != 'default'): - fp.write("# Branch %s\n" % branch) - fp.write("# Node ID %s\n" % hex(node)) - fp.write("# Parent %s\n" % hex(prev)) - if len(parents) > 1: - fp.write("# Parent %s\n" % hex(parents[1])) - fp.write(ctx.description().rstrip()) - fp.write("\n\n") - - for chunk in diff(repo, prev, node, opts=opts): - fp.write(chunk) - - for seqno, rev in enumerate(revs): - single(rev, seqno + 1, fp) - def diffstatdata(lines): filename, adds, removes = None, 0, 0 for line in lines:
--- a/mercurial/templatefilters.py Tue Mar 09 20:38:23 2010 +0100 +++ b/mercurial/templatefilters.py Tue Mar 09 20:47:35 2010 +0100 @@ -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.'''