##// END OF EJS Templates
Don't try to determine interactivity if ui() called with interactive=False....
Dirkjan Ochtman -
r5337:8c5ef3b8 default
parent child Browse files
Show More
@@ -0,0 +1,70 b''
1 #!/bin/sh
2
3 mkdir repo
4 cd repo
5 hg init
6 echo foo > bar
7 hg add bar
8 hg commit -m "test" -d "0 0"
9 hg tip
10
11 cat > request.py <<EOF
12 from mercurial import dispatch
13 from mercurial.hgweb.hgweb_mod import hgweb
14 from mercurial.hgweb.request import _wsgirequest
15 from mercurial.ui import ui
16 from mercurial import hg
17 from StringIO import StringIO
18 import sys
19
20 class FileLike(object):
21 def __init__(self, real):
22 self.real = real
23 def fileno(self):
24 print >> sys.__stdout__, 'FILENO'
25 return self.real.fileno()
26 def read(self):
27 print >> sys.__stdout__, 'READ'
28 return self.real.read()
29 def readline(self):
30 print >> sys.__stdout__, 'READLINE'
31 return self.real.readline()
32 def isatty(self):
33 print >> sys.__stdout__, 'ISATTY'
34 return False
35
36 sys.stdin = FileLike(sys.stdin)
37 errors = StringIO()
38 input = StringIO()
39 output = StringIO()
40
41 def startrsp(headers, data):
42 print '---- HEADERS'
43 print headers
44 print '---- DATA'
45 print data
46 return output.write
47
48 env = {
49 'wsgi.version': (1, 0),
50 'wsgi.url_scheme': 'http',
51 'wsgi.errors': errors,
52 'wsgi.input': input,
53 'wsgi.multithread': False,
54 'wsgi.multiprocess': False,
55 'wsgi.run_once': False,
56 'REQUEST_METHOD': 'GET',
57 'SCRIPT_NAME': '',
58 'PATH_INFO': '',
59 'QUERY_STRING': '',
60 'SERVER_NAME': '127.0.0.1',
61 'SERVER_PORT': '20059',
62 'SERVER_PROTOCOL': 'HTTP/1.0'
63 }
64
65 _wsgirequest(hgweb('.'), env, startrsp)
66 print '---- ERRORS'
67 print errors.getvalue()
68 EOF
69
70 python request.py
@@ -0,0 +1,12 b''
1 changeset: 0:61c9426e69fe
2 tag: tip
3 user: test
4 date: Thu Jan 01 00:00:00 1970 +0000
5 summary: test
6
7 ---- HEADERS
8 200 Script output follows
9 ---- DATA
10 [('content-type', 'text/html; charset=ascii')]
11 ---- ERRORS
12
@@ -1,459 +1,461 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 _isatty = None
27 _isatty = None
28
28
29 def __init__(self, verbose=False, debug=False, quiet=False,
29 def __init__(self, verbose=False, debug=False, quiet=False,
30 interactive=True, traceback=False, report_untrusted=True,
30 interactive=True, traceback=False, report_untrusted=True,
31 parentui=None):
31 parentui=None):
32 self.overlay = None
32 self.overlay = None
33 self.buffers = []
33 self.buffers = []
34 if parentui is None:
34 if parentui is None:
35 # this is the parent of all ui children
35 # this is the parent of all ui children
36 self.parentui = None
36 self.parentui = None
37 self.quiet = quiet
37 self.quiet = quiet
38 self.verbose = verbose
38 self.verbose = verbose
39 self.debugflag = debug
39 self.debugflag = debug
40 self.interactive = interactive
40 self.interactive = interactive
41 self.traceback = traceback
41 self.traceback = traceback
42 self.report_untrusted = report_untrusted
42 self.report_untrusted = report_untrusted
43 self.trusted_users = {}
43 self.trusted_users = {}
44 self.trusted_groups = {}
44 self.trusted_groups = {}
45 # if ucdata is not None, its keys must be a superset of cdata's
45 # if ucdata is not None, its keys must be a superset of cdata's
46 self.cdata = util.configparser()
46 self.cdata = util.configparser()
47 self.ucdata = None
47 self.ucdata = None
48 # we always trust global config files
48 # we always trust global config files
49 self.check_trusted = False
49 self.check_trusted = False
50 self.readconfig(util.rcpath())
50 self.readconfig(util.rcpath())
51 self.check_trusted = True
51 self.check_trusted = True
52 self.updateopts(verbose, debug, quiet, interactive)
52 self.updateopts(verbose, debug, quiet, interactive)
53 else:
53 else:
54 # parentui may point to an ui object which is already a child
54 # parentui may point to an ui object which is already a child
55 self.parentui = parentui.parentui or parentui
55 self.parentui = parentui.parentui or parentui
56 self.trusted_users = parentui.trusted_users.copy()
56 self.trusted_users = parentui.trusted_users.copy()
57 self.trusted_groups = parentui.trusted_groups.copy()
57 self.trusted_groups = parentui.trusted_groups.copy()
58 self.cdata = dupconfig(self.parentui.cdata)
58 self.cdata = dupconfig(self.parentui.cdata)
59 if self.parentui.ucdata:
59 if self.parentui.ucdata:
60 self.ucdata = dupconfig(self.parentui.ucdata)
60 self.ucdata = dupconfig(self.parentui.ucdata)
61 if self.parentui.overlay:
61 if self.parentui.overlay:
62 self.overlay = dupconfig(self.parentui.overlay)
62 self.overlay = dupconfig(self.parentui.overlay)
63
63
64 def __getattr__(self, key):
64 def __getattr__(self, key):
65 return getattr(self.parentui, key)
65 return getattr(self.parentui, key)
66
66
67 def isatty(self):
67 def isatty(self):
68 if ui._isatty is None:
68 if ui._isatty is None:
69 ui._isatty = sys.stdin.isatty()
69 ui._isatty = sys.stdin.isatty()
70 return ui._isatty
70 return ui._isatty
71
71
72 def updateopts(self, verbose=False, debug=False, quiet=False,
72 def updateopts(self, verbose=False, debug=False, quiet=False,
73 interactive=True, traceback=False, config=[]):
73 interactive=True, traceback=False, config=[]):
74 for section, name, value in config:
74 for section, name, value in config:
75 self.setconfig(section, name, value)
75 self.setconfig(section, name, value)
76
76
77 if quiet or verbose or debug:
77 if quiet or verbose or debug:
78 self.setconfig('ui', 'quiet', str(bool(quiet)))
78 self.setconfig('ui', 'quiet', str(bool(quiet)))
79 self.setconfig('ui', 'verbose', str(bool(verbose)))
79 self.setconfig('ui', 'verbose', str(bool(verbose)))
80 self.setconfig('ui', 'debug', str(bool(debug)))
80 self.setconfig('ui', 'debug', str(bool(debug)))
81
81
82 self.verbosity_constraints()
82 self.verbosity_constraints()
83
83
84 if not interactive:
84 if not interactive:
85 self.setconfig('ui', 'interactive', 'False')
85 self.setconfig('ui', 'interactive', 'False')
86 self.interactive = False
86 self.interactive = False
87
87
88 self.traceback = self.traceback or traceback
88 self.traceback = self.traceback or traceback
89
89
90 def verbosity_constraints(self):
90 def verbosity_constraints(self):
91 self.quiet = self.configbool('ui', 'quiet')
91 self.quiet = self.configbool('ui', 'quiet')
92 self.verbose = self.configbool('ui', 'verbose')
92 self.verbose = self.configbool('ui', 'verbose')
93 self.debugflag = self.configbool('ui', 'debug')
93 self.debugflag = self.configbool('ui', 'debug')
94
94
95 if self.debugflag:
95 if self.debugflag:
96 self.verbose = True
96 self.verbose = True
97 self.quiet = False
97 self.quiet = False
98 elif self.verbose and self.quiet:
98 elif self.verbose and self.quiet:
99 self.quiet = self.verbose = False
99 self.quiet = self.verbose = False
100
100
101 def _is_trusted(self, fp, f, warn=True):
101 def _is_trusted(self, fp, f, warn=True):
102 if not self.check_trusted:
102 if not self.check_trusted:
103 return True
103 return True
104 st = util.fstat(fp)
104 st = util.fstat(fp)
105 if util.isowner(fp, st):
105 if util.isowner(fp, st):
106 return True
106 return True
107 tusers = self.trusted_users
107 tusers = self.trusted_users
108 tgroups = self.trusted_groups
108 tgroups = self.trusted_groups
109 if not tusers:
109 if not tusers:
110 user = util.username()
110 user = util.username()
111 if user is not None:
111 if user is not None:
112 self.trusted_users[user] = 1
112 self.trusted_users[user] = 1
113 self.fixconfig(section='trusted')
113 self.fixconfig(section='trusted')
114 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
114 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
115 user = util.username(st.st_uid)
115 user = util.username(st.st_uid)
116 group = util.groupname(st.st_gid)
116 group = util.groupname(st.st_gid)
117 if user not in tusers and group not in tgroups:
117 if user not in tusers and group not in tgroups:
118 if warn and self.report_untrusted:
118 if warn and self.report_untrusted:
119 self.warn(_('Not trusting file %s from untrusted '
119 self.warn(_('Not trusting file %s from untrusted '
120 'user %s, group %s\n') % (f, user, group))
120 'user %s, group %s\n') % (f, user, group))
121 return False
121 return False
122 return True
122 return True
123
123
124 def readconfig(self, fn, root=None):
124 def readconfig(self, fn, root=None):
125 if isinstance(fn, basestring):
125 if isinstance(fn, basestring):
126 fn = [fn]
126 fn = [fn]
127 for f in fn:
127 for f in fn:
128 try:
128 try:
129 fp = open(f)
129 fp = open(f)
130 except IOError:
130 except IOError:
131 continue
131 continue
132 cdata = self.cdata
132 cdata = self.cdata
133 trusted = self._is_trusted(fp, f)
133 trusted = self._is_trusted(fp, f)
134 if not trusted:
134 if not trusted:
135 if self.ucdata is None:
135 if self.ucdata is None:
136 self.ucdata = dupconfig(self.cdata)
136 self.ucdata = dupconfig(self.cdata)
137 cdata = self.ucdata
137 cdata = self.ucdata
138 elif self.ucdata is not None:
138 elif self.ucdata is not None:
139 # use a separate configparser, so that we don't accidentally
139 # use a separate configparser, so that we don't accidentally
140 # override ucdata settings later on.
140 # override ucdata settings later on.
141 cdata = util.configparser()
141 cdata = util.configparser()
142
142
143 try:
143 try:
144 cdata.readfp(fp, f)
144 cdata.readfp(fp, f)
145 except ConfigParser.ParsingError, inst:
145 except ConfigParser.ParsingError, inst:
146 msg = _("Failed to parse %s\n%s") % (f, inst)
146 msg = _("Failed to parse %s\n%s") % (f, inst)
147 if trusted:
147 if trusted:
148 raise util.Abort(msg)
148 raise util.Abort(msg)
149 self.warn(_("Ignored: %s\n") % msg)
149 self.warn(_("Ignored: %s\n") % msg)
150
150
151 if trusted:
151 if trusted:
152 if cdata != self.cdata:
152 if cdata != self.cdata:
153 updateconfig(cdata, self.cdata)
153 updateconfig(cdata, self.cdata)
154 if self.ucdata is not None:
154 if self.ucdata is not None:
155 updateconfig(cdata, self.ucdata)
155 updateconfig(cdata, self.ucdata)
156 # override data from config files with data set with ui.setconfig
156 # override data from config files with data set with ui.setconfig
157 if self.overlay:
157 if self.overlay:
158 updateconfig(self.overlay, self.cdata)
158 updateconfig(self.overlay, self.cdata)
159 if root is None:
159 if root is None:
160 root = os.path.expanduser('~')
160 root = os.path.expanduser('~')
161 self.fixconfig(root=root)
161 self.fixconfig(root=root)
162
162
163 def readsections(self, filename, *sections):
163 def readsections(self, filename, *sections):
164 """Read filename and add only the specified sections to the config data
164 """Read filename and add only the specified sections to the config data
165
165
166 The settings are added to the trusted config data.
166 The settings are added to the trusted config data.
167 """
167 """
168 if not sections:
168 if not sections:
169 return
169 return
170
170
171 cdata = util.configparser()
171 cdata = util.configparser()
172 try:
172 try:
173 try:
173 try:
174 fp = open(filename)
174 fp = open(filename)
175 except IOError, inst:
175 except IOError, inst:
176 raise util.Abort(_("unable to open %s: %s") %
176 raise util.Abort(_("unable to open %s: %s") %
177 (filename, getattr(inst, "strerror", inst)))
177 (filename, getattr(inst, "strerror", inst)))
178 try:
178 try:
179 cdata.readfp(fp, filename)
179 cdata.readfp(fp, filename)
180 finally:
180 finally:
181 fp.close()
181 fp.close()
182 except ConfigParser.ParsingError, inst:
182 except ConfigParser.ParsingError, inst:
183 raise util.Abort(_("failed to parse %s\n%s") % (filename, inst))
183 raise util.Abort(_("failed to parse %s\n%s") % (filename, inst))
184
184
185 for section in sections:
185 for section in sections:
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
188
189 updateconfig(cdata, self.cdata, sections)
189 updateconfig(cdata, self.cdata, sections)
190 if self.ucdata:
190 if self.ucdata:
191 updateconfig(cdata, self.ucdata, sections)
191 updateconfig(cdata, self.ucdata, sections)
192
192
193 def fixconfig(self, section=None, name=None, value=None, root=None):
193 def fixconfig(self, section=None, name=None, value=None, root=None):
194 # translate paths relative to root (or home) into absolute paths
194 # translate paths relative to root (or home) into absolute paths
195 if section is None or section == 'paths':
195 if section is None or section == 'paths':
196 if root is None:
196 if root is None:
197 root = os.getcwd()
197 root = os.getcwd()
198 items = section and [(name, value)] or []
198 items = section and [(name, value)] or []
199 for cdata in self.cdata, self.ucdata, self.overlay:
199 for cdata in self.cdata, self.ucdata, self.overlay:
200 if not cdata: continue
200 if not cdata: continue
201 if not items and cdata.has_section('paths'):
201 if not items and cdata.has_section('paths'):
202 pathsitems = cdata.items('paths')
202 pathsitems = cdata.items('paths')
203 else:
203 else:
204 pathsitems = items
204 pathsitems = items
205 for n, path in pathsitems:
205 for n, path in pathsitems:
206 if path and "://" not in path and not os.path.isabs(path):
206 if path and "://" not in path and not os.path.isabs(path):
207 cdata.set("paths", n, os.path.join(root, path))
207 cdata.set("paths", n, os.path.join(root, path))
208
208
209 # update verbosity/interactive/report_untrusted settings
209 # update verbosity/interactive/report_untrusted settings
210 if section is None or section == 'ui':
210 if section is None or section == 'ui':
211 if name is None or name in ('quiet', 'verbose', 'debug'):
211 if name is None or name in ('quiet', 'verbose', 'debug'):
212 self.verbosity_constraints()
212 self.verbosity_constraints()
213 if name is None or name == 'interactive':
213 if name is None or name == 'interactive':
214 self.interactive = self.configbool("ui", "interactive", None)
214 interactive = self.configbool("ui", "interactive", None)
215 if self.interactive is None:
215 if interactive is None and self.interactive:
216 self.interactive = self.isatty()
216 self.interactive = self.isatty()
217 else:
218 self.interactive = interactive
217 if name is None or name == 'report_untrusted':
219 if name is None or name == 'report_untrusted':
218 self.report_untrusted = (
220 self.report_untrusted = (
219 self.configbool("ui", "report_untrusted", True))
221 self.configbool("ui", "report_untrusted", True))
220
222
221 # update trust information
223 # update trust information
222 if (section is None or section == 'trusted') and self.trusted_users:
224 if (section is None or section == 'trusted') and self.trusted_users:
223 for user in self.configlist('trusted', 'users'):
225 for user in self.configlist('trusted', 'users'):
224 self.trusted_users[user] = 1
226 self.trusted_users[user] = 1
225 for group in self.configlist('trusted', 'groups'):
227 for group in self.configlist('trusted', 'groups'):
226 self.trusted_groups[group] = 1
228 self.trusted_groups[group] = 1
227
229
228 def setconfig(self, section, name, value):
230 def setconfig(self, section, name, value):
229 if not self.overlay:
231 if not self.overlay:
230 self.overlay = util.configparser()
232 self.overlay = util.configparser()
231 for cdata in (self.overlay, self.cdata, self.ucdata):
233 for cdata in (self.overlay, self.cdata, self.ucdata):
232 if not cdata: continue
234 if not cdata: continue
233 if not cdata.has_section(section):
235 if not cdata.has_section(section):
234 cdata.add_section(section)
236 cdata.add_section(section)
235 cdata.set(section, name, value)
237 cdata.set(section, name, value)
236 self.fixconfig(section, name, value)
238 self.fixconfig(section, name, value)
237
239
238 def _get_cdata(self, untrusted):
240 def _get_cdata(self, untrusted):
239 if untrusted and self.ucdata:
241 if untrusted and self.ucdata:
240 return self.ucdata
242 return self.ucdata
241 return self.cdata
243 return self.cdata
242
244
243 def _config(self, section, name, default, funcname, untrusted, abort):
245 def _config(self, section, name, default, funcname, untrusted, abort):
244 cdata = self._get_cdata(untrusted)
246 cdata = self._get_cdata(untrusted)
245 if cdata.has_option(section, name):
247 if cdata.has_option(section, name):
246 try:
248 try:
247 func = getattr(cdata, funcname)
249 func = getattr(cdata, funcname)
248 return func(section, name)
250 return func(section, name)
249 except (ConfigParser.InterpolationError, ValueError), inst:
251 except (ConfigParser.InterpolationError, ValueError), inst:
250 msg = _("Error in configuration section [%s] "
252 msg = _("Error in configuration section [%s] "
251 "parameter '%s':\n%s") % (section, name, inst)
253 "parameter '%s':\n%s") % (section, name, inst)
252 if abort:
254 if abort:
253 raise util.Abort(msg)
255 raise util.Abort(msg)
254 self.warn(_("Ignored: %s\n") % msg)
256 self.warn(_("Ignored: %s\n") % msg)
255 return default
257 return default
256
258
257 def _configcommon(self, section, name, default, funcname, untrusted):
259 def _configcommon(self, section, name, default, funcname, untrusted):
258 value = self._config(section, name, default, funcname,
260 value = self._config(section, name, default, funcname,
259 untrusted, abort=True)
261 untrusted, abort=True)
260 if self.debugflag and not untrusted and self.ucdata:
262 if self.debugflag and not untrusted and self.ucdata:
261 uvalue = self._config(section, name, None, funcname,
263 uvalue = self._config(section, name, None, funcname,
262 untrusted=True, abort=False)
264 untrusted=True, abort=False)
263 if uvalue is not None and uvalue != value:
265 if uvalue is not None and uvalue != value:
264 self.warn(_("Ignoring untrusted configuration option "
266 self.warn(_("Ignoring untrusted configuration option "
265 "%s.%s = %s\n") % (section, name, uvalue))
267 "%s.%s = %s\n") % (section, name, uvalue))
266 return value
268 return value
267
269
268 def config(self, section, name, default=None, untrusted=False):
270 def config(self, section, name, default=None, untrusted=False):
269 return self._configcommon(section, name, default, 'get', untrusted)
271 return self._configcommon(section, name, default, 'get', untrusted)
270
272
271 def configbool(self, section, name, default=False, untrusted=False):
273 def configbool(self, section, name, default=False, untrusted=False):
272 return self._configcommon(section, name, default, 'getboolean',
274 return self._configcommon(section, name, default, 'getboolean',
273 untrusted)
275 untrusted)
274
276
275 def configlist(self, section, name, default=None, untrusted=False):
277 def configlist(self, section, name, default=None, untrusted=False):
276 """Return a list of comma/space separated strings"""
278 """Return a list of comma/space separated strings"""
277 result = self.config(section, name, untrusted=untrusted)
279 result = self.config(section, name, untrusted=untrusted)
278 if result is None:
280 if result is None:
279 result = default or []
281 result = default or []
280 if isinstance(result, basestring):
282 if isinstance(result, basestring):
281 result = result.replace(",", " ").split()
283 result = result.replace(",", " ").split()
282 return result
284 return result
283
285
284 def has_section(self, section, untrusted=False):
286 def has_section(self, section, untrusted=False):
285 '''tell whether section exists in config.'''
287 '''tell whether section exists in config.'''
286 cdata = self._get_cdata(untrusted)
288 cdata = self._get_cdata(untrusted)
287 return cdata.has_section(section)
289 return cdata.has_section(section)
288
290
289 def _configitems(self, section, untrusted, abort):
291 def _configitems(self, section, untrusted, abort):
290 items = {}
292 items = {}
291 cdata = self._get_cdata(untrusted)
293 cdata = self._get_cdata(untrusted)
292 if cdata.has_section(section):
294 if cdata.has_section(section):
293 try:
295 try:
294 items.update(dict(cdata.items(section)))
296 items.update(dict(cdata.items(section)))
295 except ConfigParser.InterpolationError, inst:
297 except ConfigParser.InterpolationError, inst:
296 msg = _("Error in configuration section [%s]:\n"
298 msg = _("Error in configuration section [%s]:\n"
297 "%s") % (section, inst)
299 "%s") % (section, inst)
298 if abort:
300 if abort:
299 raise util.Abort(msg)
301 raise util.Abort(msg)
300 self.warn(_("Ignored: %s\n") % msg)
302 self.warn(_("Ignored: %s\n") % msg)
301 return items
303 return items
302
304
303 def configitems(self, section, untrusted=False):
305 def configitems(self, section, untrusted=False):
304 items = self._configitems(section, untrusted=untrusted, abort=True)
306 items = self._configitems(section, untrusted=untrusted, abort=True)
305 if self.debugflag and not untrusted and self.ucdata:
307 if self.debugflag and not untrusted and self.ucdata:
306 uitems = self._configitems(section, untrusted=True, abort=False)
308 uitems = self._configitems(section, untrusted=True, abort=False)
307 keys = uitems.keys()
309 keys = uitems.keys()
308 keys.sort()
310 keys.sort()
309 for k in keys:
311 for k in keys:
310 if uitems[k] != items.get(k):
312 if uitems[k] != items.get(k):
311 self.warn(_("Ignoring untrusted configuration option "
313 self.warn(_("Ignoring untrusted configuration option "
312 "%s.%s = %s\n") % (section, k, uitems[k]))
314 "%s.%s = %s\n") % (section, k, uitems[k]))
313 x = items.items()
315 x = items.items()
314 x.sort()
316 x.sort()
315 return x
317 return x
316
318
317 def walkconfig(self, untrusted=False):
319 def walkconfig(self, untrusted=False):
318 cdata = self._get_cdata(untrusted)
320 cdata = self._get_cdata(untrusted)
319 sections = cdata.sections()
321 sections = cdata.sections()
320 sections.sort()
322 sections.sort()
321 for section in sections:
323 for section in sections:
322 for name, value in self.configitems(section, untrusted):
324 for name, value in self.configitems(section, untrusted):
323 yield section, name, str(value).replace('\n', '\\n')
325 yield section, name, str(value).replace('\n', '\\n')
324
326
325 def username(self):
327 def username(self):
326 """Return default username to be used in commits.
328 """Return default username to be used in commits.
327
329
328 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
330 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
329 and stop searching if one of these is set.
331 and stop searching if one of these is set.
330 If not found, use ($LOGNAME or $USER or $LNAME or
332 If not found, use ($LOGNAME or $USER or $LNAME or
331 $USERNAME) +"@full.hostname".
333 $USERNAME) +"@full.hostname".
332 """
334 """
333 user = os.environ.get("HGUSER")
335 user = os.environ.get("HGUSER")
334 if user is None:
336 if user is None:
335 user = self.config("ui", "username")
337 user = self.config("ui", "username")
336 if user is None:
338 if user is None:
337 user = os.environ.get("EMAIL")
339 user = os.environ.get("EMAIL")
338 if user is None:
340 if user is None:
339 try:
341 try:
340 user = '%s@%s' % (util.getuser(), socket.getfqdn())
342 user = '%s@%s' % (util.getuser(), socket.getfqdn())
341 self.warn(_("No username found, using '%s' instead\n") % user)
343 self.warn(_("No username found, using '%s' instead\n") % user)
342 except KeyError:
344 except KeyError:
343 pass
345 pass
344 if not user:
346 if not user:
345 raise util.Abort(_("Please specify a username."))
347 raise util.Abort(_("Please specify a username."))
346 return user
348 return user
347
349
348 def shortuser(self, user):
350 def shortuser(self, user):
349 """Return a short representation of a user name or email address."""
351 """Return a short representation of a user name or email address."""
350 if not self.verbose: user = util.shortuser(user)
352 if not self.verbose: user = util.shortuser(user)
351 return user
353 return user
352
354
353 def expandpath(self, loc, default=None):
355 def expandpath(self, loc, default=None):
354 """Return repository location relative to cwd or from [paths]"""
356 """Return repository location relative to cwd or from [paths]"""
355 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
357 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
356 return loc
358 return loc
357
359
358 path = self.config("paths", loc)
360 path = self.config("paths", loc)
359 if not path and default is not None:
361 if not path and default is not None:
360 path = self.config("paths", default)
362 path = self.config("paths", default)
361 return path or loc
363 return path or loc
362
364
363 def pushbuffer(self):
365 def pushbuffer(self):
364 self.buffers.append([])
366 self.buffers.append([])
365
367
366 def popbuffer(self):
368 def popbuffer(self):
367 return "".join(self.buffers.pop())
369 return "".join(self.buffers.pop())
368
370
369 def write(self, *args):
371 def write(self, *args):
370 if self.buffers:
372 if self.buffers:
371 self.buffers[-1].extend([str(a) for a in args])
373 self.buffers[-1].extend([str(a) for a in args])
372 else:
374 else:
373 for a in args:
375 for a in args:
374 sys.stdout.write(str(a))
376 sys.stdout.write(str(a))
375
377
376 def write_err(self, *args):
378 def write_err(self, *args):
377 try:
379 try:
378 if not sys.stdout.closed: sys.stdout.flush()
380 if not sys.stdout.closed: sys.stdout.flush()
379 for a in args:
381 for a in args:
380 sys.stderr.write(str(a))
382 sys.stderr.write(str(a))
381 # stderr may be buffered under win32 when redirected to files,
383 # stderr may be buffered under win32 when redirected to files,
382 # including stdout.
384 # including stdout.
383 if not sys.stderr.closed: sys.stderr.flush()
385 if not sys.stderr.closed: sys.stderr.flush()
384 except IOError, inst:
386 except IOError, inst:
385 if inst.errno != errno.EPIPE:
387 if inst.errno != errno.EPIPE:
386 raise
388 raise
387
389
388 def flush(self):
390 def flush(self):
389 try: sys.stdout.flush()
391 try: sys.stdout.flush()
390 except: pass
392 except: pass
391 try: sys.stderr.flush()
393 try: sys.stderr.flush()
392 except: pass
394 except: pass
393
395
394 def readline(self, prompt=''):
396 def _readline(self, prompt=''):
395 if self.isatty():
397 if self.isatty():
396 try:
398 try:
397 # magically add command line editing support, where
399 # magically add command line editing support, where
398 # available
400 # available
399 import readline
401 import readline
400 # force demandimport to really load the module
402 # force demandimport to really load the module
401 readline.read_history_file
403 readline.read_history_file
402 except ImportError:
404 except ImportError:
403 pass
405 pass
404 return raw_input(prompt)
406 return raw_input(prompt)
405
407
406 def prompt(self, msg, pat=None, default="y", matchflags=0):
408 def prompt(self, msg, pat=None, default="y", matchflags=0):
407 if not self.interactive: return default
409 if not self.interactive: return default
408 try:
410 try:
409 r = self.readline(msg + ' ')
411 r = self._readline(msg + ' ')
410 if not pat or re.match(pat, r, matchflags):
412 if not pat or re.match(pat, r, matchflags):
411 return r
413 return r
412 else:
414 else:
413 self.write(_("unrecognized response\n"))
415 self.write(_("unrecognized response\n"))
414 except EOFError:
416 except EOFError:
415 raise util.Abort(_('response expected'))
417 raise util.Abort(_('response expected'))
416
418
417 def getpass(self, prompt=None, default=None):
419 def getpass(self, prompt=None, default=None):
418 if not self.interactive: return default
420 if not self.interactive: return default
419 return getpass.getpass(prompt or _('password: '))
421 return getpass.getpass(prompt or _('password: '))
420 def status(self, *msg):
422 def status(self, *msg):
421 if not self.quiet: self.write(*msg)
423 if not self.quiet: self.write(*msg)
422 def warn(self, *msg):
424 def warn(self, *msg):
423 self.write_err(*msg)
425 self.write_err(*msg)
424 def note(self, *msg):
426 def note(self, *msg):
425 if self.verbose: self.write(*msg)
427 if self.verbose: self.write(*msg)
426 def debug(self, *msg):
428 def debug(self, *msg):
427 if self.debugflag: self.write(*msg)
429 if self.debugflag: self.write(*msg)
428 def edit(self, text, user):
430 def edit(self, text, user):
429 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
431 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
430 text=True)
432 text=True)
431 try:
433 try:
432 f = os.fdopen(fd, "w")
434 f = os.fdopen(fd, "w")
433 f.write(text)
435 f.write(text)
434 f.close()
436 f.close()
435
437
436 editor = (os.environ.get("HGEDITOR") or
438 editor = (os.environ.get("HGEDITOR") or
437 self.config("ui", "editor") or
439 self.config("ui", "editor") or
438 os.environ.get("EDITOR", "vi"))
440 os.environ.get("EDITOR", "vi"))
439
441
440 util.system("%s \"%s\"" % (editor, name),
442 util.system("%s \"%s\"" % (editor, name),
441 environ={'HGUSER': user},
443 environ={'HGUSER': user},
442 onerr=util.Abort, errprefix=_("edit failed"))
444 onerr=util.Abort, errprefix=_("edit failed"))
443
445
444 f = open(name)
446 f = open(name)
445 t = f.read()
447 t = f.read()
446 f.close()
448 f.close()
447 t = re.sub("(?m)^HG:.*\n", "", t)
449 t = re.sub("(?m)^HG:.*\n", "", t)
448 finally:
450 finally:
449 os.unlink(name)
451 os.unlink(name)
450
452
451 return t
453 return t
452
454
453 def print_exc(self):
455 def print_exc(self):
454 '''print exception traceback if traceback printing enabled.
456 '''print exception traceback if traceback printing enabled.
455 only to call in exception handler. returns true if traceback
457 only to call in exception handler. returns true if traceback
456 printed.'''
458 printed.'''
457 if self.traceback:
459 if self.traceback:
458 traceback.print_exc()
460 traceback.print_exc()
459 return self.traceback
461 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now