annotate mercurial/pathutil.py @ 42774:da643cadec90

rawdata: update caller in wireprotov2server We update callers incrementally because this help bisecting failures. This was useful during development, so we expect it might be useful again in the future.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 07 Aug 2019 20:10:24 +0200
parents 21be76e07148
children 2372284d9457
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
25964
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
1 from __future__ import absolute_import
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
2
25964
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
3 import errno
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
4 import os
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
5 import posixpath
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
6 import stat
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
7
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
8 from .i18n import _
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
9 from . import (
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
10 encoding,
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
11 error,
30614
cfe66dcf45c0 py3: replace os.sep with pycompat.ossep (part 2 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
12 pycompat,
25964
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
13 util,
d740df4e96cf pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
14 )
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
15
23598
c02a05cc6f5e pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents: 21568
diff changeset
16 def _lowerclean(s):
c02a05cc6f5e pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents: 21568
diff changeset
17 return encoding.hfsignoreclean(s.lower())
c02a05cc6f5e pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents: 21568
diff changeset
18
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
19 class pathauditor(object):
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
20 '''ensure that a filesystem path contains no banned components.
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
21 the following properties of a path are checked:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
22
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
23 - ends with a directory separator
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
24 - under top-level .hg
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
25 - starts at the root of a windows drive
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
26 - contains ".."
27232
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
27
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
28 More check are also done about the file system states:
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
29 - traverses a symlink (e.g. a/symlink_here/b)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
30 - inside a nested repository (a callback can be used to approve
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
31 some nested repositories, e.g., subrepositories)
27232
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
32
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
33 The file system checks are only done when 'realfs' is set to True (the
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
34 default). They should be disable then we are auditing path for operation on
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
35 stored history.
33649
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
36
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
37 If 'cached' is set to True, audited paths and sub-directories are cached.
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
38 Be careful to not keep the cache of unmanaged directories for long because
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
39 audited paths may be replaced with symlinks.
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
40 '''
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
41
33649
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
42 def __init__(self, root, callback=None, realfs=True, cached=False):
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
43 self.audited = set()
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
44 self.auditeddir = set()
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
45 self.root = root
27232
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
46 self._realfs = realfs
33649
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
47 self._cached = cached
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
48 self.callback = callback
29889
6f447b9ec263 util: rename checkcase() to fscasesensitive() (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 28087
diff changeset
49 if os.path.lexists(root) and not util.fscasesensitive(root):
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
50 self.normcase = util.normcase
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
51 else:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
52 self.normcase = lambda x: x
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
53
33435
456626e9c3d1 vfs: allow to pass more argument to audit
Boris Feld <boris.feld@octobus.net>
parents: 30614
diff changeset
54 def __call__(self, path, mode=None):
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
55 '''Check the relative path.
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
56 path may contain a pattern (e.g. foodir/**.txt)'''
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
57
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
58 path = util.localpath(path)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
59 normpath = self.normcase(path)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
60 if normpath in self.audited:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
61 return
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
62 # AIX ignores "/" at end of path, others raise EISDIR.
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
63 if util.endswithsep(path):
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
64 raise error.Abort(_("path ends in directory separator: %s") % path)
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
65 parts = util.splitpath(path)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
66 if (os.path.splitdrive(path)[0]
23598
c02a05cc6f5e pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents: 21568
diff changeset
67 or _lowerclean(parts[0]) in ('.hg', '.hg.', '')
36647
052351e3e1cd py3: make os.pardir a bytes
Yuya Nishihara <yuya@tcha.org>
parents: 34980
diff changeset
68 or pycompat.ospardir in parts):
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
69 raise error.Abort(_("path contains illegal component: %s") % path)
23599
6dad422ecc5a pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents: 23598
diff changeset
70 # Windows shortname aliases
6dad422ecc5a pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents: 23598
diff changeset
71 for p in parts:
6dad422ecc5a pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents: 23598
diff changeset
72 if "~" in p:
6dad422ecc5a pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents: 23598
diff changeset
73 first, last = p.split("~", 1)
6dad422ecc5a pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents: 23598
diff changeset
74 if last.isdigit() and first.upper() in ["HG", "HG8B6C"]:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
75 raise error.Abort(_("path contains illegal component: %s")
23599
6dad422ecc5a pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents: 23598
diff changeset
76 % path)
23598
c02a05cc6f5e pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents: 21568
diff changeset
77 if '.hg' in _lowerclean(path):
c02a05cc6f5e pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents: 21568
diff changeset
78 lparts = [_lowerclean(p.lower()) for p in parts]
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
79 for p in '.hg', '.hg.':
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
80 if p in lparts[1:]:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
81 pos = lparts.index(p)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
82 base = os.path.join(*parts[:pos])
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
83 raise error.Abort(_("path '%s' is inside nested repo %r")
36649
d3b893ec5f08 py3: fix formatting of path-auditing errors
Yuya Nishihara <yuya@tcha.org>
parents: 36647
diff changeset
84 % (path, pycompat.bytestr(base)))
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
85
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
86 normparts = util.splitpath(normpath)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
87 assert len(parts) == len(normparts)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
88
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
89 parts.pop()
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
90 normparts.pop()
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
91 prefixes = []
28087
0b7ce0b16d8a pathauditor: change parts verification order to be root first
Durham Goode <durham@fb.com>
parents: 27235
diff changeset
92 # It's important that we check the path parts starting from the root.
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 29889
diff changeset
93 # This means we won't accidentally traverse a symlink into some other
28087
0b7ce0b16d8a pathauditor: change parts verification order to be root first
Durham Goode <durham@fb.com>
parents: 27235
diff changeset
94 # filesystem (which is potentially expensive to access).
0b7ce0b16d8a pathauditor: change parts verification order to be root first
Durham Goode <durham@fb.com>
parents: 27235
diff changeset
95 for i in range(len(parts)):
30614
cfe66dcf45c0 py3: replace os.sep with pycompat.ossep (part 2 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
96 prefix = pycompat.ossep.join(parts[:i + 1])
cfe66dcf45c0 py3: replace os.sep with pycompat.ossep (part 2 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
97 normprefix = pycompat.ossep.join(normparts[:i + 1])
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
98 if normprefix in self.auditeddir:
28087
0b7ce0b16d8a pathauditor: change parts verification order to be root first
Durham Goode <durham@fb.com>
parents: 27235
diff changeset
99 continue
27232
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
100 if self._realfs:
79a86a95f325 pathauditor: add a way to skip file system check
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27231
diff changeset
101 self._checkfs(prefix, path)
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
102 prefixes.append(normprefix)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
103
33649
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
104 if self._cached:
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
105 self.audited.add(normpath)
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
106 # only add prefixes to the cache after checking everything: we don't
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
107 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
377e8ddaebef pathauditor: disable cache of audited paths by default (issue5628)
Yuya Nishihara <yuya@tcha.org>
parents: 33435
diff changeset
108 self.auditeddir.update(prefixes)
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
109
27231
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
110 def _checkfs(self, prefix, path):
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
111 """raise exception if a file system backed check fails"""
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
112 curpath = os.path.join(self.root, prefix)
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
113 try:
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
114 st = os.lstat(curpath)
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
115 except OSError as err:
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
116 # EINVAL can be raised as invalid path syntax under win32.
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
117 # They must be ignored for patterns can be checked too.
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
118 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
119 raise
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
120 else:
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
121 if stat.S_ISLNK(st.st_mode):
36649
d3b893ec5f08 py3: fix formatting of path-auditing errors
Yuya Nishihara <yuya@tcha.org>
parents: 36647
diff changeset
122 msg = (_('path %r traverses symbolic link %r')
d3b893ec5f08 py3: fix formatting of path-auditing errors
Yuya Nishihara <yuya@tcha.org>
parents: 36647
diff changeset
123 % (pycompat.bytestr(path), pycompat.bytestr(prefix)))
27235
054cd38a2f19 pathutil: use temporary variables instead of complicated wrapping
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27232
diff changeset
124 raise error.Abort(msg)
27231
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
125 elif (stat.S_ISDIR(st.st_mode) and
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
126 os.path.isdir(os.path.join(curpath, '.hg'))):
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
127 if not self.callback or not self.callback(curpath):
27235
054cd38a2f19 pathutil: use temporary variables instead of complicated wrapping
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27232
diff changeset
128 msg = _("path '%s' is inside nested repo %r")
36649
d3b893ec5f08 py3: fix formatting of path-auditing errors
Yuya Nishihara <yuya@tcha.org>
parents: 36647
diff changeset
129 raise error.Abort(msg % (path, pycompat.bytestr(prefix)))
27231
6d29ce250a3d pathauditor: move file system specific check in their own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
130
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
131 def check(self, path):
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
132 try:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
133 self(path)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
134 return True
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
135 except (OSError, error.Abort):
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
136 return False
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
137
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
138 def canonpath(root, cwd, myname, auditor=None):
34980
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
139 '''return the canonical path of myname, given cwd and root
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
140
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
141 >>> def check(root, cwd, myname):
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
142 ... a = pathauditor(root, realfs=False)
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
143 ... try:
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
144 ... return canonpath(root, cwd, myname, a)
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
145 ... except error.Abort:
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
146 ... return 'aborted'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
147 >>> def unixonly(root, cwd, myname, expected='aborted'):
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
148 ... if pycompat.iswindows:
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
149 ... return expected
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
150 ... return check(root, cwd, myname)
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
151 >>> def winonly(root, cwd, myname, expected='aborted'):
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
152 ... if not pycompat.iswindows:
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
153 ... return expected
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
154 ... return check(root, cwd, myname)
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
155 >>> winonly(b'd:\\\\repo', b'c:\\\\dir', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
156 'aborted'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
157 >>> winonly(b'c:\\\\repo', b'c:\\\\dir', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
158 'aborted'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
159 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
160 'aborted'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
161 >>> winonly(b'c:\\\\repo', b'c:\\\\', b'repo\\\\filename',
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
162 ... b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
163 'filename'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
164 >>> winonly(b'c:\\\\repo', b'c:\\\\repo', b'filename', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
165 'filename'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
166 >>> winonly(b'c:\\\\repo', b'c:\\\\repo\\\\subdir', b'filename',
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
167 ... b'subdir/filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
168 'subdir/filename'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
169 >>> unixonly(b'/repo', b'/dir', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
170 'aborted'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
171 >>> unixonly(b'/repo', b'/', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
172 'aborted'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
173 >>> unixonly(b'/repo', b'/', b'repo/filename', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
174 'filename'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
175 >>> unixonly(b'/repo', b'/repo', b'filename', b'filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
176 'filename'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
177 >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename')
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
178 'subdir/filename'
705d0f2bb677 pathutil: add doctests for canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34965
diff changeset
179 '''
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
180 if util.endswithsep(root):
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
181 rootsep = root
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
182 else:
30614
cfe66dcf45c0 py3: replace os.sep with pycompat.ossep (part 2 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
183 rootsep = root + pycompat.ossep
20033
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
184 name = myname
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
185 if not os.path.isabs(name):
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
186 name = os.path.join(root, cwd, name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
187 name = os.path.normpath(name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
188 if auditor is None:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
189 auditor = pathauditor(root)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
190 if name != rootsep and name.startswith(rootsep):
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
191 name = name[len(rootsep):]
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
192 auditor(name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
193 return util.pconvert(name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
194 elif name == root:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
195 return ''
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
196 else:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
197 # Determine whether `name' is in the hierarchy at or beneath `root',
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
198 # by iterating name=dirname(name) until that causes no change (can't
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
199 # check name == '/', because that doesn't work on windows). The list
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
200 # `rel' holds the reversed list of components making up the relative
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
201 # file name we want.
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
202 rel = []
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
203 while True:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
204 try:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
205 s = util.samefile(name, root)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
206 except OSError:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
207 s = False
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
208 if s:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
209 if not rel:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
210 # name was actually the same as root (maybe a symlink)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
211 return ''
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
212 rel.reverse()
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
213 name = os.path.join(*rel)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
214 auditor(name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
215 return util.pconvert(name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
216 dirname, basename = util.split(name)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
217 rel.append(basename)
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
218 if dirname == name:
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
219 break
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
220 name = dirname
f962870712da pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff changeset
221
25011
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
222 # A common mistake is to use -R, but specify a file relative to the repo
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
223 # instead of cwd. Detect that case, and provide a hint to the user.
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
224 hint = None
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
225 try:
25022
10bbdcd89164 canonpath: fix infinite recursion
Matt Mackall <mpm@selenic.com>
parents: 25011
diff changeset
226 if cwd != root:
10bbdcd89164 canonpath: fix infinite recursion
Matt Mackall <mpm@selenic.com>
parents: 25011
diff changeset
227 canonpath(root, root, myname, auditor)
34965
f445b10dc7fb pathutil: use util.pathto() to calculate relative cwd in canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34254
diff changeset
228 relpath = util.pathto(root, cwd, '')
38592
21be76e07148 py3: use bytes.endswith() instead of bytes[n]
Yuya Nishihara <yuya@tcha.org>
parents: 36649
diff changeset
229 if relpath.endswith(pycompat.ossep):
34965
f445b10dc7fb pathutil: use util.pathto() to calculate relative cwd in canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34254
diff changeset
230 relpath = relpath[:-1]
f445b10dc7fb pathutil: use util.pathto() to calculate relative cwd in canonpath()
Matt Harbison <matt_harbison@yahoo.com>
parents: 34254
diff changeset
231 hint = (_("consider using '--cwd %s'") % relpath)
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
232 except error.Abort:
25011
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
233 pass
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
234
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25964
diff changeset
235 raise error.Abort(_("%s not under root '%s'") % (myname, root),
25011
7d6a507a4c53 pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents: 23602
diff changeset
236 hint=hint)
21568
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
237
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
238 def normasprefix(path):
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
239 '''normalize the specified path as path prefix
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
240
23139
e53f6b72a0e4 spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 21568
diff changeset
241 Returned value can be used safely for "p.startswith(prefix)",
21568
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
242 "p[len(prefix):]", and so on.
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
243
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
244 For efficiency, this expects "path" argument to be already
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
245 normalized by "os.path.normpath", "os.path.realpath", and so on.
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
246
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
247 See also issue3033 for detail about need of this function.
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
248
34254
cd022a11ec83 py3: use bytes os.sep in doctest of pathutil.py
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
249 >>> normasprefix(b'/foo/bar').replace(pycompat.ossep, b'/')
21568
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
250 '/foo/bar/'
34254
cd022a11ec83 py3: use bytes os.sep in doctest of pathutil.py
Yuya Nishihara <yuya@tcha.org>
parents: 34131
diff changeset
251 >>> normasprefix(b'/').replace(pycompat.ossep, b'/')
21568
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
252 '/'
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
253 '''
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
254 d, p = os.path.splitdrive(path)
30614
cfe66dcf45c0 py3: replace os.sep with pycompat.ossep (part 2 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
255 if len(p) != len(pycompat.ossep):
cfe66dcf45c0 py3: replace os.sep with pycompat.ossep (part 2 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
256 return path + pycompat.ossep
21568
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
257 else:
8dd17b19e722 subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20033
diff changeset
258 return path
25281
660b178f49c7 pathutil: add dirname and join functions
Durham Goode <durham@fb.com>
parents: 25022
diff changeset
259
25286
127a11f705d9 pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents: 25285
diff changeset
260 # forward two methods from posixpath that do what we need, but we'd
127a11f705d9 pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents: 25285
diff changeset
261 # rather not let our internals know that we're thinking in posix terms
127a11f705d9 pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents: 25285
diff changeset
262 # - instead we'll let them be oblivious.
127a11f705d9 pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents: 25285
diff changeset
263 join = posixpath.join
127a11f705d9 pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents: 25285
diff changeset
264 dirname = posixpath.dirname