@ -70,6 +70,7 @@ import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.NoMessageException ;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException ;
import org.eclipse.jgit.api.errors.RefNotFoundException ;
import org.eclipse.jgit.api.errors.StashApplyFailureException ;
import org.eclipse.jgit.api.errors.UnmergedPathsException ;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException ;
import org.eclipse.jgit.diff.DiffFormatter ;
@ -79,6 +80,7 @@ import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.internal.JGitText ;
import org.eclipse.jgit.lib.AbbreviatedObjectId ;
import org.eclipse.jgit.lib.AnyObjectId ;
import org.eclipse.jgit.lib.ConfigConstants ;
import org.eclipse.jgit.lib.Constants ;
import org.eclipse.jgit.lib.NullProgressMonitor ;
import org.eclipse.jgit.lib.ObjectId ;
@ -158,6 +160,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
private static final String MESSAGE_SQUASH = "message-squash" ; //$NON-NLS-1$
private static final String AUTOSTASH = "autostash" ; //$NON-NLS-1$
private static final String AUTOSTASH_MSG = "On {0}: autostash" ;
/ * *
* The available operations
* /
@ -257,6 +263,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
. resolve ( upstreamCommitId ) ) ;
break ;
case BEGIN :
autoStash ( ) ;
if ( stopAfterInitialization
| | ! walk . isMergedInto (
walk . parseCommit ( repo . resolve ( Constants . HEAD ) ) ,
@ -272,8 +279,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
RebaseResult res = initFilesAndRewind ( ) ;
if ( stopAfterInitialization )
return RebaseResult . INTERACTIVE_PREPARED_RESULT ;
if ( res ! = null )
if ( res ! = null ) {
autoStashApply ( ) ;
return res ;
}
}
if ( monitor . isCancelled ( ) )
@ -339,6 +348,57 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
private void autoStash ( ) throws GitAPIException , IOException {
if ( repo . getConfig ( ) . getBoolean ( ConfigConstants . CONFIG_REBASE_SECTION ,
ConfigConstants . CONFIG_KEY_AUTOSTASH , false ) ) {
String message = MessageFormat . format (
AUTOSTASH_MSG ,
Repository
. shortenRefName ( getHeadName ( getHead ( ) ) ) ) ;
RevCommit stashCommit = Git . wrap ( repo ) . stashCreate ( ) . setRef ( null )
. setWorkingDirectoryMessage (
message )
. call ( ) ;
if ( stashCommit ! = null ) {
FileUtils . mkdir ( rebaseState . getDir ( ) ) ;
rebaseState . createFile ( AUTOSTASH , stashCommit . getName ( ) ) ;
}
}
}
private boolean autoStashApply ( ) throws IOException , GitAPIException {
boolean conflicts = false ;
if ( rebaseState . getFile ( AUTOSTASH ) . exists ( ) ) {
String stash = rebaseState . readFile ( AUTOSTASH ) ;
try {
Git . wrap ( repo ) . stashApply ( ) . setStashRef ( stash )
. ignoreRepositoryState ( true ) . call ( ) ;
} catch ( StashApplyFailureException e ) {
conflicts = true ;
RevWalk rw = new RevWalk ( repo ) ;
ObjectId stashId = repo . resolve ( stash ) ;
RevCommit commit = rw . parseCommit ( stashId ) ;
updateStashRef ( commit , commit . getAuthorIdent ( ) ,
commit . getShortMessage ( ) ) ;
}
}
return conflicts ;
}
private void updateStashRef ( ObjectId commitId , PersonIdent refLogIdent ,
String refLogMessage ) throws IOException {
Ref currentRef = repo . getRef ( Constants . R_STASH ) ;
RefUpdate refUpdate = repo . updateRef ( Constants . R_STASH ) ;
refUpdate . setNewObjectId ( commitId ) ;
refUpdate . setRefLogIdent ( refLogIdent ) ;
refUpdate . setRefLogMessage ( refLogMessage , false ) ;
if ( currentRef ! = null )
refUpdate . setExpectedOldObjectId ( currentRef . getObjectId ( ) ) ;
else
refUpdate . setExpectedOldObjectId ( ObjectId . zeroId ( ) ) ;
refUpdate . forceUpdate ( ) ;
}
private RebaseResult processStep ( RebaseTodoLine step , boolean shouldPick )
throws IOException , GitAPIException {
if ( Action . COMMENT . equals ( step . getAction ( ) ) )
@ -432,10 +492,13 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
private RebaseResult finishRebase ( RevCommit newHead ,
boolean lastStepWasForward ) throws IOException {
boolean lastStepWasForward ) throws IOException , GitAPIException {
String headName = rebaseState . readFile ( HEAD_NAME ) ;
updateHead ( headName , newHead , upstreamCommit ) ;
boolean stashConflicts = autoStashApply ( ) ;
FileUtils . delete ( rebaseState . getDir ( ) , FileUtils . RECURSIVE ) ;
if ( stashConflicts )
return RebaseResult . STASH_APPLY_CONFLICTS_RESULT ;
if ( lastStepWasForward | | newHead = = null )
return RebaseResult . FAST_FORWARD_RESULT ;
return RebaseResult . OK_RESULT ;
@ -809,16 +872,9 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
// we need to store everything into files so that we can implement
// --skip, --continue, and --abort
Ref head = repo . getRef ( Constants . HEAD ) ;
if ( head = = null | | head . getObjectId ( ) = = null )
throw new RefNotFoundException ( MessageFormat . format (
JGitText . get ( ) . refNotResolved , Constants . HEAD ) ) ;
Ref head = getHead ( ) ;
String headName ;
if ( head . isSymbolic ( ) )
headName = head . getTarget ( ) . getName ( ) ;
else
headName = head . getObjectId ( ) . getName ( ) ;
String headName = getHeadName ( head ) ;
ObjectId headId = head . getObjectId ( ) ;
if ( headId = = null )
throw new RefNotFoundException ( MessageFormat . format (
@ -857,7 +913,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
Collections . reverse ( cherryPickList ) ;
// create the folder for the meta information
FileUtils . mkdir ( rebaseState . getDir ( ) ) ;
FileUtils . mkdir ( rebaseState . getDir ( ) , true ) ;
repo . writeOrigHead ( headId ) ;
rebaseState . createFile ( REBASE_HEAD , headId . name ( ) ) ;
@ -893,6 +949,23 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
return null ;
}
private static String getHeadName ( Ref head ) {
String headName ;
if ( head . isSymbolic ( ) )
headName = head . getTarget ( ) . getName ( ) ;
else
headName = head . getObjectId ( ) . getName ( ) ;
return headName ;
}
private Ref getHead ( ) throws IOException , RefNotFoundException {
Ref head = repo . getRef ( Constants . HEAD ) ;
if ( head = = null | | head . getObjectId ( ) = = null )
throw new RefNotFoundException ( MessageFormat . format (
JGitText . get ( ) . refNotResolved , Constants . HEAD ) ) ;
return head ;
}
private boolean isInteractive ( ) {
return interactiveHandler ! = null ;
}
@ -907,10 +980,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
* /
public RevCommit tryFastForward ( RevCommit newCommit ) throws IOException ,
GitAPIException {
Ref head = repo . getRef ( Constants . HEAD ) ;
if ( head = = null | | head . getObjectId ( ) = = null )
throw new RefNotFoundException ( MessageFormat . format (
JGitText . get ( ) . refNotResolved , Constants . HEAD ) ) ;
Ref head = getHead ( ) ;
ObjectId headId = head . getObjectId ( ) ;
if ( headId = = null )
@ -920,11 +990,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
if ( walk . isMergedInto ( newCommit , headCommit ) )
return newCommit ;
String headName ;
if ( head . isSymbolic ( ) )
headName = head . getTarget ( ) . getName ( ) ;
else
headName = head . getObjectId ( ) . getName ( ) ;
String headName = getHeadName ( head ) ;
return tryFastForward ( headName , headCommit , newCommit ) ;
}
@ -1004,7 +1070,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
private RebaseResult abort ( RebaseResult result ) throws IOException {
private RebaseResult abort ( RebaseResult result ) throws IOException ,
GitAPIException {
try {
ObjectId origHead = repo . readOrigHead ( ) ;
String commitId = origHead ! = null ? origHead . name ( ) : null ;
@ -1053,9 +1120,12 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
JGitText . get ( ) . abortingRebaseFailed ) ;
}
}
boolean stashConflicts = autoStashApply ( ) ;
// cleanup the files
FileUtils . delete ( rebaseState . getDir ( ) , FileUtils . RECURSIVE ) ;
repo . writeCherryPickHead ( null ) ;
if ( stashConflicts )
return RebaseResult . STASH_APPLY_CONFLICTS_RESULT ;
return result ;
} finally {