@ -177,6 +177,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
private final File rebaseDir ;
private InteractiveHandler interactiveHandler ;
/ * *
* @param repo
* /
@ -254,6 +256,30 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
ObjectReader or = repo . newObjectReader ( ) ;
List < Step > steps = loadSteps ( ) ;
if ( isInteractive ( ) ) {
interactiveHandler . prepareSteps ( steps ) ;
BufferedWriter fw = new BufferedWriter (
new OutputStreamWriter ( new FileOutputStream ( new File (
rebaseDir , GIT_REBASE_TODO ) ) ,
Constants . CHARACTER_ENCODING ) ) ;
fw . newLine ( ) ;
try {
StringBuilder sb = new StringBuilder ( ) ;
for ( Step step : steps ) {
sb . setLength ( 0 ) ;
sb . append ( step . action . token ) ;
sb . append ( " " ) ;
sb . append ( step . commit . name ( ) ) ;
sb . append ( " " ) ;
sb . append ( new String ( step . shortMessage ,
Constants . CHARACTER_ENCODING ) . trim ( ) ) ;
fw . write ( sb . toString ( ) ) ;
fw . newLine ( ) ;
}
} finally {
fw . close ( ) ;
}
}
for ( Step step : steps ) {
popSteps ( 1 ) ;
Collection < ObjectId > ids = or . resolve ( step . commit ) ;
@ -295,6 +321,17 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
newHead = cherryPickResult . getNewHead ( ) ;
}
}
switch ( step . action ) {
case PICK :
continue ; // continue rebase process on pick command
case REWORD :
String oldMessage = commitToPick . getFullMessage ( ) ;
String newMessage = interactiveHandler
. modifyCommitMessage ( oldMessage ) ;
newHead = new Git ( repo ) . commit ( ) . setMessage ( newMessage )
. setAmend ( true ) . call ( ) ;
continue ;
}
} finally {
monitor . endTask ( ) ;
}
@ -492,6 +529,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
String popCandidate = br . readLine ( ) ;
if ( popCandidate = = null )
break ;
if ( popCandidate . length ( ) = = 0 )
continue ;
if ( popCandidate . charAt ( 0 ) = = '#' )
continue ;
int spaceIndex = popCandidate . indexOf ( ' ' ) ;
@ -564,9 +603,9 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
RevCommit headCommit = walk . lookupCommit ( headId ) ;
RevCommit upstream = walk . lookupCommit ( upstreamCommit . getId ( ) ) ;
if ( walk . isMergedInto ( upstream , headCommit ) )
if ( ! isInteractive ( ) & & walk . isMergedInto ( upstream , headCommit ) )
return RebaseResult . UP_TO_DATE_RESULT ;
else if ( walk . isMergedInto ( headCommit , upstream ) ) {
else if ( ! isInteractive ( ) & & walk . isMergedInto ( headCommit , upstream ) ) {
// head is already merged into upstream, fast-foward
monitor . beginTask ( MessageFormat . format (
JGitText . get ( ) . resettingHead ,
@ -647,6 +686,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
return null ;
}
private boolean isInteractive ( ) {
return interactiveHandler ! = null ;
}
/ * *
* checks if we can fast - forward and returns the new head if it is possible
*
@ -988,15 +1031,59 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
return this ;
}
static enum Action {
PICK ( "pick" ) ; // later add SQUASH, EDIT, etc.
/ * *
* Enables interactive rebase
*
* @param handler
* @return this
* /
public RebaseCommand runInteractively ( InteractiveHandler handler ) {
this . interactiveHandler = handler ;
return this ;
}
/ * *
* Allows configure rebase interactive process and modify commit message
* /
public interface InteractiveHandler {
/ * *
* Given list of { @code steps } should be modified according to user
* rebase configuration
* @param steps
* initial configuration of rebase interactive
* /
void prepareSteps ( List < Step > steps ) ;
/ * *
* Used for editing commit message on REWORD
*
* @param commit
* @return new commit message
* /
String modifyCommitMessage ( String commit ) ;
}
/ * *
* Describes rebase actions
* /
public static enum Action {
/** Use commit */
PICK ( "pick" , "p" ) ,
/** Use commit, but edit the commit message */
REWORD ( "reword" , "r" ) ; // later add SQUASH, EDIT, etc.
private final String token ;
private Action ( String token ) {
private final String shortToken ;
private Action ( String token , String shortToken ) {
this . token = token ;
this . shortToken = shortToken ;
}
/ * *
* @return full action token name
* /
public String toToken ( ) {
return this . token ;
}
@ -1007,15 +1094,20 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
static Action parse ( String token ) {
if ( token . equals ( "pick" ) | | token . equals ( "p" ) )
if ( token . equals ( PICK . token ) | | token . equals ( PICK . shortToken ) )
return PICK ;
if ( token . equals ( REWORD . token ) | | token . equals ( REWORD . shortToken ) )
return REWORD ;
throw new JGitInternalException ( MessageFormat . format (
JGitText . get ( ) . unknownOrUnsupportedCommand , token ,
PICK . toToken ( ) ) ) ;
}
}
static class Step {
/ * *
* Describes single rebase step
* /
public static class Step {
Action action ;
AbbreviatedObjectId commit ;
@ -1026,6 +1118,36 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
this . action = action ;
}
/ * *
* @return rebase action type
* /
public Action getAction ( ) {
return action ;
}
/ * *
* @param action
* /
public void setAction ( Action action ) {
this . action = action ;
}
/ * *
* @return abbreviated commit SHA - 1 of commit that action will be
* performed on
* /
public AbbreviatedObjectId getCommit ( ) {
return commit ;
}
/ * *
* @return short message commit of commit that action will be performed
* on
* /
public byte [ ] getShortMessage ( ) {
return shortMessage ;
}
@Override
public String toString ( ) {
return "Step[" + action + ", "