Patchwork [4,of,6,v2] windows: add relpath which knows about \\?\ prefix

login
register
mail settings
Submitter Kostia Balytskyi
Date Sept. 19, 2017, 4:57 p.m.
Message ID <59578c527e95704396e0.1505840268@devvm1416.lla2.facebook.com>
Download mbox | patch
Permalink /patch/24027/
State Deferred, archived
Headers show

Comments

Kostia Balytskyi - Sept. 19, 2017, 4:57 p.m.
# HG changeset patch
# User Kostia Balytskyi <ikostia@fb.com>
# Date 1505837708 25200
#      Tue Sep 19 09:15:08 2017 -0700
# Node ID 59578c527e95704396e044444e77435cbab6a966
# Parent  3294e39ad1c3adf26308eae859280437f1671220
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.

Patch

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 _
@@ -460,11 +459,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
@@ -2227,7 +2227,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
@@ -185,7 +185,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
@@ -679,3 +679,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
@@ -559,7 +559,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
@@ -151,6 +151,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
@@ -270,6 +270,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