Move BuildInfo translation of signature Nodes to rel_paths into the class itself.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 4 Jun 2005 16:43:13 +0000 (16:43 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 4 Jun 2005 16:43:13 +0000 (16:43 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1307 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Debug.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/NodeTests.py
src/engine/SCons/Node/__init__.py
src/engine/SCons/SConf.py
src/engine/SCons/SConsign.py
src/engine/SCons/SConsignTests.py
src/engine/SCons/Sig/__init__.py

index 0dbb116df882854dc28e6db99a615891ed843998..179eb66bd0edd1efe4a512d256136679e52ec02b 100644 (file)
@@ -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()
index 07093d0b2b37cb1924d19ca4fce37e4a5f60edf9..c728eceb0813464fe3eee26872e2973aba5ac255 100644 (file)
@@ -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__"
index 70b9672ae167ec3c51eea991e586ef40ee0d490b..3be1d6b6f454267d1013ed7335bb67ebc1fad49b 100644 (file)
@@ -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
index b9d5a75b8035bdd0bf3b48ca1cc9c397c60e899e..627d02019447d622c773056aa694febbfb07cbf9 100644 (file)
@@ -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
index b89ca4aed6f73766c5f975b1f79486df6896ffaf..3d1a14526d18c622d1aa687186a9258e3410437d 100644 (file)
@@ -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
index cbe0b8c641e6f99eba6ba597748a0a0c7a65d6f7..073cfc45370afe7b1649add5c7e0258fe8ce6c97 100644 (file)
@@ -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:
index 025ad8eea8c94ca08701854a91271c9cb6139d73..e292aedaaa477399a3874fea90230b429d2a512e 100644 (file)
@@ -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
 
 
index 2a9680e06d285bebdf8936ff71e475a223d87fa7..d746dfa4d87c4d8edd8311ee9b9776f8e109a02f 100644 (file)
@@ -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:
     """