##// END OF EJS Templates
Merge with crew
Matt Mackall -
r4218:2216535f merge default
parent child Browse files
Show More
@@ -1,454 +1,454 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 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 gettext as _
8 from i18n import gettext as _
9 from demandload import *
9 from demandload import *
10 demandload(globals(), "errno getpass os re socket sys tempfile")
10 demandload(globals(), "errno getpass os re socket sys tempfile")
11 demandload(globals(), "ConfigParser traceback util")
11 demandload(globals(), "ConfigParser traceback util")
12
12
13 def dupconfig(orig):
13 def dupconfig(orig):
14 new = util.configparser(orig.defaults())
14 new = util.configparser(orig.defaults())
15 updateconfig(orig, new)
15 updateconfig(orig, new)
16 return new
16 return new
17
17
18 def updateconfig(source, dest, sections=None):
18 def updateconfig(source, dest, sections=None):
19 if not sections:
19 if not sections:
20 sections = source.sections()
20 sections = source.sections()
21 for section in sections:
21 for section in sections:
22 if not dest.has_section(section):
22 if not dest.has_section(section):
23 dest.add_section(section)
23 dest.add_section(section)
24 for name, value in source.items(section, raw=True):
24 for name, value in source.items(section, raw=True):
25 dest.set(section, name, value)
25 dest.set(section, name, value)
26
26
27 class ui(object):
27 class ui(object):
28 def __init__(self, verbose=False, debug=False, quiet=False,
28 def __init__(self, verbose=False, debug=False, quiet=False,
29 interactive=True, traceback=False, report_untrusted=True,
29 interactive=True, traceback=False, report_untrusted=True,
30 parentui=None):
30 parentui=None):
31 self.overlay = None
31 self.overlay = None
32 self.buffers = []
32 self.buffers = []
33 if parentui is None:
33 if parentui is None:
34 # this is the parent of all ui children
34 # this is the parent of all ui children
35 self.parentui = None
35 self.parentui = None
36 self.readhooks = []
36 self.readhooks = []
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.readhooks = self.parentui.readhooks[:]
56 self.readhooks = self.parentui.readhooks[:]
57 self.trusted_users = parentui.trusted_users.copy()
57 self.trusted_users = parentui.trusted_users.copy()
58 self.trusted_groups = parentui.trusted_groups.copy()
58 self.trusted_groups = parentui.trusted_groups.copy()
59 self.cdata = dupconfig(self.parentui.cdata)
59 self.cdata = dupconfig(self.parentui.cdata)
60 if self.parentui.ucdata:
60 if self.parentui.ucdata:
61 self.ucdata = dupconfig(self.parentui.ucdata)
61 self.ucdata = dupconfig(self.parentui.ucdata)
62 if self.parentui.overlay:
62 if self.parentui.overlay:
63 self.overlay = dupconfig(self.parentui.overlay)
63 self.overlay = dupconfig(self.parentui.overlay)
64
64
65 def __getattr__(self, key):
65 def __getattr__(self, key):
66 return getattr(self.parentui, key)
66 return getattr(self.parentui, key)
67
67
68 def updateopts(self, verbose=False, debug=False, quiet=False,
68 def updateopts(self, verbose=False, debug=False, quiet=False,
69 interactive=True, traceback=False, config=[]):
69 interactive=True, traceback=False, config=[]):
70 for section, name, value in config:
70 for section, name, value in config:
71 self.setconfig(section, name, value)
71 self.setconfig(section, name, value)
72
72
73 if quiet or verbose or debug:
73 if quiet or verbose or debug:
74 self.setconfig('ui', 'quiet', str(bool(quiet)))
74 self.setconfig('ui', 'quiet', str(bool(quiet)))
75 self.setconfig('ui', 'verbose', str(bool(verbose)))
75 self.setconfig('ui', 'verbose', str(bool(verbose)))
76 self.setconfig('ui', 'debug', str(bool(debug)))
76 self.setconfig('ui', 'debug', str(bool(debug)))
77
77
78 self.verbosity_constraints()
78 self.verbosity_constraints()
79
79
80 if not interactive:
80 if not interactive:
81 self.setconfig('ui', 'interactive', 'False')
81 self.setconfig('ui', 'interactive', 'False')
82 self.interactive = False
82 self.interactive = False
83
83
84 self.traceback = self.traceback or traceback
84 self.traceback = self.traceback or traceback
85
85
86 def verbosity_constraints(self):
86 def verbosity_constraints(self):
87 self.quiet = self.configbool('ui', 'quiet')
87 self.quiet = self.configbool('ui', 'quiet')
88 self.verbose = self.configbool('ui', 'verbose')
88 self.verbose = self.configbool('ui', 'verbose')
89 self.debugflag = self.configbool('ui', 'debug')
89 self.debugflag = self.configbool('ui', 'debug')
90
90
91 if self.debugflag:
91 if self.debugflag:
92 self.verbose = True
92 self.verbose = True
93 self.quiet = False
93 self.quiet = False
94 elif self.verbose and self.quiet:
94 elif self.verbose and self.quiet:
95 self.quiet = self.verbose = False
95 self.quiet = self.verbose = False
96
96
97 def _is_trusted(self, fp, f, warn=True):
97 def _is_trusted(self, fp, f, warn=True):
98 if not self.check_trusted:
98 if not self.check_trusted:
99 return True
99 return True
100 st = util.fstat(fp)
100 st = util.fstat(fp)
101 if util.isowner(fp, st):
101 if util.isowner(fp, st):
102 return True
102 return True
103 tusers = self.trusted_users
103 tusers = self.trusted_users
104 tgroups = self.trusted_groups
104 tgroups = self.trusted_groups
105 if not tusers:
105 if not tusers:
106 user = util.username()
106 user = util.username()
107 if user is not None:
107 if user is not None:
108 self.trusted_users[user] = 1
108 self.trusted_users[user] = 1
109 self.fixconfig(section='trusted')
109 self.fixconfig(section='trusted')
110 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
110 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
111 user = util.username(st.st_uid)
111 user = util.username(st.st_uid)
112 group = util.groupname(st.st_gid)
112 group = util.groupname(st.st_gid)
113 if user not in tusers and group not in tgroups:
113 if user not in tusers and group not in tgroups:
114 if warn and self.report_untrusted:
114 if warn and self.report_untrusted:
115 self.warn(_('Not trusting file %s from untrusted '
115 self.warn(_('Not trusting file %s from untrusted '
116 'user %s, group %s\n') % (f, user, group))
116 'user %s, group %s\n') % (f, user, group))
117 return False
117 return False
118 return True
118 return True
119
119
120 def readconfig(self, fn, root=None):
120 def readconfig(self, fn, root=None):
121 if isinstance(fn, basestring):
121 if isinstance(fn, basestring):
122 fn = [fn]
122 fn = [fn]
123 for f in fn:
123 for f in fn:
124 try:
124 try:
125 fp = open(f)
125 fp = open(f)
126 except IOError:
126 except IOError:
127 continue
127 continue
128 cdata = self.cdata
128 cdata = self.cdata
129 trusted = self._is_trusted(fp, f)
129 trusted = self._is_trusted(fp, f)
130 if not trusted:
130 if not trusted:
131 if self.ucdata is None:
131 if self.ucdata is None:
132 self.ucdata = dupconfig(self.cdata)
132 self.ucdata = dupconfig(self.cdata)
133 cdata = self.ucdata
133 cdata = self.ucdata
134 elif self.ucdata is not None:
134 elif self.ucdata is not None:
135 # use a separate configparser, so that we don't accidentally
135 # use a separate configparser, so that we don't accidentally
136 # override ucdata settings later on.
136 # override ucdata settings later on.
137 cdata = util.configparser()
137 cdata = util.configparser()
138
138
139 try:
139 try:
140 cdata.readfp(fp, f)
140 cdata.readfp(fp, f)
141 except ConfigParser.ParsingError, inst:
141 except ConfigParser.ParsingError, inst:
142 msg = _("Failed to parse %s\n%s") % (f, inst)
142 msg = _("Failed to parse %s\n%s") % (f, inst)
143 if trusted:
143 if trusted:
144 raise util.Abort(msg)
144 raise util.Abort(msg)
145 self.warn(_("Ignored: %s\n") % msg)
145 self.warn(_("Ignored: %s\n") % msg)
146
146
147 if trusted:
147 if trusted:
148 if cdata != self.cdata:
148 if cdata != self.cdata:
149 updateconfig(cdata, self.cdata)
149 updateconfig(cdata, self.cdata)
150 if self.ucdata is not None:
150 if self.ucdata is not None:
151 updateconfig(cdata, self.ucdata)
151 updateconfig(cdata, self.ucdata)
152 # override data from config files with data set with ui.setconfig
152 # override data from config files with data set with ui.setconfig
153 if self.overlay:
153 if self.overlay:
154 updateconfig(self.overlay, self.cdata)
154 updateconfig(self.overlay, self.cdata)
155 if root is None:
155 if root is None:
156 root = os.path.expanduser('~')
156 root = os.path.expanduser('~')
157 self.fixconfig(root=root)
157 self.fixconfig(root=root)
158 for hook in self.readhooks:
158 for hook in self.readhooks:
159 hook(self)
159 hook(self)
160
160
161 def addreadhook(self, hook):
161 def addreadhook(self, hook):
162 self.readhooks.append(hook)
162 self.readhooks.append(hook)
163
163
164 def readsections(self, filename, *sections):
164 def readsections(self, filename, *sections):
165 """Read filename and add only the specified sections to the config data
165 """Read filename and add only the specified sections to the config data
166
166
167 The settings are added to the trusted config data.
167 The settings are added to the trusted config data.
168 """
168 """
169 if not sections:
169 if not sections:
170 return
170 return
171
171
172 cdata = util.configparser()
172 cdata = util.configparser()
173 try:
173 try:
174 cdata.read(filename)
174 cdata.read(filename)
175 except ConfigParser.ParsingError, inst:
175 except ConfigParser.ParsingError, inst:
176 raise util.Abort(_("failed to parse %s\n%s") % (filename,
176 raise util.Abort(_("failed to parse %s\n%s") % (filename,
177 inst))
177 inst))
178
178
179 for section in sections:
179 for section in sections:
180 if not cdata.has_section(section):
180 if not cdata.has_section(section):
181 cdata.add_section(section)
181 cdata.add_section(section)
182
182
183 updateconfig(cdata, self.cdata, sections)
183 updateconfig(cdata, self.cdata, sections)
184 if self.ucdata:
184 if self.ucdata:
185 updateconfig(cdata, self.ucdata, sections)
185 updateconfig(cdata, self.ucdata, sections)
186
186
187 def fixconfig(self, section=None, name=None, value=None, root=None):
187 def fixconfig(self, section=None, name=None, value=None, root=None):
188 # translate paths relative to root (or home) into absolute paths
188 # translate paths relative to root (or home) into absolute paths
189 if section is None or section == 'paths':
189 if section is None or section == 'paths':
190 if root is None:
190 if root is None:
191 root = os.getcwd()
191 root = os.getcwd()
192 items = section and [(name, value)] or []
192 items = section and [(name, value)] or []
193 for cdata in self.cdata, self.ucdata, self.overlay:
193 for cdata in self.cdata, self.ucdata, self.overlay:
194 if not cdata: continue
194 if not cdata: continue
195 if not items and cdata.has_section('paths'):
195 if not items and cdata.has_section('paths'):
196 pathsitems = cdata.items('paths')
196 pathsitems = cdata.items('paths')
197 else:
197 else:
198 pathsitems = items
198 pathsitems = items
199 for n, path in pathsitems:
199 for n, path in pathsitems:
200 if path and "://" not in path and not os.path.isabs(path):
200 if path and "://" not in path and not os.path.isabs(path):
201 cdata.set("paths", n, os.path.join(root, path))
201 cdata.set("paths", n, os.path.join(root, path))
202
202
203 # update quiet/verbose/debug and interactive status
203 # update quiet/verbose/debug and interactive status
204 if section is None or section == 'ui':
204 if section is None or section == 'ui':
205 if name is None or name in ('quiet', 'verbose', 'debug'):
205 if name is None or name in ('quiet', 'verbose', 'debug'):
206 self.verbosity_constraints()
206 self.verbosity_constraints()
207
207
208 if name is None or name == 'interactive':
208 if name is None or name == 'interactive':
209 self.interactive = self.configbool("ui", "interactive", True)
209 self.interactive = self.configbool("ui", "interactive", True)
210
210
211 # update trust information
211 # update trust information
212 if (section is None or section == 'trusted') and self.trusted_users:
212 if (section is None or section == 'trusted') and self.trusted_users:
213 for user in self.configlist('trusted', 'users'):
213 for user in self.configlist('trusted', 'users'):
214 self.trusted_users[user] = 1
214 self.trusted_users[user] = 1
215 for group in self.configlist('trusted', 'groups'):
215 for group in self.configlist('trusted', 'groups'):
216 self.trusted_groups[group] = 1
216 self.trusted_groups[group] = 1
217
217
218 def setconfig(self, section, name, value):
218 def setconfig(self, section, name, value):
219 if not self.overlay:
219 if not self.overlay:
220 self.overlay = util.configparser()
220 self.overlay = util.configparser()
221 for cdata in (self.overlay, self.cdata, self.ucdata):
221 for cdata in (self.overlay, self.cdata, self.ucdata):
222 if not cdata: continue
222 if not cdata: continue
223 if not cdata.has_section(section):
223 if not cdata.has_section(section):
224 cdata.add_section(section)
224 cdata.add_section(section)
225 cdata.set(section, name, value)
225 cdata.set(section, name, value)
226 self.fixconfig(section, name, value)
226 self.fixconfig(section, name, value)
227
227
228 def _get_cdata(self, untrusted):
228 def _get_cdata(self, untrusted):
229 if untrusted and self.ucdata:
229 if untrusted and self.ucdata:
230 return self.ucdata
230 return self.ucdata
231 return self.cdata
231 return self.cdata
232
232
233 def _config(self, section, name, default, funcname, untrusted, abort):
233 def _config(self, section, name, default, funcname, untrusted, abort):
234 cdata = self._get_cdata(untrusted)
234 cdata = self._get_cdata(untrusted)
235 if cdata.has_option(section, name):
235 if cdata.has_option(section, name):
236 try:
236 try:
237 func = getattr(cdata, funcname)
237 func = getattr(cdata, funcname)
238 return func(section, name)
238 return func(section, name)
239 except ConfigParser.InterpolationError, inst:
239 except ConfigParser.InterpolationError, inst:
240 msg = _("Error in configuration section [%s] "
240 msg = _("Error in configuration section [%s] "
241 "parameter '%s':\n%s") % (section, name, inst)
241 "parameter '%s':\n%s") % (section, name, inst)
242 if abort:
242 if abort:
243 raise util.Abort(msg)
243 raise util.Abort(msg)
244 self.warn(_("Ignored: %s\n") % msg)
244 self.warn(_("Ignored: %s\n") % msg)
245 return default
245 return default
246
246
247 def _configcommon(self, section, name, default, funcname, untrusted):
247 def _configcommon(self, section, name, default, funcname, untrusted):
248 value = self._config(section, name, default, funcname,
248 value = self._config(section, name, default, funcname,
249 untrusted, abort=True)
249 untrusted, abort=True)
250 if self.debugflag and not untrusted and self.ucdata:
250 if self.debugflag and not untrusted and self.ucdata:
251 uvalue = self._config(section, name, None, funcname,
251 uvalue = self._config(section, name, None, funcname,
252 untrusted=True, abort=False)
252 untrusted=True, abort=False)
253 if uvalue is not None and uvalue != value:
253 if uvalue is not None and uvalue != value:
254 self.warn(_("Ignoring untrusted configuration option "
254 self.warn(_("Ignoring untrusted configuration option "
255 "%s.%s = %s\n") % (section, name, uvalue))
255 "%s.%s = %s\n") % (section, name, uvalue))
256 return value
256 return value
257
257
258 def config(self, section, name, default=None, untrusted=False):
258 def config(self, section, name, default=None, untrusted=False):
259 return self._configcommon(section, name, default, 'get', untrusted)
259 return self._configcommon(section, name, default, 'get', untrusted)
260
260
261 def configbool(self, section, name, default=False, untrusted=False):
261 def configbool(self, section, name, default=False, untrusted=False):
262 return self._configcommon(section, name, default, 'getboolean',
262 return self._configcommon(section, name, default, 'getboolean',
263 untrusted)
263 untrusted)
264
264
265 def configlist(self, section, name, default=None, untrusted=False):
265 def configlist(self, section, name, default=None, untrusted=False):
266 """Return a list of comma/space separated strings"""
266 """Return a list of comma/space separated strings"""
267 result = self.config(section, name, untrusted=untrusted)
267 result = self.config(section, name, untrusted=untrusted)
268 if result is None:
268 if result is None:
269 result = default or []
269 result = default or []
270 if isinstance(result, basestring):
270 if isinstance(result, basestring):
271 result = result.replace(",", " ").split()
271 result = result.replace(",", " ").split()
272 return result
272 return result
273
273
274 def has_config(self, section, untrusted=False):
274 def has_config(self, section, untrusted=False):
275 '''tell whether section exists in config.'''
275 '''tell whether section exists in config.'''
276 cdata = self._get_cdata(untrusted)
276 cdata = self._get_cdata(untrusted)
277 return cdata.has_section(section)
277 return cdata.has_section(section)
278
278
279 def _configitems(self, section, untrusted, abort):
279 def _configitems(self, section, untrusted, abort):
280 items = {}
280 items = {}
281 cdata = self._get_cdata(untrusted)
281 cdata = self._get_cdata(untrusted)
282 if cdata.has_section(section):
282 if cdata.has_section(section):
283 try:
283 try:
284 items.update(dict(cdata.items(section)))
284 items.update(dict(cdata.items(section)))
285 except ConfigParser.InterpolationError, inst:
285 except ConfigParser.InterpolationError, inst:
286 msg = _("Error in configuration section [%s]:\n"
286 msg = _("Error in configuration section [%s]:\n"
287 "%s") % (section, inst)
287 "%s") % (section, inst)
288 if abort:
288 if abort:
289 raise util.Abort(msg)
289 raise util.Abort(msg)
290 self.warn(_("Ignored: %s\n") % msg)
290 self.warn(_("Ignored: %s\n") % msg)
291 return items
291 return items
292
292
293 def configitems(self, section, untrusted=False):
293 def configitems(self, section, untrusted=False):
294 items = self._configitems(section, untrusted=untrusted, abort=True)
294 items = self._configitems(section, untrusted=untrusted, abort=True)
295 if self.debugflag and not untrusted and self.ucdata:
295 if self.debugflag and not untrusted and self.ucdata:
296 uitems = self._configitems(section, untrusted=True, abort=False)
296 uitems = self._configitems(section, untrusted=True, abort=False)
297 keys = uitems.keys()
297 keys = uitems.keys()
298 keys.sort()
298 keys.sort()
299 for k in keys:
299 for k in keys:
300 if uitems[k] != items.get(k):
300 if uitems[k] != items.get(k):
301 self.warn(_("Ignoring untrusted configuration option "
301 self.warn(_("Ignoring untrusted configuration option "
302 "%s.%s = %s\n") % (section, k, uitems[k]))
302 "%s.%s = %s\n") % (section, k, uitems[k]))
303 x = items.items()
303 x = items.items()
304 x.sort()
304 x.sort()
305 return x
305 return x
306
306
307 def walkconfig(self, untrusted=False):
307 def walkconfig(self, untrusted=False):
308 cdata = self._get_cdata(untrusted)
308 cdata = self._get_cdata(untrusted)
309 sections = cdata.sections()
309 sections = cdata.sections()
310 sections.sort()
310 sections.sort()
311 for section in sections:
311 for section in sections:
312 for name, value in self.configitems(section, untrusted):
312 for name, value in self.configitems(section, untrusted):
313 yield section, name, value.replace('\n', '\\n')
313 yield section, name, value.replace('\n', '\\n')
314
314
315 def extensions(self):
315 def extensions(self):
316 result = self.configitems("extensions")
316 result = self.configitems("extensions")
317 for i, (key, value) in enumerate(result):
317 for i, (key, value) in enumerate(result):
318 if value:
318 if value:
319 result[i] = (key, os.path.expanduser(value))
319 result[i] = (key, os.path.expanduser(value))
320 return result
320 return result
321
321
322 def hgignorefiles(self):
322 def hgignorefiles(self):
323 result = []
323 result = []
324 for key, value in self.configitems("ui"):
324 for key, value in self.configitems("ui"):
325 if key == 'ignore' or key.startswith('ignore.'):
325 if key == 'ignore' or key.startswith('ignore.'):
326 result.append(os.path.expanduser(value))
326 result.append(os.path.expanduser(value))
327 return result
327 return result
328
328
329 def configrevlog(self):
329 def configrevlog(self):
330 result = {}
330 result = {}
331 for key, value in self.configitems("revlog"):
331 for key, value in self.configitems("revlog"):
332 result[key.lower()] = value
332 result[key.lower()] = value
333 return result
333 return result
334
334
335 def username(self):
335 def username(self):
336 """Return default username to be used in commits.
336 """Return default username to be used in commits.
337
337
338 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
338 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
339 and stop searching if one of these is set.
339 and stop searching if one of these is set.
340 If not found, use ($LOGNAME or $USER or $LNAME or
340 If not found, use ($LOGNAME or $USER or $LNAME or
341 $USERNAME) +"@full.hostname".
341 $USERNAME) +"@full.hostname".
342 """
342 """
343 user = os.environ.get("HGUSER")
343 user = os.environ.get("HGUSER")
344 if user is None:
344 if user is None:
345 user = self.config("ui", "username")
345 user = self.config("ui", "username")
346 if user is None:
346 if user is None:
347 user = os.environ.get("EMAIL")
347 user = os.environ.get("EMAIL")
348 if user is None:
348 if user is None:
349 try:
349 try:
350 user = '%s@%s' % (util.getuser(), socket.getfqdn())
350 user = '%s@%s' % (util.getuser(), socket.getfqdn())
351 self.warn(_("No username found, using '%s' instead\n") % user)
351 self.warn(_("No username found, using '%s' instead\n") % user)
352 except KeyError:
352 except KeyError:
353 pass
353 pass
354 if not user:
354 if not user:
355 raise util.Abort(_("Please specify a username."))
355 raise util.Abort(_("Please specify a username."))
356 return user
356 return user
357
357
358 def shortuser(self, user):
358 def shortuser(self, user):
359 """Return a short representation of a user name or email address."""
359 """Return a short representation of a user name or email address."""
360 if not self.verbose: user = util.shortuser(user)
360 if not self.verbose: user = util.shortuser(user)
361 return user
361 return user
362
362
363 def expandpath(self, loc, default=None):
363 def expandpath(self, loc, default=None):
364 """Return repository location relative to cwd or from [paths]"""
364 """Return repository location relative to cwd or from [paths]"""
365 if "://" in loc or os.path.isdir(loc):
365 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
366 return loc
366 return loc
367
367
368 path = self.config("paths", loc)
368 path = self.config("paths", loc)
369 if not path and default is not None:
369 if not path and default is not None:
370 path = self.config("paths", default)
370 path = self.config("paths", default)
371 return path or loc
371 return path or loc
372
372
373 def pushbuffer(self):
373 def pushbuffer(self):
374 self.buffers.append([])
374 self.buffers.append([])
375
375
376 def popbuffer(self):
376 def popbuffer(self):
377 return "".join(self.buffers.pop())
377 return "".join(self.buffers.pop())
378
378
379 def write(self, *args):
379 def write(self, *args):
380 if self.buffers:
380 if self.buffers:
381 self.buffers[-1].extend([str(a) for a in args])
381 self.buffers[-1].extend([str(a) for a in args])
382 else:
382 else:
383 for a in args:
383 for a in args:
384 sys.stdout.write(str(a))
384 sys.stdout.write(str(a))
385
385
386 def write_err(self, *args):
386 def write_err(self, *args):
387 try:
387 try:
388 if not sys.stdout.closed: sys.stdout.flush()
388 if not sys.stdout.closed: sys.stdout.flush()
389 for a in args:
389 for a in args:
390 sys.stderr.write(str(a))
390 sys.stderr.write(str(a))
391 except IOError, inst:
391 except IOError, inst:
392 if inst.errno != errno.EPIPE:
392 if inst.errno != errno.EPIPE:
393 raise
393 raise
394
394
395 def flush(self):
395 def flush(self):
396 try: sys.stdout.flush()
396 try: sys.stdout.flush()
397 except: pass
397 except: pass
398 try: sys.stderr.flush()
398 try: sys.stderr.flush()
399 except: pass
399 except: pass
400
400
401 def readline(self):
401 def readline(self):
402 return sys.stdin.readline()[:-1]
402 return sys.stdin.readline()[:-1]
403 def prompt(self, msg, pat=None, default="y"):
403 def prompt(self, msg, pat=None, default="y"):
404 if not self.interactive: return default
404 if not self.interactive: return default
405 while 1:
405 while 1:
406 self.write(msg, " ")
406 self.write(msg, " ")
407 r = self.readline()
407 r = self.readline()
408 if not pat or re.match(pat, r):
408 if not pat or re.match(pat, r):
409 return r
409 return r
410 else:
410 else:
411 self.write(_("unrecognized response\n"))
411 self.write(_("unrecognized response\n"))
412 def getpass(self, prompt=None, default=None):
412 def getpass(self, prompt=None, default=None):
413 if not self.interactive: return default
413 if not self.interactive: return default
414 return getpass.getpass(prompt or _('password: '))
414 return getpass.getpass(prompt or _('password: '))
415 def status(self, *msg):
415 def status(self, *msg):
416 if not self.quiet: self.write(*msg)
416 if not self.quiet: self.write(*msg)
417 def warn(self, *msg):
417 def warn(self, *msg):
418 self.write_err(*msg)
418 self.write_err(*msg)
419 def note(self, *msg):
419 def note(self, *msg):
420 if self.verbose: self.write(*msg)
420 if self.verbose: self.write(*msg)
421 def debug(self, *msg):
421 def debug(self, *msg):
422 if self.debugflag: self.write(*msg)
422 if self.debugflag: self.write(*msg)
423 def edit(self, text, user):
423 def edit(self, text, user):
424 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
424 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
425 text=True)
425 text=True)
426 try:
426 try:
427 f = os.fdopen(fd, "w")
427 f = os.fdopen(fd, "w")
428 f.write(text)
428 f.write(text)
429 f.close()
429 f.close()
430
430
431 editor = (os.environ.get("HGEDITOR") or
431 editor = (os.environ.get("HGEDITOR") or
432 self.config("ui", "editor") or
432 self.config("ui", "editor") or
433 os.environ.get("EDITOR", "vi"))
433 os.environ.get("EDITOR", "vi"))
434
434
435 util.system("%s \"%s\"" % (editor, name),
435 util.system("%s \"%s\"" % (editor, name),
436 environ={'HGUSER': user},
436 environ={'HGUSER': user},
437 onerr=util.Abort, errprefix=_("edit failed"))
437 onerr=util.Abort, errprefix=_("edit failed"))
438
438
439 f = open(name)
439 f = open(name)
440 t = f.read()
440 t = f.read()
441 f.close()
441 f.close()
442 t = re.sub("(?m)^HG:.*\n", "", t)
442 t = re.sub("(?m)^HG:.*\n", "", t)
443 finally:
443 finally:
444 os.unlink(name)
444 os.unlink(name)
445
445
446 return t
446 return t
447
447
448 def print_exc(self):
448 def print_exc(self):
449 '''print exception traceback if traceback printing enabled.
449 '''print exception traceback if traceback printing enabled.
450 only to call in exception handler. returns true if traceback
450 only to call in exception handler. returns true if traceback
451 printed.'''
451 printed.'''
452 if self.traceback:
452 if self.traceback:
453 traceback.print_exc()
453 traceback.print_exc()
454 return self.traceback
454 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now