aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Stocker2012-10-20 16:00:13 (EDT)
committerRobin Stocker2012-11-12 16:51:18 (EST)
commit0f88d7b72ff09297954930cbe2a23cf8feff9382 (patch)
treeef4358f7897c96fff2215f4b8c3e58dfac92920a
parent106e8b87625cd1ad6b2cec14d676c23174422352 (diff)
downloadjgit-0f88d7b72ff09297954930cbe2a23cf8feff9382.zip
jgit-0f88d7b72ff09297954930cbe2a23cf8feff9382.tar.gz
jgit-0f88d7b72ff09297954930cbe2a23cf8feff9382.tar.bz2
CommitCommand: Ensure unmerged paths are added correctly with setOnlyrefs/changes/23/8323/2
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
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java54
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java51
2 files changed, 82 insertions, 23 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
index 3e73c75..45f312f 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
@@ -55,6 +55,8 @@ import java.util.TimeZone;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.diff.DiffEntry;
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.Constants;
import org.eclipse.jgit.lib.FileMode;
@@ -471,4 +473,56 @@ public class CommitCommandTest extends RepositoryTestCase {
assertEquals("New Author", amendedAuthor.getName());
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);
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index ee92083..eab2e8d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -58,10 +58,8 @@ import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.api.errors.UnmergedPathsException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheBuildIterator;
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.DirCacheIterator;
import org.eclipse.jgit.errors.UnmergedPathException;
@@ -298,25 +296,26 @@ public class CommitCommand extends GitCommand<RevCommit> {
throws IOException {
ObjectInserter inserter = null;
- // get DirCacheEditor to modify the index if required
- DirCacheEditor dcEditor = index.editor();
+ // get DirCacheBuilder for existing index
+ DirCacheBuilder existingBuilder = index.builder();
// get DirCacheBuilder for newly created in-core index to build a
// temporary index for this commit
DirCache inCoreIndex = DirCache.newInCore();
- DirCacheBuilder dcBuilder = inCoreIndex.builder();
+ DirCacheBuilder tempBuilder = inCoreIndex.builder();
onlyProcessed = new boolean[only.size()];
boolean emptyCommit = true;
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 hIdx = -1;
if (headId != null)
hIdx = treeWalk.addTree(new RevWalk(repo).parseTree(headId));
treeWalk.setRecursive(true);
+ String lastAddedFile = null;
while (treeWalk.next()) {
String path = treeWalk.getPathString();
// check if current entry's path matches a specified path
@@ -326,11 +325,12 @@ public class CommitCommand extends GitCommand<RevCommit> {
if (hIdx != -1)
hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
+ DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
+ DirCacheIterator.class);
+
if (pos >= 0) {
// include entry in commit
- DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
- DirCacheIterator.class);
FileTreeIterator fTree = treeWalk.getTree(fIdx,
FileTreeIterator.class);
@@ -339,6 +339,13 @@ public class CommitCommand extends GitCommand<RevCommit> {
if (!tracked)
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) {
// create a new DirCacheEntry with data retrieved from disk
final DirCacheEntry dcEntry = new DirCacheEntry(path);
@@ -371,15 +378,10 @@ public class CommitCommand extends GitCommand<RevCommit> {
}
}
- // update index
- dcEditor.add(new PathEdit(path) {
- @Override
- public void apply(DirCacheEntry ent) {
- ent.copyMetaData(dcEntry);
- }
- });
+ // add to existing index
+ existingBuilder.add(dcEntry);
// add to temporary in-core index
- dcBuilder.add(dcEntry);
+ tempBuilder.add(dcEntry);
if (emptyCommit
&& (hTree == null || !hTree.idEqual(fTree) || hTree
@@ -388,9 +390,8 @@ public class CommitCommand extends GitCommand<RevCommit> {
// this is a change
emptyCommit = false;
} else {
- // if no file exists on disk, remove entry from index and
- // don't add it to temporary in-core index
- dcEditor.add(new DeletePath(path));
+ // if no file exists on disk, neither add it to
+ // index nor to temporary in-core index
if (emptyCommit && hTree != null)
// this is a change
@@ -408,8 +409,12 @@ public class CommitCommand extends GitCommand<RevCommit> {
dcEntry.setFileMode(hTree.getEntryFileMode());
// 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 class CommitCommand extends GitCommand<RevCommit> {
throw new JGitInternalException(JGitText.get().emptyCommit);
// update index
- dcEditor.commit();
+ existingBuilder.commit();
// finish temporary in-core index used for this commit
- dcBuilder.finish();
+ tempBuilder.finish();
return inCoreIndex;
}