@ -78,6 +78,7 @@ import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuildIterator ;
import org.eclipse.jgit.dircache.DirCacheBuilder ;
import org.eclipse.jgit.dircache.DirCacheCheckout ;
import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata ;
import org.eclipse.jgit.dircache.DirCacheEntry ;
import org.eclipse.jgit.errors.BinaryBlobException ;
import org.eclipse.jgit.errors.CorruptObjectException ;
@ -297,6 +298,12 @@ public class ResolveMerger extends ThreeWayMerger {
* /
private int inCoreLimit ;
/ * *
* Keeps { @link CheckoutMetadata } for { @link # checkout ( ) } and
* { @link # cleanUp ( ) } .
* /
private Map < String , CheckoutMetadata > checkoutMetadata ;
private static MergeAlgorithm getMergeAlgorithm ( Config config ) {
SupportedAlgorithm diffAlg = config . getEnum (
CONFIG_DIFF_SECTION , null , CONFIG_KEY_ALGORITHM ,
@ -313,6 +320,8 @@ public class ResolveMerger extends ThreeWayMerger {
return new String [ ] { "BASE" , "OURS" , "THEIRS" } ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
private static final Attributes NO_ATTRIBUTES = new Attributes ( ) ;
/ * *
* Constructor for ResolveMerger .
*
@ -369,17 +378,22 @@ public class ResolveMerger extends ThreeWayMerger {
/** {@inheritDoc} */
@Override
protected boolean mergeImpl ( ) throws IOException {
if ( implicitDirCache )
if ( implicitDirCache ) {
dircache = nonNullRepo ( ) . lockDirCache ( ) ;
}
if ( ! inCore ) {
checkoutMetadata = new HashMap < > ( ) ;
}
try {
return mergeTrees ( mergeBase ( ) , sourceTrees [ 0 ] , sourceTrees [ 1 ] ,
false ) ;
} finally {
if ( implicitDirCache )
checkoutMetadata = null ;
if ( implicitDirCache ) {
dircache . unlock ( ) ;
}
}
}
private void checkout ( ) throws NoWorkTreeException , IOException {
// Iterate in reverse so that "folder/file" is deleted before
@ -400,7 +414,8 @@ public class ResolveMerger extends ThreeWayMerger {
if ( cacheEntry . getFileMode ( ) = = FileMode . GITLINK ) {
new File ( nonNullRepo ( ) . getWorkTree ( ) , entry . getKey ( ) ) . mkdirs ( ) ;
} else {
DirCacheCheckout . checkoutEntry ( db , cacheEntry , reader ) ;
DirCacheCheckout . checkoutEntry ( db , cacheEntry , reader , false ,
checkoutMetadata . get ( entry . getKey ( ) ) ) ;
modifiedFiles . add ( entry . getKey ( ) ) ;
}
}
@ -428,10 +443,12 @@ public class ResolveMerger extends ThreeWayMerger {
DirCache dc = nonNullRepo ( ) . readDirCache ( ) ;
Iterator < String > mpathsIt = modifiedFiles . iterator ( ) ;
while ( mpathsIt . hasNext ( ) ) {
String mpath = mpathsIt . next ( ) ;
String mpath = mpathsIt . next ( ) ;
DirCacheEntry entry = dc . getEntry ( mpath ) ;
if ( entry ! = null )
DirCacheCheckout . checkoutEntry ( db , entry , reader ) ;
if ( entry ! = null ) {
DirCacheCheckout . checkoutEntry ( db , entry , reader , false ,
checkoutMetadata . get ( mpath ) ) ;
}
mpathsIt . remove ( ) ;
}
}
@ -480,6 +497,71 @@ public class ResolveMerger extends ThreeWayMerger {
return newEntry ;
}
/ * *
* Remembers the { @link CheckoutMetadata } for the given path ; it may be
* needed in { @link # checkout ( ) } or in { @link # cleanUp ( ) } .
*
* @param path
* of the current node
* @param attributes
* for the current node
* @throws IOException
* if the smudge filter cannot be determined
* @since 5 . 1
* /
protected void addCheckoutMetadata ( String path , Attributes attributes )
throws IOException {
if ( checkoutMetadata ! = null ) {
EolStreamType eol = EolStreamTypeUtil . detectStreamType (
OperationType . CHECKOUT_OP , workingTreeOptions , attributes ) ;
CheckoutMetadata data = new CheckoutMetadata ( eol ,
tw . getFilterCommand ( Constants . ATTR_FILTER_TYPE_SMUDGE ) ) ;
checkoutMetadata . put ( path , data ) ;
}
}
/ * *
* Adds a { @link DirCacheEntry } for direct checkout and remembers its
* { @link CheckoutMetadata } .
*
* @param path
* of the entry
* @param entry
* to add
* @param attributes
* for the current entry
* @throws IOException
* if the { @link CheckoutMetadata } cannot be determined
* @since 5 . 1
* /
protected void addToCheckout ( String path , DirCacheEntry entry ,
Attributes attributes ) throws IOException {
toBeCheckedOut . put ( path , entry ) ;
addCheckoutMetadata ( path , attributes ) ;
}
/ * *
* Remember a path for deletion , and remember its { @link CheckoutMetadata }
* in case it has to be restored in { @link # cleanUp ( ) } .
*
* @param path
* of the entry
* @param isFile
* whether it is a file
* @param attributes
* for the entry
* @throws IOException
* if the { @link CheckoutMetadata } cannot be determined
* @since 5 . 1
* /
protected void addDeletion ( String path , boolean isFile ,
Attributes attributes ) throws IOException {
toBeDeleted . add ( path ) ;
if ( isFile ) {
addCheckoutMetadata ( path , attributes ) ;
}
}
/ * *
* Processes one path and tries to merge taking git attributes in account .
* This method will do all trivial ( not content ) merges and will also detect
@ -586,7 +668,7 @@ public class ResolveMerger extends ThreeWayMerger {
// This will happen later. Set these values to 0 for know.
DirCacheEntry e = add ( tw . getRawPath ( ) , theirs ,
DirCacheEntry . STAGE_0 , 0 , 0 ) ;
toBeCheckedOut . p ut( tw . getPathString ( ) , e ) ;
addToChecko ut( tw . getPathString ( ) , e , attributes ) ;
}
return true ;
} else {
@ -627,8 +709,9 @@ public class ResolveMerger extends ThreeWayMerger {
// This will happen later. Set these values to 0 for know.
DirCacheEntry e = add ( tw . getRawPath ( ) , theirs ,
DirCacheEntry . STAGE_0 , 0 , 0 ) ;
if ( e ! = null )
toBeCheckedOut . put ( tw . getPathString ( ) , e ) ;
if ( e ! = null ) {
addToCheckout ( tw . getPathString ( ) , e , attributes ) ;
}
return true ;
} else {
// we want THEIRS ... but THEIRS contains a folder or the
@ -642,7 +725,7 @@ public class ResolveMerger extends ThreeWayMerger {
// Base, ours, and theirs all contain a folder: don't delete
return true ;
}
toBeDeleted . add ( tw . getPathString ( ) ) ;
addDeletion ( tw . getPathString ( ) , nonTree ( modeO ) , attributes ) ;
return true ;
}
}
@ -726,9 +809,12 @@ public class ResolveMerger extends ThreeWayMerger {
result . setContainsConflicts ( false ) ;
}
updateIndex ( base , ours , theirs , result , attributes ) ;
if ( result . containsConflicts ( ) & & ! ignoreConflicts )
unmergedPaths . add ( tw . getPathString ( ) ) ;
modifiedFiles . add ( tw . getPathString ( ) ) ;
String currentPath = tw . getPathString ( ) ;
if ( result . containsConflicts ( ) & & ! ignoreConflicts ) {
unmergedPaths . add ( currentPath ) ;
}
modifiedFiles . add ( currentPath ) ;
addCheckoutMetadata ( currentPath , attributes ) ;
} else if ( modeO ! = modeT ) {
// OURS or THEIRS has been deleted
if ( ( ( modeO ! = 0 & & ! tw . idEqual ( T_BASE , T_OURS ) ) | | ( modeT ! = 0 & & ! tw
@ -747,8 +833,9 @@ public class ResolveMerger extends ThreeWayMerger {
if ( isWorktreeDirty ( work , ourDce ) )
return false ;
if ( nonTree ( modeT ) ) {
if ( e ! = null )
toBeCheckedOut . put ( tw . getPathString ( ) , e ) ;
if ( e ! = null ) {
addToCheckout ( tw . getPathString ( ) , e , attributes ) ;
}
}
}
@ -1249,7 +1336,8 @@ public class ResolveMerger extends ThreeWayMerger {
hasWorkingTreeIterator ? treeWalk . getTree ( T_FILE ,
WorkingTreeIterator . class ) : null ,
ignoreConflicts , hasAttributeNodeProvider
? treeWalk . getAttributes ( ) : new Attributes ( ) ) ) {
? treeWalk . getAttributes ( )
: NO_ATTRIBUTES ) ) {
cleanUp ( ) ;
return false ;
}