diff --git a/doc/manual/configuration.rst b/doc/manual/configuration.rst index 04f0f567..9fa2b769 100644 --- a/doc/manual/configuration.rst +++ b/doc/manual/configuration.rst @@ -1291,10 +1291,14 @@ The following settings are supported: | | | At the dependency both names will refer to the same | | | | tool. | +-------------+-----------------+-----------------------------------------------------+ -| clean | Boolean | Drop all the environment and tools collected so far | -| | | for this dependency. This is mostly useful to make | +| inherit | Boolean | Inherit environment and tools available for this | +| | | dependency. | +| | | When set to "false" all the environment and tools | +| | | are dropped. This is mostly useful to make | | | | an existing root-package become a dependency | | | | of another root package. | +| | | | +| | | Default: "true" | +-------------+-----------------+-----------------------------------------------------+ .. _configuration-recipes-env: diff --git a/pym/bob/input.py b/pym/bob/input.py index f71025a7..9723ffaf 100644 --- a/pym/bob/input.py +++ b/pym/bob/input.py @@ -1855,11 +1855,11 @@ class Recipe(object): """ class Dependency(object): - def __init__(self, recipe, env, fwd, use, cond, tools, checkoutDep, clean): + def __init__(self, recipe, env, fwd, use, cond, tools, checkoutDep, inherit): self.recipe = recipe self.envOverride = env self.provideGlobal = fwd - self.clean = clean + self.inherit = inherit self.use = use self.useEnv = "environment" in self.use self.useTools = "tools" in self.use @@ -1871,9 +1871,9 @@ def __init__(self, recipe, env, fwd, use, cond, tools, checkoutDep, clean): self.checkoutDep = checkoutDep @staticmethod - def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep, clean): + def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep, inherit): if isinstance(dep, str): - return [ Recipe.Dependency(dep, env, fwd, use, cond, tools, checkoutDep, clean) ] + return [ Recipe.Dependency(dep, env, fwd, use, cond, tools, checkoutDep, inherit) ] else: envOverride = dep.get("environment") if envOverride: @@ -1885,7 +1885,7 @@ def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep, clean): tools.update(toolOverride) fwd = dep.get("forward", fwd) use = dep.get("use", use) - clean = dep.get("clean", clean) + inherit = dep.get("inherit", inherit) newCond = dep.get("if") if newCond is not None: cond = cond + [newCond] if cond is not None else [ newCond ] @@ -1894,22 +1894,22 @@ def __parseEntry(dep, env, fwd, use, cond, tools, checkoutDep, clean): if name: if "depends" in dep: raise ParseError("A dependency must not use 'name' and 'depends' at the same time!") - return [ Recipe.Dependency(name, env, fwd, use, cond, tools, checkoutDep, clean) ] + return [ Recipe.Dependency(name, env, fwd, use, cond, tools, checkoutDep, inherit) ] dependencies = dep.get("depends") if dependencies is None: raise ParseError("Either 'name' or 'depends' required for dependencies!") return Recipe.Dependency.parseEntries(dependencies, env, fwd, use, cond, tools, - checkoutDep, clean) + checkoutDep, inherit) @staticmethod def parseEntries(deps, env={}, fwd=False, use=["result", "deps"], - cond=None, tools={}, checkoutDep=False, clean=False): + cond=None, tools={}, checkoutDep=False, inherit=True): """Returns an iterator yielding all dependencies as flat list""" # return flattened list of dependencies return chain.from_iterable( Recipe.Dependency.__parseEntry(dep, env, fwd, use, cond, tools, - checkoutDep, clean) + checkoutDep, inherit) for dep in deps ) @staticmethod @@ -2310,7 +2310,21 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None, resolvedDeps = [] for dep in self.__deps: - env.setFunArgs({ "recipe" : self, "sandbox" : bool(sandbox) and sandboxEnabled, + thisDepEnv = depEnv + thisDepTools = depTools + thisDepDiffTools = depDiffTools + thisSandbox = sandbox + thisSandboxEnabled = sandboxEnabled + thisDepDiffSandbox = depDiffSandbox + if not dep.inherit: + thisDepEnv = self.getRecipeSet().getRootEnv() + thisDepTools = Env() + thisDepDiffTools = {} + thisDepDiffSandbox = ... + thisSandbox = None + thisSandboxEnabled = False + + env.setFunArgs({ "recipe" : self, "sandbox" : bool(thisSandbox) and thisSandboxEnabled, "__tools" : tools }) recipe = env.substitute(dep.recipe, "dependency::"+dep.recipe) @@ -2319,41 +2333,36 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None, if dep.condition and not all(env.evaluate(cond, "dependency "+recipe) for cond in dep.condition): continue - if dep.clean: - thisDepEnv = self.getRecipeSet().getRootEnv() - thisDepTools = Env() - thisDepDiffTools = Env() + if dep.toolOverride: + try: + thisDepTools = thisDepTools.derive({ + k : depTools[v] for k,v in dep.toolOverride.items() }) + except KeyError as e: + raise ParseError("Cannot remap unkown tool '{}' for dependency '{}'!" + .format(e.args[0], recipe)) + thisDepDiffTools = thisDepDiffTools.copy() + thisDepDiffTools.update({ + k : depDiffTools.get(v, v) + for k, v in dep.toolOverride.items() }) else: - if dep.toolOverride: - try: - thisDepTools = depTools.derive({ - k : depTools[v] for k,v in dep.toolOverride.items() }) - except KeyError as e: - raise ParseError("Cannot remap unkown tool '{}' for dependency '{}'!" - .format(e.args[0], recipe)) - thisDepDiffTools = depDiffTools.copy() - thisDepDiffTools.update({ - k : depDiffTools.get(v, v) - for k, v in dep.toolOverride.items() }) - else: - thisDepTools = depTools - thisDepDiffTools = depDiffTools + thisDepTools = thisDepTools + thisDepDiffTools = thisDepDiffTools - thisDepEnv = depEnv.derive( - { key : env.substitute(value, "depends["+recipe+"].environment["+key+"]") - for key, value in dep.envOverride.items() }) + thisDepEnv = thisDepEnv.derive( + { key : env.substitute(value, "depends["+recipe+"].environment["+key+"]") + for key, value in dep.envOverride.items() }) r = self.__recipeSet.getRecipe(recipe) try: if r.__packageName in stack: raise ParseError("Recipes are cyclic (1st package in cylce)") depStack = stack + [r.__packageName] - p, s = r.prepare(thisDepEnv, sandboxEnabled, depStates, + p, s = r.prepare(thisDepEnv, thisSandboxEnabled, depStates, depSandbox, thisDepTools, depStack) subTreePackages.add(p.getName()) subTreePackages.update(s) depCoreStep = p.getCorePackageStep() - depRef = CoreRef(depCoreStep, [p.getName()], thisDepDiffTools, depDiffSandbox) + depRef = CoreRef(depCoreStep, [p.getName()], thisDepDiffTools, thisDepDiffSandbox) except ParseError as e: e.pushFrame(r.getPackageName()) raise e @@ -2372,7 +2381,7 @@ def prepare(self, inputEnv, sandboxEnabled, inputStates, inputSandbox=None, # Remember dependency diffs before changing them origDepDiffTools = thisDepDiffTools - origDepDiffSandbox = depDiffSandbox + origDepDiffSandbox = thisDepDiffSandbox # pick up various results of package for (n, s) in states.items(): @@ -3574,7 +3583,7 @@ def __createSchemas(self): schema.Optional('name') : str, schema.Optional('use') : useClauses, schema.Optional('forward') : bool, - schema.Optional('clean') : bool, + schema.Optional('inherit') : bool, schema.Optional('environment') : VarDefineValidator("depends::environment"), schema.Optional('if') : schema.Or(str, IfExpression), schema.Optional('tools') : { toolNameSchema : toolNameSchema }, diff --git a/test/unit/test_input_recipeset.py b/test/unit/test_input_recipeset.py index 04f960e0..24fa69ee 100644 --- a/test/unit/test_input_recipeset.py +++ b/test/unit/test_input_recipeset.py @@ -647,8 +647,8 @@ def testCheckoutDepVariants(self): self.assertNotEqual(paVId, pbVId, "checkout steps are different") - def testCleanDep(self): - """ Test the `clean` property for dependencies """ + def testDepInherit(self): + """ Test the `inherit` property for dependencies """ self.writeDefault( {"environment" : {"DEFAULT" : "42" }}) @@ -665,11 +665,21 @@ def testCleanDep(self): self.writeRecipe("a", """\ inherit: [foo] depends: + - name: sandbox + use: [sandbox] + forward: True - name: b-env use: [environment] forward: true - name: b - clean: True + inherit: False + - name: c + inherit: False + environment: + C: "1" + tools: + c: foo + - d packageScript: "true" """) @@ -684,6 +694,18 @@ def testCleanDep(self): packageScript: "true" """) + self.writeRecipe("c", """\ + packageVars: [C] + packageTools: [c] + packageScript: "true" + """) + + self.writeRecipe("d", """\ + packageVars: [B] + packageTools: [foo] + packageScript: "true" + """) + self.writeRecipe("foo", """\ packageTools: [foo] packageScript: "true" @@ -691,17 +713,28 @@ def testCleanDep(self): foo: . """) + self.writeRecipe("sandbox", """\ + provideSandbox: + paths: ["."] + """) + recipes = RecipeSet() recipes.parse() - packages = recipes.generatePackages(lambda x,y: "unused") + packages = recipes.generatePackages(lambda s,m: "unused", True) pa_b = packages.walkPackagePath("a/b") pb = packages.walkPackagePath("b") + pb_e = packages.walkPackagePath("a/b-env") + pc = packages.walkPackagePath("a/c") + pd = packages.walkPackagePath("a/d") self.assertEqual(pa_b.getPackageStep().getVariantId(), pb.getPackageStep().getVariantId()) - self.assertEqual( - {"DEFAULT" : "42"}, - pb.getPackageStep().getEnv()) + self.assertEqual({"DEFAULT" : "42"}, pb.getPackageStep().getEnv()) + self.assertEqual({"C" : "1"}, pc.getPackageStep().getEnv()) + self.assertEqual(list(pc.getPackageStep().getTools()), ["c"]) + self.assertEqual(pc.getPackageStep().getSandbox(), None) + self.assertNotEqual(pb_e.getPackageStep().getSandbox(), None) + self.assertNotEqual(pd.getPackageStep().getSandbox(), None) class TestDependencyEnv(RecipesTmp, TestCase): """Tests related to "environment" block in dependencies"""