@ -47,11 +47,13 @@ import static org.eclipse.jgit.lib.Constants.R_TAGS;
import java.io.IOException ;
import java.text.MessageFormat ;
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.Comparator ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
import java.util.Optional ;
import java.util.stream.Collectors ;
import org.eclipse.jgit.api.errors.GitAPIException ;
import org.eclipse.jgit.api.errors.JGitInternalException ;
@ -197,17 +199,34 @@ public class DescribeCommand extends GitCommand<String> {
return this ;
}
private boolean tagMatches ( Ref tag ) {
if ( tag = = null ) {
return false ;
private Optional < Ref > getBestMatch ( List < Ref > tags ) {
if ( tags = = null | | tags . size ( ) = = 0 ) {
return Optional . empty ( ) ;
} else if ( matchers . size ( ) = = 0 ) {
return true ;
// No matchers, simply return the first tag entry
return Optional . of ( tags . get ( 0 ) ) ;
} else {
return matchers . stream ( )
. anyMatch ( m - > m . matches ( tag . getName ( ) , false ) ) ;
// Find the first tag that matches one of the matchers; precedence according to matcher definition order
for ( IMatcher matcher : matchers ) {
Optional < Ref > match = tags . stream ( )
. filter ( tag - > matcher . matches ( tag . getName ( ) , false ) )
. findFirst ( ) ;
if ( match . isPresent ( ) ) {
return match ;
}
}
return Optional . empty ( ) ;
}
}
private ObjectId getObjectIdFromRef ( Ref r ) {
ObjectId key = repo . peel ( r ) . getPeeledObjectId ( ) ;
if ( key = = null ) {
key = r . getObjectId ( ) ;
}
return key ;
}
/ * *
* Describes the specified commit . Target defaults to HEAD if no commit was
* set explicitly .
@ -228,14 +247,9 @@ public class DescribeCommand extends GitCommand<String> {
if ( target = = null )
setTarget ( Constants . HEAD ) ;
Map < ObjectId , Ref > tags = new HashMap < > ( ) ;
for ( Ref r : repo . getRefDatabase ( ) . getRefs ( R_TAGS ) . values ( ) ) {
ObjectId key = repo . peel ( r ) . getPeeledObjectId ( ) ;
if ( key = = null )
key = r . getObjectId ( ) ;
tags . put ( key , r ) ;
}
Collection < Ref > tagList = repo . getRefDatabase ( ) . getRefs ( R_TAGS ) . values ( ) ;
Map < ObjectId , List < Ref > > tags = tagList . stream ( )
. collect ( Collectors . groupingBy ( this : : getObjectIdFromRef ) ) ;
// combined flags of all the candidate instances
final RevFlagSet allFlags = new RevFlagSet ( ) ;
@ -281,11 +295,11 @@ public class DescribeCommand extends GitCommand<String> {
}
List < Candidate > candidates = new ArrayList < > ( ) ; // all the candidates we find
// is the target already pointing to a tag? if so, we are done!
Ref tagOnTarget = tags . get ( target ) ;
if ( tagMatches ( tagOnTarget ) ) {
return longDesc ? longDescription ( tagOnTarget , 0 , target ) : tagOnTarget
. getName ( ) . substring ( R_TAGS . length ( ) ) ;
// is the target already pointing to a suitable tag? if so, we are done!
Optional < Ref > bestMatch = getBestMatch ( tags . get ( target ) ) ;
if ( bestMatch . isPresent ( ) ) {
return longDesc ? longDescription ( bestMatch . get ( ) , 0 , target ) :
bestMatch . get ( ) . getName ( ) . substring ( R_TAGS . length ( ) ) ;
}
w . markStart ( target ) ;
@ -297,9 +311,9 @@ public class DescribeCommand extends GitCommand<String> {
// if a tag already dominates this commit,
// then there's no point in picking a tag on this commit
// since the one that dominates it is always more preferable
Ref t = tags . get ( c ) ;
if ( tagMatches ( t ) ) {
Candidate cd = new Candidate ( c , t ) ;
bestMatch = getBestMatch ( tags . get ( c ) ) ;
if ( bestMatch . isPresent ( ) ) {
Candidate cd = new Candidate ( c , bes tMatch . get ( ) ) ;
candidates . add ( cd ) ;
cd . depth = seen ;
}