Commits

Anonymous committed 46c1025

Support specifying absolute path names without drive letters on Win32.

Comments (0)

Files changed (5)

   - 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.

src/engine/SCons/EnvironmentTests.py

     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')
                     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
                     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
                     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

src/engine/SCons/Node/FS.py

         The path argument must be a valid absolute path.
         """
         if __debug__: logInstanceCreation(self, 'Node.FS')
+
         self.Root = {}
         self.SConstruct_dir = None
         self.CachePath = None
         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 = '.'
             path_orig = [ path_first, ] + path_orig
             path_norm = [ _my_normcase(path_first), ] + path_norm
         else:
+            # Absolute path
             drive = _my_normcase(drive)
-            # Absolute path
             try:
                 directory = self.Root[drive]
             except KeyError:
                     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
         """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 = {}

src/engine/SCons/Node/FSTests.py

         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 != '/':
                     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_)

test/default-drive.py

+#!/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()