[PATCH 6 of 6] diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler
mg at lazybytes.net
Mon Aug 30 17:01:38 CDT 2010
# HG changeset patch
# User Martin Geisler <mg at lazybytes.net>
# Date 1283205545 -7200
# Node ID e93052792d3508248266440ef85405362fdc464d
# Parent 63bb43d8d1fbd7650d8b428632136f3763c29fa4
diff: recurse into subrepositories with --subrepos/-S flag
diff --git a/hgext/keyword.py b/hgext/keyword.py
--- a/hgext/keyword.py
+++ b/hgext/keyword.py
@@ -511,14 +511,14 @@
self.lines = kwt.shrinklines(self.fname, self.lines)
def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
- opts=None):
+ opts=None, prefix=''):
'''Monkeypatch patch.diff to avoid expansion except when
comparing against working dir.'''
if node2 is not None:
kwt.match = util.never
elif node1 is not None and node1 != repo['.'].node():
kwt.restrict = True
- return orig(repo, node1, node2, match, changes, opts)
+ return orig(repo, node1, node2, match, changes, opts, prefix)
def kwweb_skip(orig, web, req, tmpl):
'''Wraps webcommands.x turning off keyword expansion.'''
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -5,7 +5,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
-from node import hex, nullid, nullrev, short
+from node import hex, bin, nullid, nullrev, short
from i18n import _
import os, sys, errno, re, glob, tempfile
import util, templater, patch, error, encoding, templatekw
@@ -655,7 +655,7 @@
single(rev, seqno + 1, fp)
def diffordiffstat(ui, repo, diffopts, node1, node2, match,
- changes=None, stat=False, fp=None):
+ changes=None, stat=False, fp=None, prefix='', listsubrepos=False):
'''show diff or diffstat.'''
if fp is None:
write = ui.write
@@ -668,16 +668,28 @@
width = 80
if not ui.plain():
width = util.termwidth()
- chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
+ chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
+ prefix=prefix)
for chunk, label in patch.diffstatui(util.iterlines(chunks),
width=width,
git=diffopts.git):
write(chunk, label=label)
else:
for chunk, label in patch.diffui(repo, node1, node2, match,
- changes, diffopts):
+ changes, diffopts, prefix=prefix):
write(chunk, label=label)
+ if listsubrepos:
+ ctx1 = repo[node1]
+ for subpath in ctx1.substate:
+ sub = ctx1.sub(subpath)
+ if node2 is not None:
+ node2 = bin(repo[node2].substate[subpath][1])
+ submatch = matchmod.subrepomatcher(subpath, match)
+ sub.diff(diffopts, node2, submatch, changes=changes,
+ stat=stat, fp=fp, prefix=prefix)
+
+
class changeset_printer(object):
'''show changeset information when templating not requested.'''
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1453,7 +1453,8 @@
diffopts = patch.diffopts(ui, opts)
m = cmdutil.match(repo, pats, opts)
- cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
+ cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
+ listsubrepos=opts.get('subrepos'))
def export(ui, repo, *changesets, **opts):
"""dump the header and diffs for one or more changesets
@@ -4156,7 +4157,8 @@
[('r', 'rev', [],
_('revision'), _('REV')),
('c', 'change', '',
- _('change made by revision'), _('REV'))
+ _('change made by revision'), _('REV')),
+ ('S', 'subrepos', None, _('recurse into subrepositories'))
] + diffopts + diffopts2 + walkopts,
_('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
"^export":
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1404,7 +1404,7 @@
context=get('unified', getter=ui.config))
def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None,
- losedatafn=None):
+ losedatafn=None, prefix=''):
'''yields diff of changes to files between two nodes, or node and
working directory.
@@ -1418,6 +1418,9 @@
called with the name of current file being diffed as 'fn'. If set
to None, patches will always be upgraded to git format when
necessary.
+
+ prefix is a filename prefix that is prepended to all filenames on
+ display (used for subrepos).
'''
if opts is None:
@@ -1462,7 +1465,7 @@
copy = copies.copies(repo, ctx1, ctx2, repo[nullid])[0]
difffn = lambda opts, losedata: trydiff(repo, revs, ctx1, ctx2,
- modified, added, removed, copy, getfilectx, opts, losedata)
+ modified, added, removed, copy, getfilectx, opts, losedata, prefix)
if opts.upgrade and not opts.git:
try:
def losedata(fn):
@@ -1518,7 +1521,10 @@
header.append('new mode %s\n' % nmode)
def trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
- copy, getfilectx, opts, losedatafn):
+ copy, getfilectx, opts, losedatafn, prefix):
+
+ def join(f):
+ return os.path.join(prefix, f)
date1 = util.datestr(ctx1.date())
man1 = ctx1.manifest()
@@ -1557,8 +1563,8 @@
gone.add(a)
else:
op = 'copy'
- header.append('%s from %s\n' % (op, a))
- header.append('%s to %s\n' % (op, f))
+ header.append('%s from %s\n' % (op, join(a)))
+ header.append('%s to %s\n' % (op, join(f)))
to = getfilectx(a, ctx1).data()
else:
losedatafn(f)
@@ -1600,7 +1606,7 @@
elif binary or nflag != oflag:
losedatafn(f)
if opts.git:
- header.insert(0, mdiff.diffline(revs, a, b, opts))
+ header.insert(0, mdiff.diffline(revs, join(a), join(b), opts))
if dodiff:
if dodiff == 'binary':
@@ -1609,7 +1615,7 @@
text = mdiff.unidiff(to, date1,
# ctx2 date may be dynamic
tn, util.datestr(ctx2.date()),
- a, b, revs, opts=opts)
+ join(a), join(b), revs, opts=opts)
if header and (text or len(header) > 1):
yield ''.join(header)
if text:
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -7,7 +7,7 @@
import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
from i18n import _
-import config, util, node, error
+import config, util, node, error, cmdutil
hg = None
nullstate = ('', '', 'empty')
@@ -244,6 +244,9 @@
def status(self, rev2, **opts):
raise NotImplementedError
+ def diff(self, diffopts, node2, match, prefix, **opts):
+ raise NotImplementedError
+
class hgsubrepo(abstractsubrepo):
def __init__(self, ctx, path, state):
@@ -280,6 +283,13 @@
ctx2 = self._repo[rev2]
return self._repo.status(ctx1, ctx2, **opts)
+ def diff(self, diffopts, node2, match, prefix, **opts):
+ node1 = node.bin(self._state[1])
+ cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
+ node1, node2, match,
+ prefix=os.path.join(prefix, self._path),
+ listsubrepos=True, **opts)
+
def dirty(self):
r = self._state[1]
if r == '':
diff --git a/tests/test-debugcomplete.t b/tests/test-debugcomplete.t
--- a/tests/test-debugcomplete.t
+++ b/tests/test-debugcomplete.t
@@ -180,7 +180,7 @@
annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
commit: addremove, close-branch, include, exclude, message, logfile, date, user
- diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
+ diff: rev, change, subrepos, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
export: output, switch-parent, rev, text, git, nodates
forget: include, exclude
init: ssh, remotecmd
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -459,6 +459,7 @@
-r --rev REV [+] revision
-c --change REV change made by revision
+ -S --subrepos recurse into subrepositories
-a --text treat all files as text
-g --git use git extended diff format
--nodates omit dates from diff headers
diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t
--- a/tests/test-subrepo-recursion.t
+++ b/tests/test-subrepo-recursion.t
@@ -2,6 +2,7 @@
$ echo '[defaults]' >> $HGRCPATH
$ echo 'status = -S' >> $HGRCPATH
+ $ echo 'diff = --nodates -S' >> $HGRCPATH
Create test repository:
@@ -29,6 +30,13 @@
$ echo x2 >> inner/x.txt
$ hg status
M inner/x.txt
+ $ hg diff
+ diff -r 7d0a8eea9f9f inner/x.txt
+ --- a/inner/x.txt
+ +++ b/inner/x.txt
+ @@ -1,1 +1,2 @@
+ x1
+ +x2
Status call crossing repository boundaries:
@@ -38,8 +46,15 @@
M inner/x.txt
$ hg status -I '**/?.txt'
M inner/x.txt
+ $ hg diff -I '**/?.txt'
+ diff -r 7d0a8eea9f9f inner/x.txt
+ --- a/inner/x.txt
+ +++ b/inner/x.txt
+ @@ -1,1 +1,2 @@
+ x1
+ +x2
-Status from within a subdirectory:
+Testing from within a subdirectory:
$ mkdir dir
$ cd dir
@@ -47,15 +62,29 @@
$ hg status
M inner/x.txt
? dir/b.txt
+ $ hg diff ..
+ diff -r 7d0a8eea9f9f inner/x.txt
+ --- a/inner/x.txt
+ +++ b/inner/x.txt
+ @@ -1,1 +1,2 @@
+ x1
+ +x2
-Status with relative path:
+Testing with a relative path:
$ hg status ..
M ../inner/x.txt
? b.txt
+ $ hg diff ..
+ diff -r 7d0a8eea9f9f inner/x.txt
+ --- a/inner/x.txt
+ +++ b/inner/x.txt
+ @@ -1,1 +1,2 @@
+ x1
+ +x2
$ cd ..
-Status between revisions:
+Testing with revisions in outer repository:
$ rm -r dir
$ hg commit -m a3
@@ -64,3 +93,16 @@
$ hg status --rev 2:3
M .hgsubstate
M inner/x.txt
+ $ hg diff --rev 2:3
+ diff -r eb2a1b9015ca -r f0e16205556b .hgsubstate
+ --- a/.hgsubstate
+ +++ b/.hgsubstate
+ @@ -1,1 +1,1 @@
+ -7d0a8eea9f9fb4d93ad00e4a2e82078724fa7cc2 inner
+ +ba133242445e5702c7068b181908b3cd38692d0b inner
+ diff -r 7d0a8eea9f9f -r ba133242445e inner/x.txt
+ --- a/inner/x.txt
+ +++ b/inner/x.txt
+ @@ -1,1 +1,2 @@
+ x1
+ +x2
More information about the Mercurial-devel
mailing list