diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index fc20ca9c..64899209 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -51,8 +51,13 @@ List getBranchesInstalls() { def runExample(Map ctxt, String example) { for (extension in ctxt.extensions) { if (example.contains(extension)) { - def command = example.contains(".py") ? "python ${example}" : "${example}" - ctxt.shFunction(command) + example = example.replace("\\","/") + split_path = example.split('/') + String script = split_path[split_path.length-1] + String path = example - script + script = isUnix() ? "./${script}" : "${script}" + String command = script.contains(".py") ? "python ${script}" : "${script}" + ctxt.shFunction("cd ${path} && ${command}") } } } diff --git a/examples/consuming_packages/versioning/conflicts/force/engine/conanfile.py b/examples/consuming_packages/versioning/conflicts/force/engine/conanfile.py new file mode 100644 index 00000000..435cd83a --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/force/engine/conanfile.py @@ -0,0 +1,7 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "engine" + version = "1.0" + + requires = "math/1.0" diff --git a/examples/consuming_packages/versioning/conflicts/force/game/conanfile.py b/examples/consuming_packages/versioning/conflicts/force/game/conanfile.py new file mode 100644 index 00000000..134d6a84 --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/force/game/conanfile.py @@ -0,0 +1,9 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "game" + version = "1.0" + + def requirements(self): + self.requires("engine/1.0") + self.requires("math/2.0") diff --git a/examples/consuming_packages/versioning/conflicts/force/math/conanfile.py b/examples/consuming_packages/versioning/conflicts/force/math/conanfile.py new file mode 100644 index 00000000..4151efab --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/force/math/conanfile.py @@ -0,0 +1,4 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "math" diff --git a/examples/consuming_packages/versioning/conflicts/force/run_example.py b/examples/consuming_packages/versioning/conflicts/force/run_example.py new file mode 100644 index 00000000..6a76a16a --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/force/run_example.py @@ -0,0 +1,47 @@ +import os +import subprocess + +def run(cmd, error=False): + # Used by tools/scm check_repo only (see if repo ok with status) + print("Running: {}".format(cmd)) + process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + out, err = process.communicate() + out = out.decode("utf-8") + err = err.decode("utf-8") + ret = process.returncode + + output = err + out + if ret != 0 and not error: + raise Exception("Failed cmd: {}\n{}".format(cmd, output)) + if ret == 0 and error: + raise Exception("Cmd succeded (failure expected): {}\n{}".format(cmd, output)) + return output + + +# This is a half diamond +# game -> engine -> math/1.0 +# \--------------> math/2.0 (conflict) +# solved with force=True + +# Demo the conflict +run('conan remove "*" -f') # Make sure no packages from last run +run("conan create math --version=1.0") +run("conan create math --version=2.0") +run("conan create engine") +out = run("conan install game", error=True) +assert "ERROR: Version conflict: engine/1.0->math/1.0, game/1.0->math/2.0" in out + +# Add the requires "force=True" fixes it +content = open("game/conanfile.py").read() +new_content = content.replace('self.requires("math/2.0")', + 'self.requires("math/2.0", force=True)') +open("game/conanfile.py", "w").write(new_content) +# The jump in major version requires building a new engine/1.0 binary +out = run("conan install game", error=True) # binary missing +assert "ERROR: Missing binary: engine/1.0" in out + +# With force=True and --build=missing, it works +run("conan install game --build=missing") + +# restore the original contents: +open("game/conanfile.py", "w").write(content) diff --git a/examples/consuming_packages/versioning/conflicts/override/ai/conanfile.py b/examples/consuming_packages/versioning/conflicts/override/ai/conanfile.py new file mode 100644 index 00000000..be77fda2 --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/override/ai/conanfile.py @@ -0,0 +1,7 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "ai" + version = "1.0" + + requires = "math/2.0" diff --git a/examples/consuming_packages/versioning/conflicts/override/engine/conanfile.py b/examples/consuming_packages/versioning/conflicts/override/engine/conanfile.py new file mode 100644 index 00000000..435cd83a --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/override/engine/conanfile.py @@ -0,0 +1,7 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "engine" + version = "1.0" + + requires = "math/1.0" diff --git a/examples/consuming_packages/versioning/conflicts/override/game/conanfile.py b/examples/consuming_packages/versioning/conflicts/override/game/conanfile.py new file mode 100644 index 00000000..65533a61 --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/override/game/conanfile.py @@ -0,0 +1,9 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "game" + version = "1.0" + + def requirements(self): + self.requires("engine/1.0") + self.requires("ai/1.0") diff --git a/examples/consuming_packages/versioning/conflicts/override/math/conanfile.py b/examples/consuming_packages/versioning/conflicts/override/math/conanfile.py new file mode 100644 index 00000000..4151efab --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/override/math/conanfile.py @@ -0,0 +1,4 @@ +from conan import ConanFile + +class Pkg(ConanFile): + name = "math" diff --git a/examples/consuming_packages/versioning/conflicts/override/run_example.py b/examples/consuming_packages/versioning/conflicts/override/run_example.py new file mode 100644 index 00000000..19f17bd6 --- /dev/null +++ b/examples/consuming_packages/versioning/conflicts/override/run_example.py @@ -0,0 +1,48 @@ +import os +import subprocess + +def run(cmd, error=False): + # Used by tools/scm check_repo only (see if repo ok with status) + print("Running: {}".format(cmd)) + process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + out, err = process.communicate() + out = out.decode("utf-8") + err = err.decode("utf-8") + ret = process.returncode + + output = err + out + if ret != 0 and not error: + raise Exception("Failed cmd: {}\n{}".format(cmd, output)) + if ret == 0 and error: + raise Exception("Cmd succeded (failure expected): {}\n{}".format(cmd, output)) + return output + + +# This is a full diamond +# game -> engine -> math/1.0 +# \----> ai -----> math/2.0 (conflict) +# solved with override=True + +# Demo the conflict +run('conan remove "*" -f') # Make sure no packages from last run +run("conan create math --version=1.0") +run("conan create math --version=2.0") +run("conan create engine") +run("conan create ai") +out = run("conan install game", error=True) +# NOTE This output shows the downstream conflict not the immediate +assert "ERROR: Version conflict: ai/1.0->math/2.0, game/1.0->math/1.0" in out + +# Add the requires "force=True" fixes it +content = open("game/conanfile.py").read() +new_content = content + ' self.requires("math/2.0", override=True)\n' +open("game/conanfile.py", "w").write(new_content) +# The jump in major version requires building a new engine/1.0 binary +out = run("conan install game", error=True) # binary missing +assert "ERROR: Missing binary: engine/1.0" in out + +# With force=True and --build=missing, it works +run("conan install game --build=missing") + +# restore the original contents: +open("game/conanfile.py", "w").write(content)