##// END OF EJS Templates
ui: cleanup _is_trusted a bit
Matt Mackall -
r8141:e40b629b default
parent child Browse files
Show More
@@ -1,435 +1,435 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from i18n import _
8 from i18n import _
9 import errno, getpass, os, re, socket, sys, tempfile
9 import errno, getpass, os, re, socket, sys, tempfile
10 import ConfigParser, traceback, util
10 import ConfigParser, traceback, util
11
11
12 def dupconfig(orig):
12 def dupconfig(orig):
13 new = util.configparser(orig.defaults())
13 new = util.configparser(orig.defaults())
14 updateconfig(orig, new)
14 updateconfig(orig, new)
15 return new
15 return new
16
16
17 def updateconfig(source, dest, sections=None):
17 def updateconfig(source, dest, sections=None):
18 if not sections:
18 if not sections:
19 sections = source.sections()
19 sections = source.sections()
20 for section in sections:
20 for section in sections:
21 if not dest.has_section(section):
21 if not dest.has_section(section):
22 dest.add_section(section)
22 dest.add_section(section)
23 for name, value in source.items(section, raw=True):
23 for name, value in source.items(section, raw=True):
24 dest.set(section, name, value)
24 dest.set(section, name, value)
25
25
26 class ui(object):
26 class ui(object):
27 def __init__(self, parentui=None):
27 def __init__(self, parentui=None):
28 self.buffers = []
28 self.buffers = []
29 self.quiet = self.verbose = self.debugflag = self.traceback = False
29 self.quiet = self.verbose = self.debugflag = self.traceback = False
30 self.interactive = self.report_untrusted = True
30 self.interactive = self.report_untrusted = True
31
31
32 if parentui is None:
32 if parentui is None:
33 # this is the parent of all ui children
33 # this is the parent of all ui children
34 self.parentui = None
34 self.parentui = None
35 self.trusted_users = {}
35 self.trusted_users = {}
36 self.trusted_groups = {}
36 self.trusted_groups = {}
37 self.overlay = util.configparser()
37 self.overlay = util.configparser()
38 self.cdata = util.configparser()
38 self.cdata = util.configparser()
39 self.ucdata = util.configparser()
39 self.ucdata = util.configparser()
40
40 # we always trust global config files
41 # we always trust global config files
41 self.readconfig(util.rcpath(), assumetrusted=True)
42 self.readconfig(util.rcpath(), assumetrusted=True)
42 else:
43 else:
43 # parentui may point to an ui object which is already a child
44 # parentui may point to an ui object which is already a child
44 self.parentui = parentui.parentui or parentui
45 self.parentui = parentui.parentui or parentui
45 self.buffers = parentui.buffers
46 self.buffers = parentui.buffers
46 self.trusted_users = parentui.trusted_users.copy()
47 self.trusted_users = parentui.trusted_users.copy()
47 self.trusted_groups = parentui.trusted_groups.copy()
48 self.trusted_groups = parentui.trusted_groups.copy()
48 self.cdata = dupconfig(self.parentui.cdata)
49 self.cdata = dupconfig(self.parentui.cdata)
49 self.ucdata = dupconfig(self.parentui.ucdata)
50 self.ucdata = dupconfig(self.parentui.ucdata)
50
51
51 # we want the overlay from the parent, not the root
52 # we want the overlay from the parent, not the root
52 self.overlay = dupconfig(parentui.overlay)
53 self.overlay = dupconfig(parentui.overlay)
53
54
54 def __getattr__(self, key):
55 def __getattr__(self, key):
55 return getattr(self.parentui, key)
56 return getattr(self.parentui, key)
56
57
57 _isatty = None
58 _isatty = None
58 def isatty(self):
59 def isatty(self):
59 if ui._isatty is None:
60 if ui._isatty is None:
60 try:
61 try:
61 ui._isatty = sys.stdin.isatty()
62 ui._isatty = sys.stdin.isatty()
62 except AttributeError: # not a real file object
63 except AttributeError: # not a real file object
63 ui._isatty = False
64 ui._isatty = False
64 return ui._isatty
65 return ui._isatty
65
66
66 def _is_trusted(self, fp, f, warn=True):
67 def _is_trusted(self, fp, f):
67 st = util.fstat(fp)
68 st = util.fstat(fp)
68 if util.isowner(fp, st):
69 if util.isowner(fp, st):
69 return True
70 return True
71
70 tusers = self.trusted_users
72 tusers = self.trusted_users
71 tgroups = self.trusted_groups
73 tgroups = self.trusted_groups
72 if not tusers:
74 if '*' in tusers or '*' in tgroups:
73 user = util.username()
75 return True
74 if user is not None:
76
75 self.trusted_users[user] = 1
77 user = util.username(st.st_uid)
76 self.fixconfig(section='trusted')
78 group = util.groupname(st.st_gid)
77 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
79 if user in tusers or group in tgroups or user == util.username():
78 user = util.username(st.st_uid)
80 return True
79 group = util.groupname(st.st_gid)
81
80 if user not in tusers and group not in tgroups:
82 if self.report_untrusted:
81 if warn and self.report_untrusted:
83 self.warn(_('Not trusting file %s from untrusted '
82 self.warn(_('Not trusting file %s from untrusted '
84 'user %s, group %s\n') % (f, user, group))
83 'user %s, group %s\n') % (f, user, group))
85 return False
84 return False
85 return True
86
86
87 def readconfig(self, fn, root=None, assumetrusted=False):
87 def readconfig(self, fn, root=None, assumetrusted=False):
88 cdata = util.configparser()
88 cdata = util.configparser()
89
89
90 if isinstance(fn, basestring):
90 if isinstance(fn, basestring):
91 fn = [fn]
91 fn = [fn]
92 for f in fn:
92 for f in fn:
93 try:
93 try:
94 fp = open(f)
94 fp = open(f)
95 except IOError:
95 except IOError:
96 continue
96 continue
97
97
98 trusted = assumetrusted or self._is_trusted(fp, f)
98 trusted = assumetrusted or self._is_trusted(fp, f)
99
99
100 try:
100 try:
101 cdata.readfp(fp, f)
101 cdata.readfp(fp, f)
102 except ConfigParser.ParsingError, inst:
102 except ConfigParser.ParsingError, inst:
103 msg = _("Failed to parse %s\n%s") % (f, inst)
103 msg = _("Failed to parse %s\n%s") % (f, inst)
104 if trusted:
104 if trusted:
105 raise util.Abort(msg)
105 raise util.Abort(msg)
106 self.warn(_("Ignored: %s\n") % msg)
106 self.warn(_("Ignored: %s\n") % msg)
107
107
108 if trusted:
108 if trusted:
109 updateconfig(cdata, self.cdata)
109 updateconfig(cdata, self.cdata)
110 updateconfig(self.overlay, self.cdata)
110 updateconfig(self.overlay, self.cdata)
111 updateconfig(cdata, self.ucdata)
111 updateconfig(cdata, self.ucdata)
112 updateconfig(self.overlay, self.ucdata)
112 updateconfig(self.overlay, self.ucdata)
113
113
114 if root is None:
114 if root is None:
115 root = os.path.expanduser('~')
115 root = os.path.expanduser('~')
116 self.fixconfig(root=root)
116 self.fixconfig(root=root)
117
117
118 def readsections(self, filename, *sections):
118 def readsections(self, filename, *sections):
119 """Read filename and add only the specified sections to the config data
119 """Read filename and add only the specified sections to the config data
120
120
121 The settings are added to the trusted config data.
121 The settings are added to the trusted config data.
122 """
122 """
123 if not sections:
123 if not sections:
124 return
124 return
125
125
126 cdata = util.configparser()
126 cdata = util.configparser()
127 try:
127 try:
128 try:
128 try:
129 fp = open(filename)
129 fp = open(filename)
130 except IOError, inst:
130 except IOError, inst:
131 raise util.Abort(_("unable to open %s: %s") %
131 raise util.Abort(_("unable to open %s: %s") %
132 (filename, getattr(inst, "strerror", inst)))
132 (filename, getattr(inst, "strerror", inst)))
133 try:
133 try:
134 cdata.readfp(fp, filename)
134 cdata.readfp(fp, filename)
135 finally:
135 finally:
136 fp.close()
136 fp.close()
137 except ConfigParser.ParsingError, inst:
137 except ConfigParser.ParsingError, inst:
138 raise util.Abort(_("failed to parse %s\n%s") % (filename, inst))
138 raise util.Abort(_("failed to parse %s\n%s") % (filename, inst))
139
139
140 for section in sections:
140 for section in sections:
141 if not cdata.has_section(section):
141 if not cdata.has_section(section):
142 cdata.add_section(section)
142 cdata.add_section(section)
143
143
144 updateconfig(cdata, self.cdata, sections)
144 updateconfig(cdata, self.cdata, sections)
145 updateconfig(cdata, self.ucdata, sections)
145 updateconfig(cdata, self.ucdata, sections)
146
146
147 def fixconfig(self, section=None, name=None, value=None, root=None):
147 def fixconfig(self, section=None, name=None, value=None, root=None):
148 # translate paths relative to root (or home) into absolute paths
148 # translate paths relative to root (or home) into absolute paths
149 if section is None or section == 'paths':
149 if section is None or section == 'paths':
150 if root is None:
150 if root is None:
151 root = os.getcwd()
151 root = os.getcwd()
152 items = section and [(name, value)] or []
152 items = section and [(name, value)] or []
153 for cdata in self.cdata, self.ucdata, self.overlay:
153 for cdata in self.cdata, self.ucdata, self.overlay:
154 if not items and cdata.has_section('paths'):
154 if not items and cdata.has_section('paths'):
155 pathsitems = cdata.items('paths')
155 pathsitems = cdata.items('paths')
156 else:
156 else:
157 pathsitems = items
157 pathsitems = items
158 for n, path in pathsitems:
158 for n, path in pathsitems:
159 if path and "://" not in path and not os.path.isabs(path):
159 if path and "://" not in path and not os.path.isabs(path):
160 cdata.set("paths", n,
160 cdata.set("paths", n,
161 os.path.normpath(os.path.join(root, path)))
161 os.path.normpath(os.path.join(root, path)))
162
162
163 # update ui options
163 # update ui options
164 if section is None or section == 'ui':
164 if section is None or section == 'ui':
165 self.debugflag = self.configbool('ui', 'debug')
165 self.debugflag = self.configbool('ui', 'debug')
166 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
166 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
167 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
167 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
168 if self.verbose and self.quiet:
168 if self.verbose and self.quiet:
169 self.quiet = self.verbose = False
169 self.quiet = self.verbose = False
170
170
171 self.report_untrusted = self.configbool("ui", "report_untrusted",
171 self.report_untrusted = self.configbool("ui", "report_untrusted",
172 True)
172 True)
173 self.interactive = self.configbool("ui", "interactive",
173 self.interactive = self.configbool("ui", "interactive",
174 self.isatty())
174 self.isatty())
175 self.traceback = self.configbool('ui', 'traceback', False)
175 self.traceback = self.configbool('ui', 'traceback', False)
176
176
177 # update trust information
177 # update trust information
178 if (section is None or section == 'trusted') and self.trusted_users:
178 if section is None or section == 'trusted':
179 for user in self.configlist('trusted', 'users'):
179 for user in self.configlist('trusted', 'users'):
180 self.trusted_users[user] = 1
180 self.trusted_users[user] = 1
181 for group in self.configlist('trusted', 'groups'):
181 for group in self.configlist('trusted', 'groups'):
182 self.trusted_groups[group] = 1
182 self.trusted_groups[group] = 1
183
183
184 def setconfig(self, section, name, value):
184 def setconfig(self, section, name, value):
185 for cdata in (self.overlay, self.cdata, self.ucdata):
185 for cdata in (self.overlay, self.cdata, self.ucdata):
186 if not cdata.has_section(section):
186 if not cdata.has_section(section):
187 cdata.add_section(section)
187 cdata.add_section(section)
188 cdata.set(section, name, value)
188 cdata.set(section, name, value)
189 self.fixconfig(section, name, value)
189 self.fixconfig(section, name, value)
190
190
191 def _get_cdata(self, untrusted):
191 def _get_cdata(self, untrusted):
192 if untrusted:
192 if untrusted:
193 return self.ucdata
193 return self.ucdata
194 return self.cdata
194 return self.cdata
195
195
196 def _config(self, section, name, default, funcname, untrusted, abort):
196 def _config(self, section, name, default, funcname, untrusted, abort):
197 cdata = self._get_cdata(untrusted)
197 cdata = self._get_cdata(untrusted)
198 if cdata.has_option(section, name):
198 if cdata.has_option(section, name):
199 try:
199 try:
200 func = getattr(cdata, funcname)
200 func = getattr(cdata, funcname)
201 return func(section, name)
201 return func(section, name)
202 except (ConfigParser.InterpolationError, ValueError), inst:
202 except (ConfigParser.InterpolationError, ValueError), inst:
203 msg = _("Error in configuration section [%s] "
203 msg = _("Error in configuration section [%s] "
204 "parameter '%s':\n%s") % (section, name, inst)
204 "parameter '%s':\n%s") % (section, name, inst)
205 if abort:
205 if abort:
206 raise util.Abort(msg)
206 raise util.Abort(msg)
207 self.warn(_("Ignored: %s\n") % msg)
207 self.warn(_("Ignored: %s\n") % msg)
208 return default
208 return default
209
209
210 def _configcommon(self, section, name, default, funcname, untrusted):
210 def _configcommon(self, section, name, default, funcname, untrusted):
211 value = self._config(section, name, default, funcname,
211 value = self._config(section, name, default, funcname,
212 untrusted, abort=True)
212 untrusted, abort=True)
213 if self.debugflag and not untrusted:
213 if self.debugflag and not untrusted:
214 uvalue = self._config(section, name, None, funcname,
214 uvalue = self._config(section, name, None, funcname,
215 untrusted=True, abort=False)
215 untrusted=True, abort=False)
216 if uvalue is not None and uvalue != value:
216 if uvalue is not None and uvalue != value:
217 self.warn(_("Ignoring untrusted configuration option "
217 self.warn(_("Ignoring untrusted configuration option "
218 "%s.%s = %s\n") % (section, name, uvalue))
218 "%s.%s = %s\n") % (section, name, uvalue))
219 return value
219 return value
220
220
221 def config(self, section, name, default=None, untrusted=False):
221 def config(self, section, name, default=None, untrusted=False):
222 return self._configcommon(section, name, default, 'get', untrusted)
222 return self._configcommon(section, name, default, 'get', untrusted)
223
223
224 def configbool(self, section, name, default=False, untrusted=False):
224 def configbool(self, section, name, default=False, untrusted=False):
225 return self._configcommon(section, name, default, 'getboolean',
225 return self._configcommon(section, name, default, 'getboolean',
226 untrusted)
226 untrusted)
227
227
228 def configlist(self, section, name, default=None, untrusted=False):
228 def configlist(self, section, name, default=None, untrusted=False):
229 """Return a list of comma/space separated strings"""
229 """Return a list of comma/space separated strings"""
230 result = self.config(section, name, untrusted=untrusted)
230 result = self.config(section, name, untrusted=untrusted)
231 if result is None:
231 if result is None:
232 result = default or []
232 result = default or []
233 if isinstance(result, basestring):
233 if isinstance(result, basestring):
234 result = result.replace(",", " ").split()
234 result = result.replace(",", " ").split()
235 return result
235 return result
236
236
237 def has_section(self, section, untrusted=False):
237 def has_section(self, section, untrusted=False):
238 '''tell whether section exists in config.'''
238 '''tell whether section exists in config.'''
239 cdata = self._get_cdata(untrusted)
239 cdata = self._get_cdata(untrusted)
240 return cdata.has_section(section)
240 return cdata.has_section(section)
241
241
242 def _configitems(self, section, untrusted, abort):
242 def _configitems(self, section, untrusted, abort):
243 items = {}
243 items = {}
244 cdata = self._get_cdata(untrusted)
244 cdata = self._get_cdata(untrusted)
245 if cdata.has_section(section):
245 if cdata.has_section(section):
246 try:
246 try:
247 items.update(dict(cdata.items(section)))
247 items.update(dict(cdata.items(section)))
248 except ConfigParser.InterpolationError, inst:
248 except ConfigParser.InterpolationError, inst:
249 msg = _("Error in configuration section [%s]:\n"
249 msg = _("Error in configuration section [%s]:\n"
250 "%s") % (section, inst)
250 "%s") % (section, inst)
251 if abort:
251 if abort:
252 raise util.Abort(msg)
252 raise util.Abort(msg)
253 self.warn(_("Ignored: %s\n") % msg)
253 self.warn(_("Ignored: %s\n") % msg)
254 return items
254 return items
255
255
256 def configitems(self, section, untrusted=False):
256 def configitems(self, section, untrusted=False):
257 items = self._configitems(section, untrusted=untrusted, abort=True)
257 items = self._configitems(section, untrusted=untrusted, abort=True)
258 if self.debugflag and not untrusted:
258 if self.debugflag and not untrusted:
259 uitems = self._configitems(section, untrusted=True, abort=False)
259 uitems = self._configitems(section, untrusted=True, abort=False)
260 for k in util.sort(uitems):
260 for k in util.sort(uitems):
261 if uitems[k] != items.get(k):
261 if uitems[k] != items.get(k):
262 self.warn(_("Ignoring untrusted configuration option "
262 self.warn(_("Ignoring untrusted configuration option "
263 "%s.%s = %s\n") % (section, k, uitems[k]))
263 "%s.%s = %s\n") % (section, k, uitems[k]))
264 return util.sort(items.items())
264 return util.sort(items.items())
265
265
266 def walkconfig(self, untrusted=False):
266 def walkconfig(self, untrusted=False):
267 cdata = self._get_cdata(untrusted)
267 cdata = self._get_cdata(untrusted)
268 sections = cdata.sections()
268 sections = cdata.sections()
269 sections.sort()
269 sections.sort()
270 for section in sections:
270 for section in sections:
271 for name, value in self.configitems(section, untrusted):
271 for name, value in self.configitems(section, untrusted):
272 yield section, name, str(value).replace('\n', '\\n')
272 yield section, name, str(value).replace('\n', '\\n')
273
273
274 def username(self):
274 def username(self):
275 """Return default username to be used in commits.
275 """Return default username to be used in commits.
276
276
277 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
277 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
278 and stop searching if one of these is set.
278 and stop searching if one of these is set.
279 If not found and ui.askusername is True, ask the user, else use
279 If not found and ui.askusername is True, ask the user, else use
280 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
280 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
281 """
281 """
282 user = os.environ.get("HGUSER")
282 user = os.environ.get("HGUSER")
283 if user is None:
283 if user is None:
284 user = self.config("ui", "username")
284 user = self.config("ui", "username")
285 if user is None:
285 if user is None:
286 user = os.environ.get("EMAIL")
286 user = os.environ.get("EMAIL")
287 if user is None and self.configbool("ui", "askusername"):
287 if user is None and self.configbool("ui", "askusername"):
288 user = self.prompt(_("enter a commit username:"), default=None)
288 user = self.prompt(_("enter a commit username:"), default=None)
289 if user is None:
289 if user is None:
290 try:
290 try:
291 user = '%s@%s' % (util.getuser(), socket.getfqdn())
291 user = '%s@%s' % (util.getuser(), socket.getfqdn())
292 self.warn(_("No username found, using '%s' instead\n") % user)
292 self.warn(_("No username found, using '%s' instead\n") % user)
293 except KeyError:
293 except KeyError:
294 pass
294 pass
295 if not user:
295 if not user:
296 raise util.Abort(_("Please specify a username."))
296 raise util.Abort(_("Please specify a username."))
297 if "\n" in user:
297 if "\n" in user:
298 raise util.Abort(_("username %s contains a newline\n") % repr(user))
298 raise util.Abort(_("username %s contains a newline\n") % repr(user))
299 return user
299 return user
300
300
301 def shortuser(self, user):
301 def shortuser(self, user):
302 """Return a short representation of a user name or email address."""
302 """Return a short representation of a user name or email address."""
303 if not self.verbose: user = util.shortuser(user)
303 if not self.verbose: user = util.shortuser(user)
304 return user
304 return user
305
305
306 def expandpath(self, loc, default=None):
306 def expandpath(self, loc, default=None):
307 """Return repository location relative to cwd or from [paths]"""
307 """Return repository location relative to cwd or from [paths]"""
308 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
308 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
309 return loc
309 return loc
310
310
311 path = self.config("paths", loc)
311 path = self.config("paths", loc)
312 if not path and default is not None:
312 if not path and default is not None:
313 path = self.config("paths", default)
313 path = self.config("paths", default)
314 return path or loc
314 return path or loc
315
315
316 def pushbuffer(self):
316 def pushbuffer(self):
317 self.buffers.append([])
317 self.buffers.append([])
318
318
319 def popbuffer(self):
319 def popbuffer(self):
320 return "".join(self.buffers.pop())
320 return "".join(self.buffers.pop())
321
321
322 def write(self, *args):
322 def write(self, *args):
323 if self.buffers:
323 if self.buffers:
324 self.buffers[-1].extend([str(a) for a in args])
324 self.buffers[-1].extend([str(a) for a in args])
325 else:
325 else:
326 for a in args:
326 for a in args:
327 sys.stdout.write(str(a))
327 sys.stdout.write(str(a))
328
328
329 def write_err(self, *args):
329 def write_err(self, *args):
330 try:
330 try:
331 if not sys.stdout.closed: sys.stdout.flush()
331 if not sys.stdout.closed: sys.stdout.flush()
332 for a in args:
332 for a in args:
333 sys.stderr.write(str(a))
333 sys.stderr.write(str(a))
334 # stderr may be buffered under win32 when redirected to files,
334 # stderr may be buffered under win32 when redirected to files,
335 # including stdout.
335 # including stdout.
336 if not sys.stderr.closed: sys.stderr.flush()
336 if not sys.stderr.closed: sys.stderr.flush()
337 except IOError, inst:
337 except IOError, inst:
338 if inst.errno != errno.EPIPE:
338 if inst.errno != errno.EPIPE:
339 raise
339 raise
340
340
341 def flush(self):
341 def flush(self):
342 try: sys.stdout.flush()
342 try: sys.stdout.flush()
343 except: pass
343 except: pass
344 try: sys.stderr.flush()
344 try: sys.stderr.flush()
345 except: pass
345 except: pass
346
346
347 def _readline(self, prompt=''):
347 def _readline(self, prompt=''):
348 if self.isatty():
348 if self.isatty():
349 try:
349 try:
350 # magically add command line editing support, where
350 # magically add command line editing support, where
351 # available
351 # available
352 import readline
352 import readline
353 # force demandimport to really load the module
353 # force demandimport to really load the module
354 readline.read_history_file
354 readline.read_history_file
355 # windows sometimes raises something other than ImportError
355 # windows sometimes raises something other than ImportError
356 except Exception:
356 except Exception:
357 pass
357 pass
358 line = raw_input(prompt)
358 line = raw_input(prompt)
359 # When stdin is in binary mode on Windows, it can cause
359 # When stdin is in binary mode on Windows, it can cause
360 # raw_input() to emit an extra trailing carriage return
360 # raw_input() to emit an extra trailing carriage return
361 if os.linesep == '\r\n' and line and line[-1] == '\r':
361 if os.linesep == '\r\n' and line and line[-1] == '\r':
362 line = line[:-1]
362 line = line[:-1]
363 return line
363 return line
364
364
365 def prompt(self, msg, pat=None, default="y"):
365 def prompt(self, msg, pat=None, default="y"):
366 """Prompt user with msg, read response, and ensure it matches pat
366 """Prompt user with msg, read response, and ensure it matches pat
367
367
368 If not interactive -- the default is returned
368 If not interactive -- the default is returned
369 """
369 """
370 if not self.interactive:
370 if not self.interactive:
371 self.note(msg, ' ', default, "\n")
371 self.note(msg, ' ', default, "\n")
372 return default
372 return default
373 while True:
373 while True:
374 try:
374 try:
375 r = self._readline(msg + ' ')
375 r = self._readline(msg + ' ')
376 if not r:
376 if not r:
377 return default
377 return default
378 if not pat or re.match(pat, r):
378 if not pat or re.match(pat, r):
379 return r
379 return r
380 else:
380 else:
381 self.write(_("unrecognized response\n"))
381 self.write(_("unrecognized response\n"))
382 except EOFError:
382 except EOFError:
383 raise util.Abort(_('response expected'))
383 raise util.Abort(_('response expected'))
384
384
385 def getpass(self, prompt=None, default=None):
385 def getpass(self, prompt=None, default=None):
386 if not self.interactive: return default
386 if not self.interactive: return default
387 try:
387 try:
388 return getpass.getpass(prompt or _('password: '))
388 return getpass.getpass(prompt or _('password: '))
389 except EOFError:
389 except EOFError:
390 raise util.Abort(_('response expected'))
390 raise util.Abort(_('response expected'))
391 def status(self, *msg):
391 def status(self, *msg):
392 if not self.quiet: self.write(*msg)
392 if not self.quiet: self.write(*msg)
393 def warn(self, *msg):
393 def warn(self, *msg):
394 self.write_err(*msg)
394 self.write_err(*msg)
395 def note(self, *msg):
395 def note(self, *msg):
396 if self.verbose: self.write(*msg)
396 if self.verbose: self.write(*msg)
397 def debug(self, *msg):
397 def debug(self, *msg):
398 if self.debugflag: self.write(*msg)
398 if self.debugflag: self.write(*msg)
399 def edit(self, text, user):
399 def edit(self, text, user):
400 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
400 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
401 text=True)
401 text=True)
402 try:
402 try:
403 f = os.fdopen(fd, "w")
403 f = os.fdopen(fd, "w")
404 f.write(text)
404 f.write(text)
405 f.close()
405 f.close()
406
406
407 editor = self.geteditor()
407 editor = self.geteditor()
408
408
409 util.system("%s \"%s\"" % (editor, name),
409 util.system("%s \"%s\"" % (editor, name),
410 environ={'HGUSER': user},
410 environ={'HGUSER': user},
411 onerr=util.Abort, errprefix=_("edit failed"))
411 onerr=util.Abort, errprefix=_("edit failed"))
412
412
413 f = open(name)
413 f = open(name)
414 t = f.read()
414 t = f.read()
415 f.close()
415 f.close()
416 t = re.sub("(?m)^HG:.*\n", "", t)
416 t = re.sub("(?m)^HG:.*\n", "", t)
417 finally:
417 finally:
418 os.unlink(name)
418 os.unlink(name)
419
419
420 return t
420 return t
421
421
422 def print_exc(self):
422 def print_exc(self):
423 '''print exception traceback if traceback printing enabled.
423 '''print exception traceback if traceback printing enabled.
424 only to call in exception handler. returns true if traceback
424 only to call in exception handler. returns true if traceback
425 printed.'''
425 printed.'''
426 if self.traceback:
426 if self.traceback:
427 traceback.print_exc()
427 traceback.print_exc()
428 return self.traceback
428 return self.traceback
429
429
430 def geteditor(self):
430 def geteditor(self):
431 '''return editor to use'''
431 '''return editor to use'''
432 return (os.environ.get("HGEDITOR") or
432 return (os.environ.get("HGEDITOR") or
433 self.config("ui", "editor") or
433 self.config("ui", "editor") or
434 os.environ.get("VISUAL") or
434 os.environ.get("VISUAL") or
435 os.environ.get("EDITOR", "vi"))
435 os.environ.get("EDITOR", "vi"))
@@ -1,212 +1,211 b''
1 # same user, same group
1 # same user, same group
2 trusted
2 trusted
3 global = /some/path
3 global = /some/path
4 interpolated = /some/path/another/path
4 interpolated = /some/path/another/path
5 local = /another/path
5 local = /another/path
6 untrusted
6 untrusted
7 . . global = /some/path
7 . . global = /some/path
8 . . interpolated = /some/path/another/path
8 . . interpolated = /some/path/another/path
9 . . local = /another/path
9 . . local = /another/path
10
10
11 # same user, different group
11 # same user, different group
12 trusted
12 trusted
13 global = /some/path
13 global = /some/path
14 interpolated = /some/path/another/path
14 interpolated = /some/path/another/path
15 local = /another/path
15 local = /another/path
16 untrusted
16 untrusted
17 . . global = /some/path
17 . . global = /some/path
18 . . interpolated = /some/path/another/path
18 . . interpolated = /some/path/another/path
19 . . local = /another/path
19 . . local = /another/path
20
20
21 # different user, same group
21 # different user, same group
22 Not trusting file .hg/hgrc from untrusted user abc, group bar
22 Not trusting file .hg/hgrc from untrusted user abc, group bar
23 trusted
23 trusted
24 global = /some/path
24 global = /some/path
25 untrusted
25 untrusted
26 . . global = /some/path
26 . . global = /some/path
27 . . interpolated = /some/path/another/path
27 . . interpolated = /some/path/another/path
28 . . local = /another/path
28 . . local = /another/path
29
29
30 # different user, same group, but we trust the group
30 # different user, same group, but we trust the group
31 trusted
31 trusted
32 global = /some/path
32 global = /some/path
33 interpolated = /some/path/another/path
33 interpolated = /some/path/another/path
34 local = /another/path
34 local = /another/path
35 untrusted
35 untrusted
36 . . global = /some/path
36 . . global = /some/path
37 . . interpolated = /some/path/another/path
37 . . interpolated = /some/path/another/path
38 . . local = /another/path
38 . . local = /another/path
39
39
40 # different user, different group
40 # different user, different group
41 Not trusting file .hg/hgrc from untrusted user abc, group def
41 Not trusting file .hg/hgrc from untrusted user abc, group def
42 trusted
42 trusted
43 global = /some/path
43 global = /some/path
44 untrusted
44 untrusted
45 . . global = /some/path
45 . . global = /some/path
46 . . interpolated = /some/path/another/path
46 . . interpolated = /some/path/another/path
47 . . local = /another/path
47 . . local = /another/path
48
48
49 # different user, different group, but we trust the user
49 # different user, different group, but we trust the user
50 trusted
50 trusted
51 global = /some/path
51 global = /some/path
52 interpolated = /some/path/another/path
52 interpolated = /some/path/another/path
53 local = /another/path
53 local = /another/path
54 untrusted
54 untrusted
55 . . global = /some/path
55 . . global = /some/path
56 . . interpolated = /some/path/another/path
56 . . interpolated = /some/path/another/path
57 . . local = /another/path
57 . . local = /another/path
58
58
59 # different user, different group, but we trust the group
59 # different user, different group, but we trust the group
60 trusted
60 trusted
61 global = /some/path
61 global = /some/path
62 interpolated = /some/path/another/path
62 interpolated = /some/path/another/path
63 local = /another/path
63 local = /another/path
64 untrusted
64 untrusted
65 . . global = /some/path
65 . . global = /some/path
66 . . interpolated = /some/path/another/path
66 . . interpolated = /some/path/another/path
67 . . local = /another/path
67 . . local = /another/path
68
68
69 # different user, different group, but we trust the user and the group
69 # different user, different group, but we trust the user and the group
70 trusted
70 trusted
71 global = /some/path
71 global = /some/path
72 interpolated = /some/path/another/path
72 interpolated = /some/path/another/path
73 local = /another/path
73 local = /another/path
74 untrusted
74 untrusted
75 . . global = /some/path
75 . . global = /some/path
76 . . interpolated = /some/path/another/path
76 . . interpolated = /some/path/another/path
77 . . local = /another/path
77 . . local = /another/path
78
78
79 # we trust all users
79 # we trust all users
80 # different user, different group
80 # different user, different group
81 trusted
81 trusted
82 global = /some/path
82 global = /some/path
83 interpolated = /some/path/another/path
83 interpolated = /some/path/another/path
84 local = /another/path
84 local = /another/path
85 untrusted
85 untrusted
86 . . global = /some/path
86 . . global = /some/path
87 . . interpolated = /some/path/another/path
87 . . interpolated = /some/path/another/path
88 . . local = /another/path
88 . . local = /another/path
89
89
90 # we trust all groups
90 # we trust all groups
91 # different user, different group
91 # different user, different group
92 trusted
92 trusted
93 global = /some/path
93 global = /some/path
94 interpolated = /some/path/another/path
94 interpolated = /some/path/another/path
95 local = /another/path
95 local = /another/path
96 untrusted
96 untrusted
97 . . global = /some/path
97 . . global = /some/path
98 . . interpolated = /some/path/another/path
98 . . interpolated = /some/path/another/path
99 . . local = /another/path
99 . . local = /another/path
100
100
101 # we trust all users and groups
101 # we trust all users and groups
102 # different user, different group
102 # different user, different group
103 trusted
103 trusted
104 global = /some/path
104 global = /some/path
105 interpolated = /some/path/another/path
105 interpolated = /some/path/another/path
106 local = /another/path
106 local = /another/path
107 untrusted
107 untrusted
108 . . global = /some/path
108 . . global = /some/path
109 . . interpolated = /some/path/another/path
109 . . interpolated = /some/path/another/path
110 . . local = /another/path
110 . . local = /another/path
111
111
112 # we don't get confused by users and groups with the same name
112 # we don't get confused by users and groups with the same name
113 # different user, different group
113 # different user, different group
114 Not trusting file .hg/hgrc from untrusted user abc, group def
114 Not trusting file .hg/hgrc from untrusted user abc, group def
115 trusted
115 trusted
116 global = /some/path
116 global = /some/path
117 untrusted
117 untrusted
118 . . global = /some/path
118 . . global = /some/path
119 . . interpolated = /some/path/another/path
119 . . interpolated = /some/path/another/path
120 . . local = /another/path
120 . . local = /another/path
121
121
122 # list of user names
122 # list of user names
123 # different user, different group, but we trust the user
123 # different user, different group, but we trust the user
124 trusted
124 trusted
125 global = /some/path
125 global = /some/path
126 interpolated = /some/path/another/path
126 interpolated = /some/path/another/path
127 local = /another/path
127 local = /another/path
128 untrusted
128 untrusted
129 . . global = /some/path
129 . . global = /some/path
130 . . interpolated = /some/path/another/path
130 . . interpolated = /some/path/another/path
131 . . local = /another/path
131 . . local = /another/path
132
132
133 # list of group names
133 # list of group names
134 # different user, different group, but we trust the group
134 # different user, different group, but we trust the group
135 trusted
135 trusted
136 global = /some/path
136 global = /some/path
137 interpolated = /some/path/another/path
137 interpolated = /some/path/another/path
138 local = /another/path
138 local = /another/path
139 untrusted
139 untrusted
140 . . global = /some/path
140 . . global = /some/path
141 . . interpolated = /some/path/another/path
141 . . interpolated = /some/path/another/path
142 . . local = /another/path
142 . . local = /another/path
143
143
144 # Can't figure out the name of the user running this process
144 # Can't figure out the name of the user running this process
145 # different user, different group
145 # different user, different group
146 Not trusting file .hg/hgrc from untrusted user abc, group def
146 trusted
147 trusted
147 global = /some/path
148 global = /some/path
148 interpolated = /some/path/another/path
149 local = /another/path
150 untrusted
149 untrusted
151 . . global = /some/path
150 . . global = /some/path
152 . . interpolated = /some/path/another/path
151 . . interpolated = /some/path/another/path
153 . . local = /another/path
152 . . local = /another/path
154
153
155 # prints debug warnings
154 # prints debug warnings
156 # different user, different group
155 # different user, different group
157 Not trusting file .hg/hgrc from untrusted user abc, group def
156 Not trusting file .hg/hgrc from untrusted user abc, group def
158 trusted
157 trusted
159 Ignoring untrusted configuration option paths.interpolated = /some/path/another/path
158 Ignoring untrusted configuration option paths.interpolated = /some/path/another/path
160 Ignoring untrusted configuration option paths.local = /another/path
159 Ignoring untrusted configuration option paths.local = /another/path
161 global = /some/path
160 global = /some/path
162 untrusted
161 untrusted
163 . . global = /some/path
162 . . global = /some/path
164 .Ignoring untrusted configuration option paths.interpolated = /some/path/another/path
163 .Ignoring untrusted configuration option paths.interpolated = /some/path/another/path
165 . interpolated = /some/path/another/path
164 . interpolated = /some/path/another/path
166 .Ignoring untrusted configuration option paths.local = /another/path
165 .Ignoring untrusted configuration option paths.local = /another/path
167 . local = /another/path
166 . local = /another/path
168
167
169 # ui.readsections
168 # ui.readsections
170 quux
169 quux
171
170
172 # read trusted, untrusted, new ui, trusted
171 # read trusted, untrusted, new ui, trusted
173 Not trusting file foobar from untrusted user abc, group def
172 Not trusting file foobar from untrusted user abc, group def
174 trusted:
173 trusted:
175 Ignoring untrusted configuration option foobar.baz = quux
174 Ignoring untrusted configuration option foobar.baz = quux
176 None
175 None
177 /some/path/another/path
176 /some/path/another/path
178 untrusted:
177 untrusted:
179 quux
178 quux
180 /some/path/another/path
179 /some/path/another/path
181
180
182 # error handling
181 # error handling
183 # file doesn't exist
182 # file doesn't exist
184 # same user, same group
183 # same user, same group
185 # different user, different group
184 # different user, different group
186
185
187 # parse error
186 # parse error
188 # different user, different group
187 # different user, different group
189 Not trusting file .hg/hgrc from untrusted user abc, group def
188 Not trusting file .hg/hgrc from untrusted user abc, group def
190 Ignored: Failed to parse .hg/hgrc
189 Ignored: Failed to parse .hg/hgrc
191 File contains no section headers.
190 File contains no section headers.
192 file: .hg/hgrc, line: 1
191 file: .hg/hgrc, line: 1
193 'foo = bar'
192 'foo = bar'
194 # same user, same group
193 # same user, same group
195 raised Abort
194 raised Abort
196
195
197 # interpolation error
196 # interpolation error
198 # same user, same group
197 # same user, same group
199 # regular config:
198 # regular config:
200 trusted raised Abort
199 trusted raised Abort
201 untrusted raised Abort
200 untrusted raised Abort
202 # different user, different group
201 # different user, different group
203 Not trusting file .hg/hgrc from untrusted user abc, group def
202 Not trusting file .hg/hgrc from untrusted user abc, group def
204 trusted Ignored: Error in configuration section [foo] parameter 'bar':
203 trusted Ignored: Error in configuration section [foo] parameter 'bar':
205 bad interpolation variable reference '%('
204 bad interpolation variable reference '%('
206 None
205 None
207 untrusted raised Abort
206 untrusted raised Abort
208 # configitems:
207 # configitems:
209 trusted Ignored: Error in configuration section [foo]:
208 trusted Ignored: Error in configuration section [foo]:
210 bad interpolation variable reference '%('
209 bad interpolation variable reference '%('
211 []
210 []
212 untrusted raised Abort
211 untrusted raised Abort
General Comments 0
You need to be logged in to leave comments. Login now