当其中一个依赖项没有指定组时,如果两个依赖项之间存在版本冲突,是否可以使gradle构建失败

时间:2015-06-22 15:15:10

标签: gradle

我正在试图弄清楚当其中一个没有指定组时,如何让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);
    }
}

}

1 个答案:

答案 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)
                }
            }
        }
    }