mq: upgrade to git patch when necessary (
issue767)
--- a/hgext/mq.py Fri Jan 01 20:54:05 2010 +0100
+++ b/hgext/mq.py Fri Jan 01 21:21:34 2010 +0100
@@ -26,6 +26,18 @@
add known patch to applied stack qpush
remove patch from applied stack qpop
refresh contents of top applied patch qrefresh
+
+By default, mq will automatically use git patches when required to
+avoid losing file mode changes, copy records, binary files or empty
+files creations or deletions. This behaviour can be configured with::
+
+ [mq]
+ git = auto/keep/yes/no
+
+If set to 'keep', mq will obey the [diff] section configuration while
+preserving existing git patches upon qrefresh. If set to 'yes' or
+'no', mq will override the [diff] section and always generate git or
+regular patches, possibly losing data in the second case.
'''
from mercurial.i18n import _
@@ -225,6 +237,14 @@
self.guards_path = "guards"
self.active_guards = None
self.guards_dirty = False
+ # Handle mq.git as a bool with extended values
+ try:
+ gitmode = ui.configbool('mq', 'git', None)
+ if gitmode is None:
+ raise error.ConfigError()
+ self.gitmode = gitmode and 'yes' or 'no'
+ except error.ConfigError:
+ self.gitmode = ui.config('mq', 'git', 'auto').lower()
@util.propertycache
def applied(self):
@@ -260,23 +280,33 @@
def diffopts(self, opts={}, patchfn=None):
diffopts = patch.diffopts(self.ui, opts)
+ if self.gitmode == 'auto':
+ diffopts.upgrade = True
+ elif self.gitmode == 'keep':
+ pass
+ elif self.gitmode in ('yes', 'no'):
+ diffopts.git = self.gitmode == 'yes'
+ else:
+ raise util.Abort(_('mq.git option can be auto/keep/yes/no'
+ ' got %s') % self.gitmode)
if patchfn:
diffopts = self.patchopts(diffopts, patchfn)
return diffopts
def patchopts(self, diffopts, *patches):
"""Return a copy of input diff options with git set to true if
- referenced patch is a git patch.
+ referenced patch is a git patch and should be preserved as such.
"""
diffopts = diffopts.copy()
- for patchfn in patches:
- patchf = self.opener(patchfn, 'r')
- # if the patch was a git patch, refresh it as a git patch
- for line in patchf:
- if line.startswith('diff --git'):
- diffopts.git = True
- break
- patchf.close()
+ if not diffopts.git and self.gitmode == 'keep':
+ for patchfn in patches:
+ patchf = self.opener(patchfn, 'r')
+ # if the patch was a git patch, refresh it as a git patch
+ for line in patchf:
+ if line.startswith('diff --git'):
+ diffopts.git = True
+ break
+ patchf.close()
return diffopts
def join(self, *p):
@@ -1260,7 +1290,7 @@
patchf.write(chunk)
try:
- if diffopts.git:
+ if diffopts.git or diffopts.upgrade:
copies = {}
for dst in a:
src = repo.dirstate.copied(dst)
--- a/tests/test-mq-eol Fri Jan 01 20:54:05 2010 +0100
+++ b/tests/test-mq-eol Fri Jan 01 21:21:34 2010 +0100
@@ -4,6 +4,8 @@
echo "[extensions]" >> $HGRCPATH
echo "mq=" >> $HGRCPATH
+echo "[diff]" >> $HGRCPATH
+echo "nodates=1" >> $HGRCPATH
cat > makepatch.py <<EOF
f = file('eol.diff', 'wb')
--- a/tests/test-mq-eol.out Fri Jan 01 20:54:05 2010 +0100
+++ b/tests/test-mq-eol.out Fri Jan 01 21:21:34 2010 +0100
@@ -23,7 +23,7 @@
now at: eol.diff
test message<LF>
<LF>
-diff --git a/a b/a<LF>
+diff -r 0d0bf99a8b7a a<LF>
--- a/a<LF>
+++ b/a<LF>
@@ -1,5 +1,5 @@<LF>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq-git Fri Jan 01 21:21:34 2010 +0100
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+# Test the plumbing of mq.git option
+# Automatic upgrade itself is tested elsewhere.
+
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
+echo "[diff]" >> $HGRCPATH
+echo "nodates=1" >> $HGRCPATH
+
+hg init repo-auto
+cd repo-auto
+echo '% git=auto: regular patch creation'
+echo a > a
+hg add a
+hg qnew -d '0 0' -f adda
+cat .hg/patches/adda
+echo '% git=auto: git patch creation with copy'
+hg cp a b
+hg qnew -d '0 0' -f copy
+cat .hg/patches/copy
+echo '% git=auto: git patch when using --git'
+echo regular > regular
+hg add regular
+hg qnew -d '0 0' --git -f git
+cat .hg/patches/git
+echo '% git=auto: regular patch after qrefresh without --git'
+hg qrefresh -d '0 0'
+cat .hg/patches/git
+cd ..
+
+hg init repo-keep
+cd repo-keep
+echo '[mq]' > .hg/hgrc
+echo 'git = KEEP' >> .hg/hgrc
+echo '% git=keep: git patch with --git'
+echo a > a
+hg add a
+hg qnew -d '0 0' -f --git git
+cat .hg/patches/git
+echo '% git=keep: git patch after qrefresh without --git'
+echo a >> a
+hg qrefresh -d '0 0'
+cat .hg/patches/git
+cd ..
+
+hg init repo-yes
+cd repo-yes
+echo '[mq]' > .hg/hgrc
+echo 'git = yes' >> .hg/hgrc
+echo '% git=yes: git patch'
+echo a > a
+hg add a
+hg qnew -d '0 0' -f git
+cat .hg/patches/git
+echo '% git=yes: git patch after qrefresh'
+echo a >> a
+hg qrefresh -d '0 0'
+cat .hg/patches/git
+cd ..
+
+hg init repo-no
+cd repo-no
+echo '[diff]' > .hg/hgrc
+echo 'git = True' >> .hg/hgrc
+echo '[mq]' > .hg/hgrc
+echo 'git = False' >> .hg/hgrc
+echo '% git=no: regular patch with copy'
+echo a > a
+hg add a
+hg qnew -d '0 0' -f adda
+hg cp a b
+hg qnew -d '0 0' -f regular
+cat .hg/patches/regular
+echo '% git=no: regular patch after qrefresh with copy'
+hg cp a c
+hg qrefresh -d '0 0'
+cat .hg/patches/regular
+cd ..
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq-git.out Fri Jan 01 21:21:34 2010 +0100
@@ -0,0 +1,100 @@
+% git=auto: regular patch creation
+# HG changeset patch
+# Date 0 0
+
+diff -r 000000000000 -r ef8dafc9fa4c a
+--- /dev/null
++++ b/a
+@@ -0,0 +1,1 @@
++a
+% git=auto: git patch creation with copy
+# HG changeset patch
+# Date 0 0
+
+diff --git a/a b/b
+copy from a
+copy to b
+% git=auto: git patch when using --git
+# HG changeset patch
+# Date 0 0
+
+diff --git a/regular b/regular
+new file mode 100644
+--- /dev/null
++++ b/regular
+@@ -0,0 +1,1 @@
++regular
+% git=auto: regular patch after qrefresh without --git
+# HG changeset patch
+# Date 0 0
+
+diff -r 2962f232b49d regular
+--- /dev/null
++++ b/regular
+@@ -0,0 +1,1 @@
++regular
+% git=keep: git patch with --git
+# HG changeset patch
+# Date 0 0
+
+diff --git a/a b/a
+new file mode 100644
+--- /dev/null
++++ b/a
+@@ -0,0 +1,1 @@
++a
+% git=keep: git patch after qrefresh without --git
+# HG changeset patch
+# Date 0 0
+
+diff --git a/a b/a
+new file mode 100644
+--- /dev/null
++++ b/a
+@@ -0,0 +1,2 @@
++a
++a
+% git=yes: git patch
+# HG changeset patch
+# Date 0 0
+
+diff --git a/a b/a
+new file mode 100644
+--- /dev/null
++++ b/a
+@@ -0,0 +1,1 @@
++a
+% git=yes: git patch after qrefresh
+# HG changeset patch
+# Date 0 0
+
+diff --git a/a b/a
+new file mode 100644
+--- /dev/null
++++ b/a
+@@ -0,0 +1,2 @@
++a
++a
+% git=no: regular patch with copy
+# HG changeset patch
+# Date 0 0
+
+diff -r ef8dafc9fa4c -r 110cde11d262 b
+--- /dev/null
++++ b/b
+@@ -0,0 +1,1 @@
++a
+% git=no: regular patch after qrefresh with copy
+# HG changeset patch
+# Date 0 0
+
+diff -r ef8dafc9fa4c b
+--- /dev/null
++++ b/b
+@@ -0,0 +1,1 @@
++a
+diff -r ef8dafc9fa4c c
+--- /dev/null
++++ b/c
+@@ -0,0 +1,1 @@
++a
--- a/tests/test-mq-merge Fri Jan 01 20:54:05 2010 +0100
+++ b/tests/test-mq-merge Fri Jan 01 21:21:34 2010 +0100
@@ -16,6 +16,8 @@
echo "[extensions]" >> $HGRCPATH
echo "mq =" >> $HGRCPATH
+echo "[mq]" >> $HGRCPATH
+echo "git = keep" >> $HGRCPATH
# Commit two dummy files in "init" changeset
hg init t
--- a/tests/test-mq-qfold Fri Jan 01 20:54:05 2010 +0100
+++ b/tests/test-mq-qfold Fri Jan 01 21:21:34 2010 +0100
@@ -2,6 +2,8 @@
echo "[extensions]" >> $HGRCPATH
echo "mq=" >> $HGRCPATH
+echo "[mq]" >> $HGRCPATH
+echo "git=keep" >> $HGRCPATH
filterdiff()
{
--- a/tests/test-mq.out Fri Jan 01 20:54:05 2010 +0100
+++ b/tests/test-mq.out Fri Jan 01 21:21:34 2010 +0100
@@ -21,6 +21,18 @@
remove patch from applied stack qpop
refresh contents of top applied patch qrefresh
+By default, mq will automatically use git patches when required to avoid
+losing file mode changes, copy records, binary files or empty files creations
+or deletions. This behaviour can be configured with:
+
+ [mq]
+ git = auto/keep/yes/no
+
+If set to 'keep', mq will obey the [diff] section configuration while
+preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
+will override the [diff] section and always generate git or regular patches,
+possibly losing data in the second case.
+
list of commands:
qapplied print the patches already applied