diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py index 222a76e580..78a86ac4dc 100644 --- a/bitbake/lib/bb/command.py +++ b/bitbake/lib/bb/command.py @@ -505,6 +505,31 @@ class CommandsSync: raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex) command.remotedatastores.release(dsindex) + def dataStoreConnectorSetVarFlag(self, command, params): + dsindex = params[0] + name = params[1] + flag = params[2] + value = params[3] + datastore = command.remotedatastores[dsindex] + datastore.setVarFlag(name, flag, value) + + def dataStoreConnectorDelVar(self, command, params): + dsindex = params[0] + name = params[1] + datastore = command.remotedatastores[dsindex] + if len(params) > 2: + flag = params[2] + datastore.delVarFlag(name, flag) + else: + datastore.delVar(name) + + def dataStoreConnectorRenameVar(self, command, params): + dsindex = params[0] + name = params[1] + newname = params[2] + datastore = command.remotedatastores[dsindex] + datastore.renameVar(name, newname) + def parseRecipeFile(self, command, params): """ Parse the specified recipe file (with or without bbappends) diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py index 5777d545a8..d6dd698eff 100644 --- a/bitbake/lib/bb/data_smart.py +++ b/bitbake/lib/bb/data_smart.py @@ -609,6 +609,12 @@ class DataSmart(MutableMapping): """ Rename the variable key to newkey """ + if '_remote_data' in self.dict: + connector = self.dict["_remote_data"]["_content"] + res = connector.renameVar(key, newkey) + if not res: + return + val = self.getVar(key, 0, parsing=True) if val is not None: loginfo['variable'] = newkey @@ -652,6 +658,12 @@ class DataSmart(MutableMapping): self.setVar(var + "_prepend", value, ignore=True, parsing=True) def delVar(self, var, **loginfo): + if '_remote_data' in self.dict: + connector = self.dict["_remote_data"]["_content"] + res = connector.delVar(var) + if not res: + return + loginfo['detail'] = "" loginfo['op'] = 'del' self.varhistory.record(**loginfo) @@ -678,6 +690,12 @@ class DataSmart(MutableMapping): override = None def setVarFlag(self, var, flag, value, **loginfo): + if '_remote_data' in self.dict: + connector = self.dict["_remote_data"]["_content"] + res = connector.setVarFlag(var, flag, value) + if not res: + return + self.expand_cache = {} if 'op' not in loginfo: loginfo['op'] = "set" @@ -796,6 +814,12 @@ class DataSmart(MutableMapping): return value def delVarFlag(self, var, flag, **loginfo): + if '_remote_data' in self.dict: + connector = self.dict["_remote_data"]["_content"] + res = connector.delVarFlag(var, flag) + if not res: + return + self.expand_cache = {} local_var, _ = self._findVar(var) if not local_var: @@ -938,7 +962,10 @@ class DataSmart(MutableMapping): if "_remote_data" in d: connector = d["_remote_data"]["_content"] - klist |= connector.getKeys() + for key in connector.getKeys(): + if key in deleted: + continue + klist.add(key) return klist diff --git a/bitbake/lib/bb/tests/data.py b/bitbake/lib/bb/tests/data.py index da3f4e66f8..fe947f5ba7 100644 --- a/bitbake/lib/bb/tests/data.py +++ b/bitbake/lib/bb/tests/data.py @@ -460,26 +460,43 @@ class Serialize(unittest.TestCase): self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') +# Remote datastore tests +# These really only test the interface, since in actual usage we have a +# tinfoil connector that does everything over RPC, and this doesn't test +# that. + +class TestConnector: + d = None + def __init__(self, d): + self.d = d + def getVar(self, name): + return self.d._findVar(name) + def getKeys(self): + return set(self.d.keys()) + def getVarHistory(self, name): + return self.d.varhistory.variable(name) + def expandPythonRef(self, varname, expr, d): + localdata = self.d.createCopy() + for key in d.localkeys(): + localdata.setVar(d.getVar(key)) + varparse = bb.data_smart.VariableParse(varname, localdata) + return varparse.python_sub(expr) + def setVar(self, name, value): + self.d.setVar(name, value) + def setVarFlag(self, name, flag, value): + self.d.setVarFlag(name, flag, value) + def delVar(self, name): + self.d.delVar(name) + return False + def delVarFlag(self, name, flag): + self.d.delVarFlag(name, flag) + return False + def renameVar(self, name, newname): + self.d.renameVar(name, newname) + return False + class Remote(unittest.TestCase): def test_remote(self): - class TestConnector: - d = None - def __init__(self, d): - self.d = d - def getVar(self, name): - return self.d._findVar(name) - def getKeys(self): - return self.d.localkeys() - def getVarHistory(self, name): - return self.d.varhistory.variable(name) - def expandPythonRef(self, varname, expr, d): - localdata = self.d.createCopy() - for key in d.localkeys(): - localdata.setVar(d.getVar(key)) - varparse = bb.data_smart.VariableParse(varname, localdata) - return varparse.python_sub(expr) - def setVar(self, name, value): - self.d.setVar(name, value) d1 = bb.data.init() d1.enableTracking() @@ -500,6 +517,9 @@ class Remote(unittest.TestCase): # Test setVar on client side affects server d2.setVar('HELLO', 'other-world') self.assertEqual(d1.getVar('HELLO'), 'other-world') + # Test setVarFlag on client side affects server + d2.setVarFlag('HELLO', 'flagname', 'flagvalue') + self.assertEqual(d1.getVarFlag('HELLO', 'flagname'), 'flagvalue') # Test client side data is incorporated in python expansion (which is done on server) d2.setVar('FOO', 'bar') self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar') @@ -507,3 +527,75 @@ class Remote(unittest.TestCase): d1.setVar('FOO_test', 'baz') d1.appendVar('OVERRIDES', ':test') self.assertEqual(d2.getVar('FOO'), 'baz') + + +# Remote equivalents of local test classes +# Note that these aren't perfect since we only test in one direction + +class RemoteDataExpansions(DataExpansions): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1["foo"] = "value_of_foo" + self.d1["bar"] = "value_of_bar" + self.d1["value_of_foo"] = "value_of_'value_of_foo'" + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) + +class TestRemoteNestedExpansions(TestNestedExpansions): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1["foo"] = "foo" + self.d1["bar"] = "bar" + self.d1["value_of_foobar"] = "187" + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) + +class TestRemoteConcat(TestConcat): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1.setVar("FOO", "foo") + self.d1.setVar("VAL", "val") + self.d1.setVar("BAR", "bar") + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) + +class TestRemoteConcatOverride(TestConcatOverride): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1.setVar("FOO", "foo") + self.d1.setVar("VAL", "val") + self.d1.setVar("BAR", "bar") + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) + +class TestRemoteOverrides(TestOverrides): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1.setVar("OVERRIDES", "foo:bar:local") + self.d1.setVar("TEST", "testvalue") + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) + +class TestRemoteKeyExpansion(TestKeyExpansion): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1.setVar("FOO", "foo") + self.d1.setVar("BAR", "foo") + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) + +class TestRemoteFlags(TestFlags): + def setUp(self): + self.d1 = bb.data.init() + self.d = bb.data.init() + self.d1.setVar("foo", "value of foo") + self.d1.setVarFlag("foo", "flag1", "value of flag1") + self.d1.setVarFlag("foo", "flag2", "value of flag2") + connector = TestConnector(self.d1) + self.d.setVar('_remote_data', connector) diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py index 00cec59b83..19b41be46c 100644 --- a/bitbake/lib/bb/tinfoil.py +++ b/bitbake/lib/bb/tinfoil.py @@ -1,6 +1,6 @@ # tinfoil: a simple wrapper around cooker for bitbake-based command-line utilities # -# Copyright (C) 2012-2016 Intel Corporation +# Copyright (C) 2012-2017 Intel Corporation # Copyright (C) 2011 Mentor Graphics Corporation # # This program is free software; you can redistribute it and/or modify @@ -84,6 +84,34 @@ class TinfoilDataStoreConnector: # Not currently implemented - indicate that setting should # be redirected to local side return True + def setVarFlag(self, varname, flagname, value): + if self.dsindex is None: + self.tinfoil.run_command('dataStoreConnectorSetVarFlag', self.dsindex, varname, flagname, value) + else: + # Not currently implemented - indicate that setting should + # be redirected to local side + return True + def delVar(self, varname): + if self.dsindex is None: + self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname) + else: + # Not currently implemented - indicate that setting should + # be redirected to local side + return True + def delVarFlag(self, varname, flagname): + if self.dsindex is None: + self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname, flagname) + else: + # Not currently implemented - indicate that setting should + # be redirected to local side + return True + def renameVar(self, name, newname): + if self.dsindex is None: + self.tinfoil.run_command('dataStoreConnectorRenameVar', self.dsindex, name, newname) + else: + # Not currently implemented - indicate that setting should + # be redirected to local side + return True class TinfoilCookerAdapter: """