changeset 23523:01a8dfc79cdc

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.
author Mathias De Maré <mathias.demare@gmail.com>
date Wed, 10 Dec 2014 10:32:51 +0100
parents 49a58b33d1ce
children a1a7c94def6d
files mercurial/help/subrepos.txt mercurial/subrepo.py tests/test-subrepo-git.t
diffstat 3 files changed, 161 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/help/subrepos.txt	Wed Dec 10 08:41:21 2014 +0100
+++ b/mercurial/help/subrepos.txt	Wed Dec 10 10:32:51 2014 +0100
@@ -98,8 +98,8 @@
 
 :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.
--- a/mercurial/subrepo.py	Wed Dec 10 08:41:21 2014 +0100
+++ b/mercurial/subrepo.py	Wed Dec 10 10:32:51 2014 +0100
@@ -1593,6 +1593,48 @@
         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]
 
--- a/tests/test-subrepo-git.t	Wed Dec 10 08:41:21 2014 +0100
+++ b/tests/test-subrepo-git.t	Wed Dec 10 10:32:51 2014 +0100
@@ -103,6 +103,15 @@
   $ 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
@@ -664,4 +673,112 @@
   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 ..