@ -44,6 +44,7 @@ package org.eclipse.jgit.merge;
import static org.junit.Assert.assertEquals ;
import static org.junit.Assert.assertFalse ;
import static org.junit.Assert.assertTrue ;
import java.io.BufferedReader ;
import java.io.File ;
@ -178,7 +179,7 @@ public class RecursiveMergerTest extends RepositoryTestCase {
/ * *
* Merging m2 , s2 from the following topology . The same file is modified
* in both branches . The modifications should be mergeable . m2 and s2
* contain branch specific conflict resolutions . Therefore m2 and don ' t contain the same content .
* contain branch specific conflict resolutions . Therefore m2 and s2 don ' t contain the same content .
*
* < pre >
* m0 - - m1 - - m2
@ -257,6 +258,183 @@ public class RecursiveMergerTest extends RepositoryTestCase {
}
}
@Theory
/ * *
* Merging m2 , s2 from the following topology . The same file is modified
* in both branches . The modifications should be mergeable but only if the automerge of m1 and s1
* is choosen as parent . Choosing m0 as parent would not be sufficient ( in contrast to the merge in
* crissCrossMerge_mergeable ) . m2 and s2 contain branch specific conflict resolutions . Therefore m2
* and s2 don ' t contain the same content .
*
* < pre >
* m0 - - m1 - - m2
* \ \ /
* \ / \
* s1 - - s2
* < / pre >
* /
public void crissCrossMerge_mergeable2 ( MergeStrategy strategy ,
IndexState indexState , WorktreeState worktreeState )
throws Exception {
if ( ! validateStates ( indexState , worktreeState ) )
return ;
BranchBuilder master = db_t . branch ( "master" ) ;
RevCommit m0 = master . commit ( ) . add ( "f" , "1\n2\n3\n" )
. message ( "m0" )
. create ( ) ;
RevCommit m1 = master . commit ( ) . add ( "f" , "1-master\n2\n3\n" )
. message ( "m1" ) . create ( ) ;
db_t . getRevWalk ( ) . parseCommit ( m1 ) ;
BranchBuilder side = db_t . branch ( "side" ) ;
RevCommit s1 = side . commit ( ) . parent ( m0 ) . add ( "f" , "1\n2\n3-side\n" )
. message ( "s1" ) . create ( ) ;
RevCommit s2 = side . commit ( ) . parent ( m1 )
. add ( "f" , "1-master\n2\n3-side-r\n" )
. message ( "s2(merge)" )
. create ( ) ;
RevCommit m2 = master . commit ( ) . parent ( s1 )
. add ( "f" , "1-master-r\n2\n3-side\n" )
. message ( "m2(merge)" )
. create ( ) ;
Git git = Git . wrap ( db ) ;
git . checkout ( ) . setName ( "master" ) . call ( ) ;
modifyWorktree ( worktreeState , "f" , "side" ) ;
modifyIndex ( indexState , "f" , "side" ) ;
ResolveMerger merger = ( ResolveMerger ) strategy . newMerger ( db ,
worktreeState = = WorktreeState . Bare ) ;
if ( worktreeState ! = WorktreeState . Bare )
merger . setWorkingTreeIterator ( new FileTreeIterator ( db ) ) ;
try {
boolean expectSuccess = true ;
if ( ! ( indexState = = IndexState . Bare
| | indexState = = IndexState . Missing | | indexState = = IndexState . SameAsHead ) )
// index is dirty
expectSuccess = false ;
else if ( worktreeState = = WorktreeState . DifferentFromHeadAndOther
| | worktreeState = = WorktreeState . SameAsOther )
expectSuccess = false ;
assertEquals ( Boolean . valueOf ( expectSuccess ) ,
Boolean . valueOf ( merger . merge ( new RevCommit [ ] { m2 , s2 } ) ) ) ;
assertEquals ( MergeStrategy . RECURSIVE , strategy ) ;
if ( ! expectSuccess )
// if the merge was not successful skip testing the state of
// index and workingtree
return ;
assertEquals (
"1-master-r\n2\n3-side-r" ,
contentAsString ( db , merger . getResultTreeId ( ) , "f" ) ) ;
if ( indexState ! = IndexState . Bare )
assertEquals (
"[f, mode:100644, content:1-master-r\n2\n3-side-r\n]" ,
indexState ( RepositoryTestCase . CONTENT ) ) ;
if ( worktreeState ! = WorktreeState . Bare
& & worktreeState ! = WorktreeState . Missing )
assertEquals (
"1-master-r\n2\n3-side-r\n" ,
read ( "f" ) ) ;
} catch ( NoMergeBaseException e ) {
assertEquals ( MergeStrategy . RESOLVE , strategy ) ;
assertEquals ( e . getReason ( ) ,
MergeBaseFailureReason . MULTIPLE_MERGE_BASES_NOT_SUPPORTED ) ;
}
}
@Theory
/ * *
* Merging m2 , s2 from the following topology . The same file is modified
* in both branches . The modifications should be mergeable but only if the automerge of m1 and s1
* is choosen as parent . On both branches delete and modify files untouched on the other branch .
* On both branches create new files . Make sure these files are correctly merged and
* exist in the workingtree .
*
* < pre >
* m0 - - m1 - - m2
* \ \ /
* \ / \
* s1 - - s2
* < / pre >
* /
public void crissCrossMerge_checkOtherFiles ( MergeStrategy strategy ,
IndexState indexState , WorktreeState worktreeState )
throws Exception {
if ( ! validateStates ( indexState , worktreeState ) )
return ;
BranchBuilder master = db_t . branch ( "master" ) ;
RevCommit m0 = master . commit ( ) . add ( "f" , "1\n2\n3\n" ) . add ( "m.m" , "0" )
. add ( "m.d" , "0" ) . add ( "s.m" , "0" ) . add ( "s.d" , "0" ) . message ( "m0" )
. create ( ) ;
RevCommit m1 = master . commit ( ) . add ( "f" , "1-master\n2\n3\n" )
. add ( "m.c" , "0" ) . add ( "m.m" , "1" ) . rm ( "m.d" ) . message ( "m1" )
. create ( ) ;
db_t . getRevWalk ( ) . parseCommit ( m1 ) ;
BranchBuilder side = db_t . branch ( "side" ) ;
RevCommit s1 = side . commit ( ) . parent ( m0 ) . add ( "f" , "1\n2\n3-side\n" )
. add ( "s.c" , "0" ) . add ( "s.m" , "1" ) . rm ( "s.d" ) . message ( "s1" )
. create ( ) ;
RevCommit s2 = side . commit ( ) . parent ( m1 )
. add ( "f" , "1-master\n2\n3-side-r\n" ) . add ( "m.m" , "1" )
. add ( "m.c" , "0" ) . rm ( "m.d" ) . message ( "s2(merge)" ) . create ( ) ;
RevCommit m2 = master . commit ( ) . parent ( s1 )
. add ( "f" , "1-master-r\n2\n3-side\n" ) . add ( "s.m" , "1" )
. add ( "s.c" , "0" ) . rm ( "s.d" ) . message ( "m2(merge)" ) . create ( ) ;
Git git = Git . wrap ( db ) ;
git . checkout ( ) . setName ( "master" ) . call ( ) ;
modifyWorktree ( worktreeState , "f" , "side" ) ;
modifyIndex ( indexState , "f" , "side" ) ;
ResolveMerger merger = ( ResolveMerger ) strategy . newMerger ( db ,
worktreeState = = WorktreeState . Bare ) ;
if ( worktreeState ! = WorktreeState . Bare )
merger . setWorkingTreeIterator ( new FileTreeIterator ( db ) ) ;
try {
boolean expectSuccess = true ;
if ( ! ( indexState = = IndexState . Bare
| | indexState = = IndexState . Missing | | indexState = = IndexState . SameAsHead ) )
// index is dirty
expectSuccess = false ;
else if ( worktreeState = = WorktreeState . DifferentFromHeadAndOther
| | worktreeState = = WorktreeState . SameAsOther )
expectSuccess = false ;
assertEquals ( Boolean . valueOf ( expectSuccess ) ,
Boolean . valueOf ( merger . merge ( new RevCommit [ ] { m2 , s2 } ) ) ) ;
assertEquals ( MergeStrategy . RECURSIVE , strategy ) ;
if ( ! expectSuccess )
// if the merge was not successful skip testing the state of
// index and workingtree
return ;
assertEquals (
"1-master-r\n2\n3-side-r" ,
contentAsString ( db , merger . getResultTreeId ( ) , "f" ) ) ;
if ( indexState ! = IndexState . Bare )
assertEquals (
"[f, mode:100644, content:1-master-r\n2\n3-side-r\n][m.c, mode:100644, content:0][m.m, mode:100644, content:1][s.c, mode:100644, content:0][s.m, mode:100644, content:1]" ,
indexState ( RepositoryTestCase . CONTENT ) ) ;
if ( worktreeState ! = WorktreeState . Bare
& & worktreeState ! = WorktreeState . Missing ) {
assertEquals (
"1-master-r\n2\n3-side-r\n" ,
read ( "f" ) ) ;
assertTrue ( check ( "s.c" ) ) ;
assertFalse ( check ( "s.d" ) ) ;
assertTrue ( check ( "s.m" ) ) ;
assertTrue ( check ( "m.c" ) ) ;
assertFalse ( check ( "m.d" ) ) ;
assertTrue ( check ( "m.m" ) ) ;
}
} catch ( NoMergeBaseException e ) {
assertEquals ( MergeStrategy . RESOLVE , strategy ) ;
assertEquals ( e . getReason ( ) ,
MergeBaseFailureReason . MULTIPLE_MERGE_BASES_NOT_SUPPORTED ) ;
}
}
@Theory
/ * *
* Merging m2 , s2 from the following topology . The same file is modified