Skip to content

Commit e58e15e

Browse files
committed
Added support for different git describe patterns and tagToVersion functions across modules in a multi-module project
1 parent af8b67b commit e58e15e

File tree

6 files changed

+274
-65
lines changed

6 files changed

+274
-65
lines changed

src/main/scala/com/github/sbt/git/GitPlugin.scala

Lines changed: 94 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ object SbtGit {
123123
gitDescribedVersion := gitReader.value.withGit(_.describedVersion(git.gitDescribePatterns.value)).map(v => git.gitTagToVersionNumber.value(v).getOrElse(v)),
124124
gitCurrentTags := gitReader.value.withGit(_.currentTags),
125125
gitCurrentBranch := Option(gitReader.value.withGit(_.branch)).getOrElse(""),
126-
gitUncommittedChanges in ThisBuild := gitReader.value.withGit(_.hasUncommittedChanges),
126+
ThisBuild / gitUncommittedChanges := gitReader.value.withGit(_.hasUncommittedChanges),
127127
scmInfo := parseScmInfo(gitReader.value.withGit(_.remoteOrigin))
128128
)
129129
private[sbt] def parseScmInfo(remoteOrigin: String): Option[ScmInfo] = {
@@ -152,11 +152,14 @@ object SbtGit {
152152

153153
val projectSettings = Seq(
154154
// Input task to run git commands directly.
155-
commands += GitCommand.command
155+
commands += GitCommand.command,
156+
gitTagToVersionNumber := git.defaultTagByVersionStrategy,
157+
gitDescribePatterns := Seq.empty[String],
158+
gitDescribedVersion := gitReader.value.withGit(_.describedVersion((ThisProject / gitDescribePatterns).value)).map(v => git.gitTagToVersionNumber.value(v).getOrElse(v)),
156159
)
157160

158161
/** A Predefined setting to use JGit runner for git. */
159-
def useJGit: Setting[_] = gitRunner in ThisBuild := JGitRunner
162+
def useJGit: Setting[_] = ThisBuild / gitRunner := JGitRunner
160163

161164
/** Setting to use console git for readable ops, to allow working with git worktrees */
162165
def useReadableConsoleGit: Setting[_] = useConsoleForROGit in ThisBuild := true
@@ -177,65 +180,89 @@ object SbtGit {
177180
*/
178181
def versionWithGit: Seq[Setting[_]] =
179182
Seq(
180-
versionProperty in ThisBuild := "project.version",
181-
uncommittedSignifier in ThisBuild := Some("SNAPSHOT"),
182-
useGitDescribe in ThisBuild := false,
183-
formattedShaVersion in ThisBuild := {
184-
val base = git.baseVersion.?.value
185-
val suffix =
186-
git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)
187-
git.gitHeadCommit.value map { sha =>
188-
git.defaultFormatShaVersion(base, sha, suffix)
189-
}
190-
},
191-
formattedDateVersion in ThisBuild := {
192-
val base = git.baseVersion.?.value
193-
git.defaultFormatDateVersion(base, new java.util.Date)
194-
},
195-
isSnapshot in ThisBuild := {
196-
git.gitCurrentTags.value.isEmpty || git.gitUncommittedChanges.value
197-
},
198-
version in ThisBuild := {
199-
val overrideVersion =
200-
git.overrideVersion(git.versionProperty.value)
201-
val uncommittedSuffix =
202-
git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)
203-
val releaseVersion =
204-
git.releaseVersion(git.gitCurrentTags.value, git.gitTagToVersionNumber.value, uncommittedSuffix)
205-
val describedVersion =
206-
git.flaggedOptional(git.useGitDescribe.value, git.describeVersion(git.gitDescribedVersion.value, uncommittedSuffix))
207-
val datedVersion = formattedDateVersion.value
208-
val commitVersion = formattedShaVersion.value
209-
//Now we fall through the potential version numbers...
210-
git.makeVersion(Seq(
211-
overrideVersion,
212-
releaseVersion,
213-
describedVersion,
214-
commitVersion
215-
)) getOrElse datedVersion // For when git isn't there at all.
183+
ThisBuild / versionProperty := "project.version",
184+
ThisBuild / uncommittedSignifier := Some("SNAPSHOT"),
185+
ThisBuild / useGitDescribe := false,
186+
ThisBuild / formattedShaVersion := {
187+
val base = git.baseVersion.?.value
188+
val suffix =
189+
git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)
190+
git.gitHeadCommit.value map { sha =>
191+
git.defaultFormatShaVersion(base, sha, suffix)
216192
}
193+
},
194+
ThisBuild / formattedDateVersion := {
195+
val base = git.baseVersion.?.value
196+
git.defaultFormatDateVersion(base, new java.util.Date)
197+
},
198+
ThisBuild / isSnapshot := {
199+
git.gitCurrentTags.value.isEmpty || git.gitUncommittedChanges.value
200+
},
201+
ThisBuild / version := {
202+
val overrideVersion =
203+
git.overrideVersion(git.versionProperty.value)
204+
val uncommittedSuffix =
205+
git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)
206+
val releaseVersion =
207+
git.releaseVersion(git.gitCurrentTags.value, (ThisBuild / gitTagToVersionNumber).value, uncommittedSuffix)
208+
val describedVersion =
209+
git.flaggedOptional(git.useGitDescribe.value, git.describeVersion((ThisBuild / gitDescribedVersion).value, uncommittedSuffix))
210+
val datedVersion = formattedDateVersion.value
211+
val commitVersion = formattedShaVersion.value
212+
//Now we fall through the potential version numbers...
213+
git.makeVersion(Seq(
214+
overrideVersion,
215+
releaseVersion,
216+
describedVersion,
217+
commitVersion
218+
)) getOrElse datedVersion // For when git isn't there at all.
219+
}
220+
)
221+
222+
def versionProjectWithGit: Seq[Setting[_]] =
223+
Seq(
224+
ThisProject / useGitDescribe := false,
225+
ThisProject / version := {
226+
val overrideVersion =
227+
git.overrideVersion(git.versionProperty.value)
228+
val uncommittedSuffix =
229+
git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)
230+
val releaseVersion =
231+
git.releaseVersion(git.gitCurrentTags.value, (ThisProject / gitTagToVersionNumber).value, uncommittedSuffix)
232+
val describedVersion =
233+
git.flaggedOptional(git.useGitDescribe.value, git.describeVersion((ThisProject / gitDescribedVersion).value, uncommittedSuffix))
234+
val datedVersion = formattedDateVersion.value
235+
val commitVersion = formattedShaVersion.value
236+
//Now we fall through the potential version numbers...
237+
git.makeVersion(Seq(
238+
overrideVersion,
239+
releaseVersion,
240+
describedVersion,
241+
commitVersion
242+
)) getOrElse datedVersion // For when git isn't there at all.
243+
}
217244
)
218245

219246
/** A holder of keys for simple config. */
220247
object git {
221248
val remoteRepo = GitKeys.gitRemoteRepo
222249
val branch = GitKeys.gitBranch
223-
val runner = GitKeys.gitRunner in ThisBuild
224-
val gitHeadCommit = GitKeys.gitHeadCommit in ThisBuild
225-
val gitHeadMessage = GitKeys.gitHeadMessage in ThisBuild
226-
val gitHeadCommitDate = GitKeys.gitHeadCommitDate in ThisBuild
227-
val useGitDescribe = GitKeys.useGitDescribe in ThisBuild
228-
val gitDescribePatterns = GitKeys.gitDescribePatterns in ThisBuild
229-
val gitDescribedVersion = GitKeys.gitDescribedVersion in ThisBuild
230-
val gitCurrentTags = GitKeys.gitCurrentTags in ThisBuild
231-
val gitCurrentBranch = GitKeys.gitCurrentBranch in ThisBuild
232-
val gitTagToVersionNumber = GitKeys.gitTagToVersionNumber in ThisBuild
233-
val baseVersion = GitKeys.baseVersion in ThisBuild
234-
val versionProperty = GitKeys.versionProperty in ThisBuild
235-
val gitUncommittedChanges = GitKeys.gitUncommittedChanges in ThisBuild
236-
val uncommittedSignifier = GitKeys.uncommittedSignifier in ThisBuild
237-
val formattedShaVersion = GitKeys.formattedShaVersion in ThisBuild
238-
val formattedDateVersion = GitKeys.formattedDateVersion in ThisBuild
250+
val runner = ThisBuild / GitKeys.gitRunner
251+
val gitHeadCommit = ThisBuild / GitKeys.gitHeadCommit
252+
val gitHeadMessage = ThisBuild / GitKeys.gitHeadMessage
253+
val gitHeadCommitDate = ThisBuild / GitKeys.gitHeadCommitDate
254+
val useGitDescribe = ThisProject / GitKeys.useGitDescribe
255+
val gitDescribePatterns = ThisProject / GitKeys.gitDescribePatterns
256+
val gitDescribedVersion = ThisProject / GitKeys.gitDescribedVersion
257+
val gitCurrentTags = ThisBuild / GitKeys.gitCurrentTags
258+
val gitCurrentBranch = ThisBuild / GitKeys.gitCurrentBranch
259+
val gitTagToVersionNumber = ThisProject / GitKeys.gitTagToVersionNumber
260+
val baseVersion = ThisBuild / GitKeys.baseVersion
261+
val versionProperty = ThisBuild / GitKeys.versionProperty
262+
val gitUncommittedChanges = ThisBuild / GitKeys.gitUncommittedChanges
263+
val uncommittedSignifier = ThisBuild / GitKeys.uncommittedSignifier
264+
val formattedShaVersion = ThisBuild / GitKeys.formattedShaVersion
265+
val formattedDateVersion = ThisBuild / GitKeys.formattedDateVersion
239266

240267

241268
val defaultTagByVersionStrategy: String => Option[String] = { tag =>
@@ -248,9 +275,9 @@ object SbtGit {
248275
}
249276

250277
def defaultFormatDateVersion(baseVersion:Option[String], date:java.util.Date):String = {
251-
val df = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")
252-
df setTimeZone java.util.TimeZone.getTimeZone("GMT")
253-
baseVersion.map(_ +"-").getOrElse("") + (df format (new java.util.Date))
278+
val df = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")
279+
df setTimeZone java.util.TimeZone.getTimeZone("GMT")
280+
baseVersion.map(_ +"-").getOrElse("") + (df format (new java.util.Date))
254281
}
255282

256283
def flaggedOptional(flag: Boolean, value: Option[String]): Option[String] =
@@ -285,13 +312,13 @@ object SbtGit {
285312
}
286313

287314
/** The autoplugin which adapts the old sbt plugin classes into a legitimate AutoPlugin.
288-
*
289-
* This will add the ability to call git directly in the sbt shell via a command, as well as add
290-
* the infrastructure to read git properties.
291-
*
292-
* We keep the old SbtGit object around in an attempt not to break projects which depend on the old
293-
* plugin directly.
294-
*/
315+
*
316+
* This will add the ability to call git directly in the sbt shell via a command, as well as add
317+
* the infrastructure to read git properties.
318+
*
319+
* We keep the old SbtGit object around in an attempt not to break projects which depend on the old
320+
* plugin directly.
321+
*/
295322
object GitPlugin extends AutoPlugin {
296323
override def requires = sbt.plugins.CorePlugin
297324
override def trigger = allRequirements
@@ -300,6 +327,7 @@ object GitPlugin extends AutoPlugin {
300327
object autoImport {
301328
val git = SbtGit.git
302329
def versionWithGit = SbtGit.versionWithGit
330+
def versionProjectWithGit = SbtGit.versionProjectWithGit
303331
def useJGit = SbtGit.useJGit
304332
def showCurrentGitBranch = SbtGit.showCurrentGitBranch
305333
}
@@ -311,6 +339,7 @@ object GitPlugin extends AutoPlugin {
311339
object GitVersioning extends AutoPlugin {
312340
override def requires = sbt.plugins.IvyPlugin && GitPlugin
313341
override def buildSettings = GitPlugin.autoImport.versionWithGit
342+
override def projectSettings = GitPlugin.autoImport.versionProjectWithGit
314343
}
315344
/** Adapter to enable the git prompt. i.e. rich prompt based on git info. */
316345
object GitBranchPrompt extends AutoPlugin {

src/sbt-test/git-versioning/multi-module-project-use-describe/README.md

Whitespace-only changes.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# sbt-git #
2+
3+
[![Join the chat at https://gitter.im/sbt/sbt-git](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sbt/sbt-git?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4+
5+
The `sbt-git` plugin offers git command line features directly inside sbt as
6+
well as allowing other plugins to make use of git.
7+
8+
## Maintenance status
9+
10+
This plugin is community maintained. See https://github.com/sbt/sbt-git/issues/182 if you'd like to help.
11+
12+
## Installation ##
13+
As of `1.0.0` this plugin requires at least **Java 8**.
14+
The latest version supporting Java 7 was `0.9.3`, while the latest version supporting Java 6 was `0.8.5`.
15+
16+
Latest:
17+
18+
Add the following to your `project/plugins.sbt` or `~/.sbt/0.13/plugins/plugins.sbt` file:
19+
20+
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0")
21+
22+
Prior to sbt 0.13.5:
23+
24+
Add the following to your `project/plugins.sbt` or `~/.sbt/0.13/plugins/plugins.sbt` file:
25+
26+
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.7.1")
27+
28+
additionally, use one of the older README.md files: (https://github.com/sbt/sbt-git/blob/v0.7.1/README.md)
29+
30+
### Using JGit ###
31+
32+
If you do not have git installed and available on your path (e.g. you use windows),
33+
make sure your `git.sbt` or `~/.sbt/0.13/git.sbt` file looks like this:
34+
35+
useJGit
36+
37+
Or you can type this into the prompt:
38+
39+
> set useJGit
40+
[info] Reapplying settings...
41+
[info] Set current project to scala-arm (in build file:...)
42+
> session save
43+
[info] Reapplying settings...
44+
[info] Set current project to scala-arm (in build file:...)
45+
46+
This will enable a java-only GIT solution that, while not supporting all the same
47+
commands that can be run in the standard git command line, is good enough for most
48+
git activities.
49+
50+
51+
## Versioning with Git ##
52+
53+
You can begin to use git to control your project versions.
54+
55+
enablePlugins(GitVersioning)
56+
57+
The git plugin will now autogenerate your version using the following rules, in order:
58+
59+
1. Looks at version-property setting (default to `project.version`), and checks the `sys.props` to see if this has a value. If so, use it.
60+
2. Otherwise, looks at the project tags. The first to match the `gitTagToVersionNumberSetting` is used to assign the version. The default is to look for tags that begin with `v` and a number, and use the number as the version. If there are multiple version tags, it will pick the highest.
61+
3. If no tags are found either, look at the head commit. We attach this to the `git.baseVersion` setting: "<base-version>.<git commit sha>"
62+
4. If no head commit is present either (which means this is a brand-new repository with no commits yet), we append the current timestamp to the base version: "<base-version>.<timestamp>".
63+
64+
The `git.baseVersion` setting represents the in-development (upcoming) version you're working on.
65+
66+
You can alter the tag-detection algorithm using the `git.gitTagToVersionNumber` setting. For example, if we wanted to alter the default version tag detection so it does not require a "v" at the start of tags, we could add the following setting:
67+
68+
git.gitTagToVersionNumber := { tag: String =>
69+
if(tag matches "[0-9]+\\..*") Some(tag)
70+
else None
71+
}
72+
73+
You can turn on version detection using `git describe` command by adding:
74+
75+
git.useGitDescribe := true
76+
77+
This way the version is derived by passing the result of `git describe` to the `gitTagToVersionNumber` function. The `describe` version is built from the last tag + number of commits since tag + short hash. We recommend adopting the git describe approach.
78+
79+
You can enhance the git describe approach with `glob` pattern matching, to match only relevant tags (as per `git describe --match` functionality). This may be useful if, for example, your repository contains multiple types of tag.
80+
81+
git.gitDescribePatterns := Seq("module-name-*")
82+
83+
Additionally, you can also customize the version number generated by overriding one of the following keys:
84+
85+
* `git.formattedShaVersion` - Should look up `git.gitHeadCommit` key and generate a version based on it.
86+
* `git.formattedDateVersion` - The version we'll use if git is unavailable on this repository, for some reason.
87+
88+
As an example, you can alter the default sha-based versions using the following code
89+
90+
git.formattedShaVersion := git.gitHeadCommit.value map { sha => s"v$sha" }
91+
92+
93+
## Prompts ##
94+
95+
You can use the git plugin to add the project name + the current branch to your prompt. Simply add this setting to every project:
96+
97+
enablePlugins(GitBranchPrompt)
98+
99+
## Usage ##
100+
101+
In an sbt prompt, simply enter any git command. e.g.
102+
103+
> git status
104+
# On branch master
105+
# Changes not staged for commit:
106+
# (use "git add <file>..." to update what will be committed)
107+
# (use "git checkout -- <file>..." to discard changes in working directory)
108+
#
109+
# modified: build.sbt
110+
# modified: project/plugins/project/Build.scala
111+
#
112+
# Untracked files:
113+
# (use "git add <file>..." to include in what will be committed)
114+
#
115+
# src/site/
116+
no changes added to commit (use "git add" and/or "git commit -a")
117+
118+
119+
## Known issues
120+
When running sbt, you will see the following warnings in console:
121+
```
122+
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
123+
SLF4J: Defaulting to no-operation (NOP) logger implementation
124+
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
125+
```
126+
127+
To get rid of them, you can force the SLF4J no-op binder by adding `libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.21"` to `~/.sbt/0.13/plugins/plugins.sbt`
128+
129+
## Running the tests
130+
131+
Tests for this plugin are written using `sbt-scripted`. Test can be executed with
132+
133+
```
134+
sbt scripted
135+
```
136+
137+
## Licensing ##
138+
139+
This software is licensed under the BSD license.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
3+
val commonSettings = Seq(
4+
git.useGitDescribe := true,
5+
git.gitDescribePatterns := Seq(s"${name.value}-*"),
6+
git.gitTagToVersionNumber := { tag =>
7+
if(tag matches s"${name.value}-[0-9].*") Some(tag.replace(s"${name.value}-", ""))
8+
else None
9+
}
10+
)
11+
def proj(name: String) = Project(name, file(name)).enablePlugins(GitVersioning).settings(commonSettings)
12+
13+
lazy val a = proj("a")
14+
lazy val b = proj("b")
15+
16+
enablePlugins(GitVersioning)
17+
18+
git.baseVersion := "1.0"
19+
git.versionProperty := "DUMMY_BUILD_VERSION"
20+
21+
val checkVersion = taskKey[Unit]("checks the version is the correct versino")
22+
checkVersion := {
23+
val v = (a / version).value
24+
val v2 = (b / version).value
25+
assert(v.startsWith("1.0-1-"), s"multi-module projects should get a version with the matching git describe pattern. $v does not match '1.0-1-'")
26+
assert(v2 == "2.0", s"multi-module projects should get a version with the matching git describe pattern. $v2 != 2.0")
27+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("com.github.sbt" % "sbt-git" % sys.props("project.version"))

0 commit comments

Comments
 (0)