[PATCH 3 of 4 STABLE] unionrepo: use pathutil.normasprefix to ensure os.sep at the end of cwd

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Wed Apr 22 09:43:58 CDT 2015


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1429713535 -32400
#      Wed Apr 22 23:38:55 2015 +0900
# Branch stable
# Node ID f0d4d87183cb8ce88a29863086cc77af52cc81d9
# Parent  00906a8bebe58bd2d27d417e76b8b0f9d4d31ca1
unionrepo: use pathutil.normasprefix to ensure os.sep at the end of cwd

Since Python 2.7.9, "os.path.join(path, '')" doesn't add "os.sep" at
the end of UNC path (see issue4557 for detail).

This makes unionrepo incorrectly work, if:

  1. cwd is the root of UNC share (e.g. "\host\share"), and
  2. mainreporoot is near cwd (e.g. "\host\sharefoo\repo")
     - host of UNC path is same as one of cwd
     - share of UNC path starts with one of cwd
  3. "repopath" isn't specified in URI (e.g. "union:path/to/repo2")

For example:

  $ hg --cwd \host\share -R \host\sharefoo\repo incoming union:path\to\repo2

In this case:

  - os.path.join(r"\host\share", "") returns r"\host\share",
  - r"\host\sharefoo\repo".startswith(r"\host\share") returns True, then
  - r"foo\repo" is treated as repopath of unionrepo instead of
    r"\host\sharefoo\repo"

This causes failure of combining "\host\sharefoo\repo" and another
repository: in addition to it, "\host\share\foo\repo" may be combined
with another repository, if it accidentally exists.

This patch uses "pathutil.normasprefix()" to ensure "os.sep" at the
end of cwd safely, even with some problematic encodings, which use
0x5c (= "os.sep" on Windows) as the tail byte of some multi-byte
characters.

BTW, normalization before "pathutil.normasprefix()" isn't needed in
this case, because "os.getcwd()" always returns normalized one.

diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py
--- a/mercurial/unionrepo.py
+++ b/mercurial/unionrepo.py
@@ -15,7 +15,7 @@ from node import nullid
 from i18n import _
 import os
 import util, mdiff, cmdutil, scmutil
-import localrepo, changelog, manifest, filelog, revlog
+import localrepo, changelog, manifest, filelog, revlog, pathutil
 
 class unionrevlog(revlog.revlog):
     def __init__(self, opener, indexfile, revlog2, linkmapper):
@@ -228,7 +228,7 @@ def instance(ui, path, create):
         if parentpath == cwd:
             parentpath = ''
         else:
-            cwd = os.path.join(cwd,'')
+            cwd = pathutil.normasprefix(cwd)
             if parentpath.startswith(cwd):
                 parentpath = parentpath[len(cwd):]
     if path.startswith('union:'):


More information about the Mercurial-devel mailing list