Fix a number of failing conflict situations
Adds further tests where the working tree is dirty (differs from index) and where we have staged but uncommitted changes. Fixed the test case 9 for file/directory conflicts. Bug: 428819 Change-Id: Ie44a288b052abe936ebb74272d0fefef3b218a7a Signed-off-by: Axel Richard <axel.richard@obeo.fr> Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com> Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
This commit is contained in:
parent
f7ac527ca7
commit
1a9f122773
|
@ -8,6 +8,8 @@ Bundle-Localization: plugin
|
|||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
Import-Package: org.eclipse.jgit.api;version="[3.4.0,3.5.0)",
|
||||
org.eclipse.jgit.api.errors;version="[3.4.0,3.5.0)",
|
||||
org.eclipse.jgit.diff;version="[3.4.0,3.5.0)",
|
||||
org.eclipse.jgit.dircache;version="[3.4.0,3.5.0)",
|
||||
org.eclipse.jgit.junit;version="[3.4.0,3.5.0)",
|
||||
org.eclipse.jgit.lib;version="[3.4.0,3.5.0)",
|
||||
|
|
|
@ -43,15 +43,21 @@
|
|||
package org.eclipse.jgit.pgm;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.CheckoutConflictException;
|
||||
import org.eclipse.jgit.diff.DiffEntry;
|
||||
import org.eclipse.jgit.lib.CLIRepositoryTestCase;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.treewalk.FileTreeIterator;
|
||||
import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -150,6 +156,7 @@ public void testCheckoutExistingBranchWithConflict() throws Exception {
|
|||
* <li>Delete file 'a' in the working tree
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The working tree should contain 'a' with FileMode.REGULAR_FILE after the
|
||||
* checkout.
|
||||
*
|
||||
|
@ -181,6 +188,359 @@ public void testCheckoutWithMissingWorkingTreeFile() throws Exception {
|
|||
assertEquals("Hello world a", read(fileA));
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add file 'b'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Add folder 'a'
|
||||
* <li>Commit
|
||||
* <li>Replace folder 'a' by file 'a' in the working tree
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The working tree should contain 'a' with FileMode.REGULAR_FILE after the
|
||||
* checkout.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestMissingThenFolderWithFileInWorkingTree()
|
||||
throws Exception {
|
||||
Git git = new Git(db);
|
||||
writeTrashFile("b", "Hello world b");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add file b").call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
File folderA = new File(db.getWorkTree(), "a");
|
||||
FileUtils.mkdirs(folderA);
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add folder a").call();
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.TREE, entry.getMode());
|
||||
|
||||
FileUtils.delete(folderA, FileUtils.RECURSIVE);
|
||||
writeTrashFile("a", "b");
|
||||
|
||||
entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
|
||||
db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
|
||||
entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
|
||||
db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add file 'a'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Replace file 'a' by folder 'a'
|
||||
* <li>Commit
|
||||
* <li>Delete folder 'a' in the working tree
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The working tree should contain 'a' with FileMode.REGULAR_FILE after the
|
||||
* checkout.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestFolderWithMissingInWorkingTree() throws Exception {
|
||||
Git git = new Git(db);
|
||||
writeTrashFile("b", "Hello world b");
|
||||
writeTrashFile("a", "b");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add file b & file a").call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
git.rm().addFilepattern("a").call();
|
||||
File folderA = new File(db.getWorkTree(), "a");
|
||||
FileUtils.mkdirs(folderA);
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add folder a").call();
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.TREE, entry.getMode());
|
||||
|
||||
FileUtils.delete(folderA, FileUtils.RECURSIVE);
|
||||
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
|
||||
entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
|
||||
db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add file 'a'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Delete file 'a'
|
||||
* <li>Commit
|
||||
* <li>Add folder 'a' in the working tree
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The checkout command should raise an error. The conflicting paths are 'a'
|
||||
* and 'a/c'.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestMissingWithFolderInWorkingTree() throws Exception {
|
||||
Git git = new Git(db);
|
||||
writeTrashFile("b", "Hello world b");
|
||||
writeTrashFile("a", "b");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add file b & file a").call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
git.rm().addFilepattern("a").call();
|
||||
git.commit().setMessage("delete file a").call();
|
||||
|
||||
FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.TREE, entry.getMode());
|
||||
|
||||
CheckoutConflictException exception = null;
|
||||
try {
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
} catch (CheckoutConflictException e) {
|
||||
exception = e;
|
||||
}
|
||||
assertNotNull(exception);
|
||||
assertEquals(2, exception.getConflictingPaths().size());
|
||||
assertEquals("a", exception.getConflictingPaths().get(0));
|
||||
assertEquals("a/c", exception.getConflictingPaths().get(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add folder 'a'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Delete folder 'a'
|
||||
* <li>Commit
|
||||
* <li>Add file 'a' in the working tree
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The checkout command should raise an error. The conflicting path is 'a'.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestFolderThenMissingWithFileInWorkingTree()
|
||||
throws Exception {
|
||||
Git git = new Git(db);
|
||||
FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
writeTrashFile("b", "Hello world b");
|
||||
git.add().addFilepattern(".").call();
|
||||
RevCommit commit1 = git.commit().setMessage("add folder a & file b")
|
||||
.call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
git.rm().addFilepattern("a").call();
|
||||
RevCommit commit2 = git.commit().setMessage("delete folder a").call();
|
||||
|
||||
TreeWalk tw = new TreeWalk(db);
|
||||
tw.addTree(commit1.getTree());
|
||||
tw.addTree(commit2.getTree());
|
||||
List<DiffEntry> scan = DiffEntry.scan(tw);
|
||||
assertEquals(1, scan.size());
|
||||
assertEquals(FileMode.MISSING, scan.get(0).getNewMode());
|
||||
assertEquals(FileMode.TREE, scan.get(0).getOldMode());
|
||||
|
||||
writeTrashFile("a", "b");
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
|
||||
CheckoutConflictException exception = null;
|
||||
try {
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
} catch (CheckoutConflictException e) {
|
||||
exception = e;
|
||||
}
|
||||
assertNotNull(exception);
|
||||
assertEquals(1, exception.getConflictingPaths().size());
|
||||
assertEquals("a", exception.getConflictingPaths().get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add folder 'a'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Replace folder 'a'by file 'a'
|
||||
* <li>Commit
|
||||
* <li>Delete file 'a' in the working tree
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The working tree should contain 'a' with FileMode.TREE after the
|
||||
* checkout.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestFolderThenFileWithMissingInWorkingTree()
|
||||
throws Exception {
|
||||
Git git = new Git(db);
|
||||
FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
writeTrashFile("b", "Hello world b");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add folder a & file b").call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
git.rm().addFilepattern("a").call();
|
||||
File fileA = new File(db.getWorkTree(), "a");
|
||||
writeTrashFile("a", "b");
|
||||
git.add().addFilepattern("a").call();
|
||||
git.commit().setMessage("add file a").call();
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
|
||||
FileUtils.delete(fileA);
|
||||
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
|
||||
entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
|
||||
db.getFS());
|
||||
assertEquals(FileMode.TREE, entry.getMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add file 'a'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Modify file 'a'
|
||||
* <li>Commit
|
||||
* <li>Delete file 'a' & replace by folder 'a' in the working tree & index
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The checkout command should raise an error. The conflicting path is 'a'.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestFileThenFileWithFolderInIndex() throws Exception {
|
||||
Git git = new Git(db);
|
||||
writeTrashFile("a", "Hello world a");
|
||||
writeTrashFile("b", "Hello world b");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add files a & b").call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
writeTrashFile("a", "b");
|
||||
git.add().addFilepattern("a").call();
|
||||
git.commit().setMessage("add file a").call();
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
|
||||
git.rm().addFilepattern("a").call();
|
||||
FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
git.add().addFilepattern(".").call();
|
||||
|
||||
entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
|
||||
db.getFS());
|
||||
assertEquals(FileMode.TREE, entry.getMode());
|
||||
|
||||
CheckoutConflictException exception = null;
|
||||
try {
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
} catch (CheckoutConflictException e) {
|
||||
exception = e;
|
||||
}
|
||||
assertNotNull(exception);
|
||||
assertEquals(1, exception.getConflictingPaths().size());
|
||||
assertEquals("a", exception.getConflictingPaths().get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps:
|
||||
* <ol>
|
||||
* <li>Add file 'a'
|
||||
* <li>Commit
|
||||
* <li>Create branch '1'
|
||||
* <li>Modify file 'a'
|
||||
* <li>Commit
|
||||
* <li>Delete file 'a' & replace by folder 'a' in the working tree & index
|
||||
* <li>Checkout branch '1'
|
||||
* </ol>
|
||||
* <p>
|
||||
* The checkout command should raise an error. The conflicting paths are 'a'
|
||||
* and 'a/c'.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void fileModeTestFileWithFolderInIndex() throws Exception {
|
||||
Git git = new Git(db);
|
||||
writeTrashFile("b", "Hello world b");
|
||||
writeTrashFile("a", "b");
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setMessage("add file b & file a").call();
|
||||
Ref branch_1 = git.branchCreate().setName("branch_1").call();
|
||||
git.rm().addFilepattern("a").call();
|
||||
writeTrashFile("a", "Hello world a");
|
||||
git.add().addFilepattern("a").call();
|
||||
git.commit().setMessage("add file a").call();
|
||||
|
||||
FileEntry entry = new FileTreeIterator.FileEntry(new File(
|
||||
db.getWorkTree(), "a"), db.getFS());
|
||||
assertEquals(FileMode.REGULAR_FILE, entry.getMode());
|
||||
|
||||
git.rm().addFilepattern("a").call();
|
||||
FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
|
||||
writeTrashFile("a/c", "Hello world c");
|
||||
git.add().addFilepattern(".").call();
|
||||
|
||||
entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
|
||||
db.getFS());
|
||||
assertEquals(FileMode.TREE, entry.getMode());
|
||||
|
||||
CheckoutConflictException exception = null;
|
||||
try {
|
||||
git.checkout().setName(branch_1.getName()).call();
|
||||
} catch (CheckoutConflictException e) {
|
||||
exception = e;
|
||||
}
|
||||
assertNotNull(exception);
|
||||
assertEquals(1, exception.getConflictingPaths().size());
|
||||
assertEquals("a", exception.getConflictingPaths().get(0));
|
||||
|
||||
// TODO: ideally we'd like to get two paths from this exception
|
||||
// assertEquals(2, exception.getConflictingPaths().size());
|
||||
// assertEquals("a", exception.getConflictingPaths().get(0));
|
||||
// assertEquals("a/c", exception.getConflictingPaths().get(1));
|
||||
}
|
||||
|
||||
static private void assertEquals(Object expected, Object actual) {
|
||||
Assert.assertEquals(expected, actual);
|
||||
}
|
||||
|
|
|
@ -619,7 +619,7 @@ public void testDirectoryFileConflicts_8() throws Exception {
|
|||
@Test
|
||||
public void testDirectoryFileConflicts_9() throws Exception {
|
||||
// 9
|
||||
doit(mk("DF"), mkmap("DF", "QP"), mk("DF/DF"));
|
||||
doit(mkmap("DF", "QP"), mkmap("DF", "QP"), mkmap("DF/DF", "DF/DF"));
|
||||
assertRemoved("DF/DF");
|
||||
assertUpdated("DF");
|
||||
}
|
||||
|
|
|
@ -562,7 +562,7 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m,
|
|||
* 6b D F F N N N N Conflict
|
||||
* 7 F D F Y Y N N Update
|
||||
* 8 F D F N Y N N Conflict
|
||||
* 9 F D F Y N N N Update
|
||||
* 9 F D F N N N Conflict
|
||||
* 10 F D D N N Y Keep
|
||||
* 11 F D D N N N Conflict
|
||||
* 12 F F D Y N Y N Update
|
||||
|
@ -610,7 +610,7 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m,
|
|||
// switch processes all relevant cases.
|
||||
switch (ffMask) {
|
||||
case 0xDDF: // 1 2
|
||||
if (isModified(name)) {
|
||||
if (f != null && isModifiedSubtree_IndexWorkingtree(name)) {
|
||||
conflict(name, dce, h, m); // 1
|
||||
} else {
|
||||
update(name, mId, mMode); // 2
|
||||
|
@ -647,32 +647,29 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m,
|
|||
break;
|
||||
case 0xFDF: // 7 8 9
|
||||
if (equalIdAndMode(hId, hMode, mId, mMode)) {
|
||||
if (isModified(name))
|
||||
if (isModifiedSubtree_IndexWorkingtree(name))
|
||||
conflict(name, dce, h, m); // 8
|
||||
else
|
||||
update(name, mId, mMode); // 7
|
||||
} else if (!isModified(name))
|
||||
update(name, mId, mMode); // 9
|
||||
else
|
||||
// To be confirmed - this case is not in the table.
|
||||
conflict(name, dce, h, m);
|
||||
} else
|
||||
conflict(name, dce, h, m); // 9
|
||||
break;
|
||||
case 0xFD0: // keep without a rule
|
||||
keep(dce);
|
||||
break;
|
||||
case 0xFFD: // 12 13 14
|
||||
if (equalIdAndMode(hId, hMode, iId, iMode))
|
||||
if (f == null
|
||||
|| f.isModified(dce, true,
|
||||
if (f != null
|
||||
&& f.isModified(dce, true,
|
||||
this.walk.getObjectReader()))
|
||||
conflict(name, dce, h, m);
|
||||
conflict(name, dce, h, m); // 13
|
||||
else
|
||||
remove(name);
|
||||
remove(name); // 12
|
||||
else
|
||||
conflict(name, dce, h, m);
|
||||
conflict(name, dce, h, m); // 14
|
||||
break;
|
||||
case 0x0DF: // 16 17
|
||||
if (!isModified(name))
|
||||
if (!isModifiedSubtree_IndexWorkingtree(name))
|
||||
update(name, mId, mMode);
|
||||
else
|
||||
conflict(name, dce, h, m);
|
||||
|
@ -684,12 +681,14 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m,
|
|||
}
|
||||
|
||||
// if we have no file at all then there is nothing to do
|
||||
if ((ffMask & 0x222) == 0)
|
||||
if ((ffMask & 0x222) == 0
|
||||
&& (f == null || FileMode.TREE.equals(f.getEntryFileMode())))
|
||||
return;
|
||||
|
||||
if ((ffMask == 0x00F) && f != null && FileMode.TREE.equals(f.getEntryFileMode())) {
|
||||
// File/Directory conflict case #20
|
||||
conflict(name, null, h, m);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i == null) {
|
||||
|
@ -768,7 +767,9 @@ else if (m == null)
|
|||
* </pre>
|
||||
*/
|
||||
|
||||
if (m == null || equalIdAndMode(mId, mMode, iId, iMode)) {
|
||||
if (m == null
|
||||
|| !isModified_IndexTree(name, iId, iMode, mId, mMode,
|
||||
mergeCommitTree)) {
|
||||
// Merge contains nothing or the same as Index
|
||||
// Nothing in Head
|
||||
// Something in Index
|
||||
|
@ -824,7 +825,7 @@ else if (m == null)
|
|||
* clean I==H I==M H M Result
|
||||
* -----------------------------------------------------
|
||||
* 10 yes yes N/A exists nothing remove path from index
|
||||
* 11 no yes N/A exists nothing fail
|
||||
* 11 no yes N/A exists nothing keep file
|
||||
* 12 yes no N/A exists nothing fail
|
||||
* 13 no no N/A exists nothing fail
|
||||
* </pre>
|
||||
|
@ -841,23 +842,31 @@ else if (m == null)
|
|||
// Something different from a submodule in Index
|
||||
// Nothing in Merge
|
||||
// Something in Head
|
||||
if (equalIdAndMode(hId, hMode, iId, iMode)) {
|
||||
if (!isModified_IndexTree(name, iId, iMode, hId, hMode,
|
||||
headCommitTree)) {
|
||||
// Index contains the same as Head
|
||||
// Something different from a submodule in Index
|
||||
// Nothing in Merge
|
||||
// Something in Head
|
||||
if (f == null
|
||||
|| f.isModified(dce, true,
|
||||
this.walk.getObjectReader()))
|
||||
if (f != null
|
||||
&& f.isModified(dce, true,
|
||||
this.walk.getObjectReader())) {
|
||||
// file is dirty
|
||||
// Index contains the same as Head
|
||||
// Something different from a submodule in Index
|
||||
// Nothing in Merge
|
||||
// Something in Head
|
||||
// -> file is dirty but is should be removed. That's
|
||||
// a conflict
|
||||
conflict(name, dce, h, m);
|
||||
|
||||
if (!FileMode.TREE.equals(f.getEntryFileMode())
|
||||
&& FileMode.TREE.equals(iMode))
|
||||
// The workingtree contains a file and the index semantically contains a folder.
|
||||
// Git considers the workingtree file as untracked. Just keep the untracked file.
|
||||
return;
|
||||
else
|
||||
// -> file is dirty and tracked but is should be
|
||||
// removed. That's a conflict
|
||||
conflict(name, dce, h, m);
|
||||
} else
|
||||
// file doesn't exist or is clean
|
||||
// Index contains the same as Head
|
||||
// Something different from a submodule in Index
|
||||
|
@ -880,8 +889,10 @@ else if (m == null)
|
|||
// Something in Head
|
||||
// Something in Index
|
||||
if (!equalIdAndMode(hId, hMode, mId, mMode)
|
||||
&& !equalIdAndMode(hId, hMode, iId, iMode)
|
||||
&& !equalIdAndMode(mId, mMode, iId, iMode))
|
||||
&& isModified_IndexTree(name, iId, iMode, hId, hMode,
|
||||
headCommitTree)
|
||||
&& isModified_IndexTree(name, iId, iMode, mId, mMode,
|
||||
mergeCommitTree))
|
||||
// All three contents in Head, Merge, Index differ from each
|
||||
// other
|
||||
// -> All contents differ. Report a conflict.
|
||||
|
@ -893,8 +904,10 @@ else if (m == null)
|
|||
// Something in Head
|
||||
// Something in Index
|
||||
|
||||
if (equalIdAndMode(hId, hMode, iId, iMode)
|
||||
&& !equalIdAndMode(mId, mMode, iId, iMode)) {
|
||||
if (!isModified_IndexTree(name, iId, iMode, hId, hMode,
|
||||
headCommitTree)
|
||||
&& isModified_IndexTree(name, iId, iMode, mId, mMode,
|
||||
mergeCommitTree)) {
|
||||
// Head contains the same as Index. Merge differs
|
||||
// Something in Merge
|
||||
|
||||
|
@ -1036,15 +1049,26 @@ private void cleanUpConflicts() throws CheckoutConflictException {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isModified(String path) throws CorruptObjectException, IOException {
|
||||
/**
|
||||
* Checks whether the subtree starting at a given path differs between Index and
|
||||
* workingtree.
|
||||
*
|
||||
* @param path
|
||||
* @return true if the subtrees differ
|
||||
* @throws CorruptObjectException
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean isModifiedSubtree_IndexWorkingtree(String path)
|
||||
throws CorruptObjectException, IOException {
|
||||
NameConflictTreeWalk tw = new NameConflictTreeWalk(repo);
|
||||
try {
|
||||
tw.addTree(new DirCacheIterator(dc));
|
||||
tw.addTree(new FileTreeIterator(repo));
|
||||
tw.setRecursive(true);
|
||||
tw.setFilter(PathFilter.create(path));
|
||||
DirCacheIterator dcIt;
|
||||
WorkingTreeIterator wtIt;
|
||||
while(tw.next()) {
|
||||
while (tw.next()) {
|
||||
dcIt = tw.getTree(0, DirCacheIterator.class);
|
||||
wtIt = tw.getTree(1, WorkingTreeIterator.class);
|
||||
if (dcIt == null || wtIt == null)
|
||||
|
@ -1055,6 +1079,58 @@ private boolean isModified(String path) throws CorruptObjectException, IOExcepti
|
|||
}
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
tw.release();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isModified_IndexTree(String path, ObjectId iId,
|
||||
FileMode iMode, ObjectId tId, FileMode tMode, ObjectId rootTree)
|
||||
throws CorruptObjectException, IOException {
|
||||
if (iMode != tMode)
|
||||
return true;
|
||||
if (FileMode.TREE.equals(iMode)
|
||||
&& (iId == null || ObjectId.zeroId().equals(iId)))
|
||||
return isModifiedSubtree_IndexTree(path, rootTree);
|
||||
else
|
||||
return !equalIdAndMode(iId, iMode, tId, tMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the subtree starting at a given path differs between Index and
|
||||
* some tree.
|
||||
*
|
||||
* @param path
|
||||
* @param tree
|
||||
* the tree to compare
|
||||
* @return true if the subtrees differ
|
||||
* @throws CorruptObjectException
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean isModifiedSubtree_IndexTree(String path, ObjectId tree)
|
||||
throws CorruptObjectException, IOException {
|
||||
NameConflictTreeWalk tw = new NameConflictTreeWalk(repo);
|
||||
try {
|
||||
tw.addTree(new DirCacheIterator(dc));
|
||||
tw.addTree(tree);
|
||||
tw.setRecursive(true);
|
||||
tw.setFilter(PathFilter.create(path));
|
||||
while (tw.next()) {
|
||||
AbstractTreeIterator dcIt = tw.getTree(0,
|
||||
DirCacheIterator.class);
|
||||
AbstractTreeIterator treeIt = tw.getTree(1,
|
||||
AbstractTreeIterator.class);
|
||||
if (dcIt == null || treeIt == null)
|
||||
return true;
|
||||
if (dcIt.getEntryRawMode() != treeIt.getEntryRawMode())
|
||||
return true;
|
||||
if (!dcIt.getEntryObjectId().equals(treeIt.getEntryObjectId()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
tw.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -832,6 +832,8 @@ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
|
|||
*/
|
||||
public boolean isModified(DirCacheEntry entry, boolean forceContentCheck,
|
||||
ObjectReader reader) throws IOException {
|
||||
if (entry == null)
|
||||
return !FileMode.MISSING.equals(getEntryFileMode());
|
||||
MetadataDiff diff = compareMetadata(entry);
|
||||
switch (diff) {
|
||||
case DIFFER_BY_TIMESTAMP:
|
||||
|
|
Loading…
Reference in New Issue