First complete plugin implementation.
This commit is contained in:
parent
2c7ceabe7a
commit
73f35a406d
7 changed files with 221 additions and 20 deletions
|
@ -8,7 +8,7 @@ externalResolvers := Seq(
|
||||||
)
|
)
|
||||||
|
|
||||||
val ProjectName: String = "sbt-gs-calver"
|
val ProjectName: String = "sbt-gs-calver"
|
||||||
val Description: String = "SBT 1.9.0+ plugin for Git-based semantic versioning."
|
val Description: String = "SBT 1.9.0+ plugin for calendar versioning."
|
||||||
|
|
||||||
def getProperty[A](
|
def getProperty[A](
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
sbt.version=1.9.8
|
sbt.version=1.9.9
|
||||||
|
|
|
@ -1,6 +1,169 @@
|
||||||
package gs
|
package gs
|
||||||
|
|
||||||
case class CalVer(value: String)
|
import java.time.LocalDate
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a rendered Calendar Version.
|
||||||
|
*
|
||||||
|
* @param value The version string.
|
||||||
|
* @param pattern The pattern which rendered the version string.
|
||||||
|
*/
|
||||||
|
case class CalVer(
|
||||||
|
value: String,
|
||||||
|
pattern: CalVer.Pattern
|
||||||
|
)
|
||||||
|
|
||||||
object CalVer {
|
object CalVer {
|
||||||
|
/**
|
||||||
|
* Render the given pattern to a Calendar Version.
|
||||||
|
*
|
||||||
|
* @param pattern The pattern to render.
|
||||||
|
* @return The rendered CalVer value.
|
||||||
|
*/
|
||||||
|
def render(pattern: Pattern): CalVer = {
|
||||||
|
val today = LocalDate.now()
|
||||||
|
CalVer(
|
||||||
|
value = pattern.items.map {
|
||||||
|
case Left(component) =>
|
||||||
|
component match {
|
||||||
|
case Component.YYYY => today.getYear().toString()
|
||||||
|
case Component.MM => today.getMonthValue().toString()
|
||||||
|
case Component.DD => today.getDayOfMonth().toString()
|
||||||
|
case Component.Label(label) => label
|
||||||
|
case Component.GitSha(length) => Git.getSha(length)
|
||||||
|
}
|
||||||
|
case Right(delimiter) => Delimiter.render(delimiter)
|
||||||
|
}.mkString,
|
||||||
|
pattern = pattern
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Defaults {
|
||||||
|
/**
|
||||||
|
* Default pattern for release versions.
|
||||||
|
*/
|
||||||
|
val ReleasePattern: Pattern =
|
||||||
|
Pattern
|
||||||
|
.builder(Component.YYYY)
|
||||||
|
.addDelimiter(Delimiter.Dot)
|
||||||
|
.addComponent(Component.MM)
|
||||||
|
.addDelimiter(Delimiter.Dot)
|
||||||
|
.addComponent(Component.DD)
|
||||||
|
.addDelimiter(Delimiter.Hyphen)
|
||||||
|
.addComponent(Component.GitSha(7))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default pattern for pre-release versions.
|
||||||
|
*/
|
||||||
|
val PreReleasePattern: Pattern =
|
||||||
|
Pattern
|
||||||
|
.builder(Component.YYYY)
|
||||||
|
.addDelimiter(Delimiter.Dot)
|
||||||
|
.addComponent(Component.MM)
|
||||||
|
.addDelimiter(Delimiter.Dot)
|
||||||
|
.addComponent(Component.DD)
|
||||||
|
.addDelimiter(Delimiter.Hyphen)
|
||||||
|
.addComponent(Component.Label("SNAPSHOT"))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed trait Component
|
||||||
|
|
||||||
|
object Component {
|
||||||
|
/**
|
||||||
|
* CalVer Component: Year.
|
||||||
|
*/
|
||||||
|
case object YYYY extends Component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CalVer Component: Month (1-12), without a leading zero.
|
||||||
|
*/
|
||||||
|
case object MM extends Component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CalVer Component: Day of Month, without a leading zero.
|
||||||
|
*/
|
||||||
|
case object DD extends Component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CalVer Component: Label.
|
||||||
|
*
|
||||||
|
* This component contains an arbitrary string value.
|
||||||
|
*
|
||||||
|
* @param value The value of the label.
|
||||||
|
*/
|
||||||
|
case class Label(value: String) extends Component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CalVer Component. Git SHA.
|
||||||
|
*
|
||||||
|
* This component defines the length (first N characters) of the Git SHA to
|
||||||
|
* take from the current branch of the current repository. An empty string
|
||||||
|
* is used if lookup fails or no commits exist.
|
||||||
|
*
|
||||||
|
* @param length The number of characters of the Git SHA to use.
|
||||||
|
*/
|
||||||
|
case class GitSha(length: Int) extends Component
|
||||||
|
|
||||||
|
def describe(component: Component): String = component match {
|
||||||
|
case YYYY => "YYYY"
|
||||||
|
case MM => "MM"
|
||||||
|
case DD => "DD"
|
||||||
|
case Label(value) => value
|
||||||
|
case GitSha(length) => s"SHA($length)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed abstract class Delimiter(val value: String)
|
||||||
|
|
||||||
|
object Delimiter {
|
||||||
|
case object Dot extends Delimiter(".")
|
||||||
|
case object Hyphen extends Delimiter("-")
|
||||||
|
case object Plus extends Delimiter("+")
|
||||||
|
case object Underscore extends Delimiter("_")
|
||||||
|
|
||||||
|
def render(delimiter: Delimiter): String = delimiter.value
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Pattern private (val items: List[Pattern.Item]) {
|
||||||
|
lazy val str: String =
|
||||||
|
items.map {
|
||||||
|
case Left(component) => Component.describe(component)
|
||||||
|
case Right(delimiter) => Delimiter.render(delimiter)
|
||||||
|
}.mkString
|
||||||
|
|
||||||
|
override def toString(): String = str
|
||||||
|
}
|
||||||
|
|
||||||
|
object Pattern {
|
||||||
|
private type Item = Either[Component, Delimiter]
|
||||||
|
|
||||||
|
def builder(component: Component): Builder = Builder(component)
|
||||||
|
|
||||||
|
final class Builder private () {
|
||||||
|
private val buffer: ListBuffer[Item] = new ListBuffer()
|
||||||
|
|
||||||
|
def addComponent(component: Component): Builder = {
|
||||||
|
val _ = buffer.append(Left(component))
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
def addDelimiter(delimiter: Delimiter): Builder = {
|
||||||
|
val _ = buffer.append(Right(delimiter))
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(): Pattern = new Pattern(buffer.toList)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Builder {
|
||||||
|
def apply(component: Component): Builder = {
|
||||||
|
val b = new Builder()
|
||||||
|
b.addComponent(component)
|
||||||
|
b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,31 @@ object CalVerKeys {
|
||||||
"Calculated CalVer."
|
"Calculated CalVer."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SBT setting which defines the CalVer pattern used to calculate the final
|
||||||
|
* version. This should not be set manually, please use
|
||||||
|
* `calVerReleasePattern` and `calVerPreReleasePattern`.
|
||||||
|
*/
|
||||||
|
lazy val calVerPattern = settingKey[CalVer.Pattern](
|
||||||
|
"Selected CalVer pattern."
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-defined SBT setting which defines the CalVer pattern to use for a
|
||||||
|
* release build.
|
||||||
|
*/
|
||||||
|
lazy val calVerReleasePattern = settingKey[Option[CalVer.Pattern]](
|
||||||
|
"Pattern to use for calculating CalVer for release builds."
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-defined SBT setting which defines the CalVer pattern to use for a
|
||||||
|
* pre-release build.
|
||||||
|
*/
|
||||||
|
lazy val calVerPreReleasePattern = settingKey[Option[CalVer.Pattern]](
|
||||||
|
"Pattern to use for calculating CalVer for pre-release builds."
|
||||||
|
)
|
||||||
|
|
||||||
/** Task which emits the current version at the informational log level.
|
/** Task which emits the current version at the informational log level.
|
||||||
*/
|
*/
|
||||||
lazy val calVerInfo = taskKey[Unit](
|
lazy val calVerInfo = taskKey[Unit](
|
||||||
|
|
|
@ -11,9 +11,22 @@ object CalVerPlugin extends AutoPlugin {
|
||||||
|
|
||||||
// Perform all version calculations and expose as a variable.
|
// Perform all version calculations and expose as a variable.
|
||||||
lazy val calVerDefaults: Seq[Setting[_]] = {
|
lazy val calVerDefaults: Seq[Setting[_]] = {
|
||||||
// Expose the relevant values as setting keys.
|
val isRelease = PluginProperties.isRelease()
|
||||||
Seq(
|
Seq(
|
||||||
calVer := ""
|
calVerReleasePattern := calVerReleasePattern.value.orElse(
|
||||||
|
Some(CalVer.Defaults.ReleasePattern)
|
||||||
|
),
|
||||||
|
calVerPreReleasePattern := calVerPreReleasePattern.value.orElse(
|
||||||
|
Some(CalVer.Defaults.PreReleasePattern)
|
||||||
|
),
|
||||||
|
calVerPattern := {
|
||||||
|
if (isRelease) {
|
||||||
|
calVerReleasePattern.value.getOrElse(CalVer.Defaults.ReleasePattern)
|
||||||
|
} else {
|
||||||
|
calVerPreReleasePattern.value.getOrElse(CalVer.Defaults.PreReleasePattern)
|
||||||
|
}
|
||||||
|
} ,
|
||||||
|
calVer := CalVer.render(calVerPattern.value).value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +38,7 @@ object CalVerPlugin extends AutoPlugin {
|
||||||
calVerInfo := {
|
calVerInfo := {
|
||||||
val log = Keys.streams.value.log
|
val log = Keys.streams.value.log
|
||||||
log.info(s"[CalVer] Version: ${calVer.value}")
|
log.info(s"[CalVer] Version: ${calVer.value}")
|
||||||
|
log.info(s"[CalVer] Pattern: ${calVerPattern.value}")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package gs
|
package gs
|
||||||
|
|
||||||
//import java.io.File
|
|
||||||
//import scala.util.Try
|
|
||||||
|
|
||||||
object Git {
|
object Git {
|
||||||
|
/**
|
||||||
/*def getLatestSemVer(): SemVer = {
|
* Get the latest SHA. If there are no commits on this branch, the empty
|
||||||
// Suppress all error output. Suppress exceptions for the failed process.
|
* string will be returned.
|
||||||
// Capture the standard output and parse it if the command succeeds.
|
*
|
||||||
|
* @param length The number of characters to take from the SHA.
|
||||||
|
* @return The latest SHA.
|
||||||
|
*/
|
||||||
|
def getSha(length: Int): String = {
|
||||||
val result = os
|
val result = os
|
||||||
.proc("git", "describe", "--tags", "--abbrev=0")
|
.proc("git", "rev-parse", "HEAD")
|
||||||
.call(
|
.call(
|
||||||
stderr = os.ProcessOutput(
|
stderr = os.ProcessOutput(
|
||||||
(
|
(
|
||||||
|
@ -21,9 +22,8 @@ object Git {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (result.exitCode != 0)
|
if (result.exitCode != 0)
|
||||||
SemVer.DefaultVersion
|
result.out.text().take(length)
|
||||||
else
|
else
|
||||||
SemVer.parse(result.out.text()).getOrElse(SemVer.DefaultVersion)
|
""
|
||||||
}*/
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,8 @@ object PluginProperties {
|
||||||
|
|
||||||
/** Use one of the following to calculate an incremented release version:
|
/** Use one of the following to calculate an incremented release version:
|
||||||
*
|
*
|
||||||
* - `sbt -Drelease=major`
|
* - `sbt -Drelease=true`
|
||||||
* - `sbt -Drelease=minor`
|
* - `sbt -Drelease=false`
|
||||||
* - `sbt -Drelease=patch`
|
|
||||||
*/
|
*/
|
||||||
val ReleaseProperty: String = "release"
|
val ReleaseProperty: String = "release"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue