Skip to content

Commit fecd5cc

Browse files
delta003iamdanfox
authored andcommitted
Improve JGit implementation (#91)
* test deep commit * Use more sensible revList() * Pass initial ObjectId into revlist * Create RevWalk inside comparator * Simplify branches in mapCommitsToTags
1 parent 2f88e87 commit fecd5cc

File tree

3 files changed

+62
-28
lines changed

3 files changed

+62
-28
lines changed

src/main/java/com/palantir/gradle/gitversion/JGitDescribe.java

+31-26
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import org.eclipse.jgit.lib.Constants;
55
import org.eclipse.jgit.lib.ObjectId;
66
import org.eclipse.jgit.lib.Ref;
7+
import org.eclipse.jgit.lib.Repository;
78
import org.eclipse.jgit.revwalk.RevCommit;
89
import org.eclipse.jgit.revwalk.RevWalk;
910
import org.slf4j.Logger;
1011
import org.slf4j.LoggerFactory;
1112

13+
import java.io.IOException;
1214
import java.util.ArrayList;
1315
import java.util.HashMap;
1416
import java.util.List;
@@ -33,22 +35,12 @@ public String describe(String prefix) {
3335
return null;
3436
}
3537

36-
RevCommit headCommit;
37-
RefWithTagNameComparator comparator;
3838
try {
3939
ObjectId headObjectId = git.getRepository().resolve(Constants.HEAD);
40-
RevWalk walk = new RevWalk(git.getRepository());
41-
headCommit = walk.parseCommit(headObjectId);
42-
comparator = new RefWithTagNameComparator(walk);
43-
} catch (Exception e) {
44-
log.debug("HEAD not found: {}", e);
45-
return null;
46-
}
4740

48-
try {
49-
List<String> revs = revList(headCommit);
41+
List<String> revs = revList(headObjectId);
5042

51-
Map<String, RefWithTagName> commitHashToTag = mapCommitsToTags(git, comparator);
43+
Map<String, RefWithTagName> commitHashToTag = mapCommitsToTags(git);
5244

5345
// Walk back commit ancestors looking for tagged one
5446
for (int depth = 0; depth < revs.size(); depth++) {
@@ -64,39 +56,52 @@ public String describe(String prefix) {
6456
}
6557

6658
// No tags found, so return commit hash of HEAD
67-
return GitUtils.abbrevHash(headCommit.toObjectId().getName());
59+
return GitUtils.abbrevHash(headObjectId.getName());
6860
} catch (Exception e) {
6961
log.debug("JGit describe failed with {}", e);
7062
return null;
7163
}
7264
}
7365

7466
// Mimics 'git rev-list --first-parent <commit>'
75-
private List<String> revList(RevCommit commit) {
76-
List<String> revs = new ArrayList<>();
77-
while (commit != null) {
78-
revs.add(commit.getName());
79-
try {
80-
// There is no way to check if this exists without failing
81-
commit = commit.getParent(0);
82-
} catch (Exception ignored) {
83-
break;
67+
private List<String> revList(ObjectId initialObjectId) throws IOException {
68+
ArrayList<String> revs = new ArrayList<>();
69+
70+
Repository repo = git.getRepository();
71+
try (RevWalk walk = new RevWalk(repo)) {
72+
RevCommit head = walk.parseCommit(initialObjectId);
73+
74+
while (true) {
75+
revs.add(head.getName());
76+
77+
RevCommit[] parents = head.getParents();
78+
if (parents == null || parents.length == 0) {
79+
break;
80+
}
81+
82+
head = walk.parseCommit(parents[0]);
8483
}
8584
}
85+
8686
return revs;
8787
}
8888

8989
// Maps all commits returned by 'git show-ref --tags -d' to output of 'git describe --tags --exact-match <commit>'
90-
private Map<String, RefWithTagName> mapCommitsToTags(Git git, RefWithTagNameComparator comparator) {
90+
private Map<String, RefWithTagName> mapCommitsToTags(Git git) {
91+
RefWithTagNameComparator comparator = new RefWithTagNameComparator(git);
92+
9193
// Maps commit hash to list of all refs pointing to given commit hash.
9294
// All keys in this map should be same as commit hashes in 'git show-ref --tags -d'
9395
Map<String, RefWithTagName> commitHashToTag = new HashMap<>();
9496
for (Map.Entry<String, Ref> entry : git.getRepository().getTags().entrySet()) {
9597
RefWithTagName refWithTagName = new RefWithTagName(entry.getValue(), entry.getKey());
96-
updateCommitHashMap(commitHashToTag, comparator, entry.getValue().getObjectId(), refWithTagName);
97-
// Also add dereferenced commit hash if exists
98+
9899
ObjectId peeledRef = refWithTagName.getRef().getPeeledObjectId();
99-
if (peeledRef != null) {
100+
if (peeledRef == null) {
101+
// lightweight tag (commit object)
102+
updateCommitHashMap(commitHashToTag, comparator, entry.getValue().getObjectId(), refWithTagName);
103+
} else {
104+
// annotated tag (tag object)
100105
updateCommitHashMap(commitHashToTag, comparator, peeledRef, refWithTagName);
101106
}
102107
}

src/main/java/com/palantir/gradle/gitversion/RefWithTagNameComparator.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.palantir.gradle.gitversion;
22

3+
import org.eclipse.jgit.api.Git;
34
import org.eclipse.jgit.lib.PersonIdent;
45
import org.eclipse.jgit.lib.Ref;
56
import org.eclipse.jgit.revwalk.RevTag;
@@ -20,8 +21,8 @@ class RefWithTagNameComparator implements Comparator<RefWithTagName> {
2021

2122
private final RevWalk walk;
2223

23-
RefWithTagNameComparator(RevWalk walk) {
24-
this.walk = walk;
24+
RefWithTagNameComparator(Git git) {
25+
this.walk = new RevWalk(git.getRepository());
2526
}
2627

2728
@Override

src/test/groovy/com/palantir/gradle/gitversion/GitVersionPluginTests.groovy

+28
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,34 @@ class GitVersionPluginTests extends Specification {
656656
buildResult.output.contains(":printVersion\n1.0.0\n")
657657
}
658658

659+
def 'test tag set on deep commit' () {
660+
given:
661+
buildFile << '''
662+
plugins {
663+
id 'com.palantir.git-version'
664+
}
665+
version gitVersion()
666+
'''.stripIndent()
667+
gitIgnoreFile << 'build'
668+
Git git = Git.init().setDirectory(projectDir).call()
669+
git.add().addFilepattern('.').call()
670+
RevCommit latestCommit = git.commit().setMessage('initial commit').call()
671+
git.tag().setAnnotated(true).setMessage('1.0.0').setName('1.0.0').call()
672+
673+
int depth = 100
674+
for (int i = 0; i < depth; i++) {
675+
git.add().addFilepattern('.').call()
676+
latestCommit = git.commit().setMessage('commit-' + i).call()
677+
}
678+
679+
when:
680+
BuildResult buildResult = with('printVersion').build()
681+
String commitSha = latestCommit.getName()
682+
683+
then:
684+
buildResult.output.contains(":printVersion\n1.0.0-${depth}-g${commitSha.substring(0, 7)}\n")
685+
}
686+
659687
private GradleRunner with(String... tasks) {
660688
List<String> arguments = new ArrayList<>(['--stacktrace'])
661689
arguments.addAll(tasks)

0 commit comments

Comments
 (0)