mirror of
https://github.com/sbt/sbt.git
synced 2026-10-06 18:14:04 +02:00
[2.x] Custom user agent (#9786)
**Problem** We want to track the network request created by sbt. **Solution** This sets both sbt version and Coursier version into the user agent.
This commit is contained in:
@@ -1284,6 +1284,15 @@ lazy val lmCoursierDependencies = Def.settings(
|
||||
excludeDependencies ++= Seq(
|
||||
ExclusionRule("org.scala-lang.modules", "scala-xml_2.13"),
|
||||
),
|
||||
// lmCoursierShaded merges every dependency into one assembly with a single surviving
|
||||
// MANIFEST.MF, so coursier's own Implementation-Version doesn't survive there to be read back
|
||||
// at runtime. Stash coursierVersion in a resource under our own package instead, which assembly
|
||||
// merges in unchanged.
|
||||
Compile / resourceGenerators += Def.task {
|
||||
val file = (Compile / resourceManaged).value / "lmcoursier" / "coursier.properties"
|
||||
IO.write(file, s"version=$coursierVersion\n")
|
||||
Seq(file)
|
||||
}.taskValue,
|
||||
)
|
||||
|
||||
lazy val lmCoursier = project
|
||||
|
||||
@@ -73,4 +73,6 @@ import scala.concurrent.duration.{ Duration, FiniteDuration }
|
||||
localArtifactsShouldBeCached: Boolean = false,
|
||||
@since
|
||||
lockFile: Option[File] = None,
|
||||
@since
|
||||
userAgent: Option[String] = None,
|
||||
)
|
||||
|
||||
@@ -256,7 +256,8 @@ class CoursierDependencyResolution(
|
||||
checksums = checksums,
|
||||
credentials = conf.credentials.map(ToCoursier.credentials),
|
||||
followHttpToHttpsRedirections = conf.followHttpToHttpsRedirections.getOrElse(true),
|
||||
localArtifactsShouldBeCached = conf.localArtifactsShouldBeCached
|
||||
localArtifactsShouldBeCached = conf.localArtifactsShouldBeCached,
|
||||
userAgent = conf.userAgent
|
||||
)
|
||||
|
||||
val excludeDependencies = conf.excludeDependencies.map { (strOrg, strName) =>
|
||||
@@ -547,6 +548,30 @@ class CoursierDependencyResolution(
|
||||
end CoursierDependencyResolution
|
||||
|
||||
object CoursierDependencyResolution:
|
||||
// Built at runtime, not as a single literal: lmCoursierShaded's relocation rewrites any string
|
||||
// constant shaped like a "coursier."-prefixed path, which would otherwise silently turn this
|
||||
// into "lmcoursier.internal.shaded.coursier.http.agent" and break the override.
|
||||
private val userAgentPropertyKey: String = Seq("coursier", "http", "agent").mkString(".")
|
||||
|
||||
lazy val coursierUserAgent: String =
|
||||
sys.props.get(userAgentPropertyKey).getOrElse(coursierUserAgent0)
|
||||
// Reads the version from a resource rather than the jar manifest, which lmCoursierShaded's assembly merge clobbers.
|
||||
private def coursierUserAgent0: String =
|
||||
val version =
|
||||
Option(getClass.getResourceAsStream("/lmcoursier/coursier.properties"))
|
||||
.flatMap { in =>
|
||||
scala.util
|
||||
.Using(in) { in0 =>
|
||||
val props = new java.util.Properties
|
||||
props.load(in0)
|
||||
Option(props.getProperty("version"))
|
||||
}
|
||||
.toOption
|
||||
.flatten
|
||||
}
|
||||
.getOrElse("2.1")
|
||||
s"Coursier/$version (+https://github.com/coursier)"
|
||||
|
||||
def apply(configuration: CoursierConfiguration): DependencyResolution =
|
||||
DependencyResolution(new CoursierDependencyResolution(configuration))
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ package object syntax:
|
||||
sameVersions = Nil,
|
||||
localArtifactsShouldBeCached = false,
|
||||
lockFile = None,
|
||||
userAgent = None,
|
||||
)
|
||||
end extension
|
||||
|
||||
@@ -120,6 +121,8 @@ package object syntax:
|
||||
|
||||
def withRetry(retry: (FiniteDuration, Int)): CoursierConfiguration =
|
||||
value.withRetry(Some((retry._1, retry._2)))
|
||||
def withUserAgent(userAgent: String): CoursierConfiguration =
|
||||
value.withUserAgent(Option(userAgent))
|
||||
end extension
|
||||
|
||||
extension (value: Publication)
|
||||
|
||||
@@ -35,6 +35,12 @@ object LMCoursier:
|
||||
private val credentialRegistry: ConcurrentHashMap[(String, String), IvyCredentials] =
|
||||
new ConcurrentHashMap
|
||||
|
||||
def defaultUserAgent(sbtVer: String): String =
|
||||
sys.props.get("sbt.http.agent").getOrElse {
|
||||
val cs = CoursierDependencyResolution.coursierUserAgent
|
||||
s"$cs sbt/$sbtVer (+https://www.scala-sbt.org/)".trim
|
||||
}
|
||||
|
||||
def defaultCacheLocation: File =
|
||||
def absoluteFile(path: String): File = new File(path).getAbsoluteFile()
|
||||
def windowsCacheDirectory: File =
|
||||
@@ -119,6 +125,7 @@ object LMCoursier:
|
||||
val missingOk = updateConfig match
|
||||
case Some(uc) => uc.missingOk
|
||||
case _ => false
|
||||
val sbtVer = appConfig.provider.id.version
|
||||
CoursierConfiguration()
|
||||
.withResolvers(rs.toVector)
|
||||
.withInterProjectDependencies(interProjectDependencies.toVector)
|
||||
@@ -144,6 +151,7 @@ object LMCoursier:
|
||||
.withSameVersions(sameVersions)
|
||||
.withLocalArtifactsShouldBeCached(localArtifactsShouldBeCached)
|
||||
.withLockFile(lockFile)
|
||||
.withUserAgent(defaultUserAgent(sbtVer))
|
||||
end coursierConfiguration
|
||||
|
||||
def coursierConfigurationTask: Def.Initialize[Task[CoursierConfiguration]] = Def.task {
|
||||
|
||||
Reference in New Issue
Block a user