qoomon/gradle-git-versioning-plugin

Plugin does not detect merged tags

Florianisme opened this issue · 8 comments

Consider the following git branch and merge history:

image

git describe --tags correctly returns the merged 1.1.0 tag, however running the plugin with gradlew version -q only detects the initial 0.0.1 tag.

Hi thanks for reporting. Currently it is the behaviour of git describe --tags --first-parent I'll try to implement git describe --tags

It is more complicated than I thought. There a several if I don't follow --first-parent only.

  • Versioning gets strange if a tag v2 is set on main branch and you merge a branch with a tag v1
    • which tag should be used?
    • the nearest one, the latest one or the one with the highest version number (split and sort by dots)?

I think the most stable solution is to have the current behaviour git describe --tags --first-parent

Can you make it configurable then?
I think it should use the nearest one, I believe that's what git describe --tags does.

I use tagging in my projects like I described earlier so I sadly can't use this otherwise great plugin.

It feels like git describe isn't a good choice for versioning at all :-)
maybe a placeholder like ${anchor.versionTag} (get the highest version tag reachable from HEAD) would be better and utillize org.apache.maven.artifact.versioning.DefaultArtifactVersion.compare function

Yes that would fit my usecase!
Can the "next"-(major, minor, patch) feature be applied to that aswell? I found that super useful.

It is harder to implement than I thought. Any support is welcome. I need to copy and modify following function to search for all first reachable tags on all branches and select the the one with the highest version (this is the simple part and can be done by org.apache.maven.artifact.versioning.DefaultArtifactVersion)

public static GitDescription describe(ObjectId revObjectId, Pattern tagPattern, Repository repository) throws IOException {

Somthing I threw together this evening as a super dirty proof-of-concept:

public static GitDescription describe(Repository repository, ObjectId revObjectId, Pattern tagPattern,
                                          Map<ObjectId, List<Ref>> reverseTagRefMap) throws IOException {

        if (revObjectId == null) {
            return new GitDescription(NO_COMMIT, "root", 0);
        }
        RevWalk walk = new RevWalk(repository);
        RevCommit start = walk.parseCommit(revObjectId); // mostly head

        Map<Integer, List<Map.Entry<ObjectId, List<Ref>>>> tagsByDistanceToRev = reverseTagRefMap.entrySet().stream()
                .collect(groupingBy(entry -> countDistanceToTagRef(walk, start, entry)));

        Optional<Ref> possibleNearestTag = tagsByDistanceToRev
                .entrySet().stream()
                .filter(entry -> entry.getKey() >= 0)
                .sorted(Comparator.comparingInt(Map.Entry::getKey))
                .limit(1)
                .map(Map.Entry::getValue)
                .map(tagRefMap -> tagRefMap.get(0))
                .map(Map.Entry::getValue)
                .map(tags -> tags.stream()
                        .sorted(new TagComparator(repository))
                        .filter(tag -> tagPattern.matcher(shortenRefName(tag.getName())).matches())
                        .findFirst().orElse(null))
                .findFirst();
....
....
}


    private static int countDistanceToTagRef(RevWalk walk, RevCommit start, Map.Entry<ObjectId, List<Ref>> entry) {
        try {
            return RevWalkUtils.count(walk, start, walk.parseCommit(entry.getKey()));
        } catch (IOException e) {
            return -1;
        }
    }

Seems to work with the one Unit tests thats testing this method.
I might try to clean it up and add some more tests in the next few days.

@Florianisme feel free to test version 6.4.0 and the new option describeTagFirstParent