summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Sig
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Sig')
-rw-r--r--src/engine/SCons/Sig/SigTests.py40
-rw-r--r--src/engine/SCons/Sig/__init__.py101
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