mirror of https://github.com/sbt/sbt.git
Merge pull request #6237 from eed3si9n/wip/package
packageTimestamp setting
This commit is contained in:
commit
83012a9644
|
|
@ -8,6 +8,7 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.jar.{ Attributes, Manifest }
|
||||
import scala.collection.JavaConverters._
|
||||
import sbt.internal.util.Types.:+:
|
||||
|
|
@ -23,6 +24,7 @@ import sbt.internal.util.HListFormats._
|
|||
import sbt.util.FileInfo.{ exists, lastModified }
|
||||
import sbt.util.CacheImplicits._
|
||||
import sbt.util.Tracked.{ inputChanged, outputChanged }
|
||||
import scala.sys.process.Process
|
||||
|
||||
sealed trait PackageOption
|
||||
|
||||
|
|
@ -43,6 +45,40 @@ object Package {
|
|||
val converted = for ((name, value) <- attributes) yield (new Attributes.Name(name), value)
|
||||
new ManifestAttributes(converted: _*)
|
||||
}
|
||||
// 2010-01-01
|
||||
private val default2010Timestamp: Long = 1262304000000L
|
||||
final case class FixedTimestamp(value: Option[Long]) extends PackageOption
|
||||
val keepTimestamps: Option[Long] = None
|
||||
val fixed2010Timestamp: Option[Long] = Some(default2010Timestamp)
|
||||
def gitCommitDateTimestamp: Option[Long] =
|
||||
try {
|
||||
Some(
|
||||
OffsetDateTime
|
||||
.parse(Process("git show -s --format=%cI").!!.trim)
|
||||
.toInstant()
|
||||
.toEpochMilli()
|
||||
)
|
||||
} catch {
|
||||
case e: Exception if e.getMessage.startsWith("Nonzero") =>
|
||||
sys.error(
|
||||
s"git repository was expected for package timestamp; use Package.fixed2010Timestamp or Package.keepTimestamps instead"
|
||||
)
|
||||
}
|
||||
def setFixedTimestamp(value: Option[Long]): PackageOption =
|
||||
FixedTimestamp(value)
|
||||
|
||||
/** by default we overwrite all timestamps in JAR to epoch time 2010-01-01 for repeatable build */
|
||||
lazy val defaultTimestamp: Option[Long] =
|
||||
sys.env
|
||||
.get("SOURCE_DATE_EPOCH")
|
||||
.map(_.toLong * 1000)
|
||||
.orElse(Some(default2010Timestamp))
|
||||
|
||||
def timeFromConfiguration(config: Configuration): Option[Long] =
|
||||
(config.options.collect { case t: FixedTimestamp => t }).headOption match {
|
||||
case Some(FixedTimestamp(value)) => value
|
||||
case _ => defaultTimestamp
|
||||
}
|
||||
|
||||
def mergeAttributes(a1: Attributes, a2: Attributes) = a1.asScala ++= a2.asScala
|
||||
// merges `mergeManifest` into `manifest` (mutating `manifest` in the process)
|
||||
|
|
@ -70,9 +106,14 @@ object Package {
|
|||
val options: Seq[PackageOption]
|
||||
)
|
||||
|
||||
@deprecated("Please specify whether to use a static timestamp", "1.4.0")
|
||||
/**
|
||||
*
|
||||
* @param conf the package configuration that should be build
|
||||
* @param cacheStoreFactory used for jar caching. We try to avoid rebuilds as much as possible
|
||||
* @param log feedback for the user
|
||||
*/
|
||||
def apply(conf: Configuration, cacheStoreFactory: CacheStoreFactory, log: Logger): Unit =
|
||||
apply(conf, cacheStoreFactory, log, None)
|
||||
apply(conf, cacheStoreFactory, log, timeFromConfiguration(conf))
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -94,6 +135,7 @@ object Package {
|
|||
case JarManifest(mergeManifest) => mergeManifests(manifest, mergeManifest); ()
|
||||
case MainClass(mainClassName) => main.put(Attributes.Name.MAIN_CLASS, mainClassName); ()
|
||||
case ManifestAttributes(attributes @ _*) => main.asScala ++= attributes; ()
|
||||
case FixedTimestamp(value) => ()
|
||||
case _ => log.warn("Ignored unknown package option " + option)
|
||||
}
|
||||
}
|
||||
|
|
@ -163,7 +205,8 @@ object Package {
|
|||
homepage map (h => (IMPLEMENTATION_URL, h.toString))
|
||||
}: _*)
|
||||
}
|
||||
@deprecated("Please specify whether to use a static timestamp", "1.4.0")
|
||||
|
||||
@deprecated("Specify whether to use a static timestamp", "1.4.0")
|
||||
def makeJar(sources: Seq[(File, String)], jar: File, manifest: Manifest, log: Logger): Unit =
|
||||
makeJar(sources, jar, manifest, log, None)
|
||||
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ object Defaults extends BuildCommon {
|
|||
bgCopyClasspath :== true,
|
||||
closeClassLoaders :== SysProp.closeClassLoaders,
|
||||
allowZombieClassLoaders :== true,
|
||||
packageTimestamp :== Package.defaultTimestamp,
|
||||
) ++ BuildServerProtocol.globalSettings
|
||||
|
||||
private[sbt] lazy val globalIvyCore: Seq[Setting[_]] =
|
||||
|
|
@ -1599,20 +1600,27 @@ object Defaults extends BuildCommon {
|
|||
val org = organization.value
|
||||
val orgName = organizationName.value
|
||||
val main = mainClass.value
|
||||
val ts = packageTimestamp.value
|
||||
val old = packageOptions.value
|
||||
|
||||
Package.addSpecManifestAttributes(n, ver, orgName) +:
|
||||
Package.addImplManifestAttributes(n, ver, homepage.value, org, orgName) +:
|
||||
Package.setFixedTimestamp(ts) +:
|
||||
main.map(Package.MainClass.apply) ++: old
|
||||
}
|
||||
)
|
||||
) ++
|
||||
inTask(packageSrc)(
|
||||
Seq(
|
||||
packageOptions := Package.addSpecManifestAttributes(
|
||||
name.value,
|
||||
version.value,
|
||||
organizationName.value
|
||||
) +: packageOptions.value
|
||||
packageOptions := {
|
||||
val old = packageOptions.value
|
||||
val ts = packageTimestamp.value
|
||||
Package.addSpecManifestAttributes(
|
||||
name.value,
|
||||
version.value,
|
||||
organizationName.value
|
||||
) +: Package.setFixedTimestamp(ts) +: old
|
||||
}
|
||||
)
|
||||
) ++
|
||||
packageTaskSettings(packageBin, packageBinMappings) ++
|
||||
|
|
@ -1778,10 +1786,7 @@ object Defaults extends BuildCommon {
|
|||
config,
|
||||
s.cacheStoreFactory,
|
||||
s.log,
|
||||
sys.env
|
||||
.get("SOURCE_DATE_EPOCH")
|
||||
.map(_.toLong * 1000)
|
||||
.orElse(Some(1262304000000L)) // 2010-01-01
|
||||
Package.timeFromConfiguration(config)
|
||||
)
|
||||
config.jar
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ object Keys {
|
|||
val packageCache = taskKey[File]("Produces the main artifact for caching.")
|
||||
|
||||
val packageOptions = taskKey[Seq[PackageOption]]("Options for packaging.").withRank(BTask)
|
||||
val packageTimestamp = settingKey[Option[Long]]("Overwrites timestamps in JAR file to make the build reproducible; None keeps the existing timestamps (useful for web resources)").withRank(CSetting)
|
||||
val packageConfiguration = taskKey[Package.Configuration]("Collects all inputs needed for packaging.").withRank(DTask)
|
||||
val artifactPath = settingKey[File]("The location of a generated artifact.").withRank(BPlusSetting)
|
||||
val artifact = settingKey[Artifact]("Describes an artifact.").withRank(BMinusSetting)
|
||||
|
|
|
|||
Loading…
Reference in New Issue