The repository state tells in which state the repo is and also which actions are currently allowed. The state MERGING is telling that a commit is not possible. But this is only true in the case of unmerged paths in the index. When we are merging but have resolved all conflicts then we are in a special state: We are still merging (means the next commit should have multiple parents) but a commit is now allowed. Since the MERGING state "canCommit()" cannot be enhanced to return true/false based on the index state (MERGING is an enum value which does not have a reference to the repository its state it is representing) I had to introduce a new state MERGING_RESOLVED. This new state will report that a commit is possible. CAUTION: there might be the chance that users of jgit previously blindly did a plain commit (with only one parent) when the RepositoryState allowed them to do so. With this change these users will now be confronted with a RepositoryState which says a commit is possible but before they can commit they'll have to check the MERGE_MESSAGE and MERGE_HEAD files and use the info from these files. Change-Id: I0a885e2fe8c85049fb23722351ab89cf2c81a431 Signed-off-by: Christian Halstrick <christian.halstrick@sap.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v0.8.1
@@ -186,10 +186,30 @@ public class DirCacheBasicTest extends RepositoryTestCase { | |||
for (int i = 0; i < ents.length; i++) | |||
b.add(ents[i]); | |||
b.finish(); | |||
assertFalse(dc.hasUnmergedPaths()); | |||
assertEquals(paths.length, dc.getEntryCount()); | |||
dc.clear(); | |||
assertEquals(0, dc.getEntryCount()); | |||
assertFalse(dc.hasUnmergedPaths()); | |||
} | |||
public void testDetectUnmergedPaths() throws Exception { | |||
final DirCache dc = DirCache.read(db); | |||
final DirCacheEntry[] ents = new DirCacheEntry[3]; | |||
ents[0] = new DirCacheEntry("a", 1); | |||
ents[0].setFileMode(FileMode.REGULAR_FILE); | |||
ents[1] = new DirCacheEntry("a", 2); | |||
ents[1].setFileMode(FileMode.REGULAR_FILE); | |||
ents[2] = new DirCacheEntry("a", 3); | |||
ents[2].setFileMode(FileMode.REGULAR_FILE); | |||
final DirCacheBuilder b = dc.builder(); | |||
for (int i = 0; i < ents.length; i++) | |||
b.add(ents[i]); | |||
b.finish(); | |||
assertTrue(dc.hasUnmergedPaths()); | |||
} | |||
public void testFindOnEmpty() throws Exception { |
@@ -784,4 +784,20 @@ public class DirCache { | |||
throws UnmergedPathException, IOException { | |||
return getCacheTree(true).writeTree(sortedEntries, 0, 0, ow); | |||
} | |||
/** | |||
* Tells whether this index contains unmerged paths. | |||
* | |||
* @return {@code true} if this index contains unmerged paths. Means: at | |||
* least one entry is of a stage different from 0. {@code false} | |||
* will be returned if all entries are of stage 0. | |||
*/ | |||
public boolean hasUnmergedPaths() { | |||
for (int i = 0; i < entryCnt; i++) { | |||
if (sortedEntries[i].getStage() > 0) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -60,6 +60,7 @@ import java.util.Set; | |||
import java.util.Vector; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import org.eclipse.jgit.dircache.DirCache; | |||
import org.eclipse.jgit.errors.ConfigInvalidException; | |||
import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.RevisionSyntaxException; | |||
@@ -1117,8 +1118,22 @@ public class Repository { | |||
return RepositoryState.REBASING_MERGE; | |||
// Both versions | |||
if (new File(gitDir,"MERGE_HEAD").exists()) | |||
if (new File(gitDir, "MERGE_HEAD").exists()) { | |||
// we are merging - now check whether we have unmerged paths | |||
try { | |||
if (!DirCache.read(this).hasUnmergedPaths()) { | |||
// no unmerged paths -> return the MERGING_RESOLVED state | |||
return RepositoryState.MERGING_RESOLVED; | |||
} | |||
} catch (IOException e) { | |||
// Can't decide whether unmerged paths exists. Return | |||
// MERGING state to be on the safe side (in state MERGING | |||
// you are not allow to do anything) | |||
e.printStackTrace(); | |||
} | |||
return RepositoryState.MERGING; | |||
} | |||
if (new File(gitDir,"BISECT_LOG").exists()) | |||
return RepositoryState.BISECTING; | |||
@@ -73,6 +73,17 @@ public enum RepositoryState { | |||
public String getDescription() { return "Conflicts"; } | |||
}, | |||
/** | |||
* An merge where all conflicts have been resolved. The index does not | |||
* contain any unmerged paths. | |||
*/ | |||
MERGING_RESOLVED { | |||
public boolean canCheckout() { return true; } | |||
public boolean canResetHead() { return true; } | |||
public boolean canCommit() { return true; } | |||
public String getDescription() { return "Merged"; } | |||
}, | |||
/** | |||
* An unfinished rebase or am. Must resolve, skip or abort before normal work can take place | |||
*/ |