@ -128,6 +128,8 @@ public class ResolveMerger extends ThreeWayMerger {
private boolean enterSubtree ;
private boolean enterSubtree ;
private boolean inCore ;
private DirCache dircache ;
private DirCache dircache ;
private WorkingTreeIterator workingTreeIt ;
private WorkingTreeIterator workingTreeIt ;
@ -135,11 +137,24 @@ public class ResolveMerger extends ThreeWayMerger {
/ * *
/ * *
* @param local
* @param local
* @param inCore
* /
* /
protected ResolveMerger ( Repository local ) {
protected ResolveMerger ( Repository local , boolean inCore ) {
super ( local ) ;
super ( local ) ;
commitNames = new String [ ] { "BASE" , "OURS" , "THEIRS" } ;
commitNames = new String [ ] { "BASE" , "OURS" , "THEIRS" } ;
oi = getObjectInserter ( ) ;
oi = getObjectInserter ( ) ;
this . inCore = inCore ;
if ( inCore ) {
dircache = DirCache . newInCore ( ) ;
}
}
/ * *
* @param local
* /
protected ResolveMerger ( Repository local ) {
this ( local , false ) ;
}
}
@Override
@Override
@ -178,12 +193,11 @@ public class ResolveMerger extends ThreeWayMerger {
tw . enterSubtree ( ) ;
tw . enterSubtree ( ) ;
}
}
if ( ! inCore ) {
// All content-merges are successfully done. If we can now write the
// All content-merges are successfully done. If we can now write the
// new
// new index we are on quite safe ground. Even if the checkout of
// index we are on quite safe ground. Even if the checkout of files
// files coming from "theirs" fails the user can work around such
// coming from "theirs" fails the user can work around such failures
// failures by checking out the index again.
// by
// checking out the index again.
if ( ! builder . commit ( ) ) {
if ( ! builder . commit ( ) ) {
cleanUp ( ) ;
cleanUp ( ) ;
throw new IndexWriteException ( ) ;
throw new IndexWriteException ( ) ;
@ -194,6 +208,11 @@ public class ResolveMerger extends ThreeWayMerger {
// all files from "theirs" which have been selected to go into the
// all files from "theirs" which have been selected to go into the
// new index.
// new index.
checkout ( ) ;
checkout ( ) ;
} else {
builder . finish ( ) ;
builder = null ;
}
if ( getUnmergedPathes ( ) . isEmpty ( ) ) {
if ( getUnmergedPathes ( ) . isEmpty ( ) ) {
resultTree = dircache . writeTree ( oi ) ;
resultTree = dircache . writeTree ( oi ) ;
return true ;
return true ;
@ -234,13 +253,19 @@ public class ResolveMerger extends ThreeWayMerger {
/ * *
/ * *
* Reverts the worktree after an unsuccessful merge . We know that for all
* Reverts the worktree after an unsuccessful merge . We know that for all
* modified files the old content was in the old index and the index
* modified files the old content was in the old index and the index
* contained only stage 0
* contained only stage 0 . In case if inCore operation just clear
* the history of modified files .
*
*
* @throws IOException
* @throws IOException
* @throws CorruptObjectException
* @throws CorruptObjectException
* @throws NoWorkTreeException
* @throws NoWorkTreeException
* /
* /
private void cleanUp ( ) throws NoWorkTreeException , CorruptObjectException , IOException {
private void cleanUp ( ) throws NoWorkTreeException , CorruptObjectException , IOException {
if ( inCore ) {
modifiedFiles . clear ( ) ;
return ;
}
DirCache dc = db . readDirCache ( ) ;
DirCache dc = db . readDirCache ( ) ;
ObjectReader or = db . getObjectDatabase ( ) . newReader ( ) ;
ObjectReader or = db . getObjectDatabase ( ) . newReader ( ) ;
Iterator < String > mpathsIt = modifiedFiles . iterator ( ) ;
Iterator < String > mpathsIt = modifiedFiles . iterator ( ) ;
@ -391,15 +416,18 @@ public class ResolveMerger extends ThreeWayMerger {
}
}
if ( nonTree ( modeO ) & & nonTree ( modeT ) ) {
if ( nonTree ( modeO ) & & nonTree ( modeT ) ) {
// We are going to update the worktree. Make sure the worktree is
if ( ! inCore ) {
// not modified
// We are going to update the worktree. Make sure the worktree
// is not modified
if ( work ! = null
if ( work ! = null
& & ( ! nonTree ( work . getEntryRawMode ( ) ) | | work . isModified (
& & ( ! nonTree ( work . getEntryRawMode ( ) ) | | work
index . getDirCacheEntry ( ) , true , true , db . getFS ( ) ) ) ) {
. isModified ( index . getDirCacheEntry ( ) , true ,
true , db . getFS ( ) ) ) ) {
failingPathes . put ( tw . getPathString ( ) ,
failingPathes . put ( tw . getPathString ( ) ,
MergeFailureReason . DIRTY_WORKTREE ) ;
MergeFailureReason . DIRTY_WORKTREE ) ;
return false ;
return false ;
}
}
}
if ( ! contentMerge ( base , ours , theirs ) ) {
if ( ! contentMerge ( base , ours , theirs ) ) {
unmergedPathes . add ( tw . getPathString ( ) ) ;
unmergedPathes . add ( tw . getPathString ( ) ) ;
@ -421,24 +449,41 @@ public class ResolveMerger extends ThreeWayMerger {
getRawText ( ours . getEntryObjectId ( ) , db ) ,
getRawText ( ours . getEntryObjectId ( ) , db ) ,
getRawText ( theirs . getEntryObjectId ( ) , db ) ) ;
getRawText ( theirs . getEntryObjectId ( ) , db ) ) ;
File of = null ;
FileOutputStream fos ;
if ( ! inCore ) {
File workTree = db . getWorkTree ( ) ;
File workTree = db . getWorkTree ( ) ;
if ( workTree = = null )
if ( workTree = = null )
// TODO: This should be handled by WorkingTreeIterators which
// TODO: This should be handled by WorkingTreeIterators which
// support write operations
// support write operations
throw new UnsupportedOperationException ( ) ;
throw new UnsupportedOperationException ( ) ;
File of = new File ( workTree , tw . getPathString ( ) ) ;
of = new File ( workTree , tw . getPathString ( ) ) ;
FileOutputStream fos = new FileOutputStream ( of ) ;
fos = new FileOutputStream ( of ) ;
try {
try {
fmt . formatMerge ( fos , result , Arrays . asList ( commitNames ) ,
fmt . formatMerge ( fos , result , Arrays . asList ( commitNames ) ,
Constants . CHARACTER_ENCODING ) ;
Constants . CHARACTER_ENCODING ) ;
} finally {
} finally {
fos . close ( ) ;
fos . close ( ) ;
}
}
}
else if ( ! result . containsConflicts ( ) ) {
// When working inCore, only trivial merges can be handled,
// so we generate objects only in conflict free cases
of = File . createTempFile ( "merge_" , "_temp" , null ) ;
fos = new FileOutputStream ( of ) ;
try {
fmt . formatMerge ( fos , result , Arrays . asList ( commitNames ) ,
Constants . CHARACTER_ENCODING ) ;
} finally {
fos . close ( ) ;
}
}
if ( result . containsConflicts ( ) ) {
if ( result . containsConflicts ( ) ) {
// a conflict occured, the file will contain conflict markers
// a conflict occured, the file will contain conflict markers
// the index will be populated with the three stages and only the
// the index will be populated with the three stages and only the
// workdir contains the halfways merged content
// workdir (if used) contains the halfways merged content
add ( tw . getRawPath ( ) , base , DirCacheEntry . STAGE_1 ) ;
add ( tw . getRawPath ( ) , base , DirCacheEntry . STAGE_1 ) ;
add ( tw . getRawPath ( ) , ours , DirCacheEntry . STAGE_2 ) ;
add ( tw . getRawPath ( ) , ours , DirCacheEntry . STAGE_2 ) ;
add ( tw . getRawPath ( ) , theirs , DirCacheEntry . STAGE_3 ) ;
add ( tw . getRawPath ( ) , theirs , DirCacheEntry . STAGE_3 ) ;
@ -457,6 +502,8 @@ public class ResolveMerger extends ThreeWayMerger {
is ) ) ;
is ) ) ;
} finally {
} finally {
is . close ( ) ;
is . close ( ) ;
if ( inCore )
of . delete ( ) ;
}
}
builder . add ( dce ) ;
builder . add ( dce ) ;
return true ;
return true ;