diff options
author | Steven Knight <knight@baldmt.com> | 2004-05-06 06:21:43 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2004-05-06 06:21:43 (GMT) |
commit | b155ebc4a869e0669ee2f7124531e0b5950c7528 (patch) | |
tree | 520cb5708efb85d177a120155048cd8e1361796e /src/engine/SCons/Sig | |
parent | 2a9941e968724723c70f106401fe8b984add626a (diff) | |
download | SCons-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.py | 138 | ||||
-rw-r--r-- | src/engine/SCons/Sig/__init__.py | 290 |
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() |