Applying a patch that adds an empty file

Greg Ward greg at gerg.ca
Thu Jul 1 12:32:16 CDT 2010


I've been investigating transplant problems and stumbled across
http://mercurial.selenic.com/bts/issue2135.  The core of the bug there
seems to be that patch never fails when applying a patch that adds an
empty file.  As a result, it's possible for patch.patch() to claim
success even though it did not make any changes.  That makes
transplant crash -- see the simplified test script in that bug report
(http://mercurial.selenic.com/bts/msg12965) if you want an example.

But this seems like a bug in patch.py to me.  First, here's patch
behaving as it should:

$ cat patch1
diff --git a/a b/a
new file mode 100644
--- /dev/null
+++ b/a
@@ -0,0 +1,1 @@
+foo
$ hg patch --no-commit -f patch1
applying patch1
$ hg patch --no-commit -f patch1
applying patch1
file a already exists
1 out of 1 hunks FAILED -- saving rejects to file a.rej
abort: patch failed to apply

That's obviously correct: apply the same patch twice and the second
attempt fails.

But if the patch is slightly different, the behaviour is completely different:

$ cat patch2
diff --git a/b b/b
new file mode 100644
--- /dev/null
+++ b/b
$ hg patch --no-commit -f patch2
applying patch2
$ hg patch --no-commit -f patch2
applying patch2

It gets weirder:

$ echo foo > b
$ hg patch --no-commit -f patch2
applying patch2

That *really* should conflict.  The patch wants b to be an empty file,
and it clearly isn't.

issue2135 reveals that transplant does not expect this inconsistent
behaviour, and ends up crashing as a result.  I think there are two
bugs here:

  * patch should fail when applying a patch that creates an empty
file, but the file already exists (empty or not)
  * transplant should detect when its commit does nothing and crash
sooner rather than later

I'm going to take a look at patch.py and see if I can figure out a fix
for it.  I already have a fix for the second problem -- will post it
shortly.

Greg


More information about the Mercurial-devel mailing list