[PATCH 3 of 3] subrepo: add partial diff support for git subrepos

Mathias De Maré mathias.demare at gmail.com
Wed Dec 10 09:48:48 UTC 2014


# HG changeset patch
# User Mathias De Maré <mathias.demare at gmail.com>
# Date 1418203971 -3600
#      Mit Dez 10 10:32:51 2014 +0100
# Node ID 94fe82410ecaa9573c5b54c25e340713eb53b32d
# Parent  239ccaaed78095a128fde4b1421de3d997068c6f
subrepo: add partial diff support for git subrepos

So far, git subrepositories were silently ignored for diffs.
This patch adds support for git subrepositories,
with the remark that --include and --exclude are not supported.
If --include or --exclude are used, the subrepo is ignored.

diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt
--- a/mercurial/help/subrepos.txt
+++ b/mercurial/help/subrepos.txt
@@ -93,18 +93,18 @@ Interaction with Mercurial Commands
     to instead commit all modified subrepositories by specifying
     -S/--subrepos, or setting "ui.commitsubrepos=True" in a
     configuration file (see :hg:`help config`).  After there are no
     longer any modified subrepositories, it records their state and
     finally commits it in the parent repository.
 
 :diff: diff does not recurse in subrepos unless -S/--subrepos is
     specified. Changes are displayed as usual, on the subrepositories
-    elements. Git and Subversion subrepositories are currently
-    silently ignored.
+    elements. Git subrepositories do not support --include/--exclude.
+    Subversion subrepositories are currently silently ignored.
 
 :forget: forget currently only handles exact file matches in subrepos.
     Git and Subversion subrepositories are currently silently ignored.
 
 :incoming: incoming does not recurse in subrepos unless -S/--subrepos
     is specified. Git and Subversion subrepositories are currently
     silently ignored.
 
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -1588,16 +1588,59 @@ class gitsubrepo(abstractsubrepo):
             for line in out.split('\n'):
                 if len(line) == 0:
                     continue
                 unknown.append(line)
 
         return scmutil.status(modified, added, removed, deleted,
                               unknown, ignored, clean)
 
+
+    @annotatesubrepoerror
+    def diff(self, ui, diffopts, node2, match, prefix, **opts):
+        node1 = self._state[1]
+        cmd = ['diff']
+        if opts['stat']:
+            cmd.append('--stat')
+        else:
+            # for Git, this also implies '-p'
+            cmd.append('-U%d' % diffopts.context)
+
+        gitprefix = os.path.join(prefix, self._path)
+
+        if diffopts.noprefix:
+            cmd.extend(['--src-prefix=%s/' % gitprefix,
+                        '--dst-prefix=%s/' % gitprefix])
+        else:
+            cmd.extend(['--src-prefix=a/%s/' % gitprefix,
+                        '--dst-prefix=b/%s/' % gitprefix])
+
+        if diffopts.ignorews:
+            cmd.append('--ignore-all-space')
+        if diffopts.ignorewsamount:
+            cmd.append('--ignore-space-change')
+        if self._gitversion(self._gitcommand(['--version'])) >= (1, 8, 4) \
+                and diffopts.ignoreblanklines:
+            cmd.append('--ignore-blank-lines')
+
+        cmd.append(node1)
+        if node2:
+            cmd.append(node2)
+
+        if match.anypats():
+            return #No support for include/exclude yet
+
+        if match.always():
+            ui.write(self._gitcommand(cmd))
+        elif match.files():
+            for f in match.files():
+                ui.write(self._gitcommand(cmd + [f]))
+        elif match(gitprefix): #Subrepo is matched
+            ui.write(self._gitcommand(cmd))
+
     def shortid(self, revid):
         return revid[:7]
 
 types = {
     'hg': hgsubrepo,
     'svn': svnsubrepo,
     'git': gitsubrepo,
     }
diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t
--- a/tests/test-subrepo-git.t
+++ b/tests/test-subrepo-git.t
@@ -98,16 +98,25 @@ clone root, make local change
   updating to branch default
   cloning subrepo s from $TESTTMP/gitroot
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ cd ../ta
   $ echo ggg >> s/g
   $ hg status --subrepos
   M s/g
+  $ hg diff --subrepos
+  diff --git a/s/g b/s/g
+  index 089258f..85341ee 100644
+  --- a/s/g
+  +++ b/s/g
+  @@ -1,2 +1,3 @@
+   g
+   gg
+  +ggg (no-eol)
   $ hg commit --subrepos -m ggg
   committing subrepository s
   $ hg debugsub
   path s
    source   ../gitroot
    revision 79695940086840c99328513acbe35f90fcd55e57
 
 clone root separately, make different local change
@@ -659,9 +668,117 @@ additional test for "git merge --ff" rou
 Test that sanitizing is omitted in meta data area:
 
   $ mkdir s/.git/.hg
   $ echo '.hg/hgrc in git metadata area' > s/.git/.hg/hgrc
   $ hg update -q -C af6d2edbb0d3
   checking out detached HEAD in subrepo s
   check out a git branch if you intend to make changes
 
+check differences made by most recent change
+  $ cd s
+  $ cat > foobar << EOF
+  > woopwoop
+  > 
+  > foo
+  > bar
+  > EOF
+  $ git add foobar
   $ cd ..
+
+  $ hg diff --subrepos
+  diff --git a/s/foobar b/s/foobar
+  new file mode 100644
+  index 0000000..8a5a5e2
+  --- /dev/null
+  +++ b/s/foobar
+  @@ -0,0 +1,4 @@
+  +woopwoop
+  +
+  +foo
+  +bar (no-eol)
+
+  $ hg commit --subrepos -m "Added foobar"
+  committing subrepository s
+  created new head
+
+  $ hg diff -c . --subrepos --nodates
+  diff -r af6d2edbb0d3 -r 255ee8cf690e .hgsubstate
+  --- a/.hgsubstate
+  +++ b/.hgsubstate
+  @@ -1,1 +1,1 @@
+  -32a343883b74769118bb1d3b4b1fbf9156f4dddc s
+  +fd4dbf828a5b2fcd36b2bcf21ea773820970d129 s
+  diff --git a/s/foobar b/s/foobar
+  new file mode 100644
+  index 0000000..8a5a5e2
+  --- /dev/null
+  +++ b/s/foobar
+  @@ -0,0 +1,4 @@
+  +woopwoop
+  +
+  +foo
+  +bar (no-eol)
+
+check output when only diffing the subrepository
+  $ hg diff -c . --subrepos s
+  diff --git a/s/foobar b/s/foobar
+  new file mode 100644
+  index 0000000..8a5a5e2
+  --- /dev/null
+  +++ b/s/foobar
+  @@ -0,0 +1,4 @@
+  +woopwoop
+  +
+  +foo
+  +bar (no-eol)
+
+check output when diffing something else
+  $ hg diff -c . --subrepos .hgsubstate --nodates
+  diff -r af6d2edbb0d3 -r 255ee8cf690e .hgsubstate
+  --- a/.hgsubstate
+  +++ b/.hgsubstate
+  @@ -1,1 +1,1 @@
+  -32a343883b74769118bb1d3b4b1fbf9156f4dddc s
+  +fd4dbf828a5b2fcd36b2bcf21ea773820970d129 s
+
+add new changes, including whitespace
+  $ cd s
+  $ cat > foobar << EOF
+  > woop    woop
+  > 
+  > foo
+  > bar
+  > EOF
+  $ echo foo > barfoo
+  $ git add barfoo
+  $ cd ..
+
+  $ hg diff --subrepos --ignore-all-space
+  diff --git a/s/barfoo b/s/barfoo
+  new file mode 100644
+  index 0000000..257cc56
+  --- /dev/null
+  +++ b/s/barfoo
+  @@ -0,0 +1 @@
+  +foo (no-eol)
+  $ hg diff --subrepos s/foobar
+  diff --git a/s/foobar b/s/foobar
+  index 8a5a5e2..bd5812a 100644
+  --- a/s/foobar
+  +++ b/s/foobar
+  @@ -1,4 +1,4 @@
+  -woopwoop
+  +woop    woop
+   
+   foo
+   bar (no-eol)
+
+  $ hg diff --subrepos --stat
+  barfoo | 1 +
+   foobar | 2 +-
+   2 files changed, 2 insertions(+), 1 deletion(-) (no-eol)
+
+ensure adding include/exclude ignores the subrepo
+  $ hg diff --subrepos -I s/foobar
+  $ hg diff --subrepos -X s/foobar
+
+  $ cd ..


More information about the Mercurial-devel mailing list