CommitCommand: Ensure unmerged paths are added correctly with setOnly
With bug 391855, PathEdit will be changed to apply an edit for each stage. With that, CommitCommand would no longer work correctly when committing an unmerged path. This changes it to use a DirCacheBuilder which allows us to correctly replace the entries for the three stages with one, which is not possible with PathEdit. Bug: 391859 Change-Id: I6dc180aec7e2cbf8d1e91f50482c95bc420f79de
This commit is contained in:
parent
106e8b8762
commit
0f88d7b72f
|
@ -55,6 +55,8 @@
|
||||||
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
||||||
import org.eclipse.jgit.diff.DiffEntry;
|
import org.eclipse.jgit.diff.DiffEntry;
|
||||||
import org.eclipse.jgit.dircache.DirCache;
|
import org.eclipse.jgit.dircache.DirCache;
|
||||||
|
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||||
|
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||||
import org.eclipse.jgit.lib.ConfigConstants;
|
import org.eclipse.jgit.lib.ConfigConstants;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.FileMode;
|
import org.eclipse.jgit.lib.FileMode;
|
||||||
|
@ -471,4 +473,56 @@ public void commitAmendWithAuthorShouldUseIt() throws Exception {
|
||||||
assertEquals("New Author", amendedAuthor.getName());
|
assertEquals("New Author", amendedAuthor.getName());
|
||||||
assertEquals("newauthor@example.org", amendedAuthor.getEmailAddress());
|
assertEquals("newauthor@example.org", amendedAuthor.getEmailAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void commitOnlyShouldCommitUnmergedPathAndNotAffectOthers()
|
||||||
|
throws Exception {
|
||||||
|
DirCache index = db.lockDirCache();
|
||||||
|
DirCacheBuilder builder = index.builder();
|
||||||
|
addUnmergedEntry("unmerged1", builder);
|
||||||
|
addUnmergedEntry("unmerged2", builder);
|
||||||
|
DirCacheEntry other = new DirCacheEntry("other");
|
||||||
|
other.setFileMode(FileMode.REGULAR_FILE);
|
||||||
|
builder.add(other);
|
||||||
|
builder.commit();
|
||||||
|
|
||||||
|
writeTrashFile("unmerged1", "unmerged1 data");
|
||||||
|
writeTrashFile("unmerged2", "unmerged2 data");
|
||||||
|
writeTrashFile("other", "other data");
|
||||||
|
|
||||||
|
assertEquals("[other, mode:100644]"
|
||||||
|
+ "[unmerged1, mode:100644, stage:1]"
|
||||||
|
+ "[unmerged1, mode:100644, stage:2]"
|
||||||
|
+ "[unmerged1, mode:100644, stage:3]"
|
||||||
|
+ "[unmerged2, mode:100644, stage:1]"
|
||||||
|
+ "[unmerged2, mode:100644, stage:2]"
|
||||||
|
+ "[unmerged2, mode:100644, stage:3]",
|
||||||
|
indexState(0));
|
||||||
|
|
||||||
|
Git git = new Git(db);
|
||||||
|
RevCommit commit = git.commit().setOnly("unmerged1")
|
||||||
|
.setMessage("Only one file").call();
|
||||||
|
|
||||||
|
assertEquals("[other, mode:100644]" + "[unmerged1, mode:100644]"
|
||||||
|
+ "[unmerged2, mode:100644, stage:1]"
|
||||||
|
+ "[unmerged2, mode:100644, stage:2]"
|
||||||
|
+ "[unmerged2, mode:100644, stage:3]",
|
||||||
|
indexState(0));
|
||||||
|
|
||||||
|
TreeWalk walk = TreeWalk.forPath(db, "unmerged1", commit.getTree());
|
||||||
|
assertEquals(FileMode.REGULAR_FILE, walk.getFileMode(0));
|
||||||
|
walk.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addUnmergedEntry(String file, DirCacheBuilder builder) {
|
||||||
|
DirCacheEntry stage1 = new DirCacheEntry(file, DirCacheEntry.STAGE_1);
|
||||||
|
DirCacheEntry stage2 = new DirCacheEntry(file, DirCacheEntry.STAGE_2);
|
||||||
|
DirCacheEntry stage3 = new DirCacheEntry(file, DirCacheEntry.STAGE_3);
|
||||||
|
stage1.setFileMode(FileMode.REGULAR_FILE);
|
||||||
|
stage2.setFileMode(FileMode.REGULAR_FILE);
|
||||||
|
stage3.setFileMode(FileMode.REGULAR_FILE);
|
||||||
|
builder.add(stage1);
|
||||||
|
builder.add(stage2);
|
||||||
|
builder.add(stage3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,10 +58,8 @@
|
||||||
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
||||||
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
||||||
import org.eclipse.jgit.dircache.DirCache;
|
import org.eclipse.jgit.dircache.DirCache;
|
||||||
|
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
|
||||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||||
import org.eclipse.jgit.dircache.DirCacheEditor;
|
|
||||||
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
|
|
||||||
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
|
||||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||||
import org.eclipse.jgit.dircache.DirCacheIterator;
|
import org.eclipse.jgit.dircache.DirCacheIterator;
|
||||||
import org.eclipse.jgit.errors.UnmergedPathException;
|
import org.eclipse.jgit.errors.UnmergedPathException;
|
||||||
|
@ -298,25 +296,26 @@ private DirCache createTemporaryIndex(ObjectId headId, DirCache index)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ObjectInserter inserter = null;
|
ObjectInserter inserter = null;
|
||||||
|
|
||||||
// get DirCacheEditor to modify the index if required
|
// get DirCacheBuilder for existing index
|
||||||
DirCacheEditor dcEditor = index.editor();
|
DirCacheBuilder existingBuilder = index.builder();
|
||||||
|
|
||||||
// get DirCacheBuilder for newly created in-core index to build a
|
// get DirCacheBuilder for newly created in-core index to build a
|
||||||
// temporary index for this commit
|
// temporary index for this commit
|
||||||
DirCache inCoreIndex = DirCache.newInCore();
|
DirCache inCoreIndex = DirCache.newInCore();
|
||||||
DirCacheBuilder dcBuilder = inCoreIndex.builder();
|
DirCacheBuilder tempBuilder = inCoreIndex.builder();
|
||||||
|
|
||||||
onlyProcessed = new boolean[only.size()];
|
onlyProcessed = new boolean[only.size()];
|
||||||
boolean emptyCommit = true;
|
boolean emptyCommit = true;
|
||||||
|
|
||||||
TreeWalk treeWalk = new TreeWalk(repo);
|
TreeWalk treeWalk = new TreeWalk(repo);
|
||||||
int dcIdx = treeWalk.addTree(new DirCacheIterator(index));
|
int dcIdx = treeWalk.addTree(new DirCacheBuildIterator(existingBuilder));
|
||||||
int fIdx = treeWalk.addTree(new FileTreeIterator(repo));
|
int fIdx = treeWalk.addTree(new FileTreeIterator(repo));
|
||||||
int hIdx = -1;
|
int hIdx = -1;
|
||||||
if (headId != null)
|
if (headId != null)
|
||||||
hIdx = treeWalk.addTree(new RevWalk(repo).parseTree(headId));
|
hIdx = treeWalk.addTree(new RevWalk(repo).parseTree(headId));
|
||||||
treeWalk.setRecursive(true);
|
treeWalk.setRecursive(true);
|
||||||
|
|
||||||
|
String lastAddedFile = null;
|
||||||
while (treeWalk.next()) {
|
while (treeWalk.next()) {
|
||||||
String path = treeWalk.getPathString();
|
String path = treeWalk.getPathString();
|
||||||
// check if current entry's path matches a specified path
|
// check if current entry's path matches a specified path
|
||||||
|
@ -326,11 +325,12 @@ private DirCache createTemporaryIndex(ObjectId headId, DirCache index)
|
||||||
if (hIdx != -1)
|
if (hIdx != -1)
|
||||||
hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
|
hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
|
||||||
|
|
||||||
|
DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
|
||||||
|
DirCacheIterator.class);
|
||||||
|
|
||||||
if (pos >= 0) {
|
if (pos >= 0) {
|
||||||
// include entry in commit
|
// include entry in commit
|
||||||
|
|
||||||
DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
|
|
||||||
DirCacheIterator.class);
|
|
||||||
FileTreeIterator fTree = treeWalk.getTree(fIdx,
|
FileTreeIterator fTree = treeWalk.getTree(fIdx,
|
||||||
FileTreeIterator.class);
|
FileTreeIterator.class);
|
||||||
|
|
||||||
|
@ -339,6 +339,13 @@ private DirCache createTemporaryIndex(ObjectId headId, DirCache index)
|
||||||
if (!tracked)
|
if (!tracked)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// for an unmerged path, DirCacheBuildIterator will yield 3
|
||||||
|
// entries, we only want to add one
|
||||||
|
if (path.equals(lastAddedFile))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lastAddedFile = path;
|
||||||
|
|
||||||
if (fTree != null) {
|
if (fTree != null) {
|
||||||
// create a new DirCacheEntry with data retrieved from disk
|
// create a new DirCacheEntry with data retrieved from disk
|
||||||
final DirCacheEntry dcEntry = new DirCacheEntry(path);
|
final DirCacheEntry dcEntry = new DirCacheEntry(path);
|
||||||
|
@ -371,15 +378,10 @@ private DirCache createTemporaryIndex(ObjectId headId, DirCache index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update index
|
// add to existing index
|
||||||
dcEditor.add(new PathEdit(path) {
|
existingBuilder.add(dcEntry);
|
||||||
@Override
|
|
||||||
public void apply(DirCacheEntry ent) {
|
|
||||||
ent.copyMetaData(dcEntry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// add to temporary in-core index
|
// add to temporary in-core index
|
||||||
dcBuilder.add(dcEntry);
|
tempBuilder.add(dcEntry);
|
||||||
|
|
||||||
if (emptyCommit
|
if (emptyCommit
|
||||||
&& (hTree == null || !hTree.idEqual(fTree) || hTree
|
&& (hTree == null || !hTree.idEqual(fTree) || hTree
|
||||||
|
@ -388,9 +390,8 @@ public void apply(DirCacheEntry ent) {
|
||||||
// this is a change
|
// this is a change
|
||||||
emptyCommit = false;
|
emptyCommit = false;
|
||||||
} else {
|
} else {
|
||||||
// if no file exists on disk, remove entry from index and
|
// if no file exists on disk, neither add it to
|
||||||
// don't add it to temporary in-core index
|
// index nor to temporary in-core index
|
||||||
dcEditor.add(new DeletePath(path));
|
|
||||||
|
|
||||||
if (emptyCommit && hTree != null)
|
if (emptyCommit && hTree != null)
|
||||||
// this is a change
|
// this is a change
|
||||||
|
@ -408,8 +409,12 @@ public void apply(DirCacheEntry ent) {
|
||||||
dcEntry.setFileMode(hTree.getEntryFileMode());
|
dcEntry.setFileMode(hTree.getEntryFileMode());
|
||||||
|
|
||||||
// add to temporary in-core index
|
// add to temporary in-core index
|
||||||
dcBuilder.add(dcEntry);
|
tempBuilder.add(dcEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preserve existing entry in index
|
||||||
|
if (dcTree != null)
|
||||||
|
existingBuilder.add(dcTree.getDirCacheEntry());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,9 +430,9 @@ public void apply(DirCacheEntry ent) {
|
||||||
throw new JGitInternalException(JGitText.get().emptyCommit);
|
throw new JGitInternalException(JGitText.get().emptyCommit);
|
||||||
|
|
||||||
// update index
|
// update index
|
||||||
dcEditor.commit();
|
existingBuilder.commit();
|
||||||
// finish temporary in-core index used for this commit
|
// finish temporary in-core index used for this commit
|
||||||
dcBuilder.finish();
|
tempBuilder.finish();
|
||||||
return inCoreIndex;
|
return inCoreIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue