Merge pull request #6237 from eed3si9n/wip/package

packageTimestamp setting
This commit is contained in:
eugene yokota 2021-01-24 23:24:09 -05:00 committed by GitHub
commit 83012a9644
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 12 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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)