Fix PatchUtil for parsing special patch format
`diff` generate incomplete header for adding or removing one line file.
Eg.
"""
--- foo
+++ bar
@@ -1 +0,0 @@ # Should be @@ -1,1 +0,0 @@
-hello, world
"""
We set the default value to 1 when the size info is missing.
Similar logic in `git apply` implementation:
https://github.com/git/git/blob/5fa0f5238b0cd46cfe7f6fa76c3f526ea98148d9/apply.c#L1400
Fixes https://github.com/bazelbuild/bazel/issues/9222
RELNOTES: None
PiperOrigin-RevId: 264799477
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/PatchUtil.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/PatchUtil.java
index cd3a4f5..8c0a2da 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/PatchUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/PatchUtil.java
@@ -64,8 +64,11 @@
ChunkHeader(String header) throws PatchFailedException {
Matcher m = CHUNK_HEADER_RE.matcher(header);
if (m.find()) {
- oldSize = Integer.parseInt(m.group(2));
- newSize = Integer.parseInt(m.group(4));
+ String size;
+ size = m.group(2);
+ oldSize = (size == null) ? 1 : Integer.parseInt(size);
+ size = m.group(4);
+ newSize = (size == null) ? 1 : Integer.parseInt(size);
} else {
throw new PatchFailedException("Wrong chunk header: " + header);
}
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/PatchUtilTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/PatchUtilTest.java
index dd00c57..5fbcace 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/PatchUtilTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/PatchUtilTest.java
@@ -66,6 +66,24 @@
}
@Test
+ public void testAddOneLineFile() throws IOException, PatchFailedException {
+ Path patchFile =
+ scratch.file(
+ "/root/patchfile",
+ "diff --git a/newfile b/newfile",
+ "new file mode 100644",
+ "index 0000000..f742c88",
+ "--- /dev/null",
+ "+++ b/newfile",
+ "@@ -0,0 +1 @@", // diff will produce such chunk header for one line file.
+ "+hello, world");
+ PatchUtil.apply(patchFile, 1, root);
+ Path newFile = root.getRelative("newfile");
+ ImmutableList<String> newFileContent = ImmutableList.of("hello, world");
+ assertThat(PatchUtil.readFile(newFile)).containsExactlyElementsIn(newFileContent);
+ }
+
+ @Test
public void testDeleteFile() throws IOException, PatchFailedException {
Path oldFile = scratch.file("/root/oldfile", "I'm an old file", "bye, world");
Path patchFile =
@@ -81,6 +99,20 @@
}
@Test
+ public void testDeleteOneLineFile() throws IOException, PatchFailedException {
+ Path oldFile = scratch.file("/root/oldfile", "bye, world");
+ Path patchFile =
+ scratch.file(
+ "/root/patchfile",
+ "--- a/oldfile",
+ "+++ /dev/null",
+ "@@ -1 +0,0 @@", // diff will produce such chunk header for one line file.
+ "-bye, world");
+ PatchUtil.apply(patchFile, 1, root);
+ assertThat(oldFile.exists()).isFalse();
+ }
+
+ @Test
public void testDeleteAllContentButNotFile() throws IOException, PatchFailedException {
// If newfile is not /dev/null, we don't delete the file even it's empty after patching,
// this is the behavior of patch command line tool.