D11059: windows: introduce a `util.abspath` to replace os.path.abspath

marmoute (Pierre-Yves David) phabricator at mercurial-scm.org
Sat Jul 10 17:46:15 UTC 2021


marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This will let us mitigate the drive letter capitalization hell.
  
  See inline comment for details.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11059

AFFECTED FILES
  mercurial/posix.py
  mercurial/util.py
  mercurial/windows.py

CHANGE DETAILS

diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -333,6 +333,25 @@
     return encoding.upper(path)  # NTFS compares via upper()
 
 
+DRIVE_RE_B = re.compile(b'^[a-z]:')
+DRIVE_RE_S = re.compile('^[a-z]:')
+
+
+def abspath(path):
+    abs_path = os.path.abspath(path)  # re-exports
+    # Python on Windows is inconsistent regarding the capitalization of drive
+    # letter and this cause issue with various path comparison along the way.
+    # So we normalize the drive later to upper case here.
+    #
+    # See https://bugs.python.org/issue40368 for and example of this hell.
+    if isinstance(abs_path, bytes):
+        if DRIVE_RE_B.match(abs_path):
+            abs_path = abs_path[0:1].upper() + abs_path[1:]
+    elif DRIVE_RE_S.match(abs_path):
+        abs_path = abs_path[0:1].upper() + abs_path[1:]
+    return abs_path
+
+
 # see posix.py for definitions
 normcasespec = encoding.normcasespecs.upper
 normcasefallback = encoding.upperfallback
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -99,6 +99,7 @@
 
 _ = i18n._
 
+abspath = platform.abspath
 bindunixsocket = platform.bindunixsocket
 cachestat = platform.cachestat
 checkexec = platform.checkexec
@@ -2632,7 +2633,7 @@
             return
         if err.errno != errno.ENOENT or not name:
             raise
-        parent = os.path.dirname(os.path.abspath(name))
+        parent = os.path.dirname(abspath(name))
         if parent == name:
             raise
         makedirs(parent, mode, notindexed)
diff --git a/mercurial/posix.py b/mercurial/posix.py
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -36,6 +36,8 @@
 
 normpath = os.path.normpath
 samestat = os.path.samestat
+abspath = os.path.abspath  # re-exports
+
 try:
     oslink = os.link
 except AttributeError:



To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel


More information about the Mercurial-devel mailing list