sbt-gs-calver/src/main/scala/gs/CalVer.scala

179 lines
4.6 KiB
Scala

package gs
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 {
/** 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.Label("v"))
.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.GitSha(7))
.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
}
}
}
}