// file only exists in working tree -> ignore it
return;
}
ObjectId iId = (i == null ? null : i.getEntryObjectId());
ObjectId mId = (m == null ? null : m.getEntryObjectId());
ObjectId hId = (h == null ? null : h.getEntryObjectId());
/**
* <pre>
* File/Directory conflicts:
* the following table from ReadTreeTest tells what to do in case of directory/file
* conflicts. I give comments here
*
* H I M Clean H==M H==I I==M Result
* ------------------------------------------------------------------
* 1 D D F Y N Y N Update
* 2 D D F N N Y N Conflict
* 3 D F D Y N N Update
* 4 D F D N N N Update
* 5 D F F Y N N Y Keep
* 6 D F F N N N Y Keep
* 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
* 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
* 13 F F D N N Y N Conflict
* 14 F F D N N N Conflict
* 15 0 F D N N N Conflict
* 16 0 D F Y N N N Update
* 17 0 D F N N N Conflict
* 18 F 0 D Update
* 19 D 0 F Update
* 20 0 0 F N (worktree=dir) Conflict
* </pre>
*/
// The information whether head,index,merge iterators are currently
// pointing to file/folder/non-existing is encoded into this variable.
//
// To decode write down ffMask in hexadecimal form. The last digit
// represents the state for the merge iterator, the second last the
// state for the index iterator and the third last represents the state
// for the head iterator. The hexadecimal constant "F" stands for
// "file",
// an "D" stands for "directory" (tree), and a "0" stands for
// non-existing
//
// Examples:
// ffMask == 0xFFD -> Head=File, Index=File, Merge=Tree
// ffMask == 0xDD0 -> Head=Tree, Index=Tree, Merge=Non-Existing
int ffMask = 0;
if (h != null)
ffMask = FileMode.TREE.equals(h.getEntryFileMode()) ? 0xD00 : 0xF00;
if (i != null)
ffMask |= FileMode.TREE.equals(i.getEntryFileMode()) ? 0x0D0
: 0x0F0;
if (m != null)
ffMask |= FileMode.TREE.equals(m.getEntryFileMode()) ? 0x00D
: 0x00F;
// Check whether we have a possible file/folder conflict. Therefore we
// need a least one file and one folder.
if (((ffMask & 0x222) != 0x000)
&& (((ffMask & 0x00F) == 0x00D) || ((ffMask & 0x0F0) == 0x0D0) || ((ffMask & 0xF00) == 0xD00))) {
// There are 3*3*3=27 possible combinations of file/folder
// conflicts. Some of them are not-relevant because
// they represent no conflict, e.g. 0xFFF, 0xDDD, ... The following
// switch processes all relevant cases.
switch (ffMask) {
case 0xDDF: // 1 2
if (isModified(name)) {
conflict(name, i.getDirCacheEntry(), h, m); // 1
} else {
update(name, m.getEntryObjectId(), m.getEntryFileMode()); // 2
}
break;
case 0xDFD: // 3 4
// CAUTION: I put it into removed instead of updated, because
// that's what our tests expect
// updated.put(name, mId);
remove(name);
break;
case 0xF0D: // 18
remove(name);
break;
case 0xDFF: // 5 6
case 0xFDD: // 10 11
// TODO: make use of tree extension as soon as available in jgit
// we would like to do something like
// if (!iId.equals(mId))
// conflict(name, i.getDirCacheEntry(), h, m);
// But since we don't know the id of a tree in the index we do
// nothing here and wait that conflicts between index and merge
// are found later
break;
case 0xD0F: // 19
update(name, mId, m.getEntryFileMode());
break;
case 0xDF0: // conflict without a rule
case 0x0FD: // 15
conflict(name, (i != null) ? i.getDirCacheEntry() : null, h, m);
break;
case 0xFDF: // 7 8 9
if (hId.equals(mId)) {
if (isModified(name))
conflict(name, i.getDirCacheEntry(), h, m); // 8
else
update(name, mId, m.getEntryFileMode()); // 7
} else if (!isModified(name))
update(name, mId, m.getEntryFileMode()); // 9
else
// To be confirmed - this case is not in the table.
conflict(name, i.getDirCacheEntry(), h, m);
break;
case 0xFD0: // keep without a rule
keep(i.getDirCacheEntry());
break;
case 0xFFD: // 12 13 14
if (hId.equals(iId)) {
dce = i.getDirCacheEntry();
if (f == null || f.isModified(dce, true))
conflict(name, i.getDirCacheEntry(), h, m);
else
remove(name);
} else
conflict(name, i.getDirCacheEntry(), h, m);
break;
case 0x0DF: // 16 17
if (!isModified(name))
update(name, mId, m.getEntryFileMode());
else
conflict(name, i.getDirCacheEntry(), h, m);
break;
default:
keep(i.getDirCacheEntry());
}
return;
}
// if we have no file at all then there is nothing to do
if ((ffMask & 0x222) == 0)
return;
if ((ffMask == 0x00F) && f != null && FileMode.TREE.equals(f.getEntryFileMode())) {
// File/Directory conflict case #20
conflict(name, null, h, m);
}
if (i == null) {
// make sure not to overwrite untracked files
if (f != null) {
// a dirty worktree: the index is empty but we have a
// workingtree-file
if (mId == null || !mId.equals(f.getEntryObjectId())) {
conflict(name, null, h, m);
return;
}
}
/**
* <pre>
* I (index) H M Result
* -------------------------------------------------------
* 0 nothing nothing nothing (does not happen)
* 1 nothing nothing exists use M
* 2 nothing exists nothing remove path from index
* 3 nothing exists exists use M
* </pre>
*/
if (h == null)
update(name, mId, m.getEntryFileMode()); // 1
else if (m == null)
remove(name); // 2
else
update(name, mId, m.getEntryFileMode()); // 3
} else {
dce = i.getDirCacheEntry();
if (h == null) {
/**
* <pre>
* clean I==H I==M H M Result
* -----------------------------------------------------
* 4 yes N/A N/A nothing nothing keep index
* 5 no N/A N/A nothing nothing keep index
*
* 6 yes N/A yes nothing exists keep index
* 7 no N/A yes nothing exists keep index
* 8 yes N/A no nothing exists fail
* 9 no N/A no nothing exists fail
* </pre>
*/
if (m == null || mId.equals(iId)) {
if (m==null && walk.isDirectoryFileConflict()) {
if (dce != null
&& (f == null || f.isModified(dce, true)))
conflict(name, i.getDirCacheEntry(), h, m);
else
remove(name);
} else
keep(i.getDirCacheEntry());
} else
conflict(name, i.getDirCacheEntry(), h, m);
} else if (m == null) {
/**
* <pre>
* 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
* 12 yes no N/A exists nothing fail
* 13 no no N/A exists nothing fail
* </pre>
*/
if (hId.equals(iId)) {
if (f == null || f.isModified(dce, true))
conflict(name, i.getDirCacheEntry(), h, m);
else
remove(name);
} else
conflict(name, i.getDirCacheEntry(), h, m);
} else {
if (!hId.equals(mId) && !hId.equals(iId) && !mId.equals(iId))
conflict(name, i.getDirCacheEntry(), h, m);
else if (hId.equals(iId) && !mId.equals(iId)) {
if (dce != null && (f == null || f.isModified(dce, true)))
conflict(name, i.getDirCacheEntry(), h, m);
else
update(name, mId, m.getEntryFileMode());
} else {