You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This avoids inherent performance issues in both dependencySubstitutions.all and resolutionStrategy.eachDependency and improves performance of both unversioned and versioned substitutions.
// We use eachDependency because dependencySubstitutions.all causes configuration task dependencies to resolve at configuration time
186
-
resolutionStrategy.eachDependency { details ->
187
-
val requested = details.requested
188
-
val requestedString = requested.toString()
189
-
val rules = versionedRulesById[requested.module] ?:return@eachDependency
190
-
val requestedSelectorVersion = requested.version
196
+
val substitutionAction =Action<DependencySubstitution> { details ->
197
+
val requested = details.requested
198
+
if (requested isModuleComponentSelector) {
199
+
val rules = rulesById[requested.moduleIdentifier] ?:return@Action
191
200
rules.forEach { rule ->
192
-
if (rule.versionSelector.accept(requestedSelectorVersion)
193
-
&&!requestedString.contains(".+")
194
-
&&!requestedString.contains("latest")
195
-
) {
196
-
// Note on `useTarget`:
197
-
// Forcing modules via ResolutionStrategy.force(Object...) uses this capability.
198
-
// from https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/DependencyResolveDetails.html
199
-
details.useTarget(rule.withVersionSelector) // We can't pass a ModuleComponentSelector here so we take the conversion hit
200
-
details.because("substituted ${rule.substitutedModule} with ${rule.withComponentSelector} because '${rule.reason}' by rule ${rule.ruleSet}")
201
-
return@eachDependency
201
+
val withComponentSelector = rule.withComponentSelector
202
+
if (rule.acceptsVersion(requested.version)) {
203
+
val message =
204
+
"substituted ${rule.substitutedVersionId} with $withComponentSelector because '${rule.reason}' by rule ${rule.ruleSet}"
205
+
details.useTarget(
206
+
withComponentSelector,
207
+
message
208
+
)
209
+
return@Action
202
210
}
203
211
}
204
212
}
205
213
}
206
214
207
-
unversionedRules.forEach { rule ->
208
-
val substitutedModule = rule.substitutedModule
209
-
val withComponentSelector = rule.withComponentSelector
210
-
var message ="substituted $withComponentSelector because '${rule.reason}' by rule ${rule.ruleSet}"
211
-
212
-
val selectorNameSections = substitutedModule.displayName.split(":")
213
-
if (selectorNameSections.size >2) {
214
-
val selectorGroupAndArtifact ="${selectorNameSections[0]}:${selectorNameSections[1]}"
215
-
message =
216
-
"substituted $selectorGroupAndArtifact with $withComponentSelector because '${rule.reason}' by rule ${rule.ruleSet}"
217
-
}
218
-
219
-
resolutionStrategy.dependencySubstitution {
220
-
it.substitute(substitutedModule)
221
-
.because(message)
222
-
.with(withComponentSelector)
223
-
}
224
-
}
215
+
/*
216
+
* Unfortunately impossible to avoid an internal/protected method dependency for now:
217
+
*
218
+
* - We can't dependencySubstitutions.all because it causes the configuration to be resolved at task graph calculation time due to the possibility of project substitutions there
219
+
* - Likewise eachDependency has it's own performance issues - https://github.com/gradle/gradle/issues/16151
220
+
*
221
+
* There's no alternative to all that only allows module substitution and we only ever substitute modules for modules, so this is completely safe.
0 commit comments