##// END OF EJS Templates
Removed unused imports of mdiff and templater from ui.py
Thomas Arendsen Hein -
r3385:9e834d03 default
parent child Browse files
Show More
@@ -1,323 +1,323
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 mdiff templater traceback util")
11 demandload(globals(), "ConfigParser traceback util")
12
12
13 def dupconfig(orig):
13 def dupconfig(orig):
14 new = ConfigParser.SafeConfigParser(orig.defaults())
14 new = ConfigParser.SafeConfigParser(orig.defaults())
15 updateconfig(orig, new)
15 updateconfig(orig, new)
16 return new
16 return new
17
17
18 def updateconfig(source, dest):
18 def updateconfig(source, dest):
19 for section in source.sections():
19 for section in source.sections():
20 if not dest.has_section(section):
20 if not dest.has_section(section):
21 dest.add_section(section)
21 dest.add_section(section)
22 for name, value in source.items(section, raw=True):
22 for name, value in source.items(section, raw=True):
23 dest.set(section, name, value)
23 dest.set(section, name, value)
24
24
25 class ui(object):
25 class ui(object):
26 def __init__(self, verbose=False, debug=False, quiet=False,
26 def __init__(self, verbose=False, debug=False, quiet=False,
27 interactive=True, traceback=False, parentui=None):
27 interactive=True, traceback=False, parentui=None):
28 self.overlay = None
28 self.overlay = None
29 self.header = []
29 self.header = []
30 self.prev_header = []
30 self.prev_header = []
31 if parentui is None:
31 if parentui is None:
32 # this is the parent of all ui children
32 # this is the parent of all ui children
33 self.parentui = None
33 self.parentui = None
34 self.readhooks = []
34 self.readhooks = []
35 self.quiet = quiet
35 self.quiet = quiet
36 self.verbose = verbose
36 self.verbose = verbose
37 self.debugflag = debug
37 self.debugflag = debug
38 self.interactive = interactive
38 self.interactive = interactive
39 self.traceback = traceback
39 self.traceback = traceback
40 self.cdata = ConfigParser.SafeConfigParser()
40 self.cdata = ConfigParser.SafeConfigParser()
41 self.readconfig(util.rcpath())
41 self.readconfig(util.rcpath())
42 self.updateopts(verbose, debug, quiet, interactive)
42 self.updateopts(verbose, debug, quiet, interactive)
43 else:
43 else:
44 # 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
45 self.parentui = parentui.parentui or parentui
45 self.parentui = parentui.parentui or parentui
46 self.readhooks = self.parentui.readhooks[:]
46 self.readhooks = self.parentui.readhooks[:]
47 self.cdata = dupconfig(self.parentui.cdata)
47 self.cdata = dupconfig(self.parentui.cdata)
48 if self.parentui.overlay:
48 if self.parentui.overlay:
49 self.overlay = dupconfig(self.parentui.overlay)
49 self.overlay = dupconfig(self.parentui.overlay)
50
50
51 def __getattr__(self, key):
51 def __getattr__(self, key):
52 return getattr(self.parentui, key)
52 return getattr(self.parentui, key)
53
53
54 def updateopts(self, verbose=False, debug=False, quiet=False,
54 def updateopts(self, verbose=False, debug=False, quiet=False,
55 interactive=True, traceback=False, config=[]):
55 interactive=True, traceback=False, config=[]):
56 for section, name, value in config:
56 for section, name, value in config:
57 self.setconfig(section, name, value)
57 self.setconfig(section, name, value)
58
58
59 if quiet or verbose or debug:
59 if quiet or verbose or debug:
60 self.setconfig('ui', 'quiet', str(bool(quiet)))
60 self.setconfig('ui', 'quiet', str(bool(quiet)))
61 self.setconfig('ui', 'verbose', str(bool(verbose)))
61 self.setconfig('ui', 'verbose', str(bool(verbose)))
62 self.setconfig('ui', 'debug', str(bool(debug)))
62 self.setconfig('ui', 'debug', str(bool(debug)))
63
63
64 self.verbosity_constraints()
64 self.verbosity_constraints()
65
65
66 if not interactive:
66 if not interactive:
67 self.setconfig('ui', 'interactive', 'False')
67 self.setconfig('ui', 'interactive', 'False')
68 self.interactive = False
68 self.interactive = False
69
69
70 self.traceback = self.traceback or traceback
70 self.traceback = self.traceback or traceback
71
71
72 def verbosity_constraints(self):
72 def verbosity_constraints(self):
73 self.quiet = self.configbool('ui', 'quiet')
73 self.quiet = self.configbool('ui', 'quiet')
74 self.verbose = self.configbool('ui', 'verbose')
74 self.verbose = self.configbool('ui', 'verbose')
75 self.debugflag = self.configbool('ui', 'debug')
75 self.debugflag = self.configbool('ui', 'debug')
76
76
77 if self.debugflag:
77 if self.debugflag:
78 self.verbose = True
78 self.verbose = True
79 self.quiet = False
79 self.quiet = False
80 elif self.verbose and self.quiet:
80 elif self.verbose and self.quiet:
81 self.quiet = self.verbose = False
81 self.quiet = self.verbose = False
82
82
83 def readconfig(self, fn, root=None):
83 def readconfig(self, fn, root=None):
84 if isinstance(fn, basestring):
84 if isinstance(fn, basestring):
85 fn = [fn]
85 fn = [fn]
86 for f in fn:
86 for f in fn:
87 try:
87 try:
88 self.cdata.read(f)
88 self.cdata.read(f)
89 except ConfigParser.ParsingError, inst:
89 except ConfigParser.ParsingError, inst:
90 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
90 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
91 # override data from config files with data set with ui.setconfig
91 # override data from config files with data set with ui.setconfig
92 if self.overlay:
92 if self.overlay:
93 updateconfig(self.overlay, self.cdata)
93 updateconfig(self.overlay, self.cdata)
94 if root is None:
94 if root is None:
95 root = os.path.expanduser('~')
95 root = os.path.expanduser('~')
96 self.fixconfig(root=root)
96 self.fixconfig(root=root)
97 for hook in self.readhooks:
97 for hook in self.readhooks:
98 hook(self)
98 hook(self)
99
99
100 def addreadhook(self, hook):
100 def addreadhook(self, hook):
101 self.readhooks.append(hook)
101 self.readhooks.append(hook)
102
102
103 def fixconfig(self, section=None, name=None, value=None, root=None):
103 def fixconfig(self, section=None, name=None, value=None, root=None):
104 # translate paths relative to root (or home) into absolute paths
104 # translate paths relative to root (or home) into absolute paths
105 if section is None or section == 'paths':
105 if section is None or section == 'paths':
106 if root is None:
106 if root is None:
107 root = os.getcwd()
107 root = os.getcwd()
108 items = section and [(name, value)] or []
108 items = section and [(name, value)] or []
109 for cdata in self.cdata, self.overlay:
109 for cdata in self.cdata, self.overlay:
110 if not cdata: continue
110 if not cdata: continue
111 if not items and cdata.has_section('paths'):
111 if not items and cdata.has_section('paths'):
112 pathsitems = cdata.items('paths')
112 pathsitems = cdata.items('paths')
113 else:
113 else:
114 pathsitems = items
114 pathsitems = items
115 for n, path in pathsitems:
115 for n, path in pathsitems:
116 if path and "://" not in path and not os.path.isabs(path):
116 if path and "://" not in path and not os.path.isabs(path):
117 cdata.set("paths", n, os.path.join(root, path))
117 cdata.set("paths", n, os.path.join(root, path))
118
118
119 # update quiet/verbose/debug and interactive status
119 # update quiet/verbose/debug and interactive status
120 if section is None or section == 'ui':
120 if section is None or section == 'ui':
121 if name is None or name in ('quiet', 'verbose', 'debug'):
121 if name is None or name in ('quiet', 'verbose', 'debug'):
122 self.verbosity_constraints()
122 self.verbosity_constraints()
123
123
124 if name is None or name == 'interactive':
124 if name is None or name == 'interactive':
125 self.interactive = self.configbool("ui", "interactive", True)
125 self.interactive = self.configbool("ui", "interactive", True)
126
126
127 def setconfig(self, section, name, value):
127 def setconfig(self, section, name, value):
128 if not self.overlay:
128 if not self.overlay:
129 self.overlay = ConfigParser.SafeConfigParser()
129 self.overlay = ConfigParser.SafeConfigParser()
130 for cdata in (self.overlay, self.cdata):
130 for cdata in (self.overlay, self.cdata):
131 if not cdata.has_section(section):
131 if not cdata.has_section(section):
132 cdata.add_section(section)
132 cdata.add_section(section)
133 cdata.set(section, name, value)
133 cdata.set(section, name, value)
134 self.fixconfig(section, name, value)
134 self.fixconfig(section, name, value)
135
135
136 def _config(self, section, name, default, funcname):
136 def _config(self, section, name, default, funcname):
137 if self.cdata.has_option(section, name):
137 if self.cdata.has_option(section, name):
138 try:
138 try:
139 func = getattr(self.cdata, funcname)
139 func = getattr(self.cdata, funcname)
140 return func(section, name)
140 return func(section, name)
141 except ConfigParser.InterpolationError, inst:
141 except ConfigParser.InterpolationError, inst:
142 raise util.Abort(_("Error in configuration section [%s] "
142 raise util.Abort(_("Error in configuration section [%s] "
143 "parameter '%s':\n%s")
143 "parameter '%s':\n%s")
144 % (section, name, inst))
144 % (section, name, inst))
145 return default
145 return default
146
146
147 def config(self, section, name, default=None):
147 def config(self, section, name, default=None):
148 return self._config(section, name, default, 'get')
148 return self._config(section, name, default, 'get')
149
149
150 def configbool(self, section, name, default=False):
150 def configbool(self, section, name, default=False):
151 return self._config(section, name, default, 'getboolean')
151 return self._config(section, name, default, 'getboolean')
152
152
153 def configlist(self, section, name, default=None):
153 def configlist(self, section, name, default=None):
154 """Return a list of comma/space separated strings"""
154 """Return a list of comma/space separated strings"""
155 result = self.config(section, name)
155 result = self.config(section, name)
156 if result is None:
156 if result is None:
157 result = default or []
157 result = default or []
158 if isinstance(result, basestring):
158 if isinstance(result, basestring):
159 result = result.replace(",", " ").split()
159 result = result.replace(",", " ").split()
160 return result
160 return result
161
161
162 def has_config(self, section):
162 def has_config(self, section):
163 '''tell whether section exists in config.'''
163 '''tell whether section exists in config.'''
164 return self.cdata.has_section(section)
164 return self.cdata.has_section(section)
165
165
166 def configitems(self, section):
166 def configitems(self, section):
167 items = {}
167 items = {}
168 if self.cdata.has_section(section):
168 if self.cdata.has_section(section):
169 try:
169 try:
170 items.update(dict(self.cdata.items(section)))
170 items.update(dict(self.cdata.items(section)))
171 except ConfigParser.InterpolationError, inst:
171 except ConfigParser.InterpolationError, inst:
172 raise util.Abort(_("Error in configuration section [%s]:\n%s")
172 raise util.Abort(_("Error in configuration section [%s]:\n%s")
173 % (section, inst))
173 % (section, inst))
174 x = items.items()
174 x = items.items()
175 x.sort()
175 x.sort()
176 return x
176 return x
177
177
178 def walkconfig(self):
178 def walkconfig(self):
179 sections = self.cdata.sections()
179 sections = self.cdata.sections()
180 sections.sort()
180 sections.sort()
181 for section in sections:
181 for section in sections:
182 for name, value in self.configitems(section):
182 for name, value in self.configitems(section):
183 yield section, name, value.replace('\n', '\\n')
183 yield section, name, value.replace('\n', '\\n')
184
184
185 def extensions(self):
185 def extensions(self):
186 result = self.configitems("extensions")
186 result = self.configitems("extensions")
187 for i, (key, value) in enumerate(result):
187 for i, (key, value) in enumerate(result):
188 if value:
188 if value:
189 result[i] = (key, os.path.expanduser(value))
189 result[i] = (key, os.path.expanduser(value))
190 return result
190 return result
191
191
192 def hgignorefiles(self):
192 def hgignorefiles(self):
193 result = []
193 result = []
194 for key, value in self.configitems("ui"):
194 for key, value in self.configitems("ui"):
195 if key == 'ignore' or key.startswith('ignore.'):
195 if key == 'ignore' or key.startswith('ignore.'):
196 result.append(os.path.expanduser(value))
196 result.append(os.path.expanduser(value))
197 return result
197 return result
198
198
199 def configrevlog(self):
199 def configrevlog(self):
200 result = {}
200 result = {}
201 for key, value in self.configitems("revlog"):
201 for key, value in self.configitems("revlog"):
202 result[key.lower()] = value
202 result[key.lower()] = value
203 return result
203 return result
204
204
205 def username(self):
205 def username(self):
206 """Return default username to be used in commits.
206 """Return default username to be used in commits.
207
207
208 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
208 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
209 and stop searching if one of these is set.
209 and stop searching if one of these is set.
210 Abort if found username is an empty string to force specifying
210 Abort if found username is an empty string to force specifying
211 the commit user elsewhere, e.g. with line option or repo hgrc.
211 the commit user elsewhere, e.g. with line option or repo hgrc.
212 If not found, use ($LOGNAME or $USER or $LNAME or
212 If not found, use ($LOGNAME or $USER or $LNAME or
213 $USERNAME) +"@full.hostname".
213 $USERNAME) +"@full.hostname".
214 """
214 """
215 user = os.environ.get("HGUSER")
215 user = os.environ.get("HGUSER")
216 if user is None:
216 if user is None:
217 user = self.config("ui", "username")
217 user = self.config("ui", "username")
218 if user is None:
218 if user is None:
219 user = os.environ.get("EMAIL")
219 user = os.environ.get("EMAIL")
220 if user is None:
220 if user is None:
221 try:
221 try:
222 user = '%s@%s' % (util.getuser(), socket.getfqdn())
222 user = '%s@%s' % (util.getuser(), socket.getfqdn())
223 except KeyError:
223 except KeyError:
224 raise util.Abort(_("Please specify a username."))
224 raise util.Abort(_("Please specify a username."))
225 return user
225 return user
226
226
227 def shortuser(self, user):
227 def shortuser(self, user):
228 """Return a short representation of a user name or email address."""
228 """Return a short representation of a user name or email address."""
229 if not self.verbose: user = util.shortuser(user)
229 if not self.verbose: user = util.shortuser(user)
230 return user
230 return user
231
231
232 def expandpath(self, loc, default=None):
232 def expandpath(self, loc, default=None):
233 """Return repository location relative to cwd or from [paths]"""
233 """Return repository location relative to cwd or from [paths]"""
234 if "://" in loc or os.path.isdir(loc):
234 if "://" in loc or os.path.isdir(loc):
235 return loc
235 return loc
236
236
237 path = self.config("paths", loc)
237 path = self.config("paths", loc)
238 if not path and default is not None:
238 if not path and default is not None:
239 path = self.config("paths", default)
239 path = self.config("paths", default)
240 return path or loc
240 return path or loc
241
241
242 def write(self, *args):
242 def write(self, *args):
243 if self.header:
243 if self.header:
244 if self.header != self.prev_header:
244 if self.header != self.prev_header:
245 self.prev_header = self.header
245 self.prev_header = self.header
246 self.write(*self.header)
246 self.write(*self.header)
247 self.header = []
247 self.header = []
248 for a in args:
248 for a in args:
249 sys.stdout.write(str(a))
249 sys.stdout.write(str(a))
250
250
251 def write_header(self, *args):
251 def write_header(self, *args):
252 for a in args:
252 for a in args:
253 self.header.append(str(a))
253 self.header.append(str(a))
254
254
255 def write_err(self, *args):
255 def write_err(self, *args):
256 try:
256 try:
257 if not sys.stdout.closed: sys.stdout.flush()
257 if not sys.stdout.closed: sys.stdout.flush()
258 for a in args:
258 for a in args:
259 sys.stderr.write(str(a))
259 sys.stderr.write(str(a))
260 except IOError, inst:
260 except IOError, inst:
261 if inst.errno != errno.EPIPE:
261 if inst.errno != errno.EPIPE:
262 raise
262 raise
263
263
264 def flush(self):
264 def flush(self):
265 try: sys.stdout.flush()
265 try: sys.stdout.flush()
266 except: pass
266 except: pass
267 try: sys.stderr.flush()
267 try: sys.stderr.flush()
268 except: pass
268 except: pass
269
269
270 def readline(self):
270 def readline(self):
271 return sys.stdin.readline()[:-1]
271 return sys.stdin.readline()[:-1]
272 def prompt(self, msg, pat=None, default="y"):
272 def prompt(self, msg, pat=None, default="y"):
273 if not self.interactive: return default
273 if not self.interactive: return default
274 while 1:
274 while 1:
275 self.write(msg, " ")
275 self.write(msg, " ")
276 r = self.readline()
276 r = self.readline()
277 if not pat or re.match(pat, r):
277 if not pat or re.match(pat, r):
278 return r
278 return r
279 else:
279 else:
280 self.write(_("unrecognized response\n"))
280 self.write(_("unrecognized response\n"))
281 def getpass(self, prompt=None, default=None):
281 def getpass(self, prompt=None, default=None):
282 if not self.interactive: return default
282 if not self.interactive: return default
283 return getpass.getpass(prompt or _('password: '))
283 return getpass.getpass(prompt or _('password: '))
284 def status(self, *msg):
284 def status(self, *msg):
285 if not self.quiet: self.write(*msg)
285 if not self.quiet: self.write(*msg)
286 def warn(self, *msg):
286 def warn(self, *msg):
287 self.write_err(*msg)
287 self.write_err(*msg)
288 def note(self, *msg):
288 def note(self, *msg):
289 if self.verbose: self.write(*msg)
289 if self.verbose: self.write(*msg)
290 def debug(self, *msg):
290 def debug(self, *msg):
291 if self.debugflag: self.write(*msg)
291 if self.debugflag: self.write(*msg)
292 def edit(self, text, user):
292 def edit(self, text, user):
293 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
293 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
294 text=True)
294 text=True)
295 try:
295 try:
296 f = os.fdopen(fd, "w")
296 f = os.fdopen(fd, "w")
297 f.write(text)
297 f.write(text)
298 f.close()
298 f.close()
299
299
300 editor = (os.environ.get("HGEDITOR") or
300 editor = (os.environ.get("HGEDITOR") or
301 self.config("ui", "editor") or
301 self.config("ui", "editor") or
302 os.environ.get("EDITOR", "vi"))
302 os.environ.get("EDITOR", "vi"))
303
303
304 util.system("%s \"%s\"" % (editor, name),
304 util.system("%s \"%s\"" % (editor, name),
305 environ={'HGUSER': user},
305 environ={'HGUSER': user},
306 onerr=util.Abort, errprefix=_("edit failed"))
306 onerr=util.Abort, errprefix=_("edit failed"))
307
307
308 f = open(name)
308 f = open(name)
309 t = f.read()
309 t = f.read()
310 f.close()
310 f.close()
311 t = re.sub("(?m)^HG:.*\n", "", t)
311 t = re.sub("(?m)^HG:.*\n", "", t)
312 finally:
312 finally:
313 os.unlink(name)
313 os.unlink(name)
314
314
315 return t
315 return t
316
316
317 def print_exc(self):
317 def print_exc(self):
318 '''print exception traceback if traceback printing enabled.
318 '''print exception traceback if traceback printing enabled.
319 only to call in exception handler. returns true if traceback
319 only to call in exception handler. returns true if traceback
320 printed.'''
320 printed.'''
321 if self.traceback:
321 if self.traceback:
322 traceback.print_exc()
322 traceback.print_exc()
323 return self.traceback
323 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now