Skip to content

Commit d69c31e

Browse files
committed
Add --commit argument to allow specifying which commit/reference to use instead of HEAD
Migrate cli code to sub-project so Eclipse works Relocate all shaded libraries
1 parent 43f09d3 commit d69c31e

File tree

10 files changed

+143
-37
lines changed

10 files changed

+143
-37
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
/output/
1515

1616
# Jonathan's IntelliJ Fuckery
17-
/.idea/
17+
/**/.idea/

build.gradle

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,10 @@ java {
2424
withSourcesJar()
2525
}
2626

27-
final cli = sourceSets.create('cli')
28-
2927
configurations {
30-
dependencyScope('cliShadowImplementation')
31-
dependencyScope('cliShadowRuntimeOnly')
32-
33-
resolvable('cliShadowClasspath') {
34-
extendsFrom cliShadowImplementation, cliShadowRuntimeOnly
35-
}
36-
37-
named(cli.runtimeClasspathConfigurationName) {
38-
extendsFrom runtimeClasspath
39-
}
40-
41-
named(cli.implementationConfigurationName) {
42-
extendsFrom cliShadowImplementation
43-
}
44-
45-
named(cli.runtimeOnlyConfigurationName) {
46-
extendsFrom cliShadowRuntimeOnly
47-
}
28+
cli {
29+
extendsFrom implementation
30+
}
4831
}
4932

5033
dependencies {
@@ -60,10 +43,7 @@ dependencies {
6043
// JSON Output
6144
implementation libs.gson
6245

63-
// CLI
64-
cliImplementation sourceSets.main.output
65-
cliShadowImplementation libs.jopt
66-
cliShadowRuntimeOnly libs.slf4j
46+
cli project(':gitversion-cli')
6747
}
6848

6949
license {
@@ -93,10 +73,27 @@ tasks.named('shadowJar', ShadowJar) {
9373
}
9474

9575
archiveClassifier = 'fatjar'
96-
from cli.output
97-
configurations = provider { [ project.configurations.getByName('runtimeClasspath'), project.configurations.getByName('cliShadowClasspath') ] }
9876

99-
minimize()
77+
configurations = project.configurations.named('cli').map { [it] }
78+
79+
enableAutoRelocation = true
80+
relocationPrefix = 'net.minecraftforge.gitver.shadow'
81+
relocate('net.minecraftforge.gitver', 'net.minecraftforge.gitver')
82+
// Rewrite JOpt's message files, so that help text is displayed nicely.
83+
transform(com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer) {
84+
paths = [ 'Messages.properties$' ]
85+
keyTransformer = { key -> 'net.minecraftforge.gitver.shadow.' + key }
86+
}
87+
transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer)
88+
transform(com.github.jengelman.gradle.plugins.shadow.transformers.ServiceFileTransformer)
89+
90+
minimize {
91+
exclude(project(':gitversion-cli'))
92+
}
93+
94+
exclude('OSGI-INF/**')
95+
exclude('META-INF/maven/**')
96+
exclude('META-INF/proguard/**')
10097
}
10198

10299
changelog {

gitversion-cli/build.gradle

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
plugins {
2+
id 'application'
3+
}
4+
5+
group = 'net.minecraftforge'
6+
version = gitversion.tagOffset
7+
8+
java {
9+
toolchain.languageVersion = JavaLanguageVersion.of(17)
10+
withSourcesJar()
11+
}
12+
13+
application {
14+
mainClass = 'net.minecraftforge.gitver.cli.Main'
15+
}
16+
17+
dependencies {
18+
implementation rootProject
19+
implementation libs.jopt
20+
runtimeOnly libs.slf4j
21+
}
File renamed without changes.

src/cli/java/net/minecraftforge/gitver/cli/Main.java renamed to gitversion-cli/src/main/java/net/minecraftforge/gitver/cli/Main.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ The root directory to use (ideally containing the .git directory).
8383
If the generated changelog should be in plain text instead of Markdown.""")
8484
.availableIf(changelogO);
8585

86+
var commitO = parser.accepts("commit",
87+
"The commit or reference to use instead of HEAD")
88+
.availableUnless(changelogO)
89+
.withRequiredArg().ofType(String.class);
90+
8691
var jsonO = parser.accepts("json",
8792
"""
8893
Use to output the Git Version info as JSON.
@@ -103,13 +108,15 @@ The root directory to use (ideally containing the .git directory).
103108
var rootDir = options.valueOfOptional(rootDir0).orElse(null);
104109
var gitDir = options.valueOfOptional(gitDir0).orElse(null);
105110
var output = options.valueOfOptional(outputO).orElse(null);
111+
var commit = options.valueOfOptional(commitO).orElse(null);
106112
try (var version = GitVersion
107113
.builder()
108114
.gitDir(gitDir)
109115
.root(rootDir)
110116
.project(projectDir)
111117
.config(configFile)
112118
.strict(strict)
119+
.commit(commit)
113120
.build()
114121
) {
115122
String result;

settings.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ dependencyResolutionManagement {
2727
versionCatalogs.register('libs') {
2828
// Plugins
2929
plugin 'licenser', 'net.minecraftforge.licenser' version '1.2.0'
30-
plugin 'gradleutils', 'net.minecraftforge.gradleutils' version '3.3.33'
30+
plugin 'gradleutils', 'net.minecraftforge.gradleutils' version '3.4.1'
3131
plugin 'shadow', 'com.gradleup.shadow' version '9.2.2'
3232

3333
// Git
@@ -37,7 +37,7 @@ dependencyResolutionManagement {
3737
library 'toml', 'org.tomlj', 'tomlj' version '1.1.1'
3838

3939
// JSON Output
40-
library 'gson', 'com.google.code.gson', 'gson' version '2.13.1'
40+
library 'gson', 'com.google.code.gson', 'gson' version '2.13.2'
4141

4242
// CLI
4343
library 'jopt', 'net.sf.jopt-simple', 'jopt-simple' version '6.0-alpha-3'
@@ -48,3 +48,5 @@ dependencyResolutionManagement {
4848
}
4949
//@formatter:on
5050
}
51+
52+
include 'gitversion-cli'

src/main/java/net/minecraftforge/gitver/api/GitVersion.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ sealed interface Builder permits GitVersionInternal.Builder {
7878

7979
Builder strict(boolean strict);
8080

81+
Builder commit(@Nullable String ref);
82+
8183
/**
8284
* Builds the GitVersion instance.
8385
*

src/main/java/net/minecraftforge/gitver/internal/GitUtils.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,31 @@ static int countCommits(Git git, String tag, String tagPrefix, Iterable<String>
8484
return countCommits(git, GitUtils.getCommitToTagMap(git), ObjectId.fromString(commitHash), tagPrefix, includePaths, excludePaths);
8585
}
8686

87+
/**
88+
* Counts commits, for the given Git repository, from the given tag to {@linkplain Constants#HEAD HEAD}. If the
89+
* given tag cannot be found, this method will return {@code -1}.
90+
* <p>
91+
* See {@link #countCommits(Git, Map, ObjectId, String, Iterable, Iterable)} for more information.
92+
*
93+
* @param git The git repository to count commits in
94+
* @param tag The tag name to start counting from
95+
* @param to The object ID (typically a commit or tag reference) to stop counting at, typically HEAD
96+
* @param includePaths The paths to include in the count
97+
* @param excludePaths The paths to exclude from the count
98+
* @return The commit count
99+
* @throws GitAPIException If an error occurs when running the log command (see
100+
* {@link org.eclipse.jgit.api.LogCommand#call() LogCommand.call()}
101+
* @throws IOException If an I/O error occurs when reading the Git repository
102+
* @see #countCommits(Git, Map, ObjectId, String, Iterable, Iterable)
103+
*/
104+
static int countCommits(Git git, String tag, ObjectId to, String tagPrefix, Iterable<String> includePaths, Iterable<String> excludePaths) throws GitAPIException, IOException {
105+
var tags = GitUtils.getTagToCommitMap(git);
106+
var commitHash = tags.get(tag);
107+
if (commitHash == null) return -1;
108+
109+
return countCommits(git, GitUtils.getCommitToTagMap(git), ObjectId.fromString(commitHash), to, tagPrefix, includePaths, excludePaths);
110+
}
111+
87112
/**
88113
* Counts commits, for the given Git repository, from the given object ID to {@linkplain Constants#HEAD HEAD}.
89114
* Additional paths can be given to include or exclude from the count.
@@ -108,6 +133,31 @@ static int countCommits(Git git, Map<String, String> commitsToTags, ObjectId fro
108133
return Util.count(getCommitLogFromTo(git, commitsToTags, from, getHead(git), tagPrefix, includePaths, excludePaths));
109134
}
110135

136+
/**
137+
* Counts commits, for the given Git repository, from the given object ID to the other given object ID..
138+
* Additional paths can be given to include or exclude from the count.
139+
* <p>
140+
* An important detail to note is that the commit given is <strong>not included</strong> in the count. This means
141+
* that if the given commit is also the HEAD, the returned count will be {@code 0}. Additionally, if there are no
142+
* commits barring the paths given from the object ID, the count will be {@code -1}. Please handle this
143+
* accordingly.
144+
*
145+
* @param git The git repository to count commits in
146+
* @param from The object ID (typically a commit or tag reference) to start counting from
147+
* @param to The object ID (typically a commit or tag reference) to stop counting at, typically HEAD
148+
* @param includePaths The paths to include in the count
149+
* @param excludePaths The paths to exclude from the count
150+
* @return The commit count
151+
* @throws GitAPIException If an error occurs when running the log command (see
152+
* {@link org.eclipse.jgit.api.LogCommand#call() LogCommand.call()}
153+
* @throws IOException If an I/O error occurs when reading the Git repository
154+
* @see org.eclipse.jgit.api.LogCommand LogCommand
155+
* @see <a href="https://git-scm.com/docs/git-log"><code>git-log</code></a>
156+
*/
157+
static int countCommits(Git git, Map<String, String> commitsToTags, ObjectId from, ObjectId to, String tagPrefix, Iterable<String> includePaths, Iterable<String> excludePaths) throws GitAPIException, IOException {
158+
return Util.count(getCommitLogFromTo(git, commitsToTags, from, to, tagPrefix, includePaths, excludePaths));
159+
}
160+
111161
/**
112162
* Gets the {@linkplain Constants#HEAD HEAD} commit of the given Git repository.
113163
*

src/main/java/net/minecraftforge/gitver/internal/GitVersionImpl.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
import java.util.Objects;
3030
import java.util.Set;
3131
import java.util.function.Function;
32-
import java.util.function.Predicate;
3332

3433
public final class GitVersionImpl implements GitVersionInternal {
3534
// Git
3635
private final boolean strict;
36+
private final @Nullable String commit;
3737
private Git git;
3838
private final Lazy<Info> info = Lazy.of(() -> this.calculateInfo(this::getSubprojectCommitCount));
3939
private final Lazy<String> url = Lazy.of(this::calculateUrl);
@@ -61,8 +61,9 @@ public final class GitVersionImpl implements GitVersionInternal {
6161
private final Set<String> allIncludingPaths;
6262
private final Set<String> allExcludingPaths;
6363

64-
public GitVersionImpl(File gitDir, File root, File project, GitVersionConfig config, boolean strict) {
64+
public GitVersionImpl(File gitDir, File root, File project, GitVersionConfig config, boolean strict, @Nullable String commit) {
6565
this.strict = strict;
66+
this.commit = commit;
6667

6768
this.gitDir = gitDir;
6869
this.root = root;
@@ -141,14 +142,32 @@ public GitVersion.Info getInfo() {
141142
return this.url.get();
142143
}
143144

145+
private ObjectId resolve(String ref) {
146+
try {
147+
var ret = this.git.getRepository().resolve(ref);
148+
if (ret == null)
149+
throw new IllegalArgumentException("Unknown commit reference: " + ref);
150+
return ret;
151+
} catch (IOException e) {
152+
return Util.sneak(e);
153+
}
154+
}
155+
144156
/** @see #info */
145157
private Info calculateInfo(CommitCountProvider commitCountProvider) {
146158
try {
147159
this.open();
148160

161+
var commitId = resolve(this.commit == null ? Constants.HEAD : this.commit);
162+
149163
var describedTag = Util.make(this.git.describe(), it -> {
150164
it.setTags(true);
151165
it.setLong(true);
166+
try {
167+
it.setTarget(commitId);
168+
} catch (IOException e) {
169+
Util.sneak(e);
170+
}
152171

153172
try {
154173
it.setMatch(this.tagPrefix + "[[:digit:]]**");
@@ -180,10 +199,10 @@ private Info calculateInfo(CommitCountProvider commitCountProvider) {
180199
var tag = desc[0].substring(Util.indexOf(desc[0], Character::isDigit, 0));
181200

182201
var offset = commitCountProvider.getAsString(this.git, desc[0], desc[1], this.strict);
183-
var hash = desc[2];
202+
var hash = desc[2]; // Technically this has a 'g' prefix but its been around for so long I don't really care
184203
var branch = longBranch != null ? Repository.shortenRefName(longBranch) : null;
185-
var commit = ObjectId.toString(head.getObjectId());
186-
var abbreviatedId = head.getObjectId().abbreviate(8).name();
204+
var commit = ObjectId.toString(commitId);
205+
var abbreviatedId = commitId.abbreviate(8).name();
187206

188207
return new Info(tag, offset, hash, branch, commit, abbreviatedId);
189208
} catch (Exception e) {
@@ -337,7 +356,8 @@ private int getSubprojectCommitCount(Git git, String tag) {
337356
if (this.localPath.isEmpty() && this.allExcludingPaths.isEmpty()) return -1;
338357

339358
try {
340-
int count = GitUtils.countCommits(git, tag, this.tagPrefix, this.allIncludingPaths, this.allExcludingPaths);
359+
var end = resolve(this.commit == null ? Constants.HEAD : this.commit);
360+
int count = GitUtils.countCommits(git, tag, end, this.tagPrefix, this.allIncludingPaths, this.allExcludingPaths);
341361
return Math.max(count, 0);
342362
} catch (GitAPIException | IOException e) {
343363
throw new GitVersionExceptionInternal("Failed to count commits with the following parameters: Tag %s, Include Paths [%s], Exclude Paths [%s]".formatted(tag, String.join(", ", this.allIncludingPaths), String.join(", ", this.allExcludingPaths)));

src/main/java/net/minecraftforge/gitver/internal/GitVersionInternal.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final class Builder implements GitVersion.Builder {
3333
private @Nullable File root;
3434
private @Nullable File project;
3535
private @Nullable GitVersionConfig config;
36+
private @Nullable String commit;
3637
private boolean strict = true;
3738

3839
private Builder() { }
@@ -73,6 +74,12 @@ public GitVersion.Builder strict(boolean strict) {
7374
return this;
7475
}
7576

77+
@Override
78+
public GitVersion.Builder commit(@Nullable String ref) {
79+
this.commit = ref;
80+
return this;
81+
}
82+
7683
@Override
7784
public GitVersion build() {
7885
if (this.root == null && this.project == null)
@@ -100,7 +107,7 @@ public GitVersion build() {
100107
}
101108
}
102109

103-
return new GitVersionImpl(this.gitDir, this.root, this.project, this.config, this.strict);
110+
return new GitVersionImpl(this.gitDir, this.root, this.project, this.config, this.strict, this.commit);
104111
} catch (GitVersionException e) {
105112
if (!this.strict)
106113
return GitVersionImpl.empty(this.project);

0 commit comments

Comments
 (0)