summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2017-03-20 17:05:53 +1300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-03-22 11:35:22 +0000
commit5b1807021e932b1150095f3d1744d8411a28a1f0 (patch)
treeb949a92af026dfb0334be4fa627c48920538fa42 /bitbake
parent99414bdb1c64f7f03e12c347cc16c43c2fa336b2 (diff)
downloadpoky-5b1807021e932b1150095f3d1744d8411a28a1f0.tar.gz
bitbake: data_smart: implement missing remote datastore operations
Enable the following operations from a remote datastore to affect the other end: * setVarFlag() * delVar() * delVarFlag() * renameVar() In practice I don't expect these to be used much, but they should be present so that the implementation is at least reasonably filled out and that the tests pass. Also add tests for the interface, mostly by subclassing the existing local test classes so that they are using a remote datastore. (These don't actually test remote usage via tinfoil, just that the datastore's interface can be used.) (Bitbake rev: 282dc0719d22a39df746eea762ebe05c66aa8f8a) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/command.py25
-rw-r--r--bitbake/lib/bb/data_smart.py29
-rw-r--r--bitbake/lib/bb/tests/data.py128
-rw-r--r--bitbake/lib/bb/tinfoil.py30
4 files changed, 192 insertions, 20 deletions
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:
505 raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex) 505 raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex)
506 command.remotedatastores.release(dsindex) 506 command.remotedatastores.release(dsindex)
507 507
508 def dataStoreConnectorSetVarFlag(self, command, params):
509 dsindex = params[0]
510 name = params[1]
511 flag = params[2]
512 value = params[3]
513 datastore = command.remotedatastores[dsindex]
514 datastore.setVarFlag(name, flag, value)
515
516 def dataStoreConnectorDelVar(self, command, params):
517 dsindex = params[0]
518 name = params[1]
519 datastore = command.remotedatastores[dsindex]
520 if len(params) > 2:
521 flag = params[2]
522 datastore.delVarFlag(name, flag)
523 else:
524 datastore.delVar(name)
525
526 def dataStoreConnectorRenameVar(self, command, params):
527 dsindex = params[0]
528 name = params[1]
529 newname = params[2]
530 datastore = command.remotedatastores[dsindex]
531 datastore.renameVar(name, newname)
532
508 def parseRecipeFile(self, command, params): 533 def parseRecipeFile(self, command, params):
509 """ 534 """
510 Parse the specified recipe file (with or without bbappends) 535 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):
609 """ 609 """
610 Rename the variable key to newkey 610 Rename the variable key to newkey
611 """ 611 """
612 if '_remote_data' in self.dict:
613 connector = self.dict["_remote_data"]["_content"]
614 res = connector.renameVar(key, newkey)
615 if not res:
616 return
617
612 val = self.getVar(key, 0, parsing=True) 618 val = self.getVar(key, 0, parsing=True)
613 if val is not None: 619 if val is not None:
614 loginfo['variable'] = newkey 620 loginfo['variable'] = newkey
@@ -652,6 +658,12 @@ class DataSmart(MutableMapping):
652 self.setVar(var + "_prepend", value, ignore=True, parsing=True) 658 self.setVar(var + "_prepend", value, ignore=True, parsing=True)
653 659
654 def delVar(self, var, **loginfo): 660 def delVar(self, var, **loginfo):
661 if '_remote_data' in self.dict:
662 connector = self.dict["_remote_data"]["_content"]
663 res = connector.delVar(var)
664 if not res:
665 return
666
655 loginfo['detail'] = "" 667 loginfo['detail'] = ""
656 loginfo['op'] = 'del' 668 loginfo['op'] = 'del'
657 self.varhistory.record(**loginfo) 669 self.varhistory.record(**loginfo)
@@ -678,6 +690,12 @@ class DataSmart(MutableMapping):
678 override = None 690 override = None
679 691
680 def setVarFlag(self, var, flag, value, **loginfo): 692 def setVarFlag(self, var, flag, value, **loginfo):
693 if '_remote_data' in self.dict:
694 connector = self.dict["_remote_data"]["_content"]
695 res = connector.setVarFlag(var, flag, value)
696 if not res:
697 return
698
681 self.expand_cache = {} 699 self.expand_cache = {}
682 if 'op' not in loginfo: 700 if 'op' not in loginfo:
683 loginfo['op'] = "set" 701 loginfo['op'] = "set"
@@ -796,6 +814,12 @@ class DataSmart(MutableMapping):
796 return value 814 return value
797 815
798 def delVarFlag(self, var, flag, **loginfo): 816 def delVarFlag(self, var, flag, **loginfo):
817 if '_remote_data' in self.dict:
818 connector = self.dict["_remote_data"]["_content"]
819 res = connector.delVarFlag(var, flag)
820 if not res:
821 return
822
799 self.expand_cache = {} 823 self.expand_cache = {}
800 local_var, _ = self._findVar(var) 824 local_var, _ = self._findVar(var)
801 if not local_var: 825 if not local_var:
@@ -938,7 +962,10 @@ class DataSmart(MutableMapping):
938 962
939 if "_remote_data" in d: 963 if "_remote_data" in d:
940 connector = d["_remote_data"]["_content"] 964 connector = d["_remote_data"]["_content"]
941 klist |= connector.getKeys() 965 for key in connector.getKeys():
966 if key in deleted:
967 continue
968 klist.add(key)
942 969
943 return klist 970 return klist
944 971
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):
460 self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') 460 self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet')
461 461
462 462
463# Remote datastore tests
464# These really only test the interface, since in actual usage we have a
465# tinfoil connector that does everything over RPC, and this doesn't test
466# that.
467
468class TestConnector:
469 d = None
470 def __init__(self, d):
471 self.d = d
472 def getVar(self, name):
473 return self.d._findVar(name)
474 def getKeys(self):
475 return set(self.d.keys())
476 def getVarHistory(self, name):
477 return self.d.varhistory.variable(name)
478 def expandPythonRef(self, varname, expr, d):
479 localdata = self.d.createCopy()
480 for key in d.localkeys():
481 localdata.setVar(d.getVar(key))
482 varparse = bb.data_smart.VariableParse(varname, localdata)
483 return varparse.python_sub(expr)
484 def setVar(self, name, value):
485 self.d.setVar(name, value)
486 def setVarFlag(self, name, flag, value):
487 self.d.setVarFlag(name, flag, value)
488 def delVar(self, name):
489 self.d.delVar(name)
490 return False
491 def delVarFlag(self, name, flag):
492 self.d.delVarFlag(name, flag)
493 return False
494 def renameVar(self, name, newname):
495 self.d.renameVar(name, newname)
496 return False
497
463class Remote(unittest.TestCase): 498class Remote(unittest.TestCase):
464 def test_remote(self): 499 def test_remote(self):
465 class TestConnector:
466 d = None
467 def __init__(self, d):
468 self.d = d
469 def getVar(self, name):
470 return self.d._findVar(name)
471 def getKeys(self):
472 return self.d.localkeys()
473 def getVarHistory(self, name):
474 return self.d.varhistory.variable(name)
475 def expandPythonRef(self, varname, expr, d):
476 localdata = self.d.createCopy()
477 for key in d.localkeys():
478 localdata.setVar(d.getVar(key))
479 varparse = bb.data_smart.VariableParse(varname, localdata)
480 return varparse.python_sub(expr)
481 def setVar(self, name, value):
482 self.d.setVar(name, value)
483 500
484 d1 = bb.data.init() 501 d1 = bb.data.init()
485 d1.enableTracking() 502 d1.enableTracking()
@@ -500,6 +517,9 @@ class Remote(unittest.TestCase):
500 # Test setVar on client side affects server 517 # Test setVar on client side affects server
501 d2.setVar('HELLO', 'other-world') 518 d2.setVar('HELLO', 'other-world')
502 self.assertEqual(d1.getVar('HELLO'), 'other-world') 519 self.assertEqual(d1.getVar('HELLO'), 'other-world')
520 # Test setVarFlag on client side affects server
521 d2.setVarFlag('HELLO', 'flagname', 'flagvalue')
522 self.assertEqual(d1.getVarFlag('HELLO', 'flagname'), 'flagvalue')
503 # Test client side data is incorporated in python expansion (which is done on server) 523 # Test client side data is incorporated in python expansion (which is done on server)
504 d2.setVar('FOO', 'bar') 524 d2.setVar('FOO', 'bar')
505 self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar') 525 self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar')
@@ -507,3 +527,75 @@ class Remote(unittest.TestCase):
507 d1.setVar('FOO_test', 'baz') 527 d1.setVar('FOO_test', 'baz')
508 d1.appendVar('OVERRIDES', ':test') 528 d1.appendVar('OVERRIDES', ':test')
509 self.assertEqual(d2.getVar('FOO'), 'baz') 529 self.assertEqual(d2.getVar('FOO'), 'baz')
530
531
532# Remote equivalents of local test classes
533# Note that these aren't perfect since we only test in one direction
534
535class RemoteDataExpansions(DataExpansions):
536 def setUp(self):
537 self.d1 = bb.data.init()
538 self.d = bb.data.init()
539 self.d1["foo"] = "value_of_foo"
540 self.d1["bar"] = "value_of_bar"
541 self.d1["value_of_foo"] = "value_of_'value_of_foo'"
542 connector = TestConnector(self.d1)
543 self.d.setVar('_remote_data', connector)
544
545class TestRemoteNestedExpansions(TestNestedExpansions):
546 def setUp(self):
547 self.d1 = bb.data.init()
548 self.d = bb.data.init()
549 self.d1["foo"] = "foo"
550 self.d1["bar"] = "bar"
551 self.d1["value_of_foobar"] = "187"
552 connector = TestConnector(self.d1)
553 self.d.setVar('_remote_data', connector)
554
555class TestRemoteConcat(TestConcat):
556 def setUp(self):
557 self.d1 = bb.data.init()
558 self.d = bb.data.init()
559 self.d1.setVar("FOO", "foo")
560 self.d1.setVar("VAL", "val")
561 self.d1.setVar("BAR", "bar")
562 connector = TestConnector(self.d1)
563 self.d.setVar('_remote_data', connector)
564
565class TestRemoteConcatOverride(TestConcatOverride):
566 def setUp(self):
567 self.d1 = bb.data.init()
568 self.d = bb.data.init()
569 self.d1.setVar("FOO", "foo")
570 self.d1.setVar("VAL", "val")
571 self.d1.setVar("BAR", "bar")
572 connector = TestConnector(self.d1)
573 self.d.setVar('_remote_data', connector)
574
575class TestRemoteOverrides(TestOverrides):
576 def setUp(self):
577 self.d1 = bb.data.init()
578 self.d = bb.data.init()
579 self.d1.setVar("OVERRIDES", "foo:bar:local")
580 self.d1.setVar("TEST", "testvalue")
581 connector = TestConnector(self.d1)
582 self.d.setVar('_remote_data', connector)
583
584class TestRemoteKeyExpansion(TestKeyExpansion):
585 def setUp(self):
586 self.d1 = bb.data.init()
587 self.d = bb.data.init()
588 self.d1.setVar("FOO", "foo")
589 self.d1.setVar("BAR", "foo")
590 connector = TestConnector(self.d1)
591 self.d.setVar('_remote_data', connector)
592
593class TestRemoteFlags(TestFlags):
594 def setUp(self):
595 self.d1 = bb.data.init()
596 self.d = bb.data.init()
597 self.d1.setVar("foo", "value of foo")
598 self.d1.setVarFlag("foo", "flag1", "value of flag1")
599 self.d1.setVarFlag("foo", "flag2", "value of flag2")
600 connector = TestConnector(self.d1)
601 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 @@
1# tinfoil: a simple wrapper around cooker for bitbake-based command-line utilities 1# tinfoil: a simple wrapper around cooker for bitbake-based command-line utilities
2# 2#
3# Copyright (C) 2012-2016 Intel Corporation 3# Copyright (C) 2012-2017 Intel Corporation
4# Copyright (C) 2011 Mentor Graphics Corporation 4# Copyright (C) 2011 Mentor Graphics Corporation
5# 5#
6# This program is free software; you can redistribute it and/or modify 6# This program is free software; you can redistribute it and/or modify
@@ -84,6 +84,34 @@ class TinfoilDataStoreConnector:
84 # Not currently implemented - indicate that setting should 84 # Not currently implemented - indicate that setting should
85 # be redirected to local side 85 # be redirected to local side
86 return True 86 return True
87 def setVarFlag(self, varname, flagname, value):
88 if self.dsindex is None:
89 self.tinfoil.run_command('dataStoreConnectorSetVarFlag', self.dsindex, varname, flagname, value)
90 else:
91 # Not currently implemented - indicate that setting should
92 # be redirected to local side
93 return True
94 def delVar(self, varname):
95 if self.dsindex is None:
96 self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname)
97 else:
98 # Not currently implemented - indicate that setting should
99 # be redirected to local side
100 return True
101 def delVarFlag(self, varname, flagname):
102 if self.dsindex is None:
103 self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname, flagname)
104 else:
105 # Not currently implemented - indicate that setting should
106 # be redirected to local side
107 return True
108 def renameVar(self, name, newname):
109 if self.dsindex is None:
110 self.tinfoil.run_command('dataStoreConnectorRenameVar', self.dsindex, name, newname)
111 else:
112 # Not currently implemented - indicate that setting should
113 # be redirected to local side
114 return True
87 115
88class TinfoilCookerAdapter: 116class TinfoilCookerAdapter:
89 """ 117 """