summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2002-07-17 23:12:12 (GMT)
committerSteven Knight <knight@baldmt.com>2002-07-17 23:12:12 (GMT)
commit64a0553a81deaa7cab0158d9f533a1f460ad2c8b (patch)
treef8aacc828f3c77f73d8bebf5b6c5ec78eacf05d5
parent1c2adf628d15657cee31f82525493bd9ab84b369 (diff)
downloadSCons-64a0553a81deaa7cab0158d9f533a1f460ad2c8b.zip
SCons-64a0553a81deaa7cab0158d9f533a1f460ad2c8b.tar.gz
SCons-64a0553a81deaa7cab0158d9f533a1f460ad2c8b.tar.bz2
Repository support (first cut).
-rw-r--r--doc/man/scons.116
-rw-r--r--src/RELEASE.txt2
-rw-r--r--src/engine/SCons/Action.py14
-rw-r--r--src/engine/SCons/ActionTests.py14
-rw-r--r--src/engine/SCons/Environment.py13
-rw-r--r--src/engine/SCons/EnvironmentTests.py48
-rw-r--r--src/engine/SCons/Node/FS.py44
-rw-r--r--src/engine/SCons/Node/FSTests.py50
-rw-r--r--src/engine/SCons/Node/NodeTests.py12
-rw-r--r--src/engine/SCons/Node/__init__.py3
-rw-r--r--src/engine/SCons/Script/SConscript.py7
-rw-r--r--src/engine/SCons/Script/__init__.py16
-rw-r--r--test/Repository/.aeignore4
-rw-r--r--test/Repository/Program.py169
-rw-r--r--test/Repository/include.py186
-rw-r--r--test/Repository/no-repository.py91
-rw-r--r--test/option--Y.py266
17 files changed, 918 insertions, 37 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index d32b7ff..f574fb3 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -634,14 +634,14 @@ Turn off -w, even if it was turned on implicitly.
.\" .TP
.\" --warn-undefined-variables
.\" Warn when an undefined variable is referenced.
-.\"
-.\" .TP
-.\" .RI -Y " repository" ", --repository=" repository
-.\" Search the specified repository for any input and target
-.\" files not found in the local directory hierarchy. Multiple
-.\" .B -Y
-.\" options may specified, in which case the
-.\" repositories are searched in the order specified.
+
+.TP
+.RI -Y " repository" ", --repository=" repository
+Search the specified repository for any input and target
+files not found in the local directory hierarchy. Multiple
+.B -Y
+options may specified, in which case the
+repositories are searched in the order specified.
.SH CONFIGURATION FILE REFERENCE
.\" .SS Python Basics
diff --git a/src/RELEASE.txt b/src/RELEASE.txt
index 7124eff..0dab6ce 100644
--- a/src/RELEASE.txt
+++ b/src/RELEASE.txt
@@ -177,8 +177,6 @@ RELEASE 0.08 - Mon, 15 Jul 2002 12:08:51 -0500
- No support yet for the following future features:
- - Repository search paths (-Y)
-
- Configurable signature calculation
- No support for caching built files.
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index c222d26..79fdd2c 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -266,11 +266,17 @@ class ActionBase:
try:
cwd = kw['dir']
- except:
+ except KeyError:
cwd = None
else:
del kw['dir']
+ def rstr(x):
+ try:
+ return x.rstr()
+ except AttributeError:
+ return str(x)
+
if kw.has_key('target'):
t = kw['target']
del kw['target']
@@ -280,7 +286,7 @@ class ActionBase:
cwd = t[0].cwd
except (IndexError, AttributeError):
pass
- dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(str, t)))
+ dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(rstr, t)))
if dict['TARGETS']:
dict['TARGET'] = dict['TARGETS'][0]
@@ -289,7 +295,7 @@ class ActionBase:
del kw['source']
if not SCons.Util.is_List(s):
s = [s]
- dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(str, s)))
+ dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(rstr, s)))
if dict['SOURCES']:
dict['SOURCE'] = dict['SOURCES'][0]
@@ -357,7 +363,7 @@ class CommandAction(ActionBase):
if execute_actions:
try:
ENV = kw['env']['ENV']
- except:
+ except KeyError:
global default_ENV
if not default_ENV:
import SCons.Environment
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index c1425ef..5fa1b8b 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -114,6 +114,20 @@ class ActionBaseTestCase(unittest.TestCase):
assert SOURCES == ['s1', 's2'], d['SOURCES']
assert str(d['SOURCE']) == 's1', d['SOURCE']
+ class N:
+ def __init__(self, name):
+ self.name = name
+ def rstr(self):
+ return 'rstr-' + self.name
+
+ d = a.subst_dict(target = [N('t3'), 't4'], source = ['s3', N('s4')])
+ TARGETS = map(lambda x: str(x), d['TARGETS'])
+ TARGETS.sort()
+ assert TARGETS == ['rstr-t3', 't4'], d['TARGETS']
+ SOURCES = map(lambda x: str(x), d['SOURCES'])
+ SOURCES.sort()
+ assert SOURCES == ['rstr-s4', 's3'], d['SOURCES']
+
class CommandActionTestCase(unittest.TestCase):
def test_init(self):
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 42aa326..da7c15a 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -492,13 +492,18 @@ class DirVarInterp(VarInterpolator):
def prepare(x, self=self):
if isinstance(x, SCons.Node.Node):
- return x
+ return [x]
elif str(x):
- return self.fs.Dir(str(x), directory=self.dir)
+ if os.path.isabs(str(x)):
+ return [self.fs.Dir(str(x), directory=self.dir)]
+ else:
+ return map(lambda d, s=str(x), fs=self.fs:
+ fs.Dir(s, directory=d),
+ [self.dir] + self.fs.Repositories)
else:
- return None
+ return []
- return map(prepare, src)
+ return reduce(lambda x, y: x+y, map(prepare, src), [])
def instance(self, dir, fs):
try:
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 75e5e83..418d891 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -507,6 +507,54 @@ class EnvironmentTestCase(unittest.TestCase):
assert len(dict['_F77INCFLAGS']) == 0, dict['_F77INCFLAGS']
assert len(dict['_LIBDIRFLAGS']) == 0, dict['_LIBDIRFLAGS']
+ blat = SCons.Node.FS.default_fs.File('blat')
+ SCons.Node.FS.default_fs.Repository('/rep1')
+ SCons.Node.FS.default_fs.Repository('/rep2')
+ env = Environment(CPPPATH = [ 'foo', '/a/b', '$FOO/bar', blat],
+ INCPREFIX = '-I ',
+ INCSUFFIX = 'XXX',
+ FOO = 'baz')
+ dict = env.autogenerate(dir = SCons.Node.FS.default_fs.Dir('/xx'))
+ assert len(dict['_CPPINCFLAGS']) == 18, dict['_CPPINCFLAGS']
+ assert dict['_CPPINCFLAGS'][0] == '$(', \
+ dict['_CPPINCFLAGS'][0]
+ assert dict['_CPPINCFLAGS'][1] == '-I', \
+ dict['_CPPINCFLAGS'][1]
+ assert dict['_CPPINCFLAGS'][2] == os.path.normpath('/xx/fooXXX'), \
+ dict['_CPPINCFLAGS'][2]
+ assert dict['_CPPINCFLAGS'][3] == '-I', \
+ dict['_CPPINCFLAGS'][3]
+ assert dict['_CPPINCFLAGS'][4] == os.path.normpath('/rep1/fooXXX'), \
+ dict['_CPPINCFLAGS'][4]
+ assert dict['_CPPINCFLAGS'][5] == '-I', \
+ dict['_CPPINCFLAGS'][5]
+ assert dict['_CPPINCFLAGS'][6] == os.path.normpath('/rep2/fooXXX'), \
+ dict['_CPPINCFLAGS'][6]
+ assert dict['_CPPINCFLAGS'][7] == '-I', \
+ dict['_CPPINCFLAGS'][7]
+ assert dict['_CPPINCFLAGS'][8] == os.path.normpath('/a/bXXX'), \
+ dict['_CPPINCFLAGS'][8]
+ assert dict['_CPPINCFLAGS'][9] == '-I', \
+ dict['_CPPINCFLAGS'][9]
+ assert dict['_CPPINCFLAGS'][10] == os.path.normpath('/xx/baz/barXXX'), \
+ dict['_CPPINCFLAGS'][10]
+ assert dict['_CPPINCFLAGS'][11] == '-I', \
+ dict['_CPPINCFLAGS'][11]
+ assert dict['_CPPINCFLAGS'][12] == os.path.normpath('/rep1/baz/barXXX'), \
+ dict['_CPPINCFLAGS'][12]
+ assert dict['_CPPINCFLAGS'][13] == '-I', \
+ dict['_CPPINCFLAGS'][13]
+ assert dict['_CPPINCFLAGS'][14] == os.path.normpath('/rep2/baz/barXXX'), \
+ dict['_CPPINCFLAGS'][14]
+ assert dict['_CPPINCFLAGS'][15] == '-I', \
+ dict['_CPPINCFLAGS'][15]
+ assert dict['_CPPINCFLAGS'][16] == os.path.normpath('blatXXX'), \
+ dict['_CPPINCFLAGS'][16]
+ assert dict['_CPPINCFLAGS'][17] == '$)', \
+ dict['_CPPINCFLAGS'][17]
+
+
+
def test_platform(self):
"""Test specifying a platform callable when instantiating."""
def p(env):
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 771ac56..2645cea 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -99,6 +99,7 @@ class FS:
self.pathTop = path
self.Root = {}
self.Top = None
+ self.Repositories = []
def set_toplevel_dir(self, path):
assert not self.Top, "You can only set the top-level path on an FS object that has not had its File, Dir, or Entry methods called yet."
@@ -152,9 +153,9 @@ class FS:
drive, path_first = os.path.splitdrive(path_comp[0])
if not path_first:
# Absolute path
- drive = _my_normcase(drive)
+ drive_path = _my_normcase(drive)
try:
- directory = self.Root[drive]
+ directory = self.Root[drive_path]
except KeyError:
if not create:
raise UserError
@@ -162,7 +163,7 @@ class FS:
dir.path = dir.path + os.sep
dir.abspath = dir.abspath + os.sep
dir.srcpath = dir.srcpath + os.sep
- self.Root[drive] = dir
+ self.Root[drive_path] = dir
directory = dir
path_comp = path_comp[1:]
else:
@@ -209,6 +210,7 @@ class FS:
"File %s found where directory expected." % path
ret = fsclass(path_comp[-1], directory)
+ ret.fs = self
directory.entries[file_name] = ret
directory.add_wkid(ret)
return ret
@@ -295,6 +297,20 @@ class FS:
raise UserError, "Source directory cannot be under build directory."
build_dir.link(src_dir, duplicate)
+ def Repository(self, *dirs):
+ """Specify repository directories to search."""
+ for d in dirs:
+ self.Repositories.append(self.Dir(d))
+
+ def Rsearch(self, path, func = os.path.exists):
+ """Search for something in a repository."""
+ for dir in self.Repositories:
+ t = os.path.join(dir.path, path)
+ if func(t):
+ return t
+ return None
+
+
class Entry(SCons.Node.Node):
"""A generic class for file system entries. This class if for
when we don't know yet whether the entry being looked up is a file
@@ -334,6 +350,7 @@ class Entry(SCons.Node.Node):
self.__doSrcpath(self.duplicate)
self.srcpath_ = self.srcpath
self.cwd = None # will hold the SConscript directory for target nodes
+ self._rfile = None
def get_dir(self):
return self.dir
@@ -372,7 +389,7 @@ class Entry(SCons.Node.Node):
raise AttributeError
def exists(self):
- return os.path.exists(str(self))
+ return os.path.exists(self.rstr())
def cached_exists(self):
try:
@@ -420,6 +437,7 @@ class Dir(Entry):
def __init__(self, name, directory):
Entry.__init__(self, name, directory)
self._morph()
+ self._rfile = None
def _morph(self):
"""Turn a file system node (either a freshly initialized
@@ -573,11 +591,11 @@ class File(Entry):
def get_contents(self):
if not self.exists():
return ''
- return open(str(self), "rb").read()
+ return open(self.rstr(), "rb").read()
def get_timestamp(self):
if self.exists():
- return os.path.getmtime(str(self))
+ return os.path.getmtime(self.rstr())
else:
return 0
@@ -594,6 +612,8 @@ class File(Entry):
self.dir.sconsign().set_timestamp(self.name, self.get_timestamp())
def get_prevsiginfo(self):
+ """Fetch the previous signature information from the
+ .sconsign entry."""
return self.dir.sconsign().get(self.name)
def get_stored_implicit(self):
@@ -650,6 +670,18 @@ class File(Entry):
else:
self.__createDir()
+ def rfile(self):
+ if not self._rfile:
+ self._rfile = self
+ if not os.path.isabs(self.path) and not os.path.isfile(self.path):
+ t = self.fs.Rsearch(self.path, os.path.isfile)
+ if t:
+ self._rfile = self.fs.File(t)
+ return self._rfile
+
+ def rstr(self):
+ return os.path.normpath(str(self.rfile()))
+
default_fs = FS()
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 1ae1215..595396a 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -530,6 +530,55 @@ class FSTestCase(unittest.TestCase):
exc_caught = 1
assert exc_caught, "Should have caught a TypeError"
+class RepositoryTestCase(unittest.TestCase):
+ def runTest(self):
+ """Test FS (file system) Repository operations
+
+ """
+ fs = SCons.Node.FS.FS()
+
+ fs.Repository('foo')
+ fs.Repository(os.path.join('foo', 'bar'))
+ fs.Repository(os.path.join('bar', 'foo'))
+ fs.Repository('bar')
+
+ assert len(fs.Repositories) == 4, fs.Repositories
+ r = map(lambda x, np=os.path.normpath: np(str(x)), fs.Repositories)
+ assert r == ['foo', 'foo/bar', 'bar/foo', 'bar'], r
+
+ test = TestCmd(workdir = '')
+ test.subdir('rep1', 'rep2', 'rep3', 'work')
+
+ rep1 = test.workpath('rep1')
+ rep2 = test.workpath('rep2')
+ rep3 = test.workpath('rep3')
+
+ os.chdir(test.workpath('work'))
+
+ fs = SCons.Node.FS.FS()
+ fs.Repository(rep1, rep2, rep3)
+
+ wf = fs.File(os.path.join('f1'))
+ assert wf.rfile() is wf
+
+ test.write([rep1, 'f2'], "")
+
+ wf = fs.File('f2')
+ assert not wf.rfile() is wf, wf.rfile()
+ assert str(wf.rfile()) == os.path.join(rep1, 'f2'), str(wf.rfile())
+
+ test.subdir([rep2, 'f3'])
+ test.write([rep3, 'f3'], "")
+
+ wf = fs.File('f3')
+ assert not wf.rfile() is wf, wf.rfile()
+ assert wf.rstr() == os.path.join(rep3, 'f3'), wf.rstr()
+
+ assert not fs.Rsearch('f1', os.path.exists)
+ assert fs.Rsearch('f2', os.path.exists)
+ assert fs.Rsearch('f3', os.path.exists)
+
+
class find_fileTestCase(unittest.TestCase):
def runTest(self):
"""Testing find_file function"""
@@ -553,6 +602,7 @@ if __name__ == "__main__":
suite = unittest.TestSuite()
suite.addTest(FSTestCase())
suite.addTest(BuildDirTestCase())
+ suite.addTest(RepositoryTestCase())
suite.addTest(find_fileTestCase())
if not unittest.TextTestRunner().run(suite).wasSuccessful():
sys.exit(1)
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 03b06bd..cbd5473 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -41,7 +41,7 @@ cycle_detected = None
class Builder:
def execute(self, **kw):
global built_it, built_target, built_source, built_args
- built_it = 1
+ built_it = 1
built_target = kw['target']
built_source = kw['source']
built_args = kw
@@ -555,6 +555,16 @@ class NodeTestCase(unittest.TestCase):
n = nw.next()
assert nw.next() == None
+ def test_rstr(self):
+ """Test the rstr() method."""
+ class MyNode(SCons.Node.Node):
+ def __init__(self, name):
+ self.name = name
+ def __str__(self):
+ return self.name
+ n1 = MyNode("n1")
+ assert n1.rstr() == 'n1', n1.rstr()
+
def test_arg2nodes(self):
"""Test the arg2nodes function."""
dict = {}
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 90cd122..2a5e5bc 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -356,6 +356,9 @@ class Node:
def current(self):
return None
+ def rstr(self):
+ return str(self)
+
def get_children(node, parent): return node.children()
def ignore_cycle(node, stack): pass
def do_nothing(node, parent): pass
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index 48c4046..e088c99 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -167,7 +167,7 @@ def SConscript(*ls, **kw):
else:
f = SCons.Node.FS.default_fs.File(str(fn))
if f.exists():
- file = open(str(f), "r")
+ file = open(f.rstr(), "r")
SCons.Node.FS.default_fs.chdir(f.dir)
if sconscript_chdir:
old_dir = os.getcwd()
@@ -276,10 +276,13 @@ def BuildDefaultGlobals():
globals['FindFile'] = FindFile
globals['GetBuildPath'] = GetBuildPath
globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
+ globals['GetLaunchDir'] = GetLaunchDir
globals['Help'] = Help
globals['Import'] = Import
globals['Library'] = SCons.Defaults.StaticLibrary
globals['Object'] = SCons.Defaults.StaticObject
+ globals['Repository'] = SCons.Node.FS.default_fs.Repository
+ globals['SetBuildSignatureType'] = SetBuildSignatureType
globals['StaticLibrary'] = SCons.Defaults.StaticLibrary
globals['StaticObject'] = SCons.Defaults.StaticObject
globals['SharedLibrary'] = SCons.Defaults.SharedLibrary
@@ -294,6 +297,4 @@ def BuildDefaultGlobals():
globals['Split'] = SCons.Util.Split
globals['Tool'] = SCons.Tool.Tool
globals['WhereIs'] = SCons.Util.WhereIs
- globals['GetLaunchDir'] = GetLaunchDir
- globals['SetBuildSignatureType'] = SetBuildSignatureType
return globals
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index 66b4fd7..10794f5 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -185,6 +185,7 @@ target_top = None
exit_status = 0 # exit status, assume success by default
profiling = 0
max_drift = None
+repositories = []
# utility functions
@@ -792,7 +793,11 @@ def options_init():
# long = ['warn-undefined-variables'],
# help = "Warn when an undefined variable is referenced.")
- Option(func = opt_not_yet, future = 1,
+ def opt_Y(opt, arg):
+ global repositories
+ repositories.append(arg)
+
+ Option(func = opt_Y,
short = 'Y', long = ['repository'], arg = 'REPOSITORY',
help = "Search REPOSITORY for source and target files.")
@@ -825,10 +830,15 @@ def _SConstruct_exists(dirname=''):
If so, it returns the path of the file. By default, it checks the
current directory.
"""
+ global repositories
for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
sfile = os.path.join(dirname, file)
if os.path.isfile(sfile):
return sfile
+ if not os.path.isabs(file):
+ for rep in repositories:
+ if os.path.isfile(os.path.join(rep, sfile)):
+ return sfile
return None
@@ -932,6 +942,10 @@ def _main():
sys.path = include_dirs + sys.path
+ global repositories
+ for rep in repositories:
+ SCons.Node.FS.default_fs.Repository(rep)
+
start_time = time.time()
for script in scripts:
SCons.Script.SConscript.SConscript(script)
diff --git a/test/Repository/.aeignore b/test/Repository/.aeignore
new file mode 100644
index 0000000..877ac53
--- /dev/null
+++ b/test/Repository/.aeignore
@@ -0,0 +1,4 @@
+*,D
+.*.swp
+.consign
+.sconsign
diff --git a/test/Repository/Program.py b/test/Repository/Program.py
new file mode 100644
index 0000000..854ede2
--- /dev/null
+++ b/test/Repository/Program.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import sys
+import TestSCons
+
+if sys.platform == 'win32':
+ _exe = '.exe'
+else:
+ _exe = ''
+
+test = TestSCons.TestSCons()
+
+test.subdir('repository', 'work')
+
+repository = test.workpath('repository')
+repository_foo_c = test.workpath('repository', 'foo.c')
+work_foo = test.workpath('work', 'foo' + _exe)
+work_foo_c = test.workpath('work', 'foo.c')
+
+test.write(['work', 'SConstruct'], r"""
+Repository('%s')
+env = Environment()
+env.Program(target= 'foo', source = Split('aaa.c bbb.c foo.c'))
+""" % repository)
+
+test.write(['repository', 'aaa.c'], r"""
+void
+aaa(void)
+{
+ printf("repository/aaa.c\n");
+}
+""")
+
+test.write(['repository', 'bbb.c'], r"""
+void
+bbb(void)
+{
+ printf("repository/bbb.c\n");
+}
+""")
+
+test.write(['repository', 'foo.c'], r"""
+extern void aaa(void);
+extern void bbb(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ aaa();
+ bbb();
+ printf("repository/foo.c\n");
+ exit (0);
+}
+""")
+
+# Make the entire repository non-writable, so we'll detect
+# if we try to write into it accidentally.
+test.writable('repository', 0)
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout = """repository/aaa.c
+repository/bbb.c
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.write(['work', 'bbb.c'], r"""
+void
+bbb(void)
+{
+ printf("work/bbb.c\n");
+}
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout = """repository/aaa.c
+work/bbb.c
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.write(['work', 'aaa.c'], r"""
+void
+aaa(void)
+{
+ printf("work/aaa.c\n");
+}
+""")
+
+test.write(['work', 'foo.c'], r"""
+extern void aaa(void);
+extern void bbb(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ aaa();
+ bbb();
+ printf("work/foo.c\n");
+ exit (0);
+}
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout = """work/aaa.c
+work/bbb.c
+work/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.unlink(['work', 'aaa.c'])
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout = """repository/aaa.c
+work/bbb.c
+work/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.unlink(['work', 'bbb.c'])
+test.unlink(['work', 'foo.c'])
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout = """repository/aaa.c
+repository/bbb.c
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.pass_test()
diff --git a/test/Repository/include.py b/test/Repository/include.py
new file mode 100644
index 0000000..1538e1a
--- /dev/null
+++ b/test/Repository/include.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import sys
+import TestSCons
+
+if sys.platform == 'win32':
+ _exe = '.exe'
+else:
+ _exe = ''
+
+test = TestSCons.TestSCons()
+
+test.subdir('repository', 'work')
+
+repository = test.workpath('repository')
+work_foo = test.workpath('work', 'foo' + _exe)
+work_foo_h = test.workpath('work', 'foo.h')
+
+test.write(['work', 'SConstruct'], """
+Repository('%s')
+env = Environment(CPPPATH = ['.'])
+env.Program(target = 'foo', source = 'foo.c')
+""" % repository)
+
+test.write(['repository', 'foo.h'], r"""
+#define STRING1 "repository/foo.h"
+#include <bar.h>
+""")
+
+test.write(['repository', 'bar.h'], r"""
+#define STRING2 "repository/bar.h"
+""")
+
+test.write(['repository', 'foo.c'], r"""
+#include <foo.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("%s\n", STRING1);
+ printf("%s\n", STRING2);
+ printf("repository/foo.c\n");
+ exit (0);
+}
+""")
+
+# Make the entire repository non-writable, so we'll detect
+# if we try to write into it accidentally.
+test.writable('repository', 0)
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""repository/foo.h
+repository/bar.h
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.write(['work', 'foo.h'], r"""
+#define STRING1 "work/foo.h"
+#include <bar.h>
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""work/foo.h
+repository/bar.h
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.write(['work', 'foo.c'], r"""
+#include <foo.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("%s\n", STRING1);
+ printf("%s\n", STRING2);
+ printf("work/foo.c\n");
+ exit (0);
+}
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""work/foo.h
+repository/bar.h
+work/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.write(['work', 'bar.h'], r"""
+#define STRING2 "work/bar.h"
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""work/foo.h
+work/bar.h
+work/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.writable('repository', 1)
+test.unlink(['work', 'foo.h'])
+test.writable('repository', 0)
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""repository/foo.h
+work/bar.h
+work/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.writable('repository', 1)
+test.unlink(['work', 'foo.c'])
+test.writable('repository', 0)
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""repository/foo.h
+work/bar.h
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.writable('repository', 1)
+test.unlink(['work', 'bar.h'])
+test.writable('repository', 0)
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout =
+"""repository/foo.h
+repository/bar.h
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+#
+test.pass_test()
diff --git a/test/Repository/no-repository.py b/test/Repository/no-repository.py
new file mode 100644
index 0000000..8659c00
--- /dev/null
+++ b/test/Repository/no-repository.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+import sys
+import TestSCons
+
+python = sys.executable
+
+if sys.platform == 'win32':
+ _exe = '.exe'
+else:
+ _exe = ''
+
+test = TestSCons.TestSCons()
+
+test.subdir('work')
+
+no_repository = test.workpath('no_repository')
+work_foo = test.workpath('work', 'foo' + _exe)
+
+test.write(['work', 'SConstruct'], """
+Repository('%s')
+env = Environment()
+env.Program(target = 'foo', source = Split('aaa.c bbb.c foo.c'))
+""" % no_repository)
+
+test.write(['work', 'aaa.c'], r"""
+void
+aaa(void)
+{
+ printf("work/aaa.c\n");
+}
+""")
+
+test.write(['work', 'bbb.c'], r"""
+void
+bbb(void)
+{
+ printf("work/bbb.c\n");
+}
+""")
+
+test.write(['work', 'foo.c'], r"""
+extern void aaa(void);
+extern void bbb(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ aaa();
+ bbb();
+ printf("work/foo.c\n");
+ exit (0);
+}
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.run(program = work_foo, stdout = """work/aaa.c
+work/bbb.c
+work/foo.c
+""")
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+test.pass_test()
diff --git a/test/option--Y.py b/test/option--Y.py
index b201bbd..c675e9b 100644
--- a/test/option--Y.py
+++ b/test/option--Y.py
@@ -24,19 +24,269 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import TestSCons
-import string
import sys
+import TestSCons
+
+if sys.platform == 'win32':
+ _exe = '.exe'
+else:
+ _exe = ''
+
+
test = TestSCons.TestSCons()
-test.write('SConstruct', "")
+test.subdir('repository', 'work1')
+
+repository = test.workpath('repository')
+repository_foo_c = test.workpath('repository', 'foo.c')
+work1_foo = test.workpath('work1', 'foo' + _exe)
+work1_foo_c = test.workpath('work1', 'foo.c')
+
+test.write(['repository', 'SConstruct'], r"""
+env = Environment()
+env.Program(target= 'foo', source = Split('aaa.c bbb.c foo.c'))
+""")
+
+test.write(['repository', 'aaa.c'], r"""
+void
+aaa(void)
+{
+ printf("repository/aaa.c\n");
+}
+""")
+
+test.write(['repository', 'bbb.c'], r"""
+void
+bbb(void)
+{
+ printf("repository/bbb.c\n");
+}
+""")
+
+test.write(['repository', 'foo.c'], r"""
+extern void aaa(void);
+extern void bbb(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ aaa();
+ bbb();
+ printf("repository/foo.c\n");
+ exit (0);
+}
+""")
+
+opts = '-Y ' + repository
+
+# Make the entire repository non-writable, so we'll detect
+# if we try to write into it accidentally.
+test.writable('repository', 0)
+
+test.run(chdir = 'work1', options = opts, arguments = '.')
+
+test.run(program = work1_foo, stdout = """repository/aaa.c
+repository/bbb.c
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work1', options = opts, arguments = '.')
+
+#
+test.write(['work1', 'bbb.c'], r"""
+void
+bbb(void)
+{
+ printf("work1/bbb.c\n");
+}
+""")
+
+test.run(chdir = 'work1', options = opts, arguments = '.')
+
+test.run(program = work1_foo, stdout = """repository/aaa.c
+work1/bbb.c
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work1', options = opts, arguments = '.')
+
+#
+test.write(['work1', 'aaa.c'], r"""
+void
+aaa(void)
+{
+ printf("work1/aaa.c\n");
+}
+""")
+
+test.write(['work1', 'foo.c'], r"""
+extern void aaa(void);
+extern void bbb(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ aaa();
+ bbb();
+ printf("work1/foo.c\n");
+ exit (0);
+}
+""")
+
+test.run(chdir = 'work1', options = opts, arguments = '.')
+
+test.run(program = work1_foo, stdout = """work1/aaa.c
+work1/bbb.c
+work1/foo.c
+""")
+
+test.up_to_date(chdir = 'work1', options = opts, arguments = '.')
+
+#
+test.unlink(['work1', 'bbb.c'])
+test.unlink(['work1', 'foo.c'])
+
+test.run(chdir = 'work1', options = opts, arguments = '.')
+
+test.run(program = work1_foo, stdout = """work1/aaa.c
+repository/bbb.c
+repository/foo.c
+""")
+
+test.up_to_date(chdir = 'work1', options = opts, arguments = '.')
+
+
+
+#
+test.subdir('r.NEW', 'r.OLD', 'work2')
+
+workpath_r_NEW = test.workpath('r.NEW')
+workpath_r_OLD = test.workpath('r.OLD')
+work2_foo = test.workpath('work2', 'foo' + _exe)
+
+SConstruct = """
+env = Environment()
+env.Program(target = 'foo', source = 'foo.c')
+"""
+
+test.write(['r.OLD', 'SConstruct'], SConstruct)
-test.run(arguments = '-Y foo',
- stderr = "Warning: the -Y option is not yet implemented\n")
+test.write(['r.NEW', 'SConstruct'], SConstruct)
-test.run(arguments = '--repository=foo',
- stderr = "Warning: the --repository option is not yet implemented\n")
+test.write(['r.OLD', 'foo.c'], r"""
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("r.OLD/foo.c\n");
+ exit (0);
+}
+""")
+opts = '-Y %s -Y %s' % (workpath_r_NEW, workpath_r_OLD)
+
+# Make the repositories non-writable, so we'll detect
+# if we try to write into them accidentally.
+test.writable('r.OLD', 0)
+test.writable('r.NEW', 0)
+
+test.run(chdir = 'work2', options = opts, arguments = '.')
+
+test.run(program = work2_foo, stdout = "r.OLD/foo.c\n")
+
+test.up_to_date(chdir = 'work2', options = opts, arguments = '.')
+
+#
+test.writable('r.NEW', 1)
+
+test.write(['r.NEW', 'foo.c'], r"""
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("r.NEW/foo.c\n");
+ exit (0);
+}
+""")
+
+test.writable('r.NEW', 0)
+
+test.run(chdir = 'work2', options = opts, arguments = '.')
+
+test.run(program = work2_foo, stdout = "r.NEW/foo.c\n")
+
+test.up_to_date(chdir = 'work2', options = opts, arguments = '.')
+
+#
+test.write(['work2', 'foo.c'], r"""
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("work2/foo.c\n");
+ exit (0);
+}
+""")
+
+test.run(chdir = 'work2', options = opts, arguments = '.')
+
+test.run(program = work2_foo, stdout = "work2/foo.c\n")
+
+test.up_to_date(chdir = 'work2', options = opts, arguments = '.')
+
+#
+test.writable('r.OLD', 1)
+test.writable('r.NEW', 1)
+
+test.write(['r.OLD', 'foo.c'], r"""
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("r.OLD/foo.c 2\n");
+ exit (0);
+}
+""")
+
+test.write(['r.NEW', 'foo.c'], r"""
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("r.NEW/foo.c 2\n");
+ exit (0);
+}
+""")
+
+test.writable('r.OLD', 0)
+test.writable('r.NEW', 0)
+
+test.up_to_date(chdir = 'work2', options = opts, arguments = '.')
+
+#
+test.unlink(['work2', 'foo.c'])
+
+test.run(chdir = 'work2', options = opts, arguments = '.')
+
+test.run(program = work2_foo, stdout = "r.NEW/foo.c 2\n")
+
+test.up_to_date(chdir = 'work2', options = opts, arguments = '.')
+
+#
+test.writable('r.NEW', 1)
+
+test.unlink(['r.NEW', 'foo.c'])
+
+test.writable('r.NEW', 0)
+
+test.run(chdir = 'work2', options = opts, arguments = '.')
+
+test.run(program = work2_foo, stdout = "r.OLD/foo.c 2\n")
+
+test.up_to_date(chdir = 'work2', options = opts, arguments = '.')
+
+
+
+#
test.pass_test()
-