##// END OF EJS Templates
scmutil: rename local function _add_dir_if_not_there
Adrian Buehlmann -
r14227:94985b5a default
parent child Browse files
Show More
@@ -1,465 +1,465 b''
1 # scmutil.py - Mercurial core utility functions
1 # scmutil.py - Mercurial core utility functions
2 #
2 #
3 # Copyright Matt Mackall <mpm@selenic.com>
3 # Copyright Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
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 from i18n import _
8 from i18n import _
9 import util, error, osutil
9 import util, error, osutil
10 import os, errno, stat, sys
10 import os, errno, stat, sys
11
11
12 def checkfilename(f):
12 def checkfilename(f):
13 '''Check that the filename f is an acceptable filename for a tracked file'''
13 '''Check that the filename f is an acceptable filename for a tracked file'''
14 if '\r' in f or '\n' in f:
14 if '\r' in f or '\n' in f:
15 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames: %r") % f)
15 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames: %r") % f)
16
16
17 def checkportable(ui, f):
17 def checkportable(ui, f):
18 '''Check if filename f is portable and warn or abort depending on config'''
18 '''Check if filename f is portable and warn or abort depending on config'''
19 checkfilename(f)
19 checkfilename(f)
20 abort, warn = checkportabilityalert(ui)
20 abort, warn = checkportabilityalert(ui)
21 if abort or warn:
21 if abort or warn:
22 msg = util.checkwinfilename(f)
22 msg = util.checkwinfilename(f)
23 if msg:
23 if msg:
24 msg = "%s: %r" % (msg, f)
24 msg = "%s: %r" % (msg, f)
25 if abort:
25 if abort:
26 raise util.Abort(msg)
26 raise util.Abort(msg)
27 ui.warn(_("warning: %s\n") % msg)
27 ui.warn(_("warning: %s\n") % msg)
28
28
29 def checkportabilityalert(ui):
29 def checkportabilityalert(ui):
30 '''check if the user's config requests nothing, a warning, or abort for
30 '''check if the user's config requests nothing, a warning, or abort for
31 non-portable filenames'''
31 non-portable filenames'''
32 val = ui.config('ui', 'portablefilenames', 'warn')
32 val = ui.config('ui', 'portablefilenames', 'warn')
33 lval = val.lower()
33 lval = val.lower()
34 bval = util.parsebool(val)
34 bval = util.parsebool(val)
35 abort = os.name == 'nt' or lval == 'abort'
35 abort = os.name == 'nt' or lval == 'abort'
36 warn = bval or lval == 'warn'
36 warn = bval or lval == 'warn'
37 if bval is None and not (warn or abort or lval == 'ignore'):
37 if bval is None and not (warn or abort or lval == 'ignore'):
38 raise error.ConfigError(
38 raise error.ConfigError(
39 _("ui.portablefilenames value is invalid ('%s')") % val)
39 _("ui.portablefilenames value is invalid ('%s')") % val)
40 return abort, warn
40 return abort, warn
41
41
42 class casecollisionauditor(object):
42 class casecollisionauditor(object):
43 def __init__(self, ui, abort, existingiter):
43 def __init__(self, ui, abort, existingiter):
44 self._ui = ui
44 self._ui = ui
45 self._abort = abort
45 self._abort = abort
46 self._map = {}
46 self._map = {}
47 for f in existingiter:
47 for f in existingiter:
48 self._map[f.lower()] = f
48 self._map[f.lower()] = f
49
49
50 def __call__(self, f):
50 def __call__(self, f):
51 fl = f.lower()
51 fl = f.lower()
52 map = self._map
52 map = self._map
53 if fl in map and map[fl] != f:
53 if fl in map and map[fl] != f:
54 msg = _('possible case-folding collision for %s') % f
54 msg = _('possible case-folding collision for %s') % f
55 if self._abort:
55 if self._abort:
56 raise util.Abort(msg)
56 raise util.Abort(msg)
57 self._ui.warn(_("warning: %s\n") % msg)
57 self._ui.warn(_("warning: %s\n") % msg)
58 map[fl] = f
58 map[fl] = f
59
59
60 class pathauditor(object):
60 class pathauditor(object):
61 '''ensure that a filesystem path contains no banned components.
61 '''ensure that a filesystem path contains no banned components.
62 the following properties of a path are checked:
62 the following properties of a path are checked:
63
63
64 - ends with a directory separator
64 - ends with a directory separator
65 - under top-level .hg
65 - under top-level .hg
66 - starts at the root of a windows drive
66 - starts at the root of a windows drive
67 - contains ".."
67 - contains ".."
68 - traverses a symlink (e.g. a/symlink_here/b)
68 - traverses a symlink (e.g. a/symlink_here/b)
69 - inside a nested repository (a callback can be used to approve
69 - inside a nested repository (a callback can be used to approve
70 some nested repositories, e.g., subrepositories)
70 some nested repositories, e.g., subrepositories)
71 '''
71 '''
72
72
73 def __init__(self, root, callback=None):
73 def __init__(self, root, callback=None):
74 self.audited = set()
74 self.audited = set()
75 self.auditeddir = set()
75 self.auditeddir = set()
76 self.root = root
76 self.root = root
77 self.callback = callback
77 self.callback = callback
78
78
79 def __call__(self, path):
79 def __call__(self, path):
80 '''Check the relative path.
80 '''Check the relative path.
81 path may contain a pattern (e.g. foodir/**.txt)'''
81 path may contain a pattern (e.g. foodir/**.txt)'''
82
82
83 if path in self.audited:
83 if path in self.audited:
84 return
84 return
85 # AIX ignores "/" at end of path, others raise EISDIR.
85 # AIX ignores "/" at end of path, others raise EISDIR.
86 if util.endswithsep(path):
86 if util.endswithsep(path):
87 raise util.Abort(_("path ends in directory separator: %s") % path)
87 raise util.Abort(_("path ends in directory separator: %s") % path)
88 normpath = os.path.normcase(path)
88 normpath = os.path.normcase(path)
89 parts = util.splitpath(normpath)
89 parts = util.splitpath(normpath)
90 if (os.path.splitdrive(path)[0]
90 if (os.path.splitdrive(path)[0]
91 or parts[0].lower() in ('.hg', '.hg.', '')
91 or parts[0].lower() in ('.hg', '.hg.', '')
92 or os.pardir in parts):
92 or os.pardir in parts):
93 raise util.Abort(_("path contains illegal component: %s") % path)
93 raise util.Abort(_("path contains illegal component: %s") % path)
94 if '.hg' in path.lower():
94 if '.hg' in path.lower():
95 lparts = [p.lower() for p in parts]
95 lparts = [p.lower() for p in parts]
96 for p in '.hg', '.hg.':
96 for p in '.hg', '.hg.':
97 if p in lparts[1:]:
97 if p in lparts[1:]:
98 pos = lparts.index(p)
98 pos = lparts.index(p)
99 base = os.path.join(*parts[:pos])
99 base = os.path.join(*parts[:pos])
100 raise util.Abort(_('path %r is inside nested repo %r')
100 raise util.Abort(_('path %r is inside nested repo %r')
101 % (path, base))
101 % (path, base))
102
102
103 parts.pop()
103 parts.pop()
104 prefixes = []
104 prefixes = []
105 while parts:
105 while parts:
106 prefix = os.sep.join(parts)
106 prefix = os.sep.join(parts)
107 if prefix in self.auditeddir:
107 if prefix in self.auditeddir:
108 break
108 break
109 curpath = os.path.join(self.root, prefix)
109 curpath = os.path.join(self.root, prefix)
110 try:
110 try:
111 st = os.lstat(curpath)
111 st = os.lstat(curpath)
112 except OSError, err:
112 except OSError, err:
113 # EINVAL can be raised as invalid path syntax under win32.
113 # EINVAL can be raised as invalid path syntax under win32.
114 # They must be ignored for patterns can be checked too.
114 # They must be ignored for patterns can be checked too.
115 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
115 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
116 raise
116 raise
117 else:
117 else:
118 if stat.S_ISLNK(st.st_mode):
118 if stat.S_ISLNK(st.st_mode):
119 raise util.Abort(
119 raise util.Abort(
120 _('path %r traverses symbolic link %r')
120 _('path %r traverses symbolic link %r')
121 % (path, prefix))
121 % (path, prefix))
122 elif (stat.S_ISDIR(st.st_mode) and
122 elif (stat.S_ISDIR(st.st_mode) and
123 os.path.isdir(os.path.join(curpath, '.hg'))):
123 os.path.isdir(os.path.join(curpath, '.hg'))):
124 if not self.callback or not self.callback(curpath):
124 if not self.callback or not self.callback(curpath):
125 raise util.Abort(_('path %r is inside nested repo %r') %
125 raise util.Abort(_('path %r is inside nested repo %r') %
126 (path, prefix))
126 (path, prefix))
127 prefixes.append(prefix)
127 prefixes.append(prefix)
128 parts.pop()
128 parts.pop()
129
129
130 self.audited.add(path)
130 self.audited.add(path)
131 # only add prefixes to the cache after checking everything: we don't
131 # only add prefixes to the cache after checking everything: we don't
132 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
132 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
133 self.auditeddir.update(prefixes)
133 self.auditeddir.update(prefixes)
134
134
135 class abstractopener(object):
135 class abstractopener(object):
136 """Abstract base class; cannot be instantiated"""
136 """Abstract base class; cannot be instantiated"""
137
137
138 def __init__(self, *args, **kwargs):
138 def __init__(self, *args, **kwargs):
139 '''Prevent instantiation; don't call this from subclasses.'''
139 '''Prevent instantiation; don't call this from subclasses.'''
140 raise NotImplementedError('attempted instantiating ' + str(type(self)))
140 raise NotImplementedError('attempted instantiating ' + str(type(self)))
141
141
142 def read(self, path):
142 def read(self, path):
143 fp = self(path, 'rb')
143 fp = self(path, 'rb')
144 try:
144 try:
145 return fp.read()
145 return fp.read()
146 finally:
146 finally:
147 fp.close()
147 fp.close()
148
148
149 def write(self, path, data):
149 def write(self, path, data):
150 fp = self(path, 'wb')
150 fp = self(path, 'wb')
151 try:
151 try:
152 return fp.write(data)
152 return fp.write(data)
153 finally:
153 finally:
154 fp.close()
154 fp.close()
155
155
156 def append(self, path, data):
156 def append(self, path, data):
157 fp = self(path, 'ab')
157 fp = self(path, 'ab')
158 try:
158 try:
159 return fp.write(data)
159 return fp.write(data)
160 finally:
160 finally:
161 fp.close()
161 fp.close()
162
162
163 class opener(abstractopener):
163 class opener(abstractopener):
164 '''Open files relative to a base directory
164 '''Open files relative to a base directory
165
165
166 This class is used to hide the details of COW semantics and
166 This class is used to hide the details of COW semantics and
167 remote file access from higher level code.
167 remote file access from higher level code.
168 '''
168 '''
169 def __init__(self, base, audit=True):
169 def __init__(self, base, audit=True):
170 self.base = base
170 self.base = base
171 if audit:
171 if audit:
172 self.auditor = pathauditor(base)
172 self.auditor = pathauditor(base)
173 else:
173 else:
174 self.auditor = util.always
174 self.auditor = util.always
175 self.createmode = None
175 self.createmode = None
176 self._trustnlink = None
176 self._trustnlink = None
177
177
178 @util.propertycache
178 @util.propertycache
179 def _can_symlink(self):
179 def _can_symlink(self):
180 return util.checklink(self.base)
180 return util.checklink(self.base)
181
181
182 def _fixfilemode(self, name):
182 def _fixfilemode(self, name):
183 if self.createmode is None:
183 if self.createmode is None:
184 return
184 return
185 os.chmod(name, self.createmode & 0666)
185 os.chmod(name, self.createmode & 0666)
186
186
187 def __call__(self, path, mode="r", text=False, atomictemp=False):
187 def __call__(self, path, mode="r", text=False, atomictemp=False):
188 r = util.checkosfilename(path)
188 r = util.checkosfilename(path)
189 if r:
189 if r:
190 raise util.Abort("%s: %r" % (r, path))
190 raise util.Abort("%s: %r" % (r, path))
191 self.auditor(path)
191 self.auditor(path)
192 f = os.path.join(self.base, path)
192 f = os.path.join(self.base, path)
193
193
194 if not text and "b" not in mode:
194 if not text and "b" not in mode:
195 mode += "b" # for that other OS
195 mode += "b" # for that other OS
196
196
197 nlink = -1
197 nlink = -1
198 dirname, basename = os.path.split(f)
198 dirname, basename = os.path.split(f)
199 # If basename is empty, then the path is malformed because it points
199 # If basename is empty, then the path is malformed because it points
200 # to a directory. Let the posixfile() call below raise IOError.
200 # to a directory. Let the posixfile() call below raise IOError.
201 if basename and mode not in ('r', 'rb'):
201 if basename and mode not in ('r', 'rb'):
202 if atomictemp:
202 if atomictemp:
203 if not os.path.isdir(dirname):
203 if not os.path.isdir(dirname):
204 util.makedirs(dirname, self.createmode)
204 util.makedirs(dirname, self.createmode)
205 return util.atomictempfile(f, mode, self.createmode)
205 return util.atomictempfile(f, mode, self.createmode)
206 try:
206 try:
207 if 'w' in mode:
207 if 'w' in mode:
208 util.unlink(f)
208 util.unlink(f)
209 nlink = 0
209 nlink = 0
210 else:
210 else:
211 # nlinks() may behave differently for files on Windows
211 # nlinks() may behave differently for files on Windows
212 # shares if the file is open.
212 # shares if the file is open.
213 fd = util.posixfile(f)
213 fd = util.posixfile(f)
214 nlink = util.nlinks(f)
214 nlink = util.nlinks(f)
215 if nlink < 1:
215 if nlink < 1:
216 nlink = 2 # force mktempcopy (issue1922)
216 nlink = 2 # force mktempcopy (issue1922)
217 fd.close()
217 fd.close()
218 except (OSError, IOError), e:
218 except (OSError, IOError), e:
219 if e.errno != errno.ENOENT:
219 if e.errno != errno.ENOENT:
220 raise
220 raise
221 nlink = 0
221 nlink = 0
222 if not os.path.isdir(dirname):
222 if not os.path.isdir(dirname):
223 util.makedirs(dirname, self.createmode)
223 util.makedirs(dirname, self.createmode)
224 if nlink > 0:
224 if nlink > 0:
225 if self._trustnlink is None:
225 if self._trustnlink is None:
226 self._trustnlink = nlink > 1 or util.checknlink(f)
226 self._trustnlink = nlink > 1 or util.checknlink(f)
227 if nlink > 1 or not self._trustnlink:
227 if nlink > 1 or not self._trustnlink:
228 util.rename(util.mktempcopy(f), f)
228 util.rename(util.mktempcopy(f), f)
229 fp = util.posixfile(f, mode)
229 fp = util.posixfile(f, mode)
230 if nlink == 0:
230 if nlink == 0:
231 self._fixfilemode(f)
231 self._fixfilemode(f)
232 return fp
232 return fp
233
233
234 def symlink(self, src, dst):
234 def symlink(self, src, dst):
235 self.auditor(dst)
235 self.auditor(dst)
236 linkname = os.path.join(self.base, dst)
236 linkname = os.path.join(self.base, dst)
237 try:
237 try:
238 os.unlink(linkname)
238 os.unlink(linkname)
239 except OSError:
239 except OSError:
240 pass
240 pass
241
241
242 dirname = os.path.dirname(linkname)
242 dirname = os.path.dirname(linkname)
243 if not os.path.exists(dirname):
243 if not os.path.exists(dirname):
244 util.makedirs(dirname, self.createmode)
244 util.makedirs(dirname, self.createmode)
245
245
246 if self._can_symlink:
246 if self._can_symlink:
247 try:
247 try:
248 os.symlink(src, linkname)
248 os.symlink(src, linkname)
249 except OSError, err:
249 except OSError, err:
250 raise OSError(err.errno, _('could not symlink to %r: %s') %
250 raise OSError(err.errno, _('could not symlink to %r: %s') %
251 (src, err.strerror), linkname)
251 (src, err.strerror), linkname)
252 else:
252 else:
253 f = self(dst, "w")
253 f = self(dst, "w")
254 f.write(src)
254 f.write(src)
255 f.close()
255 f.close()
256 self._fixfilemode(dst)
256 self._fixfilemode(dst)
257
257
258 class filteropener(abstractopener):
258 class filteropener(abstractopener):
259 '''Wrapper opener for filtering filenames with a function.'''
259 '''Wrapper opener for filtering filenames with a function.'''
260
260
261 def __init__(self, opener, filter):
261 def __init__(self, opener, filter):
262 self._filter = filter
262 self._filter = filter
263 self._orig = opener
263 self._orig = opener
264
264
265 def __call__(self, path, *args, **kwargs):
265 def __call__(self, path, *args, **kwargs):
266 return self._orig(self._filter(path), *args, **kwargs)
266 return self._orig(self._filter(path), *args, **kwargs)
267
267
268 def canonpath(root, cwd, myname, auditor=None):
268 def canonpath(root, cwd, myname, auditor=None):
269 '''return the canonical path of myname, given cwd and root'''
269 '''return the canonical path of myname, given cwd and root'''
270 if util.endswithsep(root):
270 if util.endswithsep(root):
271 rootsep = root
271 rootsep = root
272 else:
272 else:
273 rootsep = root + os.sep
273 rootsep = root + os.sep
274 name = myname
274 name = myname
275 if not os.path.isabs(name):
275 if not os.path.isabs(name):
276 name = os.path.join(root, cwd, name)
276 name = os.path.join(root, cwd, name)
277 name = os.path.normpath(name)
277 name = os.path.normpath(name)
278 if auditor is None:
278 if auditor is None:
279 auditor = pathauditor(root)
279 auditor = pathauditor(root)
280 if name != rootsep and name.startswith(rootsep):
280 if name != rootsep and name.startswith(rootsep):
281 name = name[len(rootsep):]
281 name = name[len(rootsep):]
282 auditor(name)
282 auditor(name)
283 return util.pconvert(name)
283 return util.pconvert(name)
284 elif name == root:
284 elif name == root:
285 return ''
285 return ''
286 else:
286 else:
287 # Determine whether `name' is in the hierarchy at or beneath `root',
287 # Determine whether `name' is in the hierarchy at or beneath `root',
288 # by iterating name=dirname(name) until that causes no change (can't
288 # by iterating name=dirname(name) until that causes no change (can't
289 # check name == '/', because that doesn't work on windows). For each
289 # check name == '/', because that doesn't work on windows). For each
290 # `name', compare dev/inode numbers. If they match, the list `rel'
290 # `name', compare dev/inode numbers. If they match, the list `rel'
291 # holds the reversed list of components making up the relative file
291 # holds the reversed list of components making up the relative file
292 # name we want.
292 # name we want.
293 root_st = os.stat(root)
293 root_st = os.stat(root)
294 rel = []
294 rel = []
295 while True:
295 while True:
296 try:
296 try:
297 name_st = os.stat(name)
297 name_st = os.stat(name)
298 except OSError:
298 except OSError:
299 break
299 break
300 if util.samestat(name_st, root_st):
300 if util.samestat(name_st, root_st):
301 if not rel:
301 if not rel:
302 # name was actually the same as root (maybe a symlink)
302 # name was actually the same as root (maybe a symlink)
303 return ''
303 return ''
304 rel.reverse()
304 rel.reverse()
305 name = os.path.join(*rel)
305 name = os.path.join(*rel)
306 auditor(name)
306 auditor(name)
307 return util.pconvert(name)
307 return util.pconvert(name)
308 dirname, basename = os.path.split(name)
308 dirname, basename = os.path.split(name)
309 rel.append(basename)
309 rel.append(basename)
310 if dirname == name:
310 if dirname == name:
311 break
311 break
312 name = dirname
312 name = dirname
313
313
314 raise util.Abort('%s not under root' % myname)
314 raise util.Abort('%s not under root' % myname)
315
315
316 def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
316 def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
317 '''yield every hg repository under path, recursively.'''
317 '''yield every hg repository under path, recursively.'''
318 def errhandler(err):
318 def errhandler(err):
319 if err.filename == path:
319 if err.filename == path:
320 raise err
320 raise err
321 if followsym and hasattr(os.path, 'samestat'):
321 if followsym and hasattr(os.path, 'samestat'):
322 def _add_dir_if_not_there(dirlst, dirname):
322 def adddir(dirlst, dirname):
323 match = False
323 match = False
324 samestat = os.path.samestat
324 samestat = os.path.samestat
325 dirstat = os.stat(dirname)
325 dirstat = os.stat(dirname)
326 for lstdirstat in dirlst:
326 for lstdirstat in dirlst:
327 if samestat(dirstat, lstdirstat):
327 if samestat(dirstat, lstdirstat):
328 match = True
328 match = True
329 break
329 break
330 if not match:
330 if not match:
331 dirlst.append(dirstat)
331 dirlst.append(dirstat)
332 return not match
332 return not match
333 else:
333 else:
334 followsym = False
334 followsym = False
335
335
336 if (seen_dirs is None) and followsym:
336 if (seen_dirs is None) and followsym:
337 seen_dirs = []
337 seen_dirs = []
338 _add_dir_if_not_there(seen_dirs, path)
338 adddir(seen_dirs, path)
339 for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
339 for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
340 dirs.sort()
340 dirs.sort()
341 if '.hg' in dirs:
341 if '.hg' in dirs:
342 yield root # found a repository
342 yield root # found a repository
343 qroot = os.path.join(root, '.hg', 'patches')
343 qroot = os.path.join(root, '.hg', 'patches')
344 if os.path.isdir(os.path.join(qroot, '.hg')):
344 if os.path.isdir(os.path.join(qroot, '.hg')):
345 yield qroot # we have a patch queue repo here
345 yield qroot # we have a patch queue repo here
346 if recurse:
346 if recurse:
347 # avoid recursing inside the .hg directory
347 # avoid recursing inside the .hg directory
348 dirs.remove('.hg')
348 dirs.remove('.hg')
349 else:
349 else:
350 dirs[:] = [] # don't descend further
350 dirs[:] = [] # don't descend further
351 elif followsym:
351 elif followsym:
352 newdirs = []
352 newdirs = []
353 for d in dirs:
353 for d in dirs:
354 fname = os.path.join(root, d)
354 fname = os.path.join(root, d)
355 if _add_dir_if_not_there(seen_dirs, fname):
355 if adddir(seen_dirs, fname):
356 if os.path.islink(fname):
356 if os.path.islink(fname):
357 for hgname in walkrepos(fname, True, seen_dirs):
357 for hgname in walkrepos(fname, True, seen_dirs):
358 yield hgname
358 yield hgname
359 else:
359 else:
360 newdirs.append(d)
360 newdirs.append(d)
361 dirs[:] = newdirs
361 dirs[:] = newdirs
362
362
363 def osrcpath():
363 def osrcpath():
364 '''return default os-specific hgrc search path'''
364 '''return default os-specific hgrc search path'''
365 path = systemrcpath()
365 path = systemrcpath()
366 path.extend(userrcpath())
366 path.extend(userrcpath())
367 path = [os.path.normpath(f) for f in path]
367 path = [os.path.normpath(f) for f in path]
368 return path
368 return path
369
369
370 _rcpath = None
370 _rcpath = None
371
371
372 def rcpath():
372 def rcpath():
373 '''return hgrc search path. if env var HGRCPATH is set, use it.
373 '''return hgrc search path. if env var HGRCPATH is set, use it.
374 for each item in path, if directory, use files ending in .rc,
374 for each item in path, if directory, use files ending in .rc,
375 else use item.
375 else use item.
376 make HGRCPATH empty to only look in .hg/hgrc of current repo.
376 make HGRCPATH empty to only look in .hg/hgrc of current repo.
377 if no HGRCPATH, use default os-specific path.'''
377 if no HGRCPATH, use default os-specific path.'''
378 global _rcpath
378 global _rcpath
379 if _rcpath is None:
379 if _rcpath is None:
380 if 'HGRCPATH' in os.environ:
380 if 'HGRCPATH' in os.environ:
381 _rcpath = []
381 _rcpath = []
382 for p in os.environ['HGRCPATH'].split(os.pathsep):
382 for p in os.environ['HGRCPATH'].split(os.pathsep):
383 if not p:
383 if not p:
384 continue
384 continue
385 p = util.expandpath(p)
385 p = util.expandpath(p)
386 if os.path.isdir(p):
386 if os.path.isdir(p):
387 for f, kind in osutil.listdir(p):
387 for f, kind in osutil.listdir(p):
388 if f.endswith('.rc'):
388 if f.endswith('.rc'):
389 _rcpath.append(os.path.join(p, f))
389 _rcpath.append(os.path.join(p, f))
390 else:
390 else:
391 _rcpath.append(p)
391 _rcpath.append(p)
392 else:
392 else:
393 _rcpath = osrcpath()
393 _rcpath = osrcpath()
394 return _rcpath
394 return _rcpath
395
395
396 if os.name != 'nt':
396 if os.name != 'nt':
397
397
398 def rcfiles(path):
398 def rcfiles(path):
399 rcs = [os.path.join(path, 'hgrc')]
399 rcs = [os.path.join(path, 'hgrc')]
400 rcdir = os.path.join(path, 'hgrc.d')
400 rcdir = os.path.join(path, 'hgrc.d')
401 try:
401 try:
402 rcs.extend([os.path.join(rcdir, f)
402 rcs.extend([os.path.join(rcdir, f)
403 for f, kind in osutil.listdir(rcdir)
403 for f, kind in osutil.listdir(rcdir)
404 if f.endswith(".rc")])
404 if f.endswith(".rc")])
405 except OSError:
405 except OSError:
406 pass
406 pass
407 return rcs
407 return rcs
408
408
409 def systemrcpath():
409 def systemrcpath():
410 path = []
410 path = []
411 # old mod_python does not set sys.argv
411 # old mod_python does not set sys.argv
412 if len(getattr(sys, 'argv', [])) > 0:
412 if len(getattr(sys, 'argv', [])) > 0:
413 path.extend(rcfiles(os.path.dirname(sys.argv[0]) +
413 path.extend(rcfiles(os.path.dirname(sys.argv[0]) +
414 '/../etc/mercurial'))
414 '/../etc/mercurial'))
415 path.extend(rcfiles('/etc/mercurial'))
415 path.extend(rcfiles('/etc/mercurial'))
416 return path
416 return path
417
417
418 def userrcpath():
418 def userrcpath():
419 return [os.path.expanduser('~/.hgrc')]
419 return [os.path.expanduser('~/.hgrc')]
420
420
421 else:
421 else:
422
422
423 _HKEY_LOCAL_MACHINE = 0x80000002L
423 _HKEY_LOCAL_MACHINE = 0x80000002L
424
424
425 def systemrcpath():
425 def systemrcpath():
426 '''return default os-specific hgrc search path'''
426 '''return default os-specific hgrc search path'''
427 rcpath = []
427 rcpath = []
428 filename = util.executable_path()
428 filename = util.executable_path()
429 # Use mercurial.ini found in directory with hg.exe
429 # Use mercurial.ini found in directory with hg.exe
430 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
430 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
431 if os.path.isfile(progrc):
431 if os.path.isfile(progrc):
432 rcpath.append(progrc)
432 rcpath.append(progrc)
433 return rcpath
433 return rcpath
434 # Use hgrc.d found in directory with hg.exe
434 # Use hgrc.d found in directory with hg.exe
435 progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
435 progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
436 if os.path.isdir(progrcd):
436 if os.path.isdir(progrcd):
437 for f, kind in osutil.listdir(progrcd):
437 for f, kind in osutil.listdir(progrcd):
438 if f.endswith('.rc'):
438 if f.endswith('.rc'):
439 rcpath.append(os.path.join(progrcd, f))
439 rcpath.append(os.path.join(progrcd, f))
440 return rcpath
440 return rcpath
441 # else look for a system rcpath in the registry
441 # else look for a system rcpath in the registry
442 value = util.lookup_reg('SOFTWARE\\Mercurial', None,
442 value = util.lookup_reg('SOFTWARE\\Mercurial', None,
443 _HKEY_LOCAL_MACHINE)
443 _HKEY_LOCAL_MACHINE)
444 if not isinstance(value, str) or not value:
444 if not isinstance(value, str) or not value:
445 return rcpath
445 return rcpath
446 value = value.replace('/', os.sep)
446 value = value.replace('/', os.sep)
447 for p in value.split(os.pathsep):
447 for p in value.split(os.pathsep):
448 if p.lower().endswith('mercurial.ini'):
448 if p.lower().endswith('mercurial.ini'):
449 rcpath.append(p)
449 rcpath.append(p)
450 elif os.path.isdir(p):
450 elif os.path.isdir(p):
451 for f, kind in osutil.listdir(p):
451 for f, kind in osutil.listdir(p):
452 if f.endswith('.rc'):
452 if f.endswith('.rc'):
453 rcpath.append(os.path.join(p, f))
453 rcpath.append(os.path.join(p, f))
454 return rcpath
454 return rcpath
455
455
456 def userrcpath():
456 def userrcpath():
457 '''return os-specific hgrc search path to the user dir'''
457 '''return os-specific hgrc search path to the user dir'''
458 home = os.path.expanduser('~')
458 home = os.path.expanduser('~')
459 path = [os.path.join(home, 'mercurial.ini'),
459 path = [os.path.join(home, 'mercurial.ini'),
460 os.path.join(home, '.hgrc')]
460 os.path.join(home, '.hgrc')]
461 userprofile = os.environ.get('USERPROFILE')
461 userprofile = os.environ.get('USERPROFILE')
462 if userprofile:
462 if userprofile:
463 path.append(os.path.join(userprofile, 'mercurial.ini'))
463 path.append(os.path.join(userprofile, 'mercurial.ini'))
464 path.append(os.path.join(userprofile, '.hgrc'))
464 path.append(os.path.join(userprofile, '.hgrc'))
465 return path
465 return path
General Comments 0
You need to be logged in to leave comments. Login now