Comment 17 for bug 613153

Revision history for this message
tbnorth (terry-n-brown) wrote : Re: [Bug 613153] Re: unable to describe root directory on thumb drive

Edward, not sure if you're following this thread, but the fix turned out to be entangled with a lot of @<file> stuff, so I don't want to push it without your inspection.

Repeating the basic problem: for an @<file> node there is some parent path in effect at the point where you reach the node, based on the location of the .leo file and any relevant @path directives. For determination of the full path to the target file, the @<file> node can either extend the parent path with a relative path (simplest case, just the filename), or discard the parent path with an absolute path of its own. The problem arises when the @<file> introduces a Windows drive specific \absolute\path without specifying the drive. In that case the drive should come from the original parent path.

I think the diff below does that ok. It might do it in more places than was needed to fix the original problem, but I don't think it does it in any places where it shouldn't.

Also, I think the same issue would affect the scanning of @path directives, this diff doesn't address that, although the fix_windows_absolute() method it introduces could probably be used for that application also. Here's the diff:

=== modified file 'leo/core/leoAtFile.py'
--- leo/core/leoAtFile.py 2010-08-03 22:26:10 +0000
+++ leo/core/leoAtFile.py 2010-08-05 22:24:42 +0000
@@ -688,6 +688,8 @@
         else:
             fileName = None

+ fileName = g.fix_windows_absolute(self.c, root, fileName)
+
         return fileName
     #@+node:ekr.20100224050618.11547: *5* at.isFileLike
     def isFileLike (self,s):
@@ -2815,7 +2817,10 @@
                 at.targetFileName = root.atFileNodeName()
         else:
             at.targetFileName = root.atFileNodeName()
+
+ at.targetFileName = g.fix_windows_absolute(at.c, root, at.targetFileName)
         #@-<< set at.targetFileName >>
+
         at.initWriteIvars(root,at.targetFileName,
             nosentinels = nosentinels, thinFile = thinFile,
             scriptWrite = scriptWrite, toString = toString)
@@ -5166,7 +5171,9 @@
         else:
             fn = p.anyAtFileNodeName()
         if fn:
+ fn = g.fix_windows_absolute(c, p, fn)
             path = g.os_path_finalize_join(path,fn)
+
         else:
             g.trace('can not happen: not an @<file> node:',g.callers(4))
             for p2 in p.self_and_parents():

=== modified file 'leo/core/leoCommands.py'
--- leo/core/leoCommands.py 2010-08-01 17:16:51 +0000
+++ leo/core/leoCommands.py 2010-08-05 22:59:13 +0000
@@ -559,6 +559,7 @@
             if name: break

         if name:
+ name = g.fix_windows_absolute(self, p, name)
             name = g.os_path_finalize_join(path,name)
         return name
     #@+node:ekr.20091211111443.6265: *3* c.doBatchOperations & helpers

=== modified file 'leo/core/leoGlobals.py'
--- leo/core/leoGlobals.py 2010-07-31 12:00:58 +0000
+++ leo/core/leoGlobals.py 2010-08-05 22:52:47 +0000
@@ -936,6 +936,9 @@
     if name:
         theDir = g.os_path_dirname(name)
         if theDir and g.os_path_isabs(theDir):
+
+ theDir = g.fix_windows_absolute(c,p,theDir)
+
             if g.os_path_exists(theDir):
                 default_dir = theDir
             else:
@@ -3603,6 +3606,38 @@

     # Yes, this is correct. All os_path_x functions return Unicode strings.
     return g.toUnicode(path)
+#@+node:tbrown.20100805110001.18803: *3* fix_windows_absolute
+def fix_windows_absolute(c, p, path):
+ """According to os.path.isabs(), in Windows, "\\foo\\bar.leo" is
+ an absolute path, but resolving it depends of the python process's
+ current directory. See http://bugs.python.org/issue1669539. So in
+ cases where we seem to be dealing with an "absolute" path of this
+ kind in Windows, we need to prepend the drive letter based on any
+ relevant @path directives and the location of the .leo file.
+ """
+
+ import platform
+
+ if not path or platform.system() != 'Windows' or path[0] != "\\":
+ return path
+
+ if len(path) > 1 and path[1] == "\\":
+ return path # don't mess with "\\server\share" style paths
+
+ # need drive letter from parent path
+ parent_path = c.getNodePath(p)
+
+ if not 'A' <= parent_path[0].upper() <= 'Z':
+ return path # because this state is not anticipated / understood
+
+ # this should take into account any @path directives, and, in the
+ # absence of any absolute path components, the starting point defined
+ # by the location of the .leo file
+ drive_letter = parent_path[:2]
+
+ g.es(path + " -> " + drive_letter + path)
+
+ return drive_letter + path # "E:" + "\some\thing"
 #@+node:ekr.20031218072017.3151: ** Scanning... (leoGlobals.py)
 #@+node:ekr.20031218072017.3156: *3* scanError
 # It is dubious to bump the Tangle error count here, but it really doesn't hurt.