diff options
Diffstat (limited to 'src/engine/SCons/Sig')
-rw-r--r-- | src/engine/SCons/Sig/SigTests.py | 40 | ||||
-rw-r--r-- | src/engine/SCons/Sig/__init__.py | 101 |
2 files changed, 119 insertions, 22 deletions
diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py index af2ebab..c82d2c5 100644 --- a/src/engine/SCons/Sig/SigTests.py +++ b/src/engine/SCons/Sig/SigTests.py @@ -424,7 +424,7 @@ class _SConsignTestCase(unittest.TestCase): assert f.get('foo') == (3, 1, 2) assert f.get_implicit('foo') == ['bar'] - f = SCons.Sig._SConsign(None, DummyModule()) + f = SCons.Sig._SConsign(DummyModule()) f.set_bsig('foo', 1) assert f.get('foo') == (None, 1, None) f.set_csig('foo', 2) @@ -435,7 +435,38 @@ class _SConsignTestCase(unittest.TestCase): assert f.get('foo') == (3, 1, 2) assert f.get_implicit('foo') == ['bar'] -class SConsignFileTestCase(unittest.TestCase): +class SConsignDBTestCase(unittest.TestCase): + + def runTest(self): + class DummyNode: + def __init__(self, path): + self.path = path + save_SConsign_db = SCons.Sig.SConsign_db + SCons.Sig.SConsign_db = {} + try: + d1 = SCons.Sig.SConsignDB(DummyNode('dir1')) + d1.set_timestamp('foo', 1) + d1.set_bsig('foo', 2) + d1.set_csig('foo', 3) + d1.set_timestamp('bar', 4) + d1.set_bsig('bar', 5) + d1.set_csig('bar', 6) + assert d1.get('foo') == (1, 2, 3) + assert d1.get('bar') == (4, 5, 6) + + d2 = SCons.Sig.SConsignDB(DummyNode('dir1')) + d2.set_timestamp('foo', 7) + d2.set_bsig('foo', 8) + d2.set_csig('foo', 9) + d2.set_timestamp('bar', 10) + d2.set_bsig('bar', 11) + d2.set_csig('bar', 12) + assert d2.get('foo') == (7, 8, 9) + assert d2.get('bar') == (10, 11, 12) + finally: + SCons.Sig.SConsign_db = save_SConsign_db + +class SConsignDirFileTestCase(unittest.TestCase): def runTest(self): class DummyModule: @@ -448,7 +479,7 @@ class SConsignFileTestCase(unittest.TestCase): class DummyNode: path = 'not_a_valid_path' - f = SCons.Sig.SConsignFile(DummyNode(), DummyModule()) + f = SCons.Sig.SConsignDirFile(DummyNode(), DummyModule()) f.set_bsig('foo', 1) assert f.get('foo') == (None, 1, None) f.set_csig('foo', 2) @@ -467,7 +498,8 @@ def suite(): suite.addTest(CalcTestCase()) suite.addTest(SConsignEntryTestCase()) suite.addTest(_SConsignTestCase()) - suite.addTest(SConsignFileTestCase()) + suite.addTest(SConsignDBTestCase()) + suite.addTest(SConsignDirFileTestCase()) return suite if __name__ == "__main__": diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index b4b70b4..298db66 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -49,6 +49,8 @@ default_max_drift = 2*24*60*60 #XXX Get rid of the global array so this becomes re-entrant. sig_files = [] +SConsign_db = None + # 1 means use build signature for derived source files # 0 means use content signature for derived source files build_signature = 1 @@ -77,10 +79,16 @@ class SConsignEntry: implicit = None class _SConsign: - - def __init__(self, fp=None, module=None): + """ + This is the controlling class for the signatures for the collection of + entries associated with a specific directory. The actual directory + association will be maintained by a subclass that is specific to + the underlying storage method. This class provides a common set of + methods for fetching and storing the individual bits of information + that make up signature entry. + """ + def __init__(self, module=None): """ - fp - file pointer to read entries from module - the signature module being used """ @@ -91,18 +99,6 @@ class _SConsign: self.entries = {} self.dirty = 0 - if fp: - try: - self.entries = cPickle.load(fp) - if type(self.entries) is not type({}): - self.entries = {} - raise TypeError - except: - SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, - "Ignoring corrupt .sconsign file: %s"%self.sconsign) - global sig_files - sig_files.append(self) - # A null .sconsign entry. We define this here so that it will # be easy to keep this in sync if/whenever we change the type of # information returned by the get() method, below. @@ -185,11 +181,58 @@ class _SConsign: entry.implicit = implicit self.set_entry(filename, entry) -class SConsignFile(_SConsign): +class SConsignDB(_SConsign): """ - Encapsulates reading and writing a .sconsign file. + A _SConsign subclass that reads and writes signature information + from a global .sconsign.dbm file. """ + def __init__(self, dir, module=None): + _SConsign.__init__(self, module) + + self.dir = dir + + try: + global SConsign_db + rawentries = SConsign_db[self.dir.path] + except KeyError: + pass + else: + try: + self.entries = cPickle.loads(rawentries) + if type(self.entries) is not type({}): + self.entries = {} + raise TypeError + except: + SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, + "Ignoring corrupt sconsign entry : %s"%self.dir.path) + + global sig_files + sig_files.append(self) + + def write(self): + if self.dirty: + global SConsign_db + SConsign_db[self.dir.path] = cPickle.dumps(self.entries, 1) + SConsign_db.sync() +class SConsignDir(_SConsign): + def __init__(self, fp=None, module=None): + """ + fp - file pointer to read entries from + module - the signature module being used + """ + _SConsign.__init__(self, module) + + if fp: + self.entries = cPickle.load(fp) + if type(self.entries) is not type({}): + self.entries = {} + raise TypeError + +class SConsignDirFile(SConsignDir): + """ + Encapsulates reading and writing a per-directory .sconsign file. + """ def __init__(self, dir, module=None): """ dir - the directory for the file @@ -204,7 +247,14 @@ class SConsignFile(_SConsign): except: fp = None - _SConsign.__init__(self, fp, module) + try: + SConsignDir.__init__(self, fp, module) + except: + SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, + "Ignoring corrupt .sconsign file: %s"%self.sconsign) + + global sig_files + sig_files.append(self) def write(self): """ @@ -249,6 +299,21 @@ class SConsignFile(_SConsign): except: pass +SConsignForDirectory = SConsignDirFile + +def SConsignFile(name): + """ + Arrange for all signatures to be stored in a global .sconsign.dbm + file. + """ + global SConsign_db + if SConsign_db is None: + import anydbm + SConsign_db = anydbm.open(name, "c") + + global SConsignForDirectory + SConsignForDirectory = SConsignDB + class Calculator: """ Encapsulates signature calculations and .sconsign file generating |