--- a/contrib/hgdiff Tue Mar 09 22:11:43 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 22:11:43 2010 +0100
+++ b/contrib/wix/mercurial.wxs Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/hgext/hgcia.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/hgext/inotify/__init__.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/hgext/keyword.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/hgext/mq.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/hgext/patchbomb.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/cmdutil.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/commands.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/graphmod.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/hgweb/hgwebdir_mod.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/mdiff.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/patch.py Tue Mar 09 22:18:37 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 22:11:43 2010 +0100
+++ b/mercurial/templatefilters.py Tue Mar 09 22:18:37 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.'''