Mercurial > hg
annotate mercurial/pathutil.py @ 26356:927fa07a2ba4
lock: introduce state to keep track of inheritance
This is part of a series that will allow locks to be inherited by subprocesses
in limited circumstances. In upcoming patches we will refer to this state.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Thu, 24 Sep 2015 15:57:11 -0700 |
parents | d740df4e96cf |
children | 56b2bcea2529 |
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, |
d740df4e96cf
pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
11 util, |
d740df4e96cf
pathutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
12 ) |
20033
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
13 |
23598
c02a05cc6f5e
pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents:
21568
diff
changeset
|
14 def _lowerclean(s): |
c02a05cc6f5e
pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents:
21568
diff
changeset
|
15 return encoding.hfsignoreclean(s.lower()) |
c02a05cc6f5e
pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents:
21568
diff
changeset
|
16 |
20033
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
17 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
|
18 '''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
|
19 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
|
20 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
21 - 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
|
22 - 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
|
23 - 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
|
24 - contains ".." |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
25 - 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
|
26 - 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
|
27 some nested repositories, e.g., subrepositories) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
28 ''' |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
29 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
30 def __init__(self, root, callback=None): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
31 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
|
32 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
|
33 self.root = root |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
34 self.callback = callback |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
35 if os.path.lexists(root) and not util.checkcase(root): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
36 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
|
37 else: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
38 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
|
39 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
40 def __call__(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
|
41 '''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
|
42 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
|
43 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
44 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
|
45 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
|
46 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
|
47 return |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
48 # 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
|
49 if util.endswithsep(path): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
50 raise util.Abort(_("path ends in directory separator: %s") % path) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
51 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
|
52 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
|
53 or _lowerclean(parts[0]) in ('.hg', '.hg.', '') |
20033
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
54 or os.pardir in parts): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
55 raise util.Abort(_("path contains illegal component: %s") % path) |
23599
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
56 # Windows shortname aliases |
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
57 for p in parts: |
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
58 if "~" in p: |
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
59 first, last = p.split("~", 1) |
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
60 if last.isdigit() and first.upper() in ["HG", "HG8B6C"]: |
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
61 raise util.Abort(_("path contains illegal component: %s") |
6dad422ecc5a
pathauditor: check for Windows shortname aliases
Matt Mackall <mpm@selenic.com>
parents:
23598
diff
changeset
|
62 % path) |
23598
c02a05cc6f5e
pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents:
21568
diff
changeset
|
63 if '.hg' in _lowerclean(path): |
c02a05cc6f5e
pathauditor: check for codepoints ignored on OS X
Augie Fackler <raf@durin42.com>
parents:
21568
diff
changeset
|
64 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
|
65 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
|
66 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
|
67 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
|
68 base = os.path.join(*parts[:pos]) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
69 raise util.Abort(_("path '%s' is inside nested repo %r") |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
70 % (path, base)) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
71 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
72 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
|
73 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
|
74 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
75 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
|
76 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
|
77 prefixes = [] |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
78 while parts: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
79 prefix = os.sep.join(parts) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
80 normprefix = os.sep.join(normparts) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
81 if normprefix in self.auditeddir: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
82 break |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
83 curpath = os.path.join(self.root, prefix) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
84 try: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
85 st = os.lstat(curpath) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25286
diff
changeset
|
86 except OSError as err: |
20033
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
87 # EINVAL can be raised as invalid path syntax under win32. |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
88 # They must be ignored for patterns can be checked too. |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
89 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
90 raise |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
91 else: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
92 if stat.S_ISLNK(st.st_mode): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
93 raise util.Abort( |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
94 _('path %r traverses symbolic link %r') |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
95 % (path, prefix)) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
96 elif (stat.S_ISDIR(st.st_mode) and |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
97 os.path.isdir(os.path.join(curpath, '.hg'))): |
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 not self.callback or not self.callback(curpath): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
99 raise util.Abort(_("path '%s' is inside nested " |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
100 "repo %r") |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
101 % (path, prefix)) |
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 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
|
104 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
|
105 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
106 self.audited.add(normpath) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
107 # only add prefixes to the cache after checking everything: we don't |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
108 # want to add "foo/bar/baz" before checking if there's a "foo/.hg" |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
109 self.auditeddir.update(prefixes) |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
110 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
111 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
|
112 try: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
113 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
|
114 return True |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
115 except (OSError, util.Abort): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
116 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
|
117 |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
118 def canonpath(root, cwd, myname, auditor=None): |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
119 '''return the canonical path of myname, given cwd and root''' |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
120 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
|
121 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
|
122 else: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
123 rootsep = root + os.sep |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
124 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
|
125 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
|
126 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
|
127 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
|
128 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
|
129 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
|
130 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
|
131 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
|
132 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
|
133 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
|
134 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
|
135 return '' |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
136 else: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
137 # 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
|
138 # 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
|
139 # 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
|
140 # `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
|
141 # 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
|
142 rel = [] |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
143 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
|
144 try: |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
145 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
|
146 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
|
147 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
|
148 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
|
149 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
|
150 # 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
|
151 return '' |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
152 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
|
153 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
|
154 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
|
155 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
|
156 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
|
157 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
|
158 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
|
159 break |
f962870712da
pathutil: tease out a new library to break an import cycle from canonpath use
Augie Fackler <raf@durin42.com>
parents:
diff
changeset
|
160 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
|
161 |
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
|
162 # 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
|
163 # 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
|
164 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
|
165 try: |
25022
10bbdcd89164
canonpath: fix infinite recursion
Matt Mackall <mpm@selenic.com>
parents:
25011
diff
changeset
|
166 if cwd != root: |
10bbdcd89164
canonpath: fix infinite recursion
Matt Mackall <mpm@selenic.com>
parents:
25011
diff
changeset
|
167 canonpath(root, root, myname, auditor) |
10bbdcd89164
canonpath: fix infinite recursion
Matt Mackall <mpm@selenic.com>
parents:
25011
diff
changeset
|
168 hint = (_("consider using '--cwd %s'") |
10bbdcd89164
canonpath: fix infinite recursion
Matt Mackall <mpm@selenic.com>
parents:
25011
diff
changeset
|
169 % os.path.relpath(root, cwd)) |
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
|
170 except util.Abort: |
7d6a507a4c53
pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents:
23602
diff
changeset
|
171 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
|
172 |
7d6a507a4c53
pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents:
23602
diff
changeset
|
173 raise util.Abort(_("%s not under root '%s'") % (myname, root), |
7d6a507a4c53
pathutil: hint if a path is root relative instead of cwd relative (issue4663)
Matt Harbison <matt_harbison@yahoo.com>
parents:
23602
diff
changeset
|
174 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
|
175 |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
176 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
|
177 '''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
|
178 |
23139
e53f6b72a0e4
spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents:
21568
diff
changeset
|
179 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
|
180 "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
|
181 |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
182 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
|
183 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
|
184 |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
185 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
|
186 |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
187 >>> normasprefix('/foo/bar').replace(os.sep, '/') |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
188 '/foo/bar/' |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
189 >>> normasprefix('/').replace(os.sep, '/') |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
190 '/' |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
191 ''' |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
192 d, p = os.path.splitdrive(path) |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
193 if len(p) != len(os.sep): |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
194 return path + os.sep |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
195 else: |
8dd17b19e722
subrepo: normalize path in the specific way for problematic encodings
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
20033
diff
changeset
|
196 return path |
25281
660b178f49c7
pathutil: add dirname and join functions
Durham Goode <durham@fb.com>
parents:
25022
diff
changeset
|
197 |
25286
127a11f705d9
pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents:
25285
diff
changeset
|
198 # 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
|
199 # 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
|
200 # - 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
|
201 join = posixpath.join |
127a11f705d9
pathutil: demote two local functions to just be forwards
Augie Fackler <augie@google.com>
parents:
25285
diff
changeset
|
202 dirname = posixpath.dirname |