patch: more precise NoHunk, raised for every file (issue2102) stable
authorBenoit Boissinot <benoit.boissinot@ens-lyon.org>
Sat, 20 Mar 2010 14:47:05 +0100
branchstable
changeset 10748 fb06e357e698
parent 10747 b010d899665e
child 10749 03225f14c495
child 10753 a1cb8ca051c0
patch: more precise NoHunk, raised for every file (issue2102)
mercurial/patch.py
tests/test-import
tests/test-import.out
--- a/mercurial/patch.py	Sat Mar 20 21:16:22 2010 +0100
+++ b/mercurial/patch.py	Sat Mar 20 14:47:05 2010 +0100
@@ -1012,11 +1012,11 @@
     BFILE = 1
     context = None
     lr = linereader(fp)
-    dopatch = True
     # gitworkdone is True if a git operation (copy, rename, ...) was
     # performed already for the current file. Useful when the file
     # section may have no hunk.
     gitworkdone = False
+    empty = None
 
     while True:
         newfile = newgitfile = False
@@ -1028,7 +1028,7 @@
                 current_hunk.fix_newline()
             yield 'hunk', current_hunk
             current_hunk = None
-            gitworkdone = False
+            empty = False
         if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
             ((context is not False) and x.startswith('***************')))):
             try:
@@ -1046,28 +1046,32 @@
             if emitfile:
                 emitfile = False
                 yield 'file', (afile, bfile, current_hunk)
+                empty = False
         elif state == BFILE and x.startswith('GIT binary patch'):
             current_hunk = binhunk(changed[bfile])
             hunknum += 1
             if emitfile:
                 emitfile = False
                 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk)
+                empty = False
             current_hunk.extract(lr)
         elif x.startswith('diff --git'):
             # check for git diff, scanning the whole patch file if needed
             m = gitre.match(x)
+            gitworkdone = False
             if m:
                 afile, bfile = m.group(1, 2)
                 if not git:
                     git = True
-                    dopatch, gitpatches = scangitpatch(lr, x)
+                    gitpatches = scangitpatch(lr, x)[1]
                     yield 'git', gitpatches
                     for gp in gitpatches:
                         changed[gp.path] = gp
                 # else error?
                 # copy/rename + modify should modify target, not source
                 gp = changed.get(bfile)
-                if gp and gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD'):
+                if gp and (gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD')
+                           or gp.mode):
                     afile = bfile
                     gitworkdone = True
                 newgitfile = True
@@ -1097,6 +1101,12 @@
             afile = parsefilename(x)
             bfile = parsefilename(l2)
 
+        if newfile:
+            if empty:
+                raise NoHunks
+            empty = not gitworkdone
+            gitworkdone = False
+
         if newgitfile or newfile:
             emitfile = True
             state = BFILE
@@ -1104,11 +1114,12 @@
     if current_hunk:
         if current_hunk.complete():
             yield 'hunk', current_hunk
+            empty = False
         else:
             raise PatchError(_("malformed patch %s %s") % (afile,
                              current_hunk.desc))
 
-    if hunknum == 0 and dopatch and not gitworkdone:
+    if (empty is None and not gitworkdone) or empty:
         raise NoHunks
 
 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'):
--- a/tests/test-import	Sat Mar 20 21:16:22 2010 +0100
+++ b/tests/test-import	Sat Mar 20 14:47:05 2010 +0100
@@ -433,3 +433,44 @@
 hg import -d '0 0' ../trickyheaders.patch
 hg export --git tip
 cd ..
+
+echo '% issue2102'
+hg init issue2102
+cd issue2102
+mkdir -p src/cmd/gc
+touch src/cmd/gc/mksys.bash
+hg ci -Am init
+hg import - <<EOF
+# HG changeset patch
+# User Rob Pike
+# Date 1216685449 25200
+# Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
+# Parent  93d10138ad8df586827ca90b4ddb5033e21a3a84
+help management of empty pkg and lib directories in perforce
+
+R=gri
+DELTA=4  (4 added, 0 deleted, 0 changed)
+OCL=13328
+CL=13328
+
+diff --git a/lib/place-holder b/lib/place-holder
+new file mode 100644
+--- /dev/null
++++ b/lib/place-holder
+@@ -0,0 +1,2 @@
++perforce does not maintain empty directories.
++this file helps.
+diff --git a/pkg/place-holder b/pkg/place-holder
+new file mode 100644
+--- /dev/null
++++ b/pkg/place-holder
+@@ -0,0 +1,2 @@
++perforce does not maintain empty directories.
++this file helps.
+diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
+old mode 100644
+new mode 100755
+EOF
+hg sum
+hg diff --git -c tip
+cd ..
--- a/tests/test-import.out	Sat Mar 20 21:16:22 2010 +0100
+++ b/tests/test-import.out	Sat Mar 20 14:47:05 2010 +0100
@@ -348,3 +348,28 @@
 +++ b/foo
 @@ -0,0 +1,1 @@
 +foo
+% issue2102
+adding src/cmd/gc/mksys.bash
+applying patch from stdin
+parent: 1:d59915696727 tip
+ help management of empty pkg and lib directories in perforce
+branch: default
+commit: (clean)
+update: (current)
+diff --git a/lib/place-holder b/lib/place-holder
+new file mode 100644
+--- /dev/null
++++ b/lib/place-holder
+@@ -0,0 +1,2 @@
++perforce does not maintain empty directories.
++this file helps.
+diff --git a/pkg/place-holder b/pkg/place-holder
+new file mode 100644
+--- /dev/null
++++ b/pkg/place-holder
+@@ -0,0 +1,2 @@
++perforce does not maintain empty directories.
++this file helps.
+diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
+old mode 100644
+new mode 100755