@ -79,6 +79,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject ;
import org.eclipse.jgit.revwalk.RevTree ;
import org.eclipse.jgit.revwalk.RevWalk ;
import org.eclipse.jgit.storage.file.CheckoutEntry ;
import org.eclipse.jgit.storage.file.ReflogEntry ;
import org.eclipse.jgit.storage.file.ReflogReader ;
import org.eclipse.jgit.treewalk.TreeWalk ;
@ -376,20 +377,58 @@ public abstract class Repository {
throws AmbiguousObjectException , IOException {
RevWalk rw = new RevWalk ( this ) ;
try {
return resolve ( rw , revstr ) ;
Object resolved = resolve ( rw , revstr ) ;
if ( resolved instanceof String ) {
return getRef ( ( String ) resolved ) . getLeaf ( ) . getObjectId ( ) ;
} else {
return ( ObjectId ) resolved ;
}
} finally {
rw . release ( ) ;
}
}
private ObjectId resolve ( final RevWalk rw , final String revstr ) throws IOException {
/ * *
* Simplify an expression , but unlike { @link # resolve ( String ) } it will not
* resolve a branch passed or resulting from the expression , such as @ { - } .
* Thus this method can be used to process an expression to a method that
* expects a branch or revision id .
*
* @param revstr
* @return object id or ref name from resolved expression
* @throws AmbiguousObjectException
* @throws IOException
* /
public String simplify ( final String revstr )
throws AmbiguousObjectException , IOException {
RevWalk rw = new RevWalk ( this ) ;
try {
Object resolved = resolve ( rw , revstr ) ;
if ( resolved ! = null )
if ( resolved instanceof String )
return ( String ) resolved ;
else
return ( ( AnyObjectId ) resolved ) . getName ( ) ;
return null ;
} finally {
rw . release ( ) ;
}
}
private Object resolve ( final RevWalk rw , final String revstr )
throws IOException {
char [ ] revChars = revstr . toCharArray ( ) ;
RevObject rev = null ;
String name = null ;
int done = 0 ;
for ( int i = 0 ; i < revChars . length ; + + i ) {
switch ( revChars [ i ] ) {
case '^' :
if ( rev = = null ) {
rev = parseSimple ( rw , new String ( revChars , 0 , i ) ) ;
if ( name = = null )
name = new String ( revChars , done , i ) ;
rev = parseSimple ( rw , name ) ;
name = null ;
if ( rev = = null )
return null ;
}
@ -429,6 +468,7 @@ public abstract class Repository {
rev = commit . getParent ( pnum - 1 ) ;
}
i = j - 1 ;
done = i ;
break ;
case '{' :
int k ;
@ -456,6 +496,7 @@ public abstract class Repository {
throw new RevisionSyntaxException ( revstr ) ;
else
throw new RevisionSyntaxException ( revstr ) ;
done = k ;
break ;
default :
rev = rw . parseAny ( rev ) ;
@ -485,7 +526,9 @@ public abstract class Repository {
break ;
case '~' :
if ( rev = = null ) {
rev = parseSimple ( rw , new String ( revChars , 0 , i ) ) ;
if ( name = = null )
name = new String ( revChars , done , i ) ;
rev = parseSimple ( rw , name ) ;
if ( rev = = null )
return null ;
}
@ -523,6 +566,8 @@ public abstract class Repository {
i = l - 1 ;
break ;
case '@' :
if ( rev ! = null )
throw new RevisionSyntaxException ( revstr ) ;
int m ;
String time = null ;
for ( m = i + 2 ; m < revChars . length ; + + m ) {
@ -532,47 +577,48 @@ public abstract class Repository {
}
}
if ( time ! = null ) {
String refName = new String ( revChars , 0 , i ) ;
Ref ref ;
if ( refName . equals ( "" ) ) {
// Currently checked out branch, HEAD if
// detached
ref = getRef ( Constants . HEAD ) ;
if ( time . matches ( "^-\\d+$" ) ) {
if ( name ! = null )
throw new RevisionSyntaxException ( revstr ) ;
else {
String previousCheckout = resolveReflogCheckout ( - Integer
. parseInt ( time ) ) ;
if ( ObjectId . isId ( previousCheckout ) )
rev = parseSimple ( rw , previousCheckout ) ;
else
name = previousCheckout ;
}
} else {
if ( name = = null )
name = new String ( revChars , done , i ) ;
if ( name . equals ( "" ) )
name = Constants . HEAD ;
Ref ref = getRef ( name ) ;
if ( ref = = null )
return null ;
// @{n} means current branch, not HEAD@{1} unless
// detached
if ( ref . isSymbolic ( ) )
ref = ref . getLeaf ( ) ;
if ( ref . getObjectId ( ) = = null )
return null ;
} else
ref = getRef ( refName ) ;
if ( ref = = null )
return null ;
rev = resolveReflog ( rw , ref , time ) ;
rev = resolveReflog ( rw , ref , time ) ;
name = null ;
}
i = m ;
} else
i = m - 1 ;
throw new RevisionSyntaxException ( revstr ) ;
break ;
case ':' : {
RevTree tree ;
if ( rev = = null ) {
// We might not yet have parsed the left hand side.
ObjectId id ;
try {
if ( i = = 0 )
id = resolve ( rw , Constants . HEAD ) ;
else
id = resolve ( rw , new String ( revChars , 0 , i ) ) ;
} catch ( RevisionSyntaxException badSyntax ) {
throw new RevisionSyntaxException ( revstr ) ;
}
if ( id = = null )
return null ;
tree = rw . parseTree ( id ) ;
} else {
tree = rw . parseTree ( rev ) ;
if ( name = = null )
name = new String ( revChars , done , i ) ;
if ( name . equals ( "" ) )
name = Constants . HEAD ;
rev = parseSimple ( rw , name ) ;
}
if ( rev = = null )
return null ;
tree = rw . parseTree ( rev ) ;
if ( i = = revChars . length - 1 )
return tree . copy ( ) ;
@ -581,13 +627,19 @@ public abstract class Repository {
tree ) ;
return tw ! = null ? tw . getObjectId ( 0 ) : null ;
}
default :
if ( rev ! = null )
throw new RevisionSyntaxException ( revstr ) ;
}
}
return rev ! = null ? rev . copy ( ) : resolveSimple ( revstr ) ;
if ( rev ! = null )
return rev . copy ( ) ;
if ( name ! = null )
return name ;
name = revstr . substring ( done ) ;
if ( getRef ( name ) ! = null )
return name ;
return resolveSimple ( name ) ;
}
private static boolean isHex ( char c ) {
@ -634,6 +686,19 @@ public abstract class Repository {
return null ;
}
private String resolveReflogCheckout ( int checkoutNo )
throws IOException {
List < ReflogEntry > reflogEntries = new ReflogReader ( this , Constants . HEAD )
. getReverseEntries ( ) ;
for ( ReflogEntry entry : reflogEntries ) {
CheckoutEntry checkout = entry . parseCheckout ( ) ;
if ( checkout ! = null )
if ( checkoutNo - - = = 1 )
return checkout . getFromBranch ( ) ;
}
return null ;
}
private RevCommit resolveReflog ( RevWalk rw , Ref ref , String time )
throws IOException {
int number ;
@ -643,10 +708,7 @@ public abstract class Repository {
throw new RevisionSyntaxException ( MessageFormat . format (
JGitText . get ( ) . invalidReflogRevision , time ) ) ;
}
if ( number < 0 )
throw new RevisionSyntaxException ( MessageFormat . format (
JGitText . get ( ) . invalidReflogRevision , time ) ) ;
assert number > = 0 ;
ReflogReader reader = new ReflogReader ( this , ref . getName ( ) ) ;
ReflogEntry entry = reader . getReverseEntry ( number ) ;
if ( entry = = null )