PatchApplier fix - init cache with provided tree

This change only affects inCore repositories.
Before this change, any file that wasn't part of the patch
wasn't read, and therefore wasn't part of the output tree.

Change-Id: I246ef957088f17aaf367143f7a0b3af0f8264ffb
Bug: Google b/267270348
This commit is contained in:
Nitzan Gur-Furman 2023-01-31 22:01:21 +01:00
parent eb3a708676
commit a399bd13b1
5 changed files with 47 additions and 22 deletions

View File

@ -24,6 +24,7 @@
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.PatchApplyException; import org.eclipse.jgit.api.errors.PatchApplyException;
import org.eclipse.jgit.api.errors.PatchFormatException; import org.eclipse.jgit.api.errors.PatchFormatException;
@ -71,27 +72,21 @@ public abstract static class Base extends RepositoryTestCase {
this.inCore = inCore; this.inCore = inCore;
} }
void init(final String aName) throws Exception {
init(aName, true, true);
}
protected void init(String aName, boolean preExists, boolean postExists) protected void init(String aName, boolean preExists, boolean postExists)
throws Exception { throws Exception {
// Patch and pre/postimage are read from data // Patch and pre/postimage are read from data
// org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ // org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/
this.name = aName; this.name = aName;
if (postExists) { if (postExists) {
postImage = IO expectedText = initPostImage(aName);
.readWholeStream(getTestResource(name + "_PostImage"), 0)
.array();
expectedText = new String(postImage, StandardCharsets.UTF_8);
} }
File f = new File(db.getWorkTree(), name);
if (preExists) { if (preExists) {
preImage = IO initPreImage(aName);
.readWholeStream(getTestResource(name + "_PreImage"), 0)
.array();
try (Git git = new Git(db)) {
Files.write(f.toPath(), preImage);
git.add().addFilepattern(name).call();
}
} }
try (Git git = new Git(db)) { try (Git git = new Git(db)) {
RevCommit base = git.commit().setMessage("PreImage").call(); RevCommit base = git.commit().setMessage("PreImage").call();
@ -99,8 +94,22 @@ protected void init(String aName, boolean preExists, boolean postExists)
} }
} }
void init(final String aName) throws Exception { protected void initPreImage(String aName) throws Exception {
init(aName, true, true); File f = new File(db.getWorkTree(), aName);
preImage = IO
.readWholeStream(getTestResource(aName + "_PreImage"), 0)
.array();
try (Git git = new Git(db)) {
Files.write(f.toPath(), preImage);
git.add().addFilepattern(aName).call();
}
}
protected String initPostImage(String aName) throws Exception {
postImage = IO
.readWholeStream(getTestResource(aName + "_PostImage"), 0)
.array();
return new String(postImage, StandardCharsets.UTF_8);
} }
protected Result applyPatch() protected Result applyPatch()
@ -118,27 +127,33 @@ protected static InputStream getTestResource(String patchFile) {
return PatchApplierTest.class.getClassLoader() return PatchApplierTest.class.getClassLoader()
.getResourceAsStream("org/eclipse/jgit/diff/" + patchFile); .getResourceAsStream("org/eclipse/jgit/diff/" + patchFile);
} }
void verifyChange(Result result, String aName) throws Exception { void verifyChange(Result result, String aName) throws Exception {
verifyChange(result, aName, true); verifyChange(result, aName, true);
} }
protected void verifyContent(Result result, String path, boolean exists) protected void verifyContent(Result result, String path, boolean exists)
throws Exception { throws Exception {
verifyContent(result, path, exists ? expectedText : null);
}
protected void verifyContent(Result result, String path,
@Nullable String expectedContent) throws Exception {
if (inCore) { if (inCore) {
byte[] output = readBlob(result.getTreeId(), path); byte[] output = readBlob(result.getTreeId(), path);
if (!exists) if (expectedContent == null)
assertNull(output); assertNull(output);
else { else {
assertNotNull(output); assertNotNull(output);
assertEquals(expectedText, assertEquals(expectedContent,
new String(output, StandardCharsets.UTF_8)); new String(output, StandardCharsets.UTF_8));
} }
} else { } else {
File f = new File(db.getWorkTree(), path); File f = new File(db.getWorkTree(), path);
if (!exists) if (expectedContent == null)
assertFalse(f.exists()); assertFalse(f.exists());
else else
checkFile(f, expectedText); checkFile(f, expectedContent);
} }
} }
@ -154,7 +169,7 @@ protected byte[] readBlob(ObjectId treeish, String path)
RevWalk rw = tr.getRevWalk()) { RevWalk rw = tr.getRevWalk()) {
db.incrementOpen(); db.incrementOpen();
RevTree tree = rw.parseTree(treeish); RevTree tree = rw.parseTree(treeish);
try (TreeWalk tw = TreeWalk.forPath(db,path,tree)){ try (TreeWalk tw = TreeWalk.forPath(db, path, tree)) {
if (tw == null) { if (tw == null) {
return null; return null;
} }
@ -300,7 +315,7 @@ public void testRenameNoHunks() throws Exception {
assertTrue(result.getPaths().contains("RenameNoHunks")); assertTrue(result.getPaths().contains("RenameNoHunks"));
assertTrue(result.getPaths().contains("nested/subdir/Renamed")); assertTrue(result.getPaths().contains("nested/subdir/Renamed"));
verifyContent(result,"nested/subdir/Renamed", true); verifyContent(result, "nested/subdir/Renamed", true);
} }
@Test @Test
@ -312,7 +327,7 @@ public void testRenameWithHunks() throws Exception {
assertTrue(result.getPaths().contains("RenameWithHunks")); assertTrue(result.getPaths().contains("RenameWithHunks"));
assertTrue(result.getPaths().contains("nested/subdir/Renamed")); assertTrue(result.getPaths().contains("nested/subdir/Renamed"));
verifyContent(result,"nested/subdir/Renamed", true); verifyContent(result, "nested/subdir/Renamed", true);
} }
@Test @Test
@ -355,6 +370,16 @@ public void testShiftDown2() throws Exception {
verifyChange(result, "ShiftDown2"); verifyChange(result, "ShiftDown2");
} }
@Test
public void testDoesNotAffectUnrelatedFiles() throws Exception {
initPreImage("Unaffected");
String expectedUnaffectedText = initPostImage("Unaffected");
init("X");
Result result = applyPatch();
verifyChange(result, "X");
verifyContent(result, "Unaffected", expectedUnaffectedText);
}
} }
public static class InCore extends Base { public static class InCore extends Base {

View File

@ -194,7 +194,7 @@ public Result applyPatch(InputStream patchInput)
throw new PatchFormatException(p.getErrors()); throw new PatchFormatException(p.getErrors());
} }
DirCache dirCache = (inCore()) ? DirCache.newInCore() DirCache dirCache = inCore() ? DirCache.read(reader, beforeTree)
: repo.lockDirCache(); : repo.lockDirCache();
DirCacheBuilder dirCacheBuilder = dirCache.builder(); DirCacheBuilder dirCacheBuilder = dirCache.builder();