Better properties substitution

For com.fasterxml.jackson.jaxrs:jackson-jaxrs-providers:2.6.0 in particular, having properties refering other properties
This commit is contained in:
Alexandre Archambault 2015-12-30 01:34:46 +01:00
parent aa9a43b483
commit 00d11017f7
4 changed files with 56 additions and 49 deletions

View File

@ -69,7 +69,7 @@ case class Project(
// Maven-specific // Maven-specific
parent: Option[(Module, String)], parent: Option[(Module, String)],
dependencyManagement: Seq[(String, Dependency)], dependencyManagement: Seq[(String, Dependency)],
properties: Map[String, String], properties: Seq[(String, String)],
profiles: Seq[Profile], profiles: Seq[Profile],
versions: Option[Versions], versions: Option[Versions],
snapshotVersioning: Option[SnapshotVersioning], snapshotVersioning: Option[SnapshotVersioning],

View File

@ -56,12 +56,6 @@ object Resolution {
(dict /: deps)(add) (dict /: deps)(add)
} }
def mergeProperties(
dict: Map[String, String],
other: Map[String, String]
): Map[String, String] =
dict ++ other.filterKeys(!dict.contains(_))
def addDependencies(deps: Seq[Seq[(String, Dependency)]]): Seq[(String, Dependency)] = { def addDependencies(deps: Seq[Seq[(String, Dependency)]]): Seq[(String, Dependency)] = {
val res = val res =
(deps :\ (Set.empty[DepMgmt.Key], Seq.empty[(String, Dependency)])) { (deps :\ (Set.empty[DepMgmt.Key], Seq.empty[(String, Dependency)])) {
@ -79,6 +73,32 @@ object Resolution {
quote("${") + "([a-zA-Z0-9-.]*)" + quote("}") quote("${") + "([a-zA-Z0-9-.]*)" + quote("}")
).r ).r
def substituteProps(s: String, properties: Map[String, String]) = {
val matches = propRegex
.findAllMatchIn(s)
.toList
.reverse
if (matches.isEmpty) s
else {
val output =
(new StringBuilder(s) /: matches) { (b, m) =>
properties
.get(m.group(1))
.fold(b)(b.replace(m.start, m.end, _))
}
output.result()
}
}
def propertiesMap(props: Seq[(String, String)]): Map[String, String] =
props.foldLeft(Map.empty[String, String]) {
case (acc, (k, v0)) =>
val v = substituteProps(v0, acc)
acc + (k -> v)
}
/** /**
* Substitutes `properties` in `dependencies`. * Substitutes `properties` in `dependencies`.
*/ */
@ -87,41 +107,25 @@ object Resolution {
properties: Map[String, String] properties: Map[String, String]
): Seq[(String, Dependency)] = { ): Seq[(String, Dependency)] = {
def substituteProps(s: String) = { def substituteProps0(s: String) =
val matches = propRegex substituteProps(s, properties)
.findAllMatchIn(s)
.toList
.reverse
if (matches.isEmpty) s
else {
val output =
(new StringBuilder(s) /: matches) { (b, m) =>
properties
.get(m.group(1))
.fold(b)(b.replace(m.start, m.end, _))
}
output.result()
}
}
dependencies dependencies
.map {case (config, dep) => .map {case (config, dep) =>
substituteProps(config) -> dep.copy( substituteProps0(config) -> dep.copy(
module = dep.module.copy( module = dep.module.copy(
organization = substituteProps(dep.module.organization), organization = substituteProps0(dep.module.organization),
name = substituteProps(dep.module.name) name = substituteProps0(dep.module.name)
), ),
version = substituteProps(dep.version), version = substituteProps0(dep.version),
attributes = dep.attributes.copy( attributes = dep.attributes.copy(
`type` = substituteProps(dep.attributes.`type`), `type` = substituteProps0(dep.attributes.`type`),
classifier = substituteProps(dep.attributes.classifier) classifier = substituteProps0(dep.attributes.classifier)
), ),
configuration = substituteProps(dep.configuration), configuration = substituteProps0(dep.configuration),
exclusions = dep.exclusions exclusions = dep.exclusions
.map{case (org, name) => .map{case (org, name) =>
(substituteProps(org), substituteProps(name)) (substituteProps0(org), substituteProps0(name))
} }
// FIXME The content of the optional tag may also be a property in // FIXME The content of the optional tag may also be a property in
// the original POM. Maybe not parse it that earlier? // the original POM. Maybe not parse it that earlier?
@ -320,15 +324,14 @@ object Resolution {
// come from parents or dependency management. This may not be // come from parents or dependency management. This may not be
// the right thing to do. // the right thing to do.
val properties = mergeProperties( val properties0 = project.properties ++ Seq(
project.properties, "project.groupId" -> project.module.organization,
Map( "project.artifactId" -> project.module.name,
"project.groupId" -> project.module.organization, "project.version" -> project.version
"project.artifactId" -> project.module.name,
"project.version" -> project.version
)
) )
val properties = propertiesMap(properties0)
val configurations = withParentConfigurations(from.configuration, project.configurations) val configurations = withParentConfigurations(from.configuration, project.configurations)
withExclusions( withExclusions(
@ -604,11 +607,13 @@ case class Resolution(
project: Project project: Project
): Set[ModuleVersion] = { ): Set[ModuleVersion] = {
val approxProperties = val approxProperties0 =
project.parent project.parent
.flatMap(projectCache.get) .flatMap(projectCache.get)
.map(_._2.properties) .map(_._2.properties)
.fold(project.properties)(mergeProperties(project.properties, _)) .fold(project.properties)(project.properties ++ _)
val approxProperties = propertiesMap(approxProperties0)
val profileDependencies = val profileDependencies =
profiles( profiles(
@ -678,11 +683,13 @@ case class Resolution(
*/ */
def withDependencyManagement(project: Project): Project = { def withDependencyManagement(project: Project): Project = {
val approxProperties = val approxProperties0 =
project.parent project.parent
.filter(projectCache.contains) .filter(projectCache.contains)
.map(projectCache(_)._2.properties) .map(projectCache(_)._2.properties.toMap)
.fold(project.properties)(mergeProperties(project.properties, _)) .fold(project.properties)(project.properties ++ _)
val approxProperties = propertiesMap(approxProperties0)
val profiles0 = profiles( val profiles0 = profiles(
project, project,
@ -695,7 +702,7 @@ case class Resolution(
) )
val properties0 = val properties0 =
(project.properties /: profiles0) { (acc, p) => (project.properties /: profiles0) { (acc, p) =>
mergeProperties(acc, p.properties) acc ++ p.properties
} }
val deps = ( val deps = (
@ -732,7 +739,7 @@ case class Resolution(
properties = project.parent properties = project.parent
.filter(projectCache.contains) .filter(projectCache.contains)
.map(projectCache(_)._2.properties) .map(projectCache(_)._2.properties)
.fold(properties0)(mergeProperties(properties0, _)) .fold(properties0)(properties0 ++ _)
) )
} }

View File

@ -132,7 +132,7 @@ object IvyXml {
configurations0.toMap, configurations0.toMap,
None, None,
Nil, Nil,
Map.empty, Nil,
Nil, Nil,
None, None,
None, None,

View File

@ -229,7 +229,7 @@ object Pom {
Map.empty, Map.empty,
parentModuleOpt.map((_, parentVersionOpt.getOrElse(""))), parentModuleOpt.map((_, parentVersionOpt.getOrElse(""))),
depMgmts, depMgmts,
properties.toMap, properties,
profiles, profiles,
None, None,
None, None,