summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2006-02-12 06:58:36 (GMT)
committerSteven Knight <knight@baldmt.com>2006-02-12 06:58:36 (GMT)
commit6c80eef9959691af782676c52c49eb9bab1a6808 (patch)
tree941882c923d2c6ab1f2e795b6d32177dbb786404 /src
parent130097961b7f4dc3cb8e67e629de5086d85b4053 (diff)
downloadSCons-6c80eef9959691af782676c52c49eb9bab1a6808.zip
SCons-6c80eef9959691af782676c52c49eb9bab1a6808.tar.gz
SCons-6c80eef9959691af782676c52c49eb9bab1a6808.tar.bz2
Refactor so Command() uses an FS.Entry as its target factory.
Diffstat (limited to 'src')
-rw-r--r--src/engine/SCons/Builder.py5
-rw-r--r--src/engine/SCons/BuilderTests.py2
-rw-r--r--src/engine/SCons/Environment.py1
-rw-r--r--src/engine/SCons/Node/FS.py67
-rw-r--r--src/engine/SCons/Node/FSTests.py77
-rw-r--r--src/engine/SCons/Node/__init__.py3
-rw-r--r--src/engine/SCons/SConfTests.py2
-rw-r--r--src/engine/SCons/Taskmaster.py4
-rw-r--r--src/engine/SCons/TaskmasterTests.py3
9 files changed, 61 insertions, 103 deletions
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index 9083985..ae24f43 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -535,8 +535,11 @@ class BuilderBase:
# Have to call arg2nodes yet again, since it is legal for
# emitters to spit out strings as well as Node instances.
- slist = env.arg2nodes(source, source_factory)
tlist = env.arg2nodes(target, target_factory)
+ slist = env.arg2nodes(source, source_factory)
+
+ tlist = map(lambda n: n.disambiguate(), tlist)
+ slist = map(lambda n: n.disambiguate(), slist)
return tlist, slist
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index 233336c..c80f00c 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -157,6 +157,8 @@ class MyNode_without_target_from_source:
self.builder = None
self.is_explicit = None
self.side_effect = 0
+ def disambiguate(self):
+ return self
def __str__(self):
return self.name
def builder_set(self, builder):
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 3834636..92b1e3d 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -1263,6 +1263,7 @@ class Base(SubstitutionEnvironment):
for an action."""
bkw = {
'action' : action,
+ 'target_factory' : self.fs.Entry,
'source_factory' : self.fs.Entry,
}
try: bkw['source_scanner'] = kw['source_scanner']
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 1260602..36d84db 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -53,6 +53,8 @@ import SCons.Subst
import SCons.Util
import SCons.Warnings
+from SCons.Debug import Trace
+
# The max_drift value: by default, use a cached signature value for
# any file that's been untouched for more than two days.
default_max_drift = 2*24*60*60
@@ -668,6 +670,9 @@ class Base(SCons.Node.Node):
self._proxy = ret
return ret
+ def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext):
+ return self.dir.Entry(prefix + splitext(self.name)[0] + suffix)
+
class Entry(Base):
"""This is the class for generic Node.FS entries--that is, things
that could be a File or a Dir, but we're just not sure yet.
@@ -697,11 +702,6 @@ class Entry(Base):
self.clear()
return File.rfile(self)
- def get_found_includes(self, env, scanner, path):
- """If we're looking for included files, it's because this Entry
- is really supposed to be a File itself."""
- return self.disambiguate().get_found_includes(env, scanner, path)
-
def scanner_key(self):
return self.get_suffix()
@@ -723,8 +723,23 @@ class Entry(Base):
return '' # avoid errors for dangling symlinks
raise AttributeError
- def rel_path(self, other):
- return self.disambiguate().rel_path(other)
+ def must_be_a_Dir(self):
+ """Called to make sure a Node is a Dir. Since we're an
+ Entry, we can morph into one."""
+ self.__class__ = Dir
+ self._morph()
+ return self
+
+ # The following methods can get called before the Taskmaster has
+ # had a chance to call disambiguate() directly to see if this Entry
+ # should really be a Dir or a File. We therefore use these to call
+ # disambiguate() transparently (from our caller's point of view).
+ #
+ # Right now, this minimal set of methods has been derived by just
+ # looking at some of the methods that will obviously be called early
+ # in any of the various Taskmasters' calling sequences, and then
+ # empirically figuring out which additional methods are necessary
+ # to make various tests pass.
def exists(self):
"""Return if the Entry exists. Check the file system to see
@@ -732,30 +747,11 @@ class Entry(Base):
directory."""
return self.disambiguate().exists()
- def missing(self):
- """Return if the Entry is missing. Check the file system to
- see what we should turn into first. Assume a file if there's
- no directory."""
- return self.disambiguate().missing()
-
- def get_csig(self):
- """Return the entry's content signature. Check the file system
- to see what we should turn into first. Assume a file if there's
- no directory."""
- return self.disambiguate().get_csig()
-
- def calc_signature(self, calc=None):
- """Return the Entry's calculated signature. Check the file
- system to see what we should turn into first. Assume a file if
- there's no directory."""
- return self.disambiguate().calc_signature(calc)
-
- def must_be_a_Dir(self):
- """Called to make sure a Node is a Dir. Since we're an
- Entry, we can morph into one."""
- self.__class__ = Dir
- self._morph()
- return self
+ def rel_path(self, other):
+ d = self.disambiguate()
+ if d.__class__ == Entry:
+ raise "rel_path() could not disambiguate File/Dir"
+ return d.rel_path(other)
# This is for later so we can differentiate between Entry the class and Entry
# the method of the FS class.
@@ -1204,9 +1200,6 @@ class Dir(Base):
diskcheck_match(self, self.fs.isfile,
"File %s found where directory expected.")
- def disambiguate(self):
- return self
-
def __clearRepositoryCache(self, duplicate=None):
"""Called when we change the repository(ies) for a directory.
This clears any cached information that is invalidated by changing
@@ -1706,9 +1699,6 @@ class File(Base):
if not hasattr(self, '_local'):
self._local = 0
- def disambiguate(self):
- return self
-
def scanner_key(self):
return self.get_suffix()
@@ -2054,9 +2044,6 @@ class File(Base):
dir = os.path.join(self.fs.CachePath, subdir)
return dir, os.path.join(dir, cache_sig)
- def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext):
- return self.dir.File(prefix + splitext(self.name)[0] + suffix)
-
def must_be_a_Dir(self):
"""Called to make sure a Node is a Dir. Since we're already a
File, this is a TypeError..."""
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 12be4b9..321deaa 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1369,17 +1369,34 @@ class FSTestCase(_tempdirTestCase):
f.get_string(0)
assert f.get_string(1) == 'baz', f.get_string(1)
+ def test_target_from_source(self):
+ """Test the method for generating target nodes from sources"""
+ fs = self.fs
+
x = fs.File('x.c')
t = x.target_from_source('pre-', '-suf')
assert str(t) == 'pre-x-suf', str(t)
+ assert t.__class__ == SCons.Node.FS.Entry
y = fs.File('dir/y')
t = y.target_from_source('pre-', '-suf')
assert str(t) == os.path.join('dir', 'pre-y-suf'), str(t)
+ assert t.__class__ == SCons.Node.FS.Entry
z = fs.File('zz')
t = z.target_from_source('pre-', '-suf', lambda x: x[:-1])
assert str(t) == 'pre-z-suf', str(t)
+ assert t.__class__ == SCons.Node.FS.Entry
+
+ d = fs.Dir('ddd')
+ t = d.target_from_source('pre-', '-suf')
+ assert str(t) == 'pre-ddd-suf', str(t)
+ assert t.__class__ == SCons.Node.FS.Entry
+
+ e = fs.Entry('eee')
+ t = e.target_from_source('pre-', '-suf')
+ assert str(t) == 'pre-eee-suf', str(t)
+ assert t.__class__ == SCons.Node.FS.Entry
def test_same_name(self):
"""Test that a local same-named file isn't found for a Dir lookup"""
@@ -1836,10 +1853,6 @@ class EntryTestCase(_tempdirTestCase):
e1.rfile()
assert e1.__class__ is SCons.Node.FS.File, e1.__class__
- e2 = fs.Entry('e2')
- e2.get_found_includes(None, None, None)
- assert e2.__class__ is SCons.Node.FS.File, e2.__class__
-
test.subdir('e3d')
test.write('e3f', "e3f\n")
@@ -1892,13 +1905,6 @@ class EntryTestCase(_tempdirTestCase):
test.subdir('e5d')
test.write('e5f', "e5f\n")
- e5d = fs.Entry('e5d')
- sig = e5d.calc_signature(MyCalc(555))
- assert e5d.__class__ is SCons.Node.FS.Dir, e5d.__class__
- # Node has builder (MkDirBuilder), so executor will calculate
- # the build signature.
- assert sig == 777, sig
-
e5f = fs.Entry('e5f')
sig = e5f.calc_signature(MyCalc(666))
assert e5f.__class__ is SCons.Node.FS.File, e5f.__class__
@@ -1917,55 +1923,6 @@ class EntryTestCase(_tempdirTestCase):
self.fs.Entry('#topdir')
self.fs.Entry('#topdir/a/b/c')
- def test_missing(self):
- """Test that the Entry.missing() method disambiguates node types"""
- test = TestCmd(workdir='')
- # FS doesn't like the cwd to be something other than its root.
- os.chdir(test.workpath(""))
-
- fs = SCons.Node.FS.FS()
-
- test.subdir('emd')
- test.write('emf', "emf\n")
-
- emd = fs.Entry('emd')
- missing = emd.missing()
- assert emd.__class__ is SCons.Node.FS.Dir, emd.__class__
- assert not missing
-
- emf = fs.Entry('emf')
- missing = emf.missing()
- assert emf.__class__ is SCons.Node.FS.File, emf.__class__
- assert not missing
-
- emn = fs.Entry('emn')
- missing = emn.missing()
- assert emn.__class__ is SCons.Node.FS.File, emn.__class__
- assert missing
-
- def test_get_csig(self):
- """Test that the Entry.get_csig() method disambiguates node types"""
- test = TestCmd(workdir='')
- # FS doesn't like the cwd to be something other than its root.
- os.chdir(test.workpath(""))
-
- fs = SCons.Node.FS.FS()
-
- test.subdir('egcd')
- test.write('egcf', "egcf\n")
-
- egcd = fs.Entry('egcd')
- egcd.get_csig()
- assert egcd.__class__ is SCons.Node.FS.Dir, egcd.__class__
-
- egcf = fs.Entry('egcf')
- egcf.get_csig()
- assert egcf.__class__ is SCons.Node.FS.File, egcf.__class__
-
- egcn = fs.Entry('egcn')
- egcn.get_csig()
- assert egcn.__class__ is SCons.Node.FS.File, egcn.__class__
-
class FileTestCase(_tempdirTestCase):
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 6a0a238..483e88b 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -212,6 +212,9 @@ class Node:
# what line in what file created the node, for example).
Annotate(self)
+ def disambiguate(self):
+ return self
+
def get_suffix(self):
return ''
diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py
index 961dc21..85b4690 100644
--- a/src/engine/SCons/SConfTests.py
+++ b/src/engine/SCons/SConfTests.py
@@ -164,6 +164,8 @@ class SConfTestCase(unittest.TestCase):
self.state = None
self.side_effects = []
self.builder = None
+ def disambiguate(self):
+ return self
def has_builder(self):
return 1
def add_pre_action(self, *actions):
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index 5d68989..6d5f87c 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -227,7 +227,7 @@ class Task:
"""
self.out_of_date = []
for t in self.targets:
- if t.current():
+ if t.disambiguate().current():
t.set_state(SCons.Node.up_to_date)
else:
self.out_of_date.append(t)
@@ -308,7 +308,7 @@ class Taskmaster:
T = self.trace
while self.candidates:
- node = self.candidates.pop()
+ node = self.candidates.pop().disambiguate()
state = node.get_state()
if CollectStats:
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index c35a89c..f3cb5f0 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -62,6 +62,9 @@ class Node:
self._bsig_val = None
self._current_val = 0
+ def disambiguate(self):
+ return self
+
def retrieve_from_cache(self):
global cache_text
if self.cached: