From 61193fdb029d59dc3808e5d7b31d3d1e6abf797e Mon Sep 17 00:00:00 2001 From: stevenknight Date: Sat, 4 Jun 2005 16:43:13 +0000 Subject: [PATCH] Move BuildInfo translation of signature Nodes to rel_paths into the class itself. git-svn-id: http://scons.tigris.org/svn/scons/trunk@1307 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Debug.py | 1 + src/engine/SCons/Node/FS.py | 53 ++++++++++++++++++++++++++---- src/engine/SCons/Node/NodeTests.py | 21 +++++------- src/engine/SCons/Node/__init__.py | 14 +++----- src/engine/SCons/SConf.py | 11 ++++--- src/engine/SCons/SConsign.py | 19 +++++++++-- src/engine/SCons/SConsignTests.py | 29 +++++++++++----- src/engine/SCons/Sig/__init__.py | 4 +++ 8 files changed, 107 insertions(+), 45 deletions(-) diff --git a/src/engine/SCons/Debug.py b/src/engine/SCons/Debug.py index 0dbb116d..179eb66b 100644 --- a/src/engine/SCons/Debug.py +++ b/src/engine/SCons/Debug.py @@ -122,6 +122,7 @@ def caller(back=0): entry[key] = entry[key] + 1 except KeyError: entry[key] = 1 + return '%s:%d(%s)' % func_shorten(key) def dump_caller_counts(file=sys.stdout): keys = caller_dicts.keys() diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 07093d0b..c728eceb 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1465,12 +1465,52 @@ class RootDir(Dir): return _null class BuildInfo: + # bsig needs to stay here, if it's initialized in __init__() then + # the assignment overwrites any values read from .sconsign files. bsig = None + def __init__(self, node): + self.node = node def __cmp__(self, other): try: return cmp(self.bsig, other.bsig) except AttributeError: return 1 + def convert_to_sconsign(self): + """Convert this BuildInfo object for writing to a .sconsign file + + We hung onto the node that we refer to so that we can translate + the lists of bsources, bdepends and bimplicit Nodes into strings + relative to the node, but we don't want to write out that Node + itself to the .sconsign file, so we delete the attribute in + preparation. + """ + rel_path = self.node.rel_path + delattr(self, 'node') + for attr in ['bsources', 'bdepends', 'bimplicit']: + try: + val = getattr(self, attr) + except AttributeError: + pass + else: + setattr(self, attr, map(rel_path, val)) + def convert_from_sconsign(self, dir, name): + """Convert a newly-read BuildInfo object for in-SCons use + + An on-disk BuildInfo comes without a reference to the node + for which it's intended, so we have to convert the arguments + and add back a self.node attribute. The bsources, bdepends and + bimplicit lists all come from disk as paths relative to that node, + so convert them to actual Nodes for use by the rest of SCons. + """ + self.node = dir.Entry(name) + Entry_func = self.node.dir.Entry + for attr in ['bsources', 'bdepends', 'bimplicit']: + try: + val = getattr(self, attr) + except AttributeError: + pass + else: + setattr(self, attr, map(Entry_func, val)) class File(Base): """A class for files in a file system. @@ -1537,7 +1577,7 @@ class File(Base): try: stored = self.dir.sconsign().get_entry(self.name) except (KeyError, OSError): - return BuildInfo() + return self.new_binfo() else: if isinstance(stored, BuildInfo): return stored @@ -1546,16 +1586,15 @@ class File(Base): # 0.95 or before. The relevant attribute names are the same, # though, so just copy the attributes over to an object of # the correct type. - binfo = BuildInfo() + binfo = self.new_binfo() for key, val in stored.__dict__.items(): setattr(binfo, key, val) return binfo def get_stored_implicit(self): binfo = self.get_stored_info() - try: implicit = binfo.bimplicit + try: return binfo.bimplicit except AttributeError: return None - else: return map(self.dir.Entry, implicit) def rel_path(self, other): return self.dir.rel_path(other) @@ -1727,7 +1766,7 @@ class File(Base): return Base.exists(self) def new_binfo(self): - return BuildInfo() + return BuildInfo(self) def del_cinfo(self): try: @@ -1759,7 +1798,7 @@ class File(Base): if calc.max_drift >= 0: old = self.get_stored_info() else: - old = BuildInfo() + old = self.new_binfo() try: mtime = self.get_timestamp() @@ -1810,7 +1849,7 @@ class File(Base): return None else: old = self.get_stored_info() - return (old == self.binfo) + return (self.binfo == old) def rfile(self): "__cacheable__" diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 70b9672a..3be1d6b6 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -503,24 +503,19 @@ class NodeTestCase(unittest.TestCase): """Test generating a build information structure """ node = SCons.Node.Node() - binfo = node.gen_binfo(Calculator(666)) + d = SCons.Node.Node() + i = SCons.Node.Node() + node.depends = [d] + node.implicit = [i] + binfo = node.gen_binfo(Calculator(1998)) assert isinstance(binfo, SCons.Node.BuildInfo), binfo assert hasattr(binfo, 'bsources') assert hasattr(binfo, 'bsourcesigs') - assert hasattr(binfo, 'bdepends') + assert binfo.bdepends == [d] assert hasattr(binfo, 'bdependsigs') - assert hasattr(binfo, 'bimplicit') + assert binfo.bimplicit == [i] assert hasattr(binfo, 'bimplicitsigs') - assert binfo.bsig == 666, binfo.bsig - - def test_rel_path(self): - """Test the rel_path() method - """ - node = SCons.Node.Node() - other = SCons.Node.Node() - other.__str__ = lambda: "xyzzy" - r = node.rel_path(other) - assert r == "xyzzy", r + assert binfo.bsig == 5994, binfo.bsig def test_explain(self): """Test explaining why a Node must be rebuilt diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index b9d5a75b..627d0201 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -574,7 +574,7 @@ class Node: def calc_signature(node, calc=calc): return node.calc_signature(calc) - bsources = executor.process_sources(self.rel_path, self.ignore) + sources = executor.process_sources(None, self.ignore) sourcesigs = executor.process_sources(calc_signature, self.ignore) depends = self.depends @@ -594,9 +594,9 @@ class Node: binfo.bactsig = calc.module.signature(executor) sigs.append(binfo.bactsig) - binfo.bsources = bsources - binfo.bdepends = map(self.rel_path, depends) - binfo.bimplicit = map(self.rel_path, implicit) + binfo.bsources = sources + binfo.bdepends = depends + binfo.bimplicit = implicit binfo.bsourcesigs = sourcesigs binfo.bdependsigs = dependsigs @@ -606,12 +606,6 @@ class Node: return binfo - def rel_path(self, other): - # Using other.__str__() instead of str(other) lets the Memoizer - # get the right method for the underlying Node object, not the - # __str__() method for the Memoizer wrapper object. - return other.__str__() - def del_cinfo(self): try: del self.binfo.csig diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index b89ca4ae..3d1a1452 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -159,7 +159,8 @@ class SConfBuildInfo(SCons.Node.FS.BuildInfo): result = None # -> 0/None -> no error, != 0 error string = None # the stdout / stderr output when building the target - def __init__(self, result, string, sig): + def __init__(self, node, result, string, sig): + SCons.Node.FS.BuildInfo.__init__(self, node) self.result = result self.string = string self.bsig = sig @@ -305,15 +306,15 @@ class SConfBuildTask(SCons.Taskmaster.Task): for t in self.targets: sig = t.calc_signature(sconf.calc) string = s.getvalue() - t.dir.sconsign().set_entry(t.name, - SConfBuildInfo(1,string,sig)) + binfo = SConfBuildInfo(t,1,string,sig) + t.dir.sconsign().set_entry(t.name, binfo) raise else: for t in self.targets: sig = t.calc_signature(sconf.calc) string = s.getvalue() - t.dir.sconsign().set_entry(t.name, - SConfBuildInfo(0,string,sig)) + binfo = SConfBuildInfo(t,0,string,sig) + t.dir.sconsign().set_entry(t.name, binfo) class SConf: """This is simply a class to represent a configure context. After diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index cbe0b8c6..073cfc45 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -177,9 +177,11 @@ class DB(Base): raise TypeError except KeyboardInterrupt: raise - except: + except Exception, e: SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, - "Ignoring corrupt sconsign entry : %s"%self.dir.tpath) + "Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.tpath, e)) + for key, entry in self.entries.items(): + entry.convert_from_sconsign(dir, key) if mode == "r": # This directory is actually under a repository, which means @@ -202,6 +204,8 @@ class DB(Base): # the Repository; we only write to our own .sconsign file, # not to .sconsign files in Repositories. path = norm_entry(self.dir.path) + for key, entry in self.entries.items(): + entry.convert_to_sconsign() db[path] = cPickle.dumps(self.entries, 1) if sync: @@ -256,6 +260,15 @@ class DirFile(Dir): global sig_files sig_files.append(self) + def get_entry(self, filename): + """ + Fetch the specified entry attribute, converting from .sconsign + format to in-memory format. + """ + entry = Dir.get_entry(self, filename) + entry.convert_from_sconsign(self.dir, filename) + return entry + def write(self, sync=1): """ Write the .sconsign file to disk. @@ -280,6 +293,8 @@ class DirFile(Dir): fname = self.sconsign except IOError: return + for key, entry in self.entries.items(): + entry.convert_to_sconsign() cPickle.dump(self.entries, file, 1) file.close() if fname != self.sconsign: diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py index 025ad8ee..e292aeda 100644 --- a/src/engine/SCons/SConsignTests.py +++ b/src/engine/SCons/SConsignTests.py @@ -35,6 +35,10 @@ import SCons.SConsign class BuildInfo: def __init__(self, name): self.name = name + def convert_to_sconsign(self): + self.c_to_s = 1 + def convert_from_sconsign(self, dir, name): + self.c_from_s = 1 class DummyModule: def to_string(self, sig): @@ -159,22 +163,26 @@ class SConsignDBTestCase(SConsignTestCase): class SConsignDirFileTestCase(SConsignTestCase): def runTest(self): - foo = BuildInfo('foo') - bar = BuildInfo('bar') + bi_foo = BuildInfo('foo') + bi_bar = BuildInfo('bar') f = SCons.SConsign.DirFile(DummyNode(), DummyModule()) - f.set_entry('foo', foo) - f.set_entry('bar', bar) + f.set_entry('foo', bi_foo) + f.set_entry('bar', bi_bar) e = f.get_entry('foo') - assert e == foo, e + assert e == bi_foo, e assert e.name == 'foo', e.name + assert bi_foo.c_from_s, bi_foo.c_from_s + e = f.get_entry('bar') - assert e == bar, e + assert e == bi_bar, e assert e.name == 'bar', e.name assert not hasattr(e, 'arg'), e + assert bi_bar.c_from_s, bi_bar.c_from_s + bbb = BuildInfo('bbb') bbb.arg = 'bbb arg' f.set_entry('bar', bbb) @@ -257,11 +265,16 @@ class writeTestCase(SConsignTestCase): f = SCons.SConsign.DB(DummyNode(), DummyModule()) - f.set_entry('foo', BuildInfo('foo')) - f.set_entry('bar', BuildInfo('bar')) + bi_foo = BuildInfo('foo') + bi_bar = BuildInfo('bar') + f.set_entry('foo', bi_foo) + f.set_entry('bar', bi_bar) SCons.SConsign.write() + assert bi_foo.c_to_s, bi_foo.c_to_s + assert bi_bar.c_to_s, bi_bar.c_to_s + assert fake_dbm.sync_count == 1, fake_dbm.sync_count diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index 2a9680e0..d746dfa4 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -47,6 +47,10 @@ class SConsignEntry: bsig = None csig = None implicit = None + def convert_to_sconsign(self): + pass + def convert_from_sconsign(self, dir, name): + pass class Calculator: """ -- 2.26.2