11/*
2- * This file is part of git-commit-id-plugin by Konrad Malawski <konrad.malawski@java.pl>
2+ * This file is part of git-commit-id-plugin by Konrad 'ktoso' Malawski <konrad.malawski@java.pl>
33 *
44 * git-commit-id-plugin is free software: you can redistribute it and/or modify
55 * it under the terms of the GNU Lesser General Public License as published by
1818package pl .project13 .jgit ;
1919
2020import com .google .common .annotations .VisibleForTesting ;
21- import com .google .common .base .Function ;
2221import com .google .common .base .Optional ;
2322import com .google .common .base .Preconditions ;
24- import com .google .common .base .Throwables ;
25- import com .google .common .collect .Lists ;
23+
2624import org .eclipse .jgit .api .Git ;
2725import org .eclipse .jgit .api .GitCommand ;
2826import org .eclipse .jgit .api .Status ;
2927import org .eclipse .jgit .api .errors .GitAPIException ;
30- import org .eclipse .jgit .errors .IncorrectObjectTypeException ;
3128import org .eclipse .jgit .lib .ObjectId ;
3229import org .eclipse .jgit .lib .ObjectReader ;
33- import org .eclipse .jgit .lib .Ref ;
3430import org .eclipse .jgit .lib .Repository ;
3531import org .eclipse .jgit .revwalk .RevCommit ;
36- import org .eclipse .jgit .revwalk .RevTag ;
3732import org .eclipse .jgit .revwalk .RevWalk ;
3833import org .jetbrains .annotations .NotNull ;
3934import org .jetbrains .annotations .Nullable ;
35+
4036import pl .project13 .jgit .dummy .DatedRevTag ;
4137import pl .project13 .maven .git .GitDescribeConfig ;
4238import pl .project13 .maven .git .log .LoggerBridge ;
4541
4642import java .io .IOException ;
4743import java .util .*;
48- import java .util .regex .Pattern ;
49-
50- import static com .google .common .collect .Lists .newArrayList ;
51- import static com .google .common .collect .Lists .newLinkedList ;
52- import static com .google .common .collect .Maps .newHashMap ;
53- import static com .google .common .collect .Sets .newHashSet ;
5444
5545/**
5646 * Implements git's <pre>describe</pre> command.
57- *
58- * @author Konrad Malawski
5947 */
6048public class DescribeCommand extends GitCommand <DescribeResult > {
6149
6250 private LoggerBridge loggerBridge ;
51+ private JGitCommon jGitCommon ;
6352
64- // todo not yet implemented options:
53+ // TODO not yet implemented options:
6554// private boolean containsFlag = false;
6655// private boolean allFlag = false;
6756// private boolean tagsFlag = false;
@@ -116,6 +105,7 @@ private DescribeCommand(Repository repo, boolean verbose) {
116105 super (repo );
117106 initDefaultLoggerBridge (verbose );
118107 setVerbose (verbose );
108+ this .jGitCommon = new JGitCommon ();
119109 }
120110
121111 private void initDefaultLoggerBridge (boolean verbose ) {
@@ -305,7 +295,7 @@ public DescribeResult call() throws GitAPIException {
305295 }
306296
307297 // get commits, up until the nearest tag
308- List <RevCommit > commits = findCommitsUntilSomeTag (repo , headCommit , tagObjectIdToName );
298+ List <RevCommit > commits = jGitCommon . findCommitsUntilSomeTag (repo , headCommit , tagObjectIdToName );
309299
310300 // if there is no tags or any tag is not on that branch then return generic describe
311301 if (foundZeroTags (tagObjectIdToName ) || commits .isEmpty ()) {
@@ -315,7 +305,7 @@ public DescribeResult call() throws GitAPIException {
315305
316306 // check how far away from a tag we are
317307
318- int distance = distanceBetween (repo , headCommit , commits .get (0 ));
308+ int distance = jGitCommon . distanceBetween (repo , headCommit , commits .get (0 ));
319309 String tagName = tagObjectIdToName .get (commits .get (0 )).iterator ().next ();
320310 Pair <Integer , String > howFarFromWhichTag = Pair .of (distance , tagName );
321311
@@ -396,206 +386,14 @@ RevCommit findHeadObjectId(@NotNull Repository repo) throws RuntimeException {
396386 }
397387 }
398388
399- private List <RevCommit > findCommitsUntilSomeTag (Repository repo , RevCommit head , @ NotNull Map <ObjectId , List <String >> tagObjectIdToName ) {
400- RevWalk revWalk = new RevWalk (repo );
401- try {
402- revWalk .markStart (head );
403-
404- for (RevCommit commit : revWalk ) {
405- ObjectId objId = commit .getId ();
406- if (tagObjectIdToName .size () > 0 ) {
407- List <String > maybeList = tagObjectIdToName .get (objId );
408- if (maybeList != null && maybeList .get (0 ) != null ) {
409- return Collections .singletonList (commit );
410- }
411- }
412- }
413-
414- return Collections .emptyList ();
415- } catch (Exception e ) {
416- throw new RuntimeException ("Unable to find commits until some tag" , e );
417- }
418- }
419-
420- /**
421- * Calculates the distance (number of commits) between the given parent and child commits.
422- *
423- * @return distance (number of commits) between the given commits
424- * @see <a href="https://github.com/mdonoughe/jgit-describe/blob/master/src/org/mdonoughe/JGitDescribeTask.java">mdonoughe/jgit-describe/blob/master/src/org/mdonoughe/JGitDescribeTask.java</a>
425- */
426- private int distanceBetween (@ NotNull Repository repo , @ NotNull RevCommit child , @ NotNull RevCommit parent ) {
427- RevWalk revWalk = new RevWalk (repo );
428-
429- try {
430- revWalk .markStart (child );
431-
432- Set <ObjectId > seena = newHashSet ();
433- Set <ObjectId > seenb = newHashSet ();
434- Queue <RevCommit > q = newLinkedList ();
435-
436- q .add (revWalk .parseCommit (child ));
437- int distance = 0 ;
438- ObjectId parentId = parent .getId ();
439-
440- while (q .size () > 0 ) {
441- RevCommit commit = q .remove ();
442- ObjectId commitId = commit .getId ();
443-
444- if (seena .contains (commitId )) {
445- continue ;
446- }
447- seena .add (commitId );
448-
449- if (parentId .equals (commitId )) {
450- // don't consider commits that are included in this commit
451- seeAllParents (revWalk , commit , seenb );
452- // remove things we shouldn't have included
453- for (ObjectId oid : seenb ) {
454- if (seena .contains (oid )) {
455- distance --;
456- }
457- }
458- seena .addAll (seenb );
459- continue ;
460- }
461-
462- for (ObjectId oid : commit .getParents ()) {
463- if (!seena .contains (oid )) {
464- q .add (revWalk .parseCommit (oid ));
465- }
466- }
467- distance ++;
468- }
469-
470- return distance ;
471-
472- } catch (Exception e ) {
473- throw new RuntimeException (String .format ("Unable to calculate distance between [%s] and [%s]" , child , parent ), e );
474- } finally {
475- revWalk .dispose ();
476- }
477- }
478-
479- private static void seeAllParents (@ NotNull RevWalk revWalk , RevCommit child , @ NotNull Set <ObjectId > seen ) throws IOException {
480- Queue <RevCommit > q = newLinkedList ();
481- q .add (child );
482-
483- while (q .size () > 0 ) {
484- RevCommit commit = q .remove ();
485- for (ObjectId oid : commit .getParents ()) {
486- if (seen .contains (oid )) {
487- continue ;
488- }
489- seen .add (oid );
490- q .add (revWalk .parseCommit (oid ));
491- }
492- }
493- }
494-
495389 // git commit id -> its tag (or tags)
496390 private Map <ObjectId , List <String >> findTagObjectIds (@ NotNull Repository repo , boolean tagsFlag ) {
497- Map <ObjectId , List <DatedRevTag >> commitIdsToTags = newHashMap ();
498-
499- RevWalk walk = new RevWalk (repo );
500- try {
501- walk .markStart (walk .parseCommit (repo .resolve ("HEAD" )));
502-
503- List <Ref > tagRefs = Git .wrap (repo ).tagList ().call ();
504- String matchPattern = createMatchPattern ();
505- Pattern regex = Pattern .compile (matchPattern );
506- log ("Tag refs [" , tagRefs , "]" );
507-
508- for (Ref tagRef : tagRefs ) {
509- walk .reset ();
510- String name = tagRef .getName ();
511- if (!regex .matcher (name ).matches ()) {
512- log ("Skipping tagRef with name [" , name , "] as it doesn't match [" , matchPattern , "]" );
513- continue ;
514- }
515- ObjectId resolvedCommitId = repo .resolve (name );
516-
517- // todo that's a bit of a hack...
518- try {
519- final RevTag revTag = walk .parseTag (resolvedCommitId );
520- ObjectId taggedCommitId = revTag .getObject ().getId ();
521- log ("Resolved tag [" ,revTag .getTagName (),"] [" ,revTag .getTaggerIdent (),"], points at [" ,taggedCommitId ,"] " );
522-
523- // sometimes a tag, may point to another tag, so we need to unpack it
524- while (isTagId (taggedCommitId )) {
525- taggedCommitId = walk .parseTag (taggedCommitId ).getObject ().getId ();
526- }
527-
528- if (commitIdsToTags .containsKey (taggedCommitId )) {
529- commitIdsToTags .get (taggedCommitId ).add (new DatedRevTag (revTag ));
530- } else {
531- commitIdsToTags .put (taggedCommitId , newArrayList (new DatedRevTag (revTag )));
532- }
533-
534- } catch (IncorrectObjectTypeException ex ) {
535- // it's an lightweight tag! (yeah, really)
536- if (tagsFlag ) {
537- // --tags means "include lightweight tags"
538- log ("Including lightweight tag [" , name , "]" );
539-
540- DatedRevTag datedRevTag = new DatedRevTag (resolvedCommitId , name );
541-
542- if (commitIdsToTags .containsKey (resolvedCommitId )) {
543- commitIdsToTags .get (resolvedCommitId ).add (datedRevTag );
544- } else {
545- commitIdsToTags .put (resolvedCommitId , newArrayList (datedRevTag ));
546- }
547- }
548- } catch (Exception ignored ) {
549- error ("Failed while parsing [" ,tagRef ,"] -- " , Throwables .getStackTraceAsString (ignored ));
550- }
551- }
552-
553- for (Map .Entry <ObjectId , List <DatedRevTag >> entry : commitIdsToTags .entrySet ()) {
554- log ("key [" ,entry .getKey (),"], tags => [" ,entry .getValue (),"] " );
555- }
556-
557- Map <ObjectId , List <String >> commitIdsToTagNames = transformRevTagsMapToDateSortedTagNames (commitIdsToTags );
558-
391+ String matchPattern = createMatchPattern ();
392+ Map <ObjectId , List <DatedRevTag >> commitIdsToTags = jGitCommon .getCommitIdsToTags (loggerBridge , repo , tagsFlag , matchPattern );
393+ Map <ObjectId , List <String >> commitIdsToTagNames = jGitCommon .transformRevTagsMapToDateSortedTagNames (commitIdsToTags );
559394 log ("Created map: [" ,commitIdsToTagNames ,"] " );
560395
561396 return commitIdsToTagNames ;
562- } catch (Exception e ) {
563- log ("Unable to locate tags\n [" ,Throwables .getStackTraceAsString (e ),"]" );
564- } finally {
565- walk .release ();
566- }
567-
568- return Collections .emptyMap ();
569- }
570-
571- /** Checks if the given object id resolved to a tag object */
572- private boolean isTagId (ObjectId objectId ) {
573- return objectId .toString ().startsWith ("tag " );
574- }
575-
576- private HashMap <ObjectId , List <String >> transformRevTagsMapToDateSortedTagNames (Map <ObjectId , List <DatedRevTag >> commitIdsToTags ) {
577- HashMap <ObjectId , List <String >> commitIdsToTagNames = newHashMap ();
578- for (Map .Entry <ObjectId , List <DatedRevTag >> objectIdListEntry : commitIdsToTags .entrySet ()) {
579- List <DatedRevTag > tags = objectIdListEntry .getValue ();
580-
581- List <DatedRevTag > newTags = newArrayList (tags );
582- Collections .sort (newTags , new Comparator <DatedRevTag >() {
583- @ Override
584- public int compare (DatedRevTag revTag , DatedRevTag revTag2 ) {
585- return revTag2 .date .compareTo (revTag .date );
586- }
587- });
588-
589- List <String > tagNames = Lists .transform (newTags , new Function <DatedRevTag , String >() {
590- @ Override
591- public String apply (DatedRevTag input ) {
592- return trimFullTagName (input .tagName );
593- }
594- });
595-
596- commitIdsToTagNames .put (objectIdListEntry .getKey (), tagNames );
597- }
598- return commitIdsToTagNames ;
599397 }
600398
601399 private String createMatchPattern () {
@@ -610,18 +408,8 @@ private String createMatchPattern() {
610408 return buf .toString ();
611409 }
612410
613- @ VisibleForTesting
614- static String trimFullTagName (@ NotNull String tagName ) {
615- return tagName .replaceFirst ("refs/tags/" , "" );
616- }
617-
618411 private void log (Object ... parts ) {
619412 loggerBridge .log (parts );
620413 }
621-
622- private void error (Object ... parts ) {
623- loggerBridge .error (parts );
624- }
625-
626414}
627415
0 commit comments