@ -99,6 +99,30 @@ public class MergeCommand extends GitCommand<MergeResult> {
private boolean squash ;
private boolean squash ;
private FastForwardMode fastForwardMode = FastForwardMode . FF ;
/ * *
* The modes available for fast forward merges ( corresponding to the - - ff ,
* - - no - ff and - - ff - only options ) .
* /
public enum FastForwardMode {
/ * *
* Corresponds to the default - - ff option ( for a fast forward update the
* branch pointer only ) .
* /
FF ,
/ * *
* Corresponds to the - - no - ff option ( create a merge commit even for a
* fast forward ) .
* /
NO_FF ,
/ * *
* Corresponds to the - - ff - only option ( abort unless the merge is a fast
* forward ) .
* /
FF_ONLY ;
}
/ * *
/ * *
* @param repo
* @param repo
* /
* /
@ -118,14 +142,7 @@ public class MergeCommand extends GitCommand<MergeResult> {
ConcurrentRefUpdateException , CheckoutConflictException ,
ConcurrentRefUpdateException , CheckoutConflictException ,
InvalidMergeHeadsException , WrongRepositoryStateException , NoMessageException {
InvalidMergeHeadsException , WrongRepositoryStateException , NoMessageException {
checkCallable ( ) ;
checkCallable ( ) ;
checkParameters ( ) ;
if ( commits . size ( ) ! = 1 )
throw new InvalidMergeHeadsException (
commits . isEmpty ( ) ? JGitText . get ( ) . noMergeHeadSpecified
: MessageFormat . format (
JGitText . get ( ) . mergeStrategyDoesNotSupportHeads ,
mergeStrategy . getName ( ) ,
Integer . valueOf ( commits . size ( ) ) ) ) ;
RevWalk revWalk = null ;
RevWalk revWalk = null ;
DirCacheCheckout dco = null ;
DirCacheCheckout dco = null ;
@ -179,7 +196,8 @@ public class MergeCommand extends GitCommand<MergeResult> {
return new MergeResult ( headCommit , srcCommit , new ObjectId [ ] {
return new MergeResult ( headCommit , srcCommit , new ObjectId [ ] {
headCommit , srcCommit } ,
headCommit , srcCommit } ,
MergeStatus . ALREADY_UP_TO_DATE , mergeStrategy , null , null ) ;
MergeStatus . ALREADY_UP_TO_DATE , mergeStrategy , null , null ) ;
} else if ( revWalk . isMergedInto ( headCommit , srcCommit ) ) {
} else if ( revWalk . isMergedInto ( headCommit , srcCommit )
& & fastForwardMode = = FastForwardMode . FF ) {
// FAST_FORWARD detected: skip doing a real merge but only
// FAST_FORWARD detected: skip doing a real merge but only
// update HEAD
// update HEAD
refLogMessage . append ( ": " + MergeStatus . FAST_FORWARD ) ;
refLogMessage . append ( ": " + MergeStatus . FAST_FORWARD ) ;
@ -210,6 +228,11 @@ public class MergeCommand extends GitCommand<MergeResult> {
headCommit , srcCommit } , mergeStatus , mergeStrategy ,
headCommit , srcCommit } , mergeStatus , mergeStrategy ,
null , msg ) ;
null , msg ) ;
} else {
} else {
if ( fastForwardMode = = FastForwardMode . FF_ONLY ) {
return new MergeResult ( headCommit , srcCommit ,
new ObjectId [ ] { headCommit , srcCommit } ,
MergeStatus . ABORTED , mergeStrategy , null , null ) ;
}
String mergeMessage = "" ;
String mergeMessage = "" ;
if ( ! squash ) {
if ( ! squash ) {
mergeMessage = new MergeMessageFormatter ( ) . format (
mergeMessage = new MergeMessageFormatter ( ) . format (
@ -241,7 +264,10 @@ public class MergeCommand extends GitCommand<MergeResult> {
} else
} else
noProblems = merger . merge ( headCommit , srcCommit ) ;
noProblems = merger . merge ( headCommit , srcCommit ) ;
refLogMessage . append ( ": Merge made by " ) ;
refLogMessage . append ( ": Merge made by " ) ;
if ( ! revWalk . isMergedInto ( headCommit , srcCommit ) )
refLogMessage . append ( mergeStrategy . getName ( ) ) ;
refLogMessage . append ( mergeStrategy . getName ( ) ) ;
else
refLogMessage . append ( "recursive" ) ;
refLogMessage . append ( '.' ) ;
refLogMessage . append ( '.' ) ;
if ( noProblems ) {
if ( noProblems ) {
dco = new DirCacheCheckout ( repo ,
dco = new DirCacheCheckout ( repo ,
@ -305,6 +331,21 @@ public class MergeCommand extends GitCommand<MergeResult> {
}
}
}
}
private void checkParameters ( ) throws InvalidMergeHeadsException {
if ( squash & & fastForwardMode = = FastForwardMode . NO_FF ) {
throw new JGitInternalException (
JGitText . get ( ) . cannotCombineSquashWithNoff ) ;
}
if ( commits . size ( ) ! = 1 )
throw new InvalidMergeHeadsException (
commits . isEmpty ( ) ? JGitText . get ( ) . noMergeHeadSpecified
: MessageFormat . format (
JGitText . get ( ) . mergeStrategyDoesNotSupportHeads ,
mergeStrategy . getName ( ) ,
Integer . valueOf ( commits . size ( ) ) ) ) ;
}
private void updateHead ( StringBuilder refLogMessage , ObjectId newHeadId ,
private void updateHead ( StringBuilder refLogMessage , ObjectId newHeadId ,
ObjectId oldHeadID ) throws IOException ,
ObjectId oldHeadID ) throws IOException ,
ConcurrentRefUpdateException {
ConcurrentRefUpdateException {
@ -392,4 +433,19 @@ public class MergeCommand extends GitCommand<MergeResult> {
this . squash = squash ;
this . squash = squash ;
return this ;
return this ;
}
}
/ * *
* Sets the fast forward mode .
*
* @param fastForwardMode
* corresponds to the - - ff / - - no - ff / - - ff - only options . - - ff is the
* default option .
* @return { @code this }
* @since 2 . 2
* /
public MergeCommand setFastForward ( FastForwardMode fastForwardMode ) {
checkCallable ( ) ;
this . fastForwardMode = fastForwardMode ;
return this ;
}
}
}