summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Sig
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-10-28 12:51:44 (GMT)
committerSteven Knight <knight@baldmt.com>2001-10-28 12:51:44 (GMT)
commit3bce8a9e6e70d61723e4824bd7ba84a7b9547456 (patch)
tree27e3b6c55dd969ce1e98bf8138a8d0c9125bac59 /src/engine/SCons/Sig
parente5410ac77d8740375b43cb154bedf7219279bf67 (diff)
downloadSCons-3bce8a9e6e70d61723e4824bd7ba84a7b9547456.zip
SCons-3bce8a9e6e70d61723e4824bd7ba84a7b9547456.tar.gz
SCons-3bce8a9e6e70d61723e4824bd7ba84a7b9547456.tar.bz2
Change node and .sconsign handling to separate build and content signatures.
Diffstat (limited to 'src/engine/SCons/Sig')
-rw-r--r--src/engine/SCons/Sig/SigTests.py85
-rw-r--r--src/engine/SCons/Sig/__init__.py107
2 files changed, 115 insertions, 77 deletions
diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py
index 4a303db..95789e8 100644
--- a/src/engine/SCons/Sig/SigTests.py
+++ b/src/engine/SCons/Sig/SigTests.py
@@ -52,8 +52,11 @@ class DummyNode:
self.builder = file.builder
self.depends = []
self.use_signature = 1
+ self.bsig = None
+ self.csig = None
self.oldtime = 0
- self.oldsig = 0
+ self.oldbsig = 0
+ self.oldcsig = 0
def get_contents(self):
# a file that doesn't exist has no contents:
@@ -78,17 +81,14 @@ class DummyNode:
return 0
return None
- def has_signature(self):
- return hasattr(self, "sig")
+ def set_bsig(self, bsig):
+ self.bsig = bsig
- def set_signature(self, sig):
- self.sig = sig
+ def get_bsig(self):
+ return self.bsig
- def get_signature(self):
- return self.sig
-
- def get_oldentry(self):
- return (self.oldtime, self.oldsig)
+ def get_prevsiginfo(self):
+ return (self.oldtime, self.oldbsig, self.oldcsig)
def create_files(test):
@@ -132,7 +132,8 @@ def current(calc, node):
def write(calc, nodes):
for node in nodes:
node.oldtime = node.file.timestamp
- node.oldsig = calc.get_signature(node)
+ node.oldbsig = calc.bsig(node)
+ node.oldcsig = calc.csig(node)
class SigTestBase:
@@ -246,30 +247,33 @@ class CalcTestCase(unittest.TestCase):
def current(self, newsig, oldsig):
return newsig == oldsig
def signature(self, node):
- return node.get_signature()
+ return node.get_csig()
class MyNode:
- def __init__(self, name, sig):
+ def __init__(self, name, bsig, csig):
self.name = name
- self.sig = sig
+ self.bsig = bsig
+ self.csig = csig
self.kids = []
self.builder = None
self.use_signature = 1
def children(self):
return self.kids
- def has_signature(self):
- return self.sig != None
- def get_signature(self):
- return self.sig
- def get_oldentry(self):
- return 0, self.sig
+ def exists(self):
+ return 1
+ def get_bsig(self):
+ return self.bsig
+ def get_csig(self):
+ return self.csig
+ def get_prevsiginfo(self):
+ return 0, self.bsig, self.csig
def get_timestamp(self):
return 1
self.module = MySigModule()
self.nodeclass = MyNode
self.test_Calc___init__()
- self.test_Calc_collect()
+ self.test_Calc_bsig()
self.test_Calc_get_signature()
self.test_Calc_current()
@@ -277,14 +281,19 @@ class CalcTestCase(unittest.TestCase):
self.calc = SCons.Sig.Calculator(self.module)
assert self.calc.module == self.module
- def test_Calc_collect(self):
- n1 = self.nodeclass('n1', 11)
- n2 = self.nodeclass('n2', 22)
- n3 = self.nodeclass('n3', 33)
+ def test_Calc_bsig(self):
+ n1 = self.nodeclass('n1', 11, 12)
+ n2 = self.nodeclass('n2', 22, 23)
+ n3 = self.nodeclass('n3', 33, 34)
n1.builder = 1
n1.kids = [n2, n3]
- assert self.calc.collect(n1) == 55
+ assert self.calc.bsig(n1) == 55
+
+ def test_Calc_bsig(self):
+ n = self.nodeclass('n', 11, 12)
+
+ assert self.calc.csig(n) == 12
def test_Calc_get_signature(self):
class NE(self.nodeclass):
@@ -298,24 +307,24 @@ class CalcTestCase(unittest.TestCase):
def has_signature(self):
return None
- n1 = self.nodeclass('n1', 11)
+ n1 = self.nodeclass('n1', 11, 12)
n1.use_signature = 0
assert self.calc.get_signature(n1) is None
- n2 = self.nodeclass('n2', 22)
- assert self.calc.get_signature(n2) == 22
+ n2 = self.nodeclass('n2', 22, 23)
+ assert self.calc.get_signature(n2) == 23
- n3 = self.nodeclass('n3', 33)
- n4 = self.nodeclass('n4', None)
+ n3 = self.nodeclass('n3', 33, 34)
+ n4 = self.nodeclass('n4', None, None)
n4.builder = 1
n4.kids = [n2, n3]
- assert self.calc.get_signature(n4) == 55
+ assert self.calc.get_signature(n4) == 57
- n5 = NE('n5', 55)
+ n5 = NE('n5', 55, 56)
assert self.calc.get_signature(n5) is None
- n6 = NN('n6', 66)
- assert self.calc.get_signature(n6) == 66
+ n6 = NN('n6', 66, 67)
+ assert self.calc.get_signature(n6) == 67
def test_Calc_current(self):
class N0(self.nodeclass):
@@ -328,15 +337,15 @@ class CalcTestCase(unittest.TestCase):
def current(self):
return None
- n0 = N0('n0', 11)
+ n0 = N0('n0', 11, 12)
assert not self.calc.current(n0, 10)
assert not self.calc.current(n0, 11)
- n1 = N1('n1', 22)
+ n1 = N1('n1', 22, 23)
assert self.calc.current(n1, 20)
assert self.calc.current(n1, 22)
- nn = NN('nn', 33)
+ nn = NN('nn', 33, 34)
assert not self.calc.current(nn, 30)
assert self.calc.current(nn, 33)
diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py
index 2a2667f..4095792 100644
--- a/src/engine/SCons/Sig/__init__.py
+++ b/src/engine/SCons/Sig/__init__.py
@@ -52,54 +52,75 @@ class SConsignFile:
module - the signature module being used
"""
- self.path = os.path.join(dir, '.sconsign')
+ self.dir = dir
+ self.module = module
+ self.sconsign = os.path.join(dir.path, '.sconsign')
self.entries = {}
+ self.dirty = None
try:
- file = open(self.path, 'rt')
+ file = open(self.sconsign, 'rt')
except:
pass
else:
for line in file.readlines():
filename, rest = map(string.strip, string.split(line, ":"))
- time, signature = map(string.strip, string.split(rest, " "))
- self.entries[filename] = (int(time), module.from_string(signature))
+ self.entries[filename] = rest
global sig_files
sig_files.append(self)
def get(self, filename):
"""
- Get the signature for a file
+ Get the .sconsign entry for a file
filename - the filename whose signature will be returned
- returns - (timestamp, signature)
+ returns - (timestamp, bsig, csig)
"""
try:
- return self.entries[filename]
+ arr = map(string.strip, string.split(self.entries[filename], " "))
except KeyError:
- return (0, None)
+ return (None, None, None)
+ try:
+ if arr[1] == '-': bsig = None
+ else: bsig = self.module.from_string(arr[1])
+ except IndexError:
+ bsig = None
+ try:
+ if arr[2] == '-': csig = None
+ else: csig = self.module.from_string(arr[2])
+ except IndexError:
+ csig = None
+ return (int(arr[0]), bsig, csig)
- def set(self, filename, timestamp, signature, module):
+ def set(self, filename, timestamp, bsig = None, csig = None):
"""
- Set the signature for a file
+ Set the .sconsign entry for a file
filename - the filename whose signature will be set
timestamp - the timestamp
- signature - the signature
module - the signature module being used
+ bsig - the file's build signature
+ csig - the file's content signature
"""
- self.entries[filename] = (timestamp, module.to_string(signature))
+ if bsig is None: bsig = '-'
+ else: bsig = self.module.to_string(bsig)
+ if csig is None: csig = ''
+ else: csig = ' ' + self.module.to_string(csig)
+ self.entries[filename] = "%d %s%s" % (timestamp, bsig, csig)
+ self.dirty = 1
def write(self):
"""
Write the .sconsign file to disk.
"""
-
- file = open(self.path, 'wt')
- for item in self.entries.items():
- file.write("%s: %d %s\n" % (item[0], item[1][0], item[1][1]))
+ if self.dirty:
+ file = open(self.sconsign, 'wt')
+ keys = self.entries.keys()
+ keys.sort()
+ for name in keys:
+ file.write("%s: %s\n" % (name, self.entries[name]))
class Calculator:
@@ -116,24 +137,39 @@ class Calculator:
"""
self.module = module
-
- def collect(self, node):
+ def bsig(self, node):
"""
- Collect the signatures of a node's sources.
+ Generate a node's build signature, the digested signatures
+ of its dependency files and build information.
node - the node whose sources will be collected
+ returns - the build signature
This no longer handles the recursive descent of the
node's children's signatures. We expect that they're
already built and updated by someone else, if that's
what's wanted.
"""
+ #XXX If configured, use the content signatures from the
+ #XXX .sconsign file if the timestamps match.
sigs = map(lambda n,s=self: s.get_signature(n), node.children())
return self.module.collect(filter(lambda x: not x is None, sigs))
+ def csig(self, node):
+ """
+ Generate a node's content signature, the digested signature
+ of its content.
+
+ node - the node
+ returns - the content signature
+ """
+ #XXX If configured, use the content signatures from the
+ #XXX .sconsign file if the timestamps match.
+ return self.module.signature(node)
+
def get_signature(self, node):
"""
- Get the signature for a node.
+ Get the appropriate signature for a node.
node - the node
returns - the signature or None if the signature could not
@@ -147,27 +183,22 @@ class Calculator:
# This node type doesn't use a signature (e.g. a
# directory) so bail right away.
return None
- elif node.has_signature():
- sig = node.get_signature()
elif node.builder:
- sig = self.collect(node)
+ return self.bsig(node)
+ elif not node.exists():
+ return None
else:
- if not node.exists():
- return None
-
- # XXX handle nodes that are not under the source root
- sig = self.module.signature(node)
-
- return sig
+ return self.csig(node)
def current(self, node, newsig):
"""
- Check if a node is up to date.
+ Check if a signature is up to date with respect to a node.
node - the node whose signature will be checked
+ newsig - the (presumably current) signature of the file
- returns - 0 if the signature has changed since the last invocation,
- and 1 if it hasn't
+ returns - 1 if the file is current with the specified signature,
+ 0 if it isn't
"""
c = node.current()
@@ -178,11 +209,9 @@ class Calculator:
# that doesn't exist, or a directory.
return c
- oldtime, oldsig = node.get_oldentry()
-
- newtime = node.get_timestamp()
+ oldtime, oldbsig, oldcsig = node.get_prevsiginfo()
- if not node.builder and newtime == oldtime:
- newsig = oldsig
+ if not node.builder and node.get_timestamp() == oldtime:
+ return 1
- return self.module.current(newsig, oldsig)
+ return self.module.current(newsig, oldbsig)