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