我正在试图弄清楚当其中一个没有指定组时,如何让gradle在两个依赖项之间的版本冲突上构建失败。
例如,我有一个项目依赖于来自配置的平面目录存储库(供应商)的jar
compile ':guava:r09'
和指向从maven存储库中检索的模块的传递依赖
compile 'com.google.guava:guava:13.0.1'
据我所知,通过设计 failOnVersionConflict 解析策略不会引发上述示例的冲突。我无法确定平面目录中jar的组名,因此想要引发冲突,开发人员可以相应地强制执行其中一个模块。感谢您抽出宝贵时间阅读问题。
更新
根据Ben的评论,我附加了用于引发自定义冲突的代码段。但这对我的情况没有帮助,因为我无法利用强制解决策略来解决冲突。我可以排除传递依赖关系或完全删除直接依赖关系。希望它对其他人有用。
gradle.afterProject {
project.configurations.each { conf ->
def map = new HashMap<String, List<Dependency>>()
//println "\tConfiguration- ${project.name}:${conf.name}"
conf.allDependencies.each { dep ->
//println "\t\t${dep.group}:${dep.name}:${dep.version}"
ArrayList<Dependency> dependencies = null
if(map.containsKey(dep.name))
{
dependencies = map.get(dep.name)
}
else
{
dependencies = new ArrayList<>()
map.put(dep.name, dependencies)
dependencies.add(dep)
}
if(dep.group == null || dep.group.equals("unspecified"))
{
for(Dependency depInMap : dependencies) {
if(depInMap.version == null && dep.version == null)
continue;
if(depInMap.version != null && depInMap.version.equals(dep.version))
continue;
throw new GradleException("Customized Conflict: A conflict was found in " +
"${project.name}:${conf.name} between the following modules:" +
"\n- ${dep.group}:${dep.name}:${dep.version}" +
"\n- ${depInMap.group}:${depInMap.name}:${depInMap.version}")
}
}
dependencies.add(dep);
}
}
}
答案 0 :(得分:1)
这是我提出的解决方案。下面给出了其他可能使用它的人的代码片段。代码不整齐但功能齐全。欢迎任何建议。
private static boolean isGroupEmpty(DependencyResolveDetails details){
if (details.requested.group == null) {
return true;
} else if (details.requested.group == "unspecified"){
return true;
} else if(details.requested.group.isEmpty()) {
return true;
} else {
return false;
}
}
configurations.all {
def dependencyMap = [:]
def forcedModules = resolutionStrategy.forcedModules
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def targetToUse = null
for (forcedModule in forcedModules) {
if(forcedModule.name == details.requested.name &&
(forcedModule.group == details.requested.group || isGroupEmpty(details))) {
targetToUse = "${forcedModule.group}:${forcedModule.name}:${forcedModule.version}"
}
}
if(targetToUse != null) {
println "Forcing: " + targetToUse
details.useTarget targetToUse
}
else {
if(dependencyMap.containsKey(details.requested.name)) {
DependencyResolveDetails prevDetails = dependencyMap.get(details.requested.name);
boolean groupMatches = false
if(isGroupEmpty(prevDetails) || isGroupEmpty(details) ||
prevDetails.requested.group == details.requested.group){
groupMatches = true
}
if(groupMatches)
{
boolean versionMatches = false
if(prevDetails.requested.version == details.requested.version) {
versionMatches = true
}
if(!versionMatches)
{
//If versions don't match throw an exception.
throw new GradleException("Custom Conflict: A conflict was found in " +
"${project.name} between the following modules:" +
"\n- ${prevDetails.requested.group}:${prevDetails.requested.name}:" +
"${prevDetails.requested.version}" +
"\n- ${details.requested.group}:${details.requested.name}:" +
"${details.requested.version}")
}
else {
//Use either one (in this case I force the one with empty group)
DependencyResolveDetails repl
DependencyResolveDetails pref
if(isGroupEmpty(prevDetails)) {
pref = prevDetails
repl = details
}
else {
pref = details
repl = prevDetails
dependencyMap.put(details.requested.name, details)
}
repl.useTarget "unspecified:${pref.requested.name}:${pref.requested.version}"
println "Replacing module " +
"\n - ${repl.requested.group}:${repl.requested.name}:${repl.requested.version}" +
"\n with " +
"\n - ${pref.requested.group}:${pref.requested.name}:${pref.requested.version} ."
}
}
}
else {
dependencyMap.put(details.requested.name, details)
}
}
}
}