From 70a70c501294fcb6ce2a3a002260715c365cb00e Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sat, 19 Nov 2005 16:26:31 +0000 Subject: Support specifying absolute path names without drive letters on Win32. --- src/CHANGES.txt | 3 ++ src/engine/SCons/EnvironmentTests.py | 46 +++++++++++++----------- src/engine/SCons/Node/FS.py | 16 ++++++++- src/engine/SCons/Node/FSTests.py | 8 +++-- test/default-drive.py | 70 ++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 test/default-drive.py diff --git a/src/CHANGES.txt b/src/CHANGES.txt index d087d74..1d67c5a 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -389,6 +389,9 @@ RELEASE 0.97 - XXX - Handle signature calculation properly when the Python function used for a FunctionAction is an object method. + - On Windows, assume that absolute path names without a drive letter + refer to the drive on which the SConstruct file lives. + From Chen Lee: - Handle Visual Studio project and solution files in Unicode. diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index a397d4f..58c8ae8 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -794,6 +794,12 @@ class BaseTestCase(unittest.TestCase): def test_autogenerate(dict): """Test autogenerating variables in a dictionary.""" + drive, p = os.path.splitdrive(os.getcwd()) + def normalize_path(path, drive=drive): + if path[0] in '\\/': + path = drive + path + return os.path.normpath(path) + env = Environment(LIBS = [ 'foo', 'bar', 'baz' ], LIBLINKPREFIX = 'foo', LIBLINKSUFFIX = 'bar') @@ -813,12 +819,12 @@ class BaseTestCase(unittest.TestCase): FOO = 'baz') flags = env.subst_list('$_CPPINCFLAGS', 1)[0] expect = [ '$(', - os.path.normpath('foo'), - os.path.normpath('xx/foobar'), - os.path.normpath('foo'), - os.path.normpath('xx/baz/bar'), - os.path.normpath('foo'), - os.path.normpath('blatbar'), + normalize_path('foo'), + normalize_path('xx/foobar'), + normalize_path('foo'), + normalize_path('xx/baz/bar'), + normalize_path('foo'), + normalize_path('blatbar'), '$)', ] assert flags == expect, flags @@ -829,12 +835,12 @@ class BaseTestCase(unittest.TestCase): FOO = 'baz') flags = env.subst_list('$_F77INCFLAGS', 1)[0] expect = [ '$(', - os.path.normpath('foo'), - os.path.normpath('xx/foobar'), - os.path.normpath('foo'), - os.path.normpath('xx/baz/bar'), - os.path.normpath('foo'), - os.path.normpath('blatbar'), + normalize_path('foo'), + normalize_path('xx/foobar'), + normalize_path('foo'), + normalize_path('xx/baz/bar'), + normalize_path('foo'), + normalize_path('blatbar'), '$)', ] assert flags == expect, flags @@ -855,14 +861,14 @@ class BaseTestCase(unittest.TestCase): FOO = 'baz') flags = env.subst_list('$_CPPINCFLAGS', 1)[0] expect = [ '$(', - '-I', os.path.normpath('xx/fooXXX'), - '-I', os.path.normpath('/rep1/xx/fooXXX'), - '-I', os.path.normpath('/rep2/xx/fooXXX'), - '-I', os.path.normpath('/a/bXXX'), - '-I', os.path.normpath('xx/baz/barXXX'), - '-I', os.path.normpath('/rep1/xx/baz/barXXX'), - '-I', os.path.normpath('/rep2/xx/baz/barXXX'), - '-I', os.path.normpath('blatXXX'), + '-I', normalize_path('xx/fooXXX'), + '-I', normalize_path('/rep1/xx/fooXXX'), + '-I', normalize_path('/rep2/xx/fooXXX'), + '-I', normalize_path('/a/bXXX'), + '-I', normalize_path('xx/baz/barXXX'), + '-I', normalize_path('/rep1/xx/baz/barXXX'), + '-I', normalize_path('/rep2/xx/baz/barXXX'), + '-I', normalize_path('blatXXX'), '$)' ] assert flags == expect, flags diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 810ede7..7d4d8df 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -837,6 +837,7 @@ class FS(LocalFS): The path argument must be a valid absolute path. """ if __debug__: logInstanceCreation(self, 'Node.FS') + self.Root = {} self.SConstruct_dir = None self.CachePath = None @@ -844,10 +845,12 @@ class FS(LocalFS): self.cache_show = None self.max_drift = default_max_drift + self.Top = None if path is None: self.pathTop = os.getcwd() else: self.pathTop = path + self.defaultDrive = _my_normcase(os.path.splitdrive(self.pathTop)[0]) self.Top = self._doLookup(Dir, os.path.normpath(self.pathTop)) self.Top.path = '.' @@ -913,8 +916,8 @@ class FS(LocalFS): path_orig = [ path_first, ] + path_orig path_norm = [ _my_normcase(path_first), ] + path_norm else: - drive = _my_normcase(drive) # Absolute path + drive = _my_normcase(drive) try: directory = self.Root[drive] except KeyError: @@ -922,6 +925,10 @@ class FS(LocalFS): raise SCons.Errors.UserError directory = RootDir(drive, self) self.Root[drive] = directory + if not drive: + self.Root[self.defaultDrive] = directory + elif drive == self.defaultDrive: + self.Root[''] = directory if not path_orig: return directory @@ -1649,6 +1656,13 @@ class File(Base): """Search for a list of directories in the Repository list.""" return self.fs.Rfindalldirs(pathlist, self.cwd) + #def generate_build_dict(self): + # """Return an appropriate dictionary of values for building + # this File.""" + # return {'Dir' : self.Dir, + # 'File' : self.File, + # 'RDirs' : self.RDirs} + def _morph(self): """Turn a file system node into a File object. __cache_reset__""" self.scanner_paths = {} diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 565384f..cb98f50 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -854,9 +854,11 @@ class FSTestCase(_tempdirTestCase): if os.sep != '/': seps = seps + ['/'] + drive, path = os.path.splitdrive(os.getcwd()) + for sep in seps: - def Dir_test(lpath, path_, abspath_, up_path_, fileSys=fs, s=sep): + def Dir_test(lpath, path_, abspath_, up_path_, fileSys=fs, s=sep, drive=drive): dir = fileSys.Dir(string.replace(lpath, '/', s)) if os.sep != '/': @@ -864,9 +866,11 @@ class FSTestCase(_tempdirTestCase): abspath_ = string.replace(abspath_, '/', os.sep) up_path_ = string.replace(up_path_, '/', os.sep) - def strip_slash(p): + def strip_slash(p, drive=drive): if p[-1] == os.sep and len(p) > 1: p = p[:-1] + if p[0] == os.sep: + p = drive + p return p path = strip_slash(path_) abspath = strip_slash(abspath_) diff --git a/test/default-drive.py b/test/default-drive.py new file mode 100644 index 0000000..a57cde7 --- /dev/null +++ b/test/default-drive.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# 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. +# + +""" +This test verifies (on Windows systems) that specifying an +absolute path name without a drive letter uses the SConstruct +file's drive as the default. +""" + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import os.path +import string +import sys + +import TestSCons + +test = TestSCons.TestSCons() + +if sys.platform != 'win32': + test.pass_test() + +test.subdir('src') + +test.write(['src', 'SConstruct'], """ +def cat(env, source, target): + target = str(target[0]) + source = map(str, source) + f = open(target, "wb") + for src in source: + f.write(open(src, "rb").read()) + f.close() + +env = Environment(BUILDERS={'Build':Builder(action=cat)}) +env.Build('../build/file.out', 'file.in') +""") + +test.write(['src', 'file.in'], "src/file.in\n") + +build_file_out = test.workpath('build', 'file.out') + +print os.path.splitdrive(build_file_out)[1] +test.run(chdir = 'src', + arguments = os.path.splitdrive(build_file_out)[1]) + +test.must_match(['build', 'file.out'], "src/file.in\n") + +test.pass_test() -- cgit v0.12