summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Sig
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-05-06 06:21:43 (GMT)
committerSteven Knight <knight@baldmt.com>2004-05-06 06:21:43 (GMT)
commitb155ebc4a869e0669ee2f7124531e0b5950c7528 (patch)
tree520cb5708efb85d177a120155048cd8e1361796e /src/engine/SCons/Sig
parent2a9941e968724723c70f106401fe8b984add626a (diff)
downloadSCons-b155ebc4a869e0669ee2f7124531e0b5950c7528.zip
SCons-b155ebc4a869e0669ee2f7124531e0b5950c7528.tar.gz
SCons-b155ebc4a869e0669ee2f7124531e0b5950c7528.tar.bz2
Refactor .sconsign management into its own module.
Diffstat (limited to 'src/engine/SCons/Sig')
-rw-r--r--src/engine/SCons/Sig/SigTests.py138
-rw-r--r--src/engine/SCons/Sig/__init__.py290
2 files changed, 2 insertions, 426 deletions
diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py
index 76cd931..009addd 100644
--- a/src/engine/SCons/Sig/SigTests.py
+++ b/src/engine/SCons/Sig/SigTests.py
@@ -393,139 +393,6 @@ class CalcTestCase(unittest.TestCase):
nn.always_build = 1
assert not self.calc.current(nn, 33)
-class SConsignEntryTestCase(unittest.TestCase):
-
- def runTest(self):
- e = SCons.Sig.SConsignEntry()
- assert e.timestamp == None
- assert e.csig == None
- assert e.bsig == None
- assert e.implicit == None
-
-class _SConsignTestCase(unittest.TestCase):
-
- def runTest(self):
- class DummyModule:
- def to_string(self, sig):
- return str(sig)
-
- def from_string(self, sig):
- return int(sig)
-
- class DummyNode:
- path = 'not_a_valid_path'
-
- f = SCons.Sig._SConsign()
- f.set_binfo('foo', 1, ['f1'], ['f2'], 'foo act', 'foo actsig')
- assert f.get('foo') == (None, 1, None)
- f.set_csig('foo', 2)
- assert f.get('foo') == (None, 1, 2)
- f.set_timestamp('foo', 3)
- assert f.get('foo') == (3, 1, 2)
- f.set_implicit('foo', ['bar'])
- assert f.get('foo') == (3, 1, 2)
- assert f.get_implicit('foo') == ['bar']
-
- f = SCons.Sig._SConsign(DummyModule())
- f.set_binfo('foo', 1, ['f1'], ['f2'], 'foo act', 'foo actsig')
- assert f.get('foo') == (None, 1, None)
- f.set_csig('foo', 2)
- assert f.get('foo') == (None, 1, 2)
- f.set_timestamp('foo', 3)
- assert f.get('foo') == (3, 1, 2)
- f.set_implicit('foo', ['bar'])
- assert f.get('foo') == (3, 1, 2)
- assert f.get_implicit('foo') == ['bar']
-
-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_binfo('foo', 2, ['f1'], ['f2'], 'foo act', 'foo actsig')
- d1.set_csig('foo', 3)
- d1.set_timestamp('bar', 4)
- d1.set_binfo('bar', 5, ['b1'], ['b2'], 'bar act', 'bar actsig')
- 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_binfo('foo', 8, ['f3'], ['f4'], 'foo act', 'foo actsig')
- d2.set_csig('foo', 9)
- d2.set_timestamp('bar', 10)
- d2.set_binfo('bar', 11, ['b3'], ['b4'], 'bar act', 'bar actsig')
- 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:
- def to_string(self, sig):
- return str(sig)
-
- def from_string(self, sig):
- return int(sig)
-
- class DummyNode:
- path = 'not_a_valid_path'
-
- f = SCons.Sig.SConsignDirFile(DummyNode(), DummyModule())
- f.set_binfo('foo', 1, ['f1'], ['f2'], 'foo act', 'foo actsig')
- assert f.get('foo') == (None, 1, None)
- f.set_csig('foo', 2)
- assert f.get('foo') == (None, 1, 2)
- f.set_timestamp('foo', 3)
- assert f.get('foo') == (3, 1, 2)
- f.set_implicit('foo', ['bar'])
- assert f.get('foo') == (3, 1, 2)
- assert f.get_implicit('foo') == ['bar']
-
-class SConsignFileTestCase(unittest.TestCase):
-
- def runTest(self):
- test = TestCmd.TestCmd(workdir = '')
- file = test.workpath('sconsign_file')
-
- assert SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
-
- SCons.Sig.SConsignFile(file)
-
- assert not SCons.Sig.SConsign_db is SCons.dblite, SCons.Sig.SConsign_db
-
- class Fake_DBM:
- def open(self, name, mode):
- self.name = name
- self.mode = mode
- return self
-
- fake_dbm = Fake_DBM()
-
- SCons.Sig.SConsignFile(file, fake_dbm)
-
- assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
- assert not hasattr(fake_dbm, 'name'), fake_dbm
- assert not hasattr(fake_dbm, 'mode'), fake_dbm
-
- SCons.Sig.SConsign_db = None
-
- SCons.Sig.SConsignFile(file, fake_dbm)
-
- assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
- assert fake_dbm.name == file, fake_dbm.name
- assert fake_dbm.mode == "c", fake_dbm.mode
-
def suite():
@@ -533,11 +400,6 @@ def suite():
suite.addTest(MD5TestCase())
suite.addTest(TimeStampTestCase())
suite.addTest(CalcTestCase())
- suite.addTest(SConsignEntryTestCase())
- suite.addTest(_SConsignTestCase())
- suite.addTest(SConsignDBTestCase())
- suite.addTest(SConsignDirFileTestCase())
- suite.addTest(SConsignFileTestCase())
return suite
if __name__ == "__main__":
diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py
index dac3f6c..271f252 100644
--- a/src/engine/SCons/Sig/__init__.py
+++ b/src/engine/SCons/Sig/__init__.py
@@ -46,293 +46,6 @@ except ImportError:
default_max_drift = 2*24*60*60
-#XXX Get rid of the global array so this becomes re-entrant.
-sig_files = []
-
-SConsign_db = None
-
-def write():
- global sig_files
- for sig_file in sig_files:
- sig_file.write()
-
-
-class SConsignEntry:
-
- """Objects of this type are pickled to the .sconsign file, so it
- should only contain simple builtin Python datatypes and no methods.
-
- This class is used to store cache information about nodes between
- scons runs for efficiency, and to store the build signature for
- nodes so that scons can determine if they are out of date. """
-
- # setup the default value for various attributes:
- # (We make the class variables so the default values won't get pickled
- # with the instances, which would waste a lot of space)
- timestamp = None
- bsig = None
- csig = None
- implicit = None
- bkids = []
- bkidsigs = []
- bact = None
- bactsig = None
-
-class _SConsign:
- """
- 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):
- """
- module - the signature module being used
- """
-
- if module is None:
- self.module = default_calc.module
- else:
- self.module = module
- self.entries = {}
- self.dirty = 0
-
- # 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.
- null_siginfo = (None, None, None)
-
- def get(self, filename):
- """
- Get the .sconsign entry for a file
-
- filename - the filename whose signature will be returned
- returns - (timestamp, bsig, csig)
- """
- entry = self.get_entry(filename)
- return (entry.timestamp, entry.bsig, entry.csig)
-
- def get_entry(self, filename):
- """
- Create an entry for the filename and return it, or if one already exists,
- then return it.
- """
- try:
- return self.entries[filename]
- except (KeyError, AttributeError):
- return SConsignEntry()
-
- def set_entry(self, filename, entry):
- """
- Set the entry.
- """
- self.entries[filename] = entry
- self.dirty = 1
-
- def set_csig(self, filename, csig):
- """
- Set the csig .sconsign entry for a file
-
- filename - the filename whose signature will be set
- csig - the file's content signature
- """
-
- entry = self.get_entry(filename)
- entry.csig = csig
- self.set_entry(filename, entry)
-
- def set_binfo(self, filename, bsig, bkids, bkidsigs, bact, bactsig):
- """
- Set the build info .sconsign entry for a file
-
- filename - the filename whose signature will be set
- bsig - the file's built signature
- """
-
- entry = self.get_entry(filename)
- entry.bsig = bsig
- entry.bkids = bkids
- entry.bkidsigs = bkidsigs
- entry.bact = bact
- entry.bactsig = bactsig
- self.set_entry(filename, entry)
-
- def set_timestamp(self, filename, timestamp):
- """
- Set the timestamp .sconsign entry for a file
-
- filename - the filename whose signature will be set
- timestamp - the file's timestamp
- """
-
- entry = self.get_entry(filename)
- entry.timestamp = timestamp
- self.set_entry(filename, entry)
-
- def get_implicit(self, filename):
- """Fetch the cached implicit dependencies for 'filename'"""
- entry = self.get_entry(filename)
- return entry.implicit
-
- def set_implicit(self, filename, implicit):
- """Cache the implicit dependencies for 'filename'."""
- entry = self.get_entry(filename)
- if not SCons.Util.is_List(implicit):
- implicit = [implicit]
- implicit = map(str, implicit)
- entry.implicit = implicit
- self.set_entry(filename, entry)
-
- def get_binfo(self, filename):
- """Fetch the cached implicit dependencies for 'filename'"""
- entry = self.get_entry(filename)
- return entry.bsig, entry.bkids, entry.bkidsigs, entry.bact, entry.bactsig
-
-class SConsignDB(_SConsign):
- """
- 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 KeyboardInterrupt:
- raise
- 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)
- try:
- SConsign_db.sync()
- except AttributeError:
- # Not all anydbm modules have sync() methods.
- pass
-
-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
- module - the signature module being used
- """
-
- self.dir = dir
- self.sconsign = os.path.join(dir.path, '.sconsign')
-
- try:
- fp = open(self.sconsign, 'rb')
- except IOError:
- fp = None
-
- try:
- SConsignDir.__init__(self, fp, module)
- except KeyboardInterrupt:
- raise
- except:
- SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
- "Ignoring corrupt .sconsign file: %s"%self.sconsign)
-
- global sig_files
- sig_files.append(self)
-
- def write(self):
- """
- Write the .sconsign file to disk.
-
- Try to write to a temporary file first, and rename it if we
- succeed. If we can't write to the temporary file, it's
- probably because the directory isn't writable (and if so,
- how did we build anything in this directory, anyway?), so
- try to write directly to the .sconsign file as a backup.
- If we can't rename, try to copy the temporary contents back
- to the .sconsign file. Either way, always try to remove
- the temporary file at the end.
- """
- if self.dirty:
- temp = os.path.join(self.dir.path, '.scons%d' % os.getpid())
- try:
- file = open(temp, 'wb')
- fname = temp
- except IOError:
- try:
- file = open(self.sconsign, 'wb')
- fname = self.sconsign
- except IOError:
- return
- cPickle.dump(self.entries, file, 1)
- file.close()
- if fname != self.sconsign:
- try:
- mode = os.stat(self.sconsign)[0]
- os.chmod(self.sconsign, 0666)
- os.unlink(self.sconsign)
- except OSError:
- pass
- try:
- os.rename(fname, self.sconsign)
- except OSError:
- open(self.sconsign, 'wb').write(open(fname, 'rb').read())
- os.chmod(self.sconsign, mode)
- try:
- os.unlink(temp)
- except OSError:
- pass
-
-SConsignForDirectory = SConsignDirFile
-
-def SConsignFile(name, dbm_module=None):
- """
- Arrange for all signatures to be stored in a global .sconsign.dbm
- file.
- """
- global SConsign_db
- if SConsign_db is None:
- if dbm_module is None:
- import SCons.dblite
- dbm_module = SCons.dblite
- SConsign_db = dbm_module.open(name, "c")
-
- global SConsignForDirectory
- SConsignForDirectory = SConsignDB
-
class Calculator:
"""
Encapsulates signature calculations and .sconsign file generating
@@ -420,7 +133,8 @@ class Calculator:
if self.max_drift >= 0:
oldtime, oldbsig, oldcsig = node.get_prevsiginfo()
else:
- oldtime, oldbsig, oldcsig = _SConsign.null_siginfo
+ import SCons.SConsign
+ oldtime, oldbsig, oldcsig = SCons.SConsign.Base.null_siginfo
mtime = node.get_timestamp()