Public bug reported:

Versions tested: patch 2.7.6 and 2.8 (identical behavior)

When -c (--context) is given and the input is a git-format unified diff,
patch discards the entire first file-level diff without applying any of
its hunks, prints no warning, and exits 0. In a multi-diff input, all
diffs after the first are then auto-detected as unified and applied
normally, so the result is a silent, partial application reported as
complete success.

== Reproducer ==

mkdir /tmp/pc && cd /tmp/pc
printf 'alpha\nbravo\ncharlie\n' > one.txt
printf 'delta\necho\nfoxtrot\n'  > two.txt

cat > repro.patch << 'PATCH'
diff --git a/one.txt b/one.txt
index 0000001..0000002 100644
--- a/one.txt
+++ b/one.txt
@@ -1,3 +1,3 @@
 alpha
-bravo
+BRAVO
 charlie
diff --git a/two.txt b/two.txt
index 0000003..0000004 100644
--- a/two.txt
+++ b/two.txt
@@ -1,3 +1,3 @@
 delta
-echo
+ECHO
 foxtrot
PATCH

patch -p1 -c -t --verbose -i repro.patch; echo "exit: $?"
grep -c BRAVO one.txt   # 0: first diff was not applied
grep -c ECHO two.txt    # 1: second diff was applied

== Output ==

patch -p1 -c -t --verbose -i demo.patch; echo "exit: $?"
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff --git a/one.txt b/one.txt
|index 0000001..0000002 100644
|--- a/one.txt
|+++ b/one.txt
|@@ -1,3 +1,3 @@
| alpha
|-bravo
|+BRAVO
| charlie
--------------------------
patching file one.txt
Hmm...  The next patch looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff --git a/two.txt b/two.txt
|index 0000003..0000004 100644
|--- a/two.txt
|+++ b/two.txt
--------------------------
patching file two.txt
Hunk #1 succeeded at 1.
done
exit: 0

/tmp/pc
$ grep -c BRAVO one.txt   # 0: first diff was not applied
0

/tmp/pc
$ grep -c ECHO two.txt    # 1: second diff was applied
1

== Expectation ==

A diagnostic and a nonzero exit status indicate that recognizable hunks
were discarded because they did not match the format forced on the
command line.

== Analysis ==

This appears to have been broken since "diff --git" format support was
added in 2.7.

-c sets diff_type = CONTEXT_DIFF once at option parsing
(src/patch.c:913). The main loop's increment,
reinitialize_almost_everything(), resets diff_type = NO_DIFF after every
patch (src/patch.c:199, :717), so the forced type governs only the first
diff. The later diffs are auto-detected, which is why they apply.

Edit: updated line numbers to match Noble's 2.7.6-7build3 source.

** Affects: patch (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2163450

Title:
  forced format (-c) silently discards the first hunk of a unified diff

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/patch/+bug/2163450/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to