Skip to content

Commit 1f60eda

Browse files
iamdanfoxuschi2000
authored andcommitted
Add VersionDetails#isCleanTag (#58)
1 parent 039618a commit 1f60eda

File tree

5 files changed

+199
-122
lines changed

5 files changed

+199
-122
lines changed

readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ details.lastTag
3636
details.commitDistance
3737
details.gitHash
3838
details.branchName // is null if the repository in detached HEAD mode
39+
details.isCleanTag
3940
```
4041

4142
Tasks
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2015 Palantir Technologies
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* <http://www.apache.org/licenses/LICENSE-2.0>
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.palantir.gradle.gitversion
17+
18+
class GitCli {
19+
private GitCli() {}
20+
21+
static void verifyGitCommandExists() {
22+
Process gitVersionProcess = new ProcessBuilder("git", "version").start()
23+
if (gitVersionProcess.waitFor() != 0) {
24+
throw new IllegalStateException("error invoking git command")
25+
}
26+
}
27+
28+
static String runGitCommand(File dir, String... commands) {
29+
List<String> cmdInput = new ArrayList<>()
30+
cmdInput.add("git")
31+
cmdInput.addAll(commands)
32+
ProcessBuilder pb = new ProcessBuilder(cmdInput)
33+
pb.directory(dir)
34+
pb.redirectErrorStream(true)
35+
36+
Process process = pb.start()
37+
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
38+
39+
StringBuilder builder = new StringBuilder()
40+
String line = null
41+
while ((line = reader.readLine()) != null) {
42+
builder.append(line)
43+
builder.append(System.getProperty("line.separator"))
44+
}
45+
46+
int exitCode = process.waitFor()
47+
if (exitCode != 0) {
48+
return ""
49+
}
50+
51+
return builder.toString().trim()
52+
}
53+
54+
static File getRootGitDir(File currentRoot) {
55+
File gitDir = scanForRootGitDir(currentRoot)
56+
if (!gitDir.exists()) {
57+
throw new IllegalArgumentException('Cannot find \'.git\' directory')
58+
}
59+
return gitDir
60+
}
61+
62+
private static File scanForRootGitDir(File currentRoot) {
63+
File gitDir = new File(currentRoot, '.git')
64+
65+
if (gitDir.exists()) {
66+
return gitDir
67+
}
68+
69+
// stop at the root directory, return non-existing File object
70+
if (currentRoot.parentFile == null) {
71+
return gitDir
72+
}
73+
74+
// look in parent directory
75+
return scanForRootGitDir(currentRoot.parentFile)
76+
}
77+
}

src/main/groovy/com/palantir/gradle/gitversion/GitVersionPlugin.groovy

+44-108
Original file line numberDiff line numberDiff line change
@@ -20,153 +20,89 @@ import org.eclipse.jgit.api.DescribeCommand
2020
import org.eclipse.jgit.api.Git
2121
import org.eclipse.jgit.internal.storage.file.FileRepository
2222
import org.eclipse.jgit.lib.Constants
23+
import org.eclipse.jgit.lib.ObjectId
24+
import org.eclipse.jgit.lib.Ref
2325
import org.gradle.api.Plugin
2426
import org.gradle.api.Project
2527

26-
import java.util.regex.Matcher
27-
2828
class GitVersionPlugin implements Plugin<Project> {
2929

30-
// Gradle returns 'unspecified' when no version is set
31-
private static final String UNSPECIFIED_VERSION = 'unspecified'
3230
private static final int VERSION_ABBR_LENGTH = 10
3331

32+
void apply(Project project) {
33+
project.ext.gitVersion = {
34+
return versionDetails(project).version
35+
}
36+
37+
project.ext.versionDetails = {
38+
return versionDetails(project)
39+
}
40+
41+
project.tasks.create('printVersion') {
42+
group = 'Versioning'
43+
description = 'Prints the project\'s configured version to standard out'
44+
doLast {
45+
println project.version
46+
}
47+
}
48+
}
49+
3450
@Memoized
35-
private File gitDir(Project project) {
36-
return getRootGitDir(project.rootDir)
51+
private VersionDetails versionDetails(Project project) {
52+
String description = gitDescribe(project)
53+
String hash = gitHash(project)
54+
String branchName = gitBranchName(project)
55+
boolean isClean = isClean(project)
56+
57+
return new VersionDetails(description, hash, branchName, isClean)
3758
}
3859

3960
@Memoized
4061
private Git gitRepo(Project project) {
41-
return Git.wrap(new FileRepository(gitDir(project)))
62+
File gitDir = GitCli.getRootGitDir(project.rootDir);
63+
return Git.wrap(new FileRepository(gitDir))
4264
}
4365

4466
@Memoized
45-
private String gitDesc(Project project) {
67+
private String gitDescribe(Project project) {
4668
// verify that "git" command exists (throws exception if it does not)
47-
verifyGitCommandExists()
69+
GitCli.verifyGitCommandExists()
4870

4971
Git git = gitRepo(project)
5072
try {
5173
// back-compat: the JGit "describe" command throws an exception in repositories with no commits, so call it
5274
// first to preserve this behavior in cases where this call would fail but native "git" call does not.
5375
new DescribeCommand(git.getRepository()).call()
5476

55-
String version = runGitCommand(project.rootDir, "describe", "--tags", "--always", "--first-parent") ?: UNSPECIFIED_VERSION
56-
boolean isClean = git.status().call().isClean()
57-
return version + (isClean ? '' : '.dirty')
77+
return GitCli.runGitCommand(project.rootDir, "describe", "--tags", "--always", "--first-parent")
5878
} catch (Throwable t) {
59-
return UNSPECIFIED_VERSION
79+
return null
6080
}
6181
}
6282

6383
@Memoized
6484
private String gitHash(Project project) {
6585
Git git = gitRepo(project)
66-
return git.getRepository().getRef("HEAD").getObjectId().abbreviate(VERSION_ABBR_LENGTH).name()
86+
ObjectId objectId = git.getRepository().getRef("HEAD").getObjectId();
87+
if (objectId == null) {
88+
return null
89+
}
90+
return objectId.abbreviate(VERSION_ABBR_LENGTH).name()
6791
}
6892

6993
@Memoized
7094
private String gitBranchName(Project project) {
7195
Git git = gitRepo(project)
72-
def ref = git.repository.getRef(git.repository.branch)
96+
Ref ref = git.getRepository().getRef(git.repository.branch)
7397
if (ref == null) {
7498
return null
75-
} else {
76-
return ref.getName().substring(Constants.R_HEADS.length())
7799
}
100+
return ref.getName().substring(Constants.R_HEADS.length())
78101
}
79102

80-
void apply(Project project) {
81-
project.ext.gitVersion = {
82-
return gitDesc(project)
83-
}
84-
85-
project.ext.versionDetails = {
86-
String description = gitDesc(project)
87-
if (description.equals(UNSPECIFIED_VERSION)) {
88-
return null
89-
}
90-
91-
String hash = gitHash(project)
92-
String branchName = gitBranchName(project)
93-
94-
if (!(description =~ /.*g.?[0-9a-fA-F]{3,}/)) {
95-
// Description has no git hash so it is just the tag name
96-
return new VersionDetails(description, 0, hash, branchName)
97-
}
98-
99-
Matcher match = (description =~ /(.*)-([0-9]+)-g.?[0-9a-fA-F]{3,}/)
100-
String tagName = match[0][1]
101-
int commitCount = Integer.valueOf(match[0][2])
102-
103-
return new VersionDetails(tagName, commitCount, hash, branchName)
104-
}
105-
106-
project.tasks.create('printVersion') {
107-
group = 'Versioning'
108-
description = 'Prints the project\'s configured version to standard out'
109-
doLast {
110-
println project.version
111-
}
112-
}
113-
}
114-
115-
private static File getRootGitDir(currentRoot) {
116-
File gitDir = scanForRootGitDir(currentRoot)
117-
if (!gitDir.exists()) {
118-
throw new IllegalArgumentException('Cannot find \'.git\' directory')
119-
}
120-
return gitDir
121-
}
122-
123-
private static File scanForRootGitDir(File currentRoot) {
124-
File gitDir = new File(currentRoot, '.git')
125-
126-
if (gitDir.exists()) {
127-
return gitDir
128-
}
129-
130-
// stop at the root directory, return non-existing File object
131-
if (currentRoot.parentFile == null) {
132-
return gitDir
133-
}
134-
135-
// look in parent directory
136-
return scanForRootGitDir(currentRoot.parentFile)
137-
}
138-
139-
private static void verifyGitCommandExists() {
140-
Process gitVersionProcess = new ProcessBuilder("git", "version").start()
141-
if (gitVersionProcess.waitFor() != 0) {
142-
throw new IllegalStateException("error invoking git command")
143-
}
144-
}
145-
146-
private static String runGitCommand(File dir, String ...commands) {
147-
List<String> cmdInput = new ArrayList<>()
148-
cmdInput.add("git")
149-
cmdInput.addAll(commands)
150-
ProcessBuilder pb = new ProcessBuilder(cmdInput)
151-
pb.directory(dir)
152-
pb.redirectErrorStream(true)
153-
154-
Process process = pb.start()
155-
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
156-
157-
StringBuilder builder = new StringBuilder()
158-
String line = null
159-
while ((line = reader.readLine()) != null) {
160-
builder.append(line)
161-
builder.append(System.getProperty("line.separator"))
162-
}
163-
164-
int exitCode = process.waitFor()
165-
if (exitCode != 0) {
166-
return ""
167-
}
168-
169-
return builder.toString().trim()
103+
@Memoized
104+
private boolean isClean(Project project) {
105+
Git git = gitRepo(project)
106+
return git.status().call().isClean();
170107
}
171-
172108
}

src/main/groovy/com/palantir/gradle/gitversion/VersionDetails.groovy

+46-10
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,61 @@ package com.palantir.gradle.gitversion;
1717

1818
import groovy.transform.*
1919

20-
/**
21-
* POGO containing the tag name and commit count that make
22-
* up the version string.
23-
*/
20+
import java.util.regex.Matcher
21+
2422
@ToString
2523
@EqualsAndHashCode
2624
class VersionDetails implements Serializable {
25+
26+
// Gradle returns 'unspecified' when no version is set
27+
private static final String UNSPECIFIED_VERSION = 'unspecified'
2728
private static final long serialVersionUID = -7340444937169877612L;
2829

29-
final String lastTag;
30-
final int commitDistance;
30+
final String description;
3131
final String gitHash;
3232
final String branchName;
33+
final boolean isClean;
3334

34-
public VersionDetails(String lastTag, int commitDistance, String gitHash, String branchName) {
35-
this.lastTag = lastTag;
36-
this.commitDistance = commitDistance;
35+
public VersionDetails(String description, String gitHash, String branchName, boolean isClean) {
36+
this.description = description;
3737
this.gitHash = gitHash;
38-
this.branchName = branchName
38+
this.branchName = branchName;
39+
this.isClean = isClean;
40+
}
41+
42+
public String getVersion() {
43+
if (description == null) {
44+
return UNSPECIFIED_VERSION
45+
}
46+
47+
return description + (isClean ? '' : '.dirty')
48+
}
49+
50+
public boolean getIsCleanTag() {
51+
return isClean && descriptionIsPlainTag();
3952
}
4053

54+
public int getCommitDistance() {
55+
if (descriptionIsPlainTag()) {
56+
return 0;
57+
}
58+
59+
Matcher match = (description =~ /(.*)-([0-9]+)-g.?[0-9a-fA-F]{3,}/)
60+
int commitCount = Integer.valueOf(match[0][2])
61+
return commitCount;
62+
}
63+
64+
public String getLastTag() {
65+
if (descriptionIsPlainTag()) {
66+
return description;
67+
}
68+
69+
Matcher match = (description =~ /(.*)-([0-9]+)-g.?[0-9a-fA-F]{3,}/)
70+
String tagName = match[0][1]
71+
return tagName;
72+
}
73+
74+
private boolean descriptionIsPlainTag() {
75+
return !(description =~ /.*g.?[0-9a-fA-F]{3,}/);
76+
}
4177
}

0 commit comments

Comments
 (0)