Show More
@@ -0,0 +1,144 b'' | |||||
|
1 | import os, errno, stat | |||
|
2 | ||||
|
3 | import util | |||
|
4 | from i18n import _ | |||
|
5 | ||||
|
6 | class pathauditor(object): | |||
|
7 | '''ensure that a filesystem path contains no banned components. | |||
|
8 | the following properties of a path are checked: | |||
|
9 | ||||
|
10 | - ends with a directory separator | |||
|
11 | - under top-level .hg | |||
|
12 | - starts at the root of a windows drive | |||
|
13 | - contains ".." | |||
|
14 | - traverses a symlink (e.g. a/symlink_here/b) | |||
|
15 | - inside a nested repository (a callback can be used to approve | |||
|
16 | some nested repositories, e.g., subrepositories) | |||
|
17 | ''' | |||
|
18 | ||||
|
19 | def __init__(self, root, callback=None): | |||
|
20 | self.audited = set() | |||
|
21 | self.auditeddir = set() | |||
|
22 | self.root = root | |||
|
23 | self.callback = callback | |||
|
24 | if os.path.lexists(root) and not util.checkcase(root): | |||
|
25 | self.normcase = util.normcase | |||
|
26 | else: | |||
|
27 | self.normcase = lambda x: x | |||
|
28 | ||||
|
29 | def __call__(self, path): | |||
|
30 | '''Check the relative path. | |||
|
31 | path may contain a pattern (e.g. foodir/**.txt)''' | |||
|
32 | ||||
|
33 | path = util.localpath(path) | |||
|
34 | normpath = self.normcase(path) | |||
|
35 | if normpath in self.audited: | |||
|
36 | return | |||
|
37 | # AIX ignores "/" at end of path, others raise EISDIR. | |||
|
38 | if util.endswithsep(path): | |||
|
39 | raise util.Abort(_("path ends in directory separator: %s") % path) | |||
|
40 | parts = util.splitpath(path) | |||
|
41 | if (os.path.splitdrive(path)[0] | |||
|
42 | or parts[0].lower() in ('.hg', '.hg.', '') | |||
|
43 | or os.pardir in parts): | |||
|
44 | raise util.Abort(_("path contains illegal component: %s") % path) | |||
|
45 | if '.hg' in path.lower(): | |||
|
46 | lparts = [p.lower() for p in parts] | |||
|
47 | for p in '.hg', '.hg.': | |||
|
48 | if p in lparts[1:]: | |||
|
49 | pos = lparts.index(p) | |||
|
50 | base = os.path.join(*parts[:pos]) | |||
|
51 | raise util.Abort(_("path '%s' is inside nested repo %r") | |||
|
52 | % (path, base)) | |||
|
53 | ||||
|
54 | normparts = util.splitpath(normpath) | |||
|
55 | assert len(parts) == len(normparts) | |||
|
56 | ||||
|
57 | parts.pop() | |||
|
58 | normparts.pop() | |||
|
59 | prefixes = [] | |||
|
60 | while parts: | |||
|
61 | prefix = os.sep.join(parts) | |||
|
62 | normprefix = os.sep.join(normparts) | |||
|
63 | if normprefix in self.auditeddir: | |||
|
64 | break | |||
|
65 | curpath = os.path.join(self.root, prefix) | |||
|
66 | try: | |||
|
67 | st = os.lstat(curpath) | |||
|
68 | except OSError, err: | |||
|
69 | # EINVAL can be raised as invalid path syntax under win32. | |||
|
70 | # They must be ignored for patterns can be checked too. | |||
|
71 | if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): | |||
|
72 | raise | |||
|
73 | else: | |||
|
74 | if stat.S_ISLNK(st.st_mode): | |||
|
75 | raise util.Abort( | |||
|
76 | _('path %r traverses symbolic link %r') | |||
|
77 | % (path, prefix)) | |||
|
78 | elif (stat.S_ISDIR(st.st_mode) and | |||
|
79 | os.path.isdir(os.path.join(curpath, '.hg'))): | |||
|
80 | if not self.callback or not self.callback(curpath): | |||
|
81 | raise util.Abort(_("path '%s' is inside nested " | |||
|
82 | "repo %r") | |||
|
83 | % (path, prefix)) | |||
|
84 | prefixes.append(normprefix) | |||
|
85 | parts.pop() | |||
|
86 | normparts.pop() | |||
|
87 | ||||
|
88 | self.audited.add(normpath) | |||
|
89 | # only add prefixes to the cache after checking everything: we don't | |||
|
90 | # want to add "foo/bar/baz" before checking if there's a "foo/.hg" | |||
|
91 | self.auditeddir.update(prefixes) | |||
|
92 | ||||
|
93 | def check(self, path): | |||
|
94 | try: | |||
|
95 | self(path) | |||
|
96 | return True | |||
|
97 | except (OSError, util.Abort): | |||
|
98 | return False | |||
|
99 | ||||
|
100 | def canonpath(root, cwd, myname, auditor=None): | |||
|
101 | '''return the canonical path of myname, given cwd and root''' | |||
|
102 | if util.endswithsep(root): | |||
|
103 | rootsep = root | |||
|
104 | else: | |||
|
105 | rootsep = root + os.sep | |||
|
106 | name = myname | |||
|
107 | if not os.path.isabs(name): | |||
|
108 | name = os.path.join(root, cwd, name) | |||
|
109 | name = os.path.normpath(name) | |||
|
110 | if auditor is None: | |||
|
111 | auditor = pathauditor(root) | |||
|
112 | if name != rootsep and name.startswith(rootsep): | |||
|
113 | name = name[len(rootsep):] | |||
|
114 | auditor(name) | |||
|
115 | return util.pconvert(name) | |||
|
116 | elif name == root: | |||
|
117 | return '' | |||
|
118 | else: | |||
|
119 | # Determine whether `name' is in the hierarchy at or beneath `root', | |||
|
120 | # by iterating name=dirname(name) until that causes no change (can't | |||
|
121 | # check name == '/', because that doesn't work on windows). The list | |||
|
122 | # `rel' holds the reversed list of components making up the relative | |||
|
123 | # file name we want. | |||
|
124 | rel = [] | |||
|
125 | while True: | |||
|
126 | try: | |||
|
127 | s = util.samefile(name, root) | |||
|
128 | except OSError: | |||
|
129 | s = False | |||
|
130 | if s: | |||
|
131 | if not rel: | |||
|
132 | # name was actually the same as root (maybe a symlink) | |||
|
133 | return '' | |||
|
134 | rel.reverse() | |||
|
135 | name = os.path.join(*rel) | |||
|
136 | auditor(name) | |||
|
137 | return util.pconvert(name) | |||
|
138 | dirname, basename = util.split(name) | |||
|
139 | rel.append(basename) | |||
|
140 | if dirname == name: | |||
|
141 | break | |||
|
142 | name = dirname | |||
|
143 | ||||
|
144 | raise util.Abort(_("%s not under root '%s'") % (myname, root)) |
@@ -84,7 +84,7 b" like CVS' $Log$, are not supported. A ke" | |||||
84 |
|
84 | |||
85 | from mercurial import commands, context, cmdutil, dispatch, filelog, extensions |
|
85 | from mercurial import commands, context, cmdutil, dispatch, filelog, extensions | |
86 | from mercurial import localrepo, match, patch, templatefilters, templater, util |
|
86 | from mercurial import localrepo, match, patch, templatefilters, templater, util | |
87 | from mercurial import scmutil |
|
87 | from mercurial import scmutil, pathutil | |
88 | from mercurial.hgweb import webcommands |
|
88 | from mercurial.hgweb import webcommands | |
89 | from mercurial.i18n import _ |
|
89 | from mercurial.i18n import _ | |
90 | import os, re, shutil, tempfile |
|
90 | import os, re, shutil, tempfile | |
@@ -673,7 +673,7 b' def reposetup(ui, repo):' | |||||
673 | expansion. ''' |
|
673 | expansion. ''' | |
674 | source = repo.dirstate.copied(dest) |
|
674 | source = repo.dirstate.copied(dest) | |
675 | if 'l' in wctx.flags(source): |
|
675 | if 'l' in wctx.flags(source): | |
676 |
source = |
|
676 | source = pathutil.canonpath(repo.root, cwd, | |
677 | os.path.realpath(source)) |
|
677 | os.path.realpath(source)) | |
678 | return kwt.match(source) |
|
678 | return kwt.match(source) | |
679 |
|
679 |
@@ -12,7 +12,7 b' import os' | |||||
12 | import copy |
|
12 | import copy | |
13 |
|
13 | |||
14 | from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \ |
|
14 | from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \ | |
15 | node, archival, error, merge, discovery |
|
15 | node, archival, error, merge, discovery, pathutil | |
16 | from mercurial.i18n import _ |
|
16 | from mercurial.i18n import _ | |
17 | from mercurial.node import hex |
|
17 | from mercurial.node import hex | |
18 | from hgext import rebase |
|
18 | from hgext import rebase | |
@@ -469,7 +469,7 b' def overridecopy(orig, ui, repo, pats, o' | |||||
469 | return orig(ui, repo, pats, opts, rename) |
|
469 | return orig(ui, repo, pats, opts, rename) | |
470 |
|
470 | |||
471 | def makestandin(relpath): |
|
471 | def makestandin(relpath): | |
472 |
path = |
|
472 | path = pathutil.canonpath(repo.root, repo.getcwd(), relpath) | |
473 | return os.path.join(repo.wjoin(lfutil.standin(path))) |
|
473 | return os.path.join(repo.wjoin(lfutil.standin(path))) | |
474 |
|
474 | |||
475 | fullpats = scmutil.expandpats(pats) |
|
475 | fullpats = scmutil.expandpats(pats) |
@@ -10,7 +10,7 b' from i18n import _' | |||||
10 | import os, sys, errno, re, tempfile |
|
10 | import os, sys, errno, re, tempfile | |
11 | import util, scmutil, templater, patch, error, templatekw, revlog, copies |
|
11 | import util, scmutil, templater, patch, error, templatekw, revlog, copies | |
12 | import match as matchmod |
|
12 | import match as matchmod | |
13 | import subrepo, context, repair, graphmod, revset, phases, obsolete |
|
13 | import subrepo, context, repair, graphmod, revset, phases, obsolete, pathutil | |
14 | import changelog |
|
14 | import changelog | |
15 | import bookmarks |
|
15 | import bookmarks | |
16 | import lock as lockmod |
|
16 | import lock as lockmod | |
@@ -274,7 +274,7 b' def copy(ui, repo, pats, opts, rename=Fa' | |||||
274 | # relsrc: ossep |
|
274 | # relsrc: ossep | |
275 | # otarget: ossep |
|
275 | # otarget: ossep | |
276 | def copyfile(abssrc, relsrc, otarget, exact): |
|
276 | def copyfile(abssrc, relsrc, otarget, exact): | |
277 |
abstarget = |
|
277 | abstarget = pathutil.canonpath(repo.root, cwd, otarget) | |
278 | if '/' in abstarget: |
|
278 | if '/' in abstarget: | |
279 | # We cannot normalize abstarget itself, this would prevent |
|
279 | # We cannot normalize abstarget itself, this would prevent | |
280 | # case only renames, like a => A. |
|
280 | # case only renames, like a => A. | |
@@ -367,7 +367,7 b' def copy(ui, repo, pats, opts, rename=Fa' | |||||
367 | # return: function that takes hgsep and returns ossep |
|
367 | # return: function that takes hgsep and returns ossep | |
368 | def targetpathfn(pat, dest, srcs): |
|
368 | def targetpathfn(pat, dest, srcs): | |
369 | if os.path.isdir(pat): |
|
369 | if os.path.isdir(pat): | |
370 |
abspfx = |
|
370 | abspfx = pathutil.canonpath(repo.root, cwd, pat) | |
371 | abspfx = util.localpath(abspfx) |
|
371 | abspfx = util.localpath(abspfx) | |
372 | if destdirexists: |
|
372 | if destdirexists: | |
373 | striplen = len(os.path.split(abspfx)[0]) |
|
373 | striplen = len(os.path.split(abspfx)[0]) | |
@@ -393,7 +393,7 b' def copy(ui, repo, pats, opts, rename=Fa' | |||||
393 | res = lambda p: os.path.join(dest, |
|
393 | res = lambda p: os.path.join(dest, | |
394 | os.path.basename(util.localpath(p))) |
|
394 | os.path.basename(util.localpath(p))) | |
395 | else: |
|
395 | else: | |
396 |
abspfx = |
|
396 | abspfx = pathutil.canonpath(repo.root, cwd, pat) | |
397 | if len(abspfx) < len(srcs[0][0]): |
|
397 | if len(abspfx) < len(srcs[0][0]): | |
398 | # A directory. Either the target path contains the last |
|
398 | # A directory. Either the target path contains the last | |
399 | # component of the source path or it does not. |
|
399 | # component of the source path or it does not. | |
@@ -2065,7 +2065,7 b' def revert(ui, repo, ctx, parents, *pats' | |||||
2065 | fc = ctx[f] |
|
2065 | fc = ctx[f] | |
2066 | repo.wwrite(f, fc.data(), fc.flags()) |
|
2066 | repo.wwrite(f, fc.data(), fc.flags()) | |
2067 |
|
2067 | |||
2068 |
audit_path = |
|
2068 | audit_path = pathutil.pathauditor(repo.root) | |
2069 | for f in remove[0]: |
|
2069 | for f in remove[0]: | |
2070 | if repo.dirstate[f] == 'a': |
|
2070 | if repo.dirstate[f] == 'a': | |
2071 | repo.dirstate.drop(f) |
|
2071 | repo.dirstate.drop(f) |
@@ -8,7 +8,7 b' import errno' | |||||
8 |
|
8 | |||
9 | from node import nullid |
|
9 | from node import nullid | |
10 | from i18n import _ |
|
10 | from i18n import _ | |
11 | import scmutil, util, ignore, osutil, parsers, encoding |
|
11 | import scmutil, util, ignore, osutil, parsers, encoding, pathutil | |
12 | import os, stat, errno, gc |
|
12 | import os, stat, errno, gc | |
13 |
|
13 | |||
14 | propertycache = util.propertycache |
|
14 | propertycache = util.propertycache | |
@@ -736,7 +736,7 b' class dirstate(object):' | |||||
736 | # unknown == True means we walked the full directory tree above. |
|
736 | # unknown == True means we walked the full directory tree above. | |
737 | # So if a file is not seen it was either a) not matching matchfn |
|
737 | # So if a file is not seen it was either a) not matching matchfn | |
738 | # b) ignored, c) missing, or d) under a symlink directory. |
|
738 | # b) ignored, c) missing, or d) under a symlink directory. | |
739 |
audit_path = |
|
739 | audit_path = pathutil.pathauditor(self._root) | |
740 |
|
740 | |||
741 | for nf in iter(visit): |
|
741 | for nf in iter(visit): | |
742 | # Report ignored items in the dmap as long as they are not |
|
742 | # Report ignored items in the dmap as long as they are not |
@@ -7,7 +7,7 b'' | |||||
7 | # GNU General Public License version 2 or any later version. |
|
7 | # GNU General Public License version 2 or any later version. | |
8 |
|
8 | |||
9 | import os, copy |
|
9 | import os, copy | |
10 |
from mercurial import match, patch, |
|
10 | from mercurial import match, patch, error, ui, util, pathutil | |
11 | from mercurial.i18n import _ |
|
11 | from mercurial.i18n import _ | |
12 | from mercurial.node import hex, nullid |
|
12 | from mercurial.node import hex, nullid | |
13 | from common import ErrorResponse |
|
13 | from common import ErrorResponse | |
@@ -196,7 +196,7 b' def showbookmark(repo, tmpl, t1, node=nu' | |||||
196 |
|
196 | |||
197 | def cleanpath(repo, path): |
|
197 | def cleanpath(repo, path): | |
198 | path = path.lstrip('/') |
|
198 | path = path.lstrip('/') | |
199 |
return |
|
199 | return pathutil.canonpath(repo.root, '', path) | |
200 |
|
200 | |||
201 | def changeidctx (repo, changeid): |
|
201 | def changeidctx (repo, changeid): | |
202 | try: |
|
202 | try: |
@@ -15,7 +15,7 b' import merge as mergemod' | |||||
15 | import tags as tagsmod |
|
15 | import tags as tagsmod | |
16 | from lock import release |
|
16 | from lock import release | |
17 | import weakref, errno, os, time, inspect |
|
17 | import weakref, errno, os, time, inspect | |
18 | import branchmap |
|
18 | import branchmap, pathutil | |
19 | propertycache = util.propertycache |
|
19 | propertycache = util.propertycache | |
20 | filecache = scmutil.filecache |
|
20 | filecache = scmutil.filecache | |
21 |
|
21 | |||
@@ -166,7 +166,7 b' class localrepository(object):' | |||||
166 | self.root = self.wvfs.base |
|
166 | self.root = self.wvfs.base | |
167 | self.path = self.wvfs.join(".hg") |
|
167 | self.path = self.wvfs.join(".hg") | |
168 | self.origroot = path |
|
168 | self.origroot = path | |
169 |
self.auditor = |
|
169 | self.auditor = pathutil.pathauditor(self.root, self._checknested) | |
170 | self.vfs = scmutil.vfs(self.path) |
|
170 | self.vfs = scmutil.vfs(self.path) | |
171 | self.opener = self.vfs |
|
171 | self.opener = self.vfs | |
172 | self.baseui = baseui |
|
172 | self.baseui = baseui |
@@ -6,7 +6,7 b'' | |||||
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | import re |
|
8 | import re | |
9 |
import |
|
9 | import util, fileset, pathutil | |
10 | from i18n import _ |
|
10 | from i18n import _ | |
11 |
|
11 | |||
12 | def _rematcher(pat): |
|
12 | def _rematcher(pat): | |
@@ -317,7 +317,7 b' def _normalize(names, default, root, cwd' | |||||
317 | pats = [] |
|
317 | pats = [] | |
318 | for kind, name in [_patsplit(p, default) for p in names]: |
|
318 | for kind, name in [_patsplit(p, default) for p in names]: | |
319 | if kind in ('glob', 'relpath'): |
|
319 | if kind in ('glob', 'relpath'): | |
320 |
name = |
|
320 | name = pathutil.canonpath(root, cwd, name, auditor) | |
321 | elif kind in ('relglob', 'path'): |
|
321 | elif kind in ('relglob', 'path'): | |
322 | name = util.normpath(name) |
|
322 | name = util.normpath(name) | |
323 | elif kind in ('listfile', 'listfile0'): |
|
323 | elif kind in ('listfile', 'listfile0'): |
@@ -8,8 +8,9 b'' | |||||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | from mercurial.node import nullrev |
|
9 | from mercurial.node import nullrev | |
10 | import util, error, osutil, revset, similar, encoding, phases, parsers |
|
10 | import util, error, osutil, revset, similar, encoding, phases, parsers | |
|
11 | import pathutil | |||
11 | import match as matchmod |
|
12 | import match as matchmod | |
12 |
import os, errno, re, |
|
13 | import os, errno, re, glob | |
13 |
|
14 | |||
14 | if os.name == 'nt': |
|
15 | if os.name == 'nt': | |
15 | import scmwindows as scmplatform |
|
16 | import scmwindows as scmplatform | |
@@ -108,100 +109,6 b' class casecollisionauditor(object):' | |||||
108 | self._loweredfiles.add(fl) |
|
109 | self._loweredfiles.add(fl) | |
109 | self._newfiles.add(f) |
|
110 | self._newfiles.add(f) | |
110 |
|
111 | |||
111 | class pathauditor(object): |
|
|||
112 | '''ensure that a filesystem path contains no banned components. |
|
|||
113 | the following properties of a path are checked: |
|
|||
114 |
|
||||
115 | - ends with a directory separator |
|
|||
116 | - under top-level .hg |
|
|||
117 | - starts at the root of a windows drive |
|
|||
118 | - contains ".." |
|
|||
119 | - traverses a symlink (e.g. a/symlink_here/b) |
|
|||
120 | - inside a nested repository (a callback can be used to approve |
|
|||
121 | some nested repositories, e.g., subrepositories) |
|
|||
122 | ''' |
|
|||
123 |
|
||||
124 | def __init__(self, root, callback=None): |
|
|||
125 | self.audited = set() |
|
|||
126 | self.auditeddir = set() |
|
|||
127 | self.root = root |
|
|||
128 | self.callback = callback |
|
|||
129 | if os.path.lexists(root) and not util.checkcase(root): |
|
|||
130 | self.normcase = util.normcase |
|
|||
131 | else: |
|
|||
132 | self.normcase = lambda x: x |
|
|||
133 |
|
||||
134 | def __call__(self, path): |
|
|||
135 | '''Check the relative path. |
|
|||
136 | path may contain a pattern (e.g. foodir/**.txt)''' |
|
|||
137 |
|
||||
138 | path = util.localpath(path) |
|
|||
139 | normpath = self.normcase(path) |
|
|||
140 | if normpath in self.audited: |
|
|||
141 | return |
|
|||
142 | # AIX ignores "/" at end of path, others raise EISDIR. |
|
|||
143 | if util.endswithsep(path): |
|
|||
144 | raise util.Abort(_("path ends in directory separator: %s") % path) |
|
|||
145 | parts = util.splitpath(path) |
|
|||
146 | if (os.path.splitdrive(path)[0] |
|
|||
147 | or parts[0].lower() in ('.hg', '.hg.', '') |
|
|||
148 | or os.pardir in parts): |
|
|||
149 | raise util.Abort(_("path contains illegal component: %s") % path) |
|
|||
150 | if '.hg' in path.lower(): |
|
|||
151 | lparts = [p.lower() for p in parts] |
|
|||
152 | for p in '.hg', '.hg.': |
|
|||
153 | if p in lparts[1:]: |
|
|||
154 | pos = lparts.index(p) |
|
|||
155 | base = os.path.join(*parts[:pos]) |
|
|||
156 | raise util.Abort(_("path '%s' is inside nested repo %r") |
|
|||
157 | % (path, base)) |
|
|||
158 |
|
||||
159 | normparts = util.splitpath(normpath) |
|
|||
160 | assert len(parts) == len(normparts) |
|
|||
161 |
|
||||
162 | parts.pop() |
|
|||
163 | normparts.pop() |
|
|||
164 | prefixes = [] |
|
|||
165 | while parts: |
|
|||
166 | prefix = os.sep.join(parts) |
|
|||
167 | normprefix = os.sep.join(normparts) |
|
|||
168 | if normprefix in self.auditeddir: |
|
|||
169 | break |
|
|||
170 | curpath = os.path.join(self.root, prefix) |
|
|||
171 | try: |
|
|||
172 | st = os.lstat(curpath) |
|
|||
173 | except OSError, err: |
|
|||
174 | # EINVAL can be raised as invalid path syntax under win32. |
|
|||
175 | # They must be ignored for patterns can be checked too. |
|
|||
176 | if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): |
|
|||
177 | raise |
|
|||
178 | else: |
|
|||
179 | if stat.S_ISLNK(st.st_mode): |
|
|||
180 | raise util.Abort( |
|
|||
181 | _('path %r traverses symbolic link %r') |
|
|||
182 | % (path, prefix)) |
|
|||
183 | elif (stat.S_ISDIR(st.st_mode) and |
|
|||
184 | os.path.isdir(os.path.join(curpath, '.hg'))): |
|
|||
185 | if not self.callback or not self.callback(curpath): |
|
|||
186 | raise util.Abort(_("path '%s' is inside nested " |
|
|||
187 | "repo %r") |
|
|||
188 | % (path, prefix)) |
|
|||
189 | prefixes.append(normprefix) |
|
|||
190 | parts.pop() |
|
|||
191 | normparts.pop() |
|
|||
192 |
|
||||
193 | self.audited.add(normpath) |
|
|||
194 | # only add prefixes to the cache after checking everything: we don't |
|
|||
195 | # want to add "foo/bar/baz" before checking if there's a "foo/.hg" |
|
|||
196 | self.auditeddir.update(prefixes) |
|
|||
197 |
|
||||
198 | def check(self, path): |
|
|||
199 | try: |
|
|||
200 | self(path) |
|
|||
201 | return True |
|
|||
202 | except (OSError, util.Abort): |
|
|||
203 | return False |
|
|||
204 |
|
||||
205 | class abstractvfs(object): |
|
112 | class abstractvfs(object): | |
206 | """Abstract base class; cannot be instantiated""" |
|
113 | """Abstract base class; cannot be instantiated""" | |
207 |
|
114 | |||
@@ -310,7 +217,7 b' class vfs(abstractvfs):' | |||||
310 | def _setmustaudit(self, onoff): |
|
217 | def _setmustaudit(self, onoff): | |
311 | self._audit = onoff |
|
218 | self._audit = onoff | |
312 | if onoff: |
|
219 | if onoff: | |
313 | self.audit = pathauditor(self.base) |
|
220 | self.audit = pathutil.pathauditor(self.base) | |
314 | else: |
|
221 | else: | |
315 | self.audit = util.always |
|
222 | self.audit = util.always | |
316 |
|
223 | |||
@@ -445,52 +352,6 b' class readonlyvfs(abstractvfs, auditvfs)' | |||||
445 | return self.vfs(path, mode, *args, **kw) |
|
352 | return self.vfs(path, mode, *args, **kw) | |
446 |
|
353 | |||
447 |
|
354 | |||
448 | def canonpath(root, cwd, myname, auditor=None): |
|
|||
449 | '''return the canonical path of myname, given cwd and root''' |
|
|||
450 | if util.endswithsep(root): |
|
|||
451 | rootsep = root |
|
|||
452 | else: |
|
|||
453 | rootsep = root + os.sep |
|
|||
454 | name = myname |
|
|||
455 | if not os.path.isabs(name): |
|
|||
456 | name = os.path.join(root, cwd, name) |
|
|||
457 | name = os.path.normpath(name) |
|
|||
458 | if auditor is None: |
|
|||
459 | auditor = pathauditor(root) |
|
|||
460 | if name != rootsep and name.startswith(rootsep): |
|
|||
461 | name = name[len(rootsep):] |
|
|||
462 | auditor(name) |
|
|||
463 | return util.pconvert(name) |
|
|||
464 | elif name == root: |
|
|||
465 | return '' |
|
|||
466 | else: |
|
|||
467 | # Determine whether `name' is in the hierarchy at or beneath `root', |
|
|||
468 | # by iterating name=dirname(name) until that causes no change (can't |
|
|||
469 | # check name == '/', because that doesn't work on windows). The list |
|
|||
470 | # `rel' holds the reversed list of components making up the relative |
|
|||
471 | # file name we want. |
|
|||
472 | rel = [] |
|
|||
473 | while True: |
|
|||
474 | try: |
|
|||
475 | s = util.samefile(name, root) |
|
|||
476 | except OSError: |
|
|||
477 | s = False |
|
|||
478 | if s: |
|
|||
479 | if not rel: |
|
|||
480 | # name was actually the same as root (maybe a symlink) |
|
|||
481 | return '' |
|
|||
482 | rel.reverse() |
|
|||
483 | name = os.path.join(*rel) |
|
|||
484 | auditor(name) |
|
|||
485 | return util.pconvert(name) |
|
|||
486 | dirname, basename = util.split(name) |
|
|||
487 | rel.append(basename) |
|
|||
488 | if dirname == name: |
|
|||
489 | break |
|
|||
490 | name = dirname |
|
|||
491 |
|
||||
492 | raise util.Abort(_("%s not under root '%s'") % (myname, root)) |
|
|||
493 |
|
||||
494 | def walkrepos(path, followsym=False, seen_dirs=None, recurse=False): |
|
355 | def walkrepos(path, followsym=False, seen_dirs=None, recurse=False): | |
495 | '''yield every hg repository under path, always recursively. |
|
356 | '''yield every hg repository under path, always recursively. | |
496 | The recurse flag will only control recursion into repo working dirs''' |
|
357 | The recurse flag will only control recursion into repo working dirs''' | |
@@ -768,7 +629,7 b' def _interestingfiles(repo, matcher):' | |||||
768 | This is different from dirstate.status because it doesn't care about |
|
629 | This is different from dirstate.status because it doesn't care about | |
769 | whether files are modified or clean.''' |
|
630 | whether files are modified or clean.''' | |
770 | added, unknown, deleted, removed = [], [], [], [] |
|
631 | added, unknown, deleted, removed = [], [], [], [] | |
771 | audit_path = pathauditor(repo.root) |
|
632 | audit_path = pathutil.pathauditor(repo.root) | |
772 |
|
633 | |||
773 | ctx = repo[None] |
|
634 | ctx = repo[None] | |
774 | dirstate = repo.dirstate |
|
635 | dirstate = repo.dirstate |
@@ -9,7 +9,8 b' import errno, os, re, shutil, posixpath,' | |||||
9 | import xml.dom.minidom |
|
9 | import xml.dom.minidom | |
10 | import stat, subprocess, tarfile |
|
10 | import stat, subprocess, tarfile | |
11 | from i18n import _ |
|
11 | from i18n import _ | |
12 |
import config |
|
12 | import config, util, node, error, cmdutil, bookmarks, match as matchmod | |
|
13 | import pathutil | |||
13 | hg = None |
|
14 | hg = None | |
14 | propertycache = util.propertycache |
|
15 | propertycache = util.propertycache | |
15 |
|
16 | |||
@@ -332,7 +333,7 b' def subrepo(ctx, path):' | |||||
332 | import hg as h |
|
333 | import hg as h | |
333 | hg = h |
|
334 | hg = h | |
334 |
|
335 | |||
335 |
|
|
336 | pathutil.pathauditor(ctx._repo.root)(path) | |
336 | state = ctx.substate[path] |
|
337 | state = ctx.substate[path] | |
337 | if state[2] not in types: |
|
338 | if state[2] not in types: | |
338 | raise util.Abort(_('unknown subrepo type %s') % state[2]) |
|
339 | raise util.Abort(_('unknown subrepo type %s') % state[2]) |
General Comments 0
You need to be logged in to leave comments.
Login now