[PATCH 4 of 5 RFC] windows: add relpath which knows about \\?\ prefix

Kostia Balytskyi ikostia at fb.com
Sat Aug 12 04:22:59 EDT 2017


# HG changeset patch
# User Kostia Balytskyi <ikostia at fb.com>
# Date 1502522597 25200
#      Sat Aug 12 00:23:17 2017 -0700
# Node ID 85d8ab670c128337f27013168e3f57b037d7996e
# Parent  bac7b1ae4a0c998c57cea5eac51af66853779918
windows: add relpath which knows about \\?\ prefix

We want to correctly handle things like relpath('c:\\a\\b', '\\\\\?\\c:\\a')
on Windows, since it's hard to immediately make sure that \\?\ is used
everywhere.

diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -11,7 +11,6 @@ from __future__ import absolute_import
 
 import errno
 import hashlib
-import os
 import shutil
 
 from mercurial.i18n import _
@@ -461,11 +460,11 @@ def updatelfiles(ui, repo, filelist=None
         wctx = repo[None]
         for lfile in lfiles:
             rellfile = lfile
-            rellfileorig = os.path.relpath(
+            rellfileorig = util.relpath(
                 scmutil.origpath(ui, repo, wvfs.join(rellfile)),
                 start=repo.root)
             relstandin = lfutil.standin(lfile)
-            relstandinorig = os.path.relpath(
+            relstandinorig = util.relpath(
                 scmutil.origpath(ui, repo, wvfs.join(relstandin)),
                 start=repo.root)
             if wvfs.exists(relstandin):
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -241,7 +241,7 @@ def share(ui, source, dest=None, update=
 
     if relative:
         try:
-            sharedpath = os.path.relpath(sharedpath, destvfs.base)
+            sharedpath = util.relpath(sharedpath, destvfs.base)
             requirements += 'relshared\n'
         except IOError as e:
             raise error.Abort(_('cannot calculate relative path'),
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -2190,7 +2190,7 @@ class localrepository(object):
             fp.write(text)
         finally:
             fp.close()
-        return self.pathto(fp.name[len(self.root) + 1:])
+        return self.pathto(util.relpath(fp.name, self.root))
 
 # used to avoid circular references so destructors work
 def aftertrans(files):
diff --git a/mercurial/pathutil.py b/mercurial/pathutil.py
--- a/mercurial/pathutil.py
+++ b/mercurial/pathutil.py
@@ -179,7 +179,7 @@ def canonpath(root, cwd, myname, auditor
             if cwd != root:
                 canonpath(root, root, myname, auditor)
                 hint = (_("consider using '--cwd %s'")
-                        % os.path.relpath(root, cwd))
+                        % util.relpath(root, cwd))
         except error.Abort:
             pass
 
diff --git a/mercurial/posix.py b/mercurial/posix.py
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -672,3 +672,6 @@ def absjoin(absprefix, relpath):
     the passed absolute path already contains a terminating directory
     separator."""
     return absprefix + relpath
+
+relpath = os.path.relpath
+
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -556,7 +556,7 @@ def origpath(ui, repo, filepath):
     if origbackuppath is None:
         return filepath + ".orig"
 
-    filepathfromroot = os.path.relpath(filepath, start=repo.root)
+    filepathfromroot = util.relpath(filepath, start=repo.root)
     fullorigpath = repo.wjoin(origbackuppath, filepathfromroot)
 
     origbackupdir = repo.vfs.dirname(fullorigpath)
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -150,6 +150,7 @@ umask = platform.umask
 unlink = platform.unlink
 username = platform.username
 absjoin = platform.absjoin
+relpath = platform.relpath
 
 try:
     recvfds = osutil.recvfds
diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -261,6 +261,14 @@ def absjoin(absprefix, relpath):
     else:
         return converttontpath(absprefix + relpath)
 
+def relpath(path, start=os.path.curdir):
+    """Relpath which knows how to work with //?/ prefixes"""
+    if not hasntprefix(path) and os.path.isabs(path):
+        path = converttontpath(path)
+    if not hasntprefix(start) and os.path.isabs(start):
+        start = converttontpath(start)
+    return os.path.relpath(path, start)
+
 # see posix.py for definitions
 normcasespec = encoding.normcasespecs.upper
 normcasefallback = encoding.upperfallback


More information about the Mercurial-devel mailing list