Support specifying absolute path names without drive letters on Win32.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 19 Nov 2005 16:26:31 +0000 (16:26 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 19 Nov 2005 16:26:31 +0000 (16:26 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1392 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/EnvironmentTests.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
test/default-drive.py [new file with mode: 0644]

index d087d741d1e8d59ecda26acd568ff8763ded0f64..1d67c5a2bce0a74d49f4f4b9e7e17aabb85967c5 100644 (file)
@@ -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.
index a397d4fbec51f62a9c3b0ca87fdbe580a17bcb2f..58c8ae8c99cd35f0588a1e19004fece63d3c49f4 100644 (file)
@@ -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
index 810ede73e2ce2535caab5572855b3115081984ae..7d4d8dfee5bcc0a723d53bda626ce2322698d444 100644 (file)
@@ -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 = {}
index 565384f7e2727019847ae037767de48f7c9af319..cb98f506423e42e62b61e2cee878707c74af73ae 100644 (file)
@@ -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 (file)
index 0000000..a57cde7
--- /dev/null
@@ -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()