##// END OF EJS Templates
Allow using default values with ui.configlist, too, and add a test for this.
Thomas Arendsen Hein -
r2502:18cf95ad default
parent child Browse files
Show More
@@ -0,0 +1,47 b''
1 #!/usr/bin/env python
2
3 from mercurial import ui
4
5 testui = ui.ui()
6 testui.updateopts(config=[
7 'values.string=string value',
8 'values.bool1=true',
9 'values.bool2=false',
10 'lists.list1=foo',
11 'lists.list2=foo bar baz',
12 'lists.list3=alice, bob',
13 'lists.list4=foo bar baz alice, bob',
14 ])
15
16 print repr(testui.configitems('values'))
17 print repr(testui.configitems('lists'))
18 print "---"
19 print repr(testui.config('values', 'string'))
20 print repr(testui.config('values', 'bool1'))
21 print repr(testui.config('values', 'bool2'))
22 print repr(testui.config('values', 'unknown'))
23 print "---"
24 try:
25 print repr(testui.configbool('values', 'string'))
26 except ValueError, why:
27 print why
28 print repr(testui.configbool('values', 'bool1'))
29 print repr(testui.configbool('values', 'bool2'))
30 print repr(testui.configbool('values', 'bool2', True))
31 print repr(testui.configbool('values', 'unknown'))
32 print repr(testui.configbool('values', 'unknown', True))
33 print "---"
34 print repr(testui.configlist('lists', 'list1'))
35 print repr(testui.configlist('lists', 'list2'))
36 print repr(testui.configlist('lists', 'list3'))
37 print repr(testui.configlist('lists', 'list4'))
38 print repr(testui.configlist('lists', 'list4', ['foo']))
39 print repr(testui.configlist('lists', 'unknown'))
40 print repr(testui.configlist('lists', 'unknown', ''))
41 print repr(testui.configlist('lists', 'unknown', 'foo'))
42 print repr(testui.configlist('lists', 'unknown', ['foo']))
43 print repr(testui.configlist('lists', 'unknown', 'foo bar'))
44 print repr(testui.configlist('lists', 'unknown', 'foo, bar'))
45 print repr(testui.configlist('lists', 'unknown', ['foo bar']))
46 print repr(testui.configlist('lists', 'unknown', ['foo', 'bar']))
47 print "---"
@@ -0,0 +1,29 b''
1 [('bool1', 'true'), ('bool2', 'false'), ('string', 'string value')]
2 [('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob')]
3 ---
4 'string value'
5 'true'
6 'false'
7 None
8 ---
9 Not a boolean: string value
10 True
11 False
12 False
13 False
14 True
15 ---
16 ['foo']
17 ['foo', 'bar', 'baz']
18 ['alice', 'bob']
19 ['foo', 'bar', 'baz', 'alice', 'bob']
20 ['foo', 'bar', 'baz', 'alice', 'bob']
21 []
22 []
23 ['foo']
24 ['foo']
25 ['foo', 'bar']
26 ['foo', 'bar']
27 ['foo bar']
28 ['foo', 'bar']
29 ---
@@ -1,355 +1,355 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 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 smtplib socket sys tempfile")
10 demandload(globals(), "errno getpass os re smtplib socket sys tempfile")
11 demandload(globals(), "ConfigParser templater traceback util")
11 demandload(globals(), "ConfigParser templater traceback util")
12
12
13 class ui(object):
13 class ui(object):
14 def __init__(self, verbose=False, debug=False, quiet=False,
14 def __init__(self, verbose=False, debug=False, quiet=False,
15 interactive=True, traceback=False, parentui=None):
15 interactive=True, traceback=False, parentui=None):
16 self.overlay = {}
16 self.overlay = {}
17 if parentui is None:
17 if parentui is None:
18 # this is the parent of all ui children
18 # this is the parent of all ui children
19 self.parentui = None
19 self.parentui = None
20 self.cdata = ConfigParser.SafeConfigParser()
20 self.cdata = ConfigParser.SafeConfigParser()
21 self.readconfig(util.rcpath())
21 self.readconfig(util.rcpath())
22
22
23 self.quiet = self.configbool("ui", "quiet")
23 self.quiet = self.configbool("ui", "quiet")
24 self.verbose = self.configbool("ui", "verbose")
24 self.verbose = self.configbool("ui", "verbose")
25 self.debugflag = self.configbool("ui", "debug")
25 self.debugflag = self.configbool("ui", "debug")
26 self.interactive = self.configbool("ui", "interactive", True)
26 self.interactive = self.configbool("ui", "interactive", True)
27 self.traceback = traceback
27 self.traceback = traceback
28
28
29 self.updateopts(verbose, debug, quiet, interactive)
29 self.updateopts(verbose, debug, quiet, interactive)
30 self.diffcache = None
30 self.diffcache = None
31 self.header = []
31 self.header = []
32 self.prev_header = []
32 self.prev_header = []
33 self.revlogopts = self.configrevlog()
33 self.revlogopts = self.configrevlog()
34 else:
34 else:
35 # parentui may point to an ui object which is already a child
35 # parentui may point to an ui object which is already a child
36 self.parentui = parentui.parentui or parentui
36 self.parentui = parentui.parentui or parentui
37 parent_cdata = self.parentui.cdata
37 parent_cdata = self.parentui.cdata
38 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
38 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
39 # make interpolation work
39 # make interpolation work
40 for section in parent_cdata.sections():
40 for section in parent_cdata.sections():
41 self.cdata.add_section(section)
41 self.cdata.add_section(section)
42 for name, value in parent_cdata.items(section, raw=True):
42 for name, value in parent_cdata.items(section, raw=True):
43 self.cdata.set(section, name, value)
43 self.cdata.set(section, name, value)
44
44
45 def __getattr__(self, key):
45 def __getattr__(self, key):
46 return getattr(self.parentui, key)
46 return getattr(self.parentui, key)
47
47
48 def updateopts(self, verbose=False, debug=False, quiet=False,
48 def updateopts(self, verbose=False, debug=False, quiet=False,
49 interactive=True, traceback=False, config=[]):
49 interactive=True, traceback=False, config=[]):
50 self.quiet = (self.quiet or quiet) and not verbose and not debug
50 self.quiet = (self.quiet or quiet) and not verbose and not debug
51 self.verbose = (self.verbose or verbose) or debug
51 self.verbose = (self.verbose or verbose) or debug
52 self.debugflag = (self.debugflag or debug)
52 self.debugflag = (self.debugflag or debug)
53 self.interactive = (self.interactive and interactive)
53 self.interactive = (self.interactive and interactive)
54 self.traceback = self.traceback or traceback
54 self.traceback = self.traceback or traceback
55 for cfg in config:
55 for cfg in config:
56 try:
56 try:
57 name, value = cfg.split('=', 1)
57 name, value = cfg.split('=', 1)
58 section, name = name.split('.', 1)
58 section, name = name.split('.', 1)
59 if not self.cdata.has_section(section):
59 if not self.cdata.has_section(section):
60 self.cdata.add_section(section)
60 self.cdata.add_section(section)
61 if not section or not name:
61 if not section or not name:
62 raise IndexError
62 raise IndexError
63 self.cdata.set(section, name, value)
63 self.cdata.set(section, name, value)
64 except (IndexError, ValueError):
64 except (IndexError, ValueError):
65 raise util.Abort(_('malformed --config option: %s') % cfg)
65 raise util.Abort(_('malformed --config option: %s') % cfg)
66
66
67 def readconfig(self, fn, root=None):
67 def readconfig(self, fn, root=None):
68 if isinstance(fn, basestring):
68 if isinstance(fn, basestring):
69 fn = [fn]
69 fn = [fn]
70 for f in fn:
70 for f in fn:
71 try:
71 try:
72 self.cdata.read(f)
72 self.cdata.read(f)
73 except ConfigParser.ParsingError, inst:
73 except ConfigParser.ParsingError, inst:
74 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
74 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
75 # translate paths relative to root (or home) into absolute paths
75 # translate paths relative to root (or home) into absolute paths
76 if root is None:
76 if root is None:
77 root = os.path.expanduser('~')
77 root = os.path.expanduser('~')
78 for name, path in self.configitems("paths"):
78 for name, path in self.configitems("paths"):
79 if path and path.find("://") == -1 and not os.path.isabs(path):
79 if path and path.find("://") == -1 and not os.path.isabs(path):
80 self.cdata.set("paths", name, os.path.join(root, path))
80 self.cdata.set("paths", name, os.path.join(root, path))
81
81
82 def setconfig(self, section, name, val):
82 def setconfig(self, section, name, val):
83 self.overlay[(section, name)] = val
83 self.overlay[(section, name)] = val
84
84
85 def config(self, section, name, default=None):
85 def config(self, section, name, default=None):
86 if self.overlay.has_key((section, name)):
86 if self.overlay.has_key((section, name)):
87 return self.overlay[(section, name)]
87 return self.overlay[(section, name)]
88 if self.cdata.has_option(section, name):
88 if self.cdata.has_option(section, name):
89 try:
89 try:
90 return self.cdata.get(section, name)
90 return self.cdata.get(section, name)
91 except ConfigParser.InterpolationError, inst:
91 except ConfigParser.InterpolationError, inst:
92 raise util.Abort(_("Error in configuration:\n%s") % inst)
92 raise util.Abort(_("Error in configuration:\n%s") % inst)
93 if self.parentui is None:
93 if self.parentui is None:
94 return default
94 return default
95 else:
95 else:
96 return self.parentui.config(section, name, default)
96 return self.parentui.config(section, name, default)
97
97
98 def configlist(self, section, name, default=None):
98 def configlist(self, section, name, default=None):
99 """Return a list of comma/space separated strings"""
99 """Return a list of comma/space separated strings"""
100 result = self.config(section, name)
100 result = self.config(section, name)
101 if result is None:
101 if result is None:
102 return []
102 result = default or []
103 else:
103 if isinstance(result, basestring):
104 return result.replace(",", " ").split()
104 result = result.replace(",", " ").split()
105
105 return result
106
106
107 def configbool(self, section, name, default=False):
107 def configbool(self, section, name, default=False):
108 if self.overlay.has_key((section, name)):
108 if self.overlay.has_key((section, name)):
109 return self.overlay[(section, name)]
109 return self.overlay[(section, name)]
110 if self.cdata.has_option(section, name):
110 if self.cdata.has_option(section, name):
111 try:
111 try:
112 return self.cdata.getboolean(section, name)
112 return self.cdata.getboolean(section, name)
113 except ConfigParser.InterpolationError, inst:
113 except ConfigParser.InterpolationError, inst:
114 raise util.Abort(_("Error in configuration:\n%s") % inst)
114 raise util.Abort(_("Error in configuration:\n%s") % inst)
115 if self.parentui is None:
115 if self.parentui is None:
116 return default
116 return default
117 else:
117 else:
118 return self.parentui.configbool(section, name, default)
118 return self.parentui.configbool(section, name, default)
119
119
120 def has_config(self, section):
120 def has_config(self, section):
121 '''tell whether section exists in config.'''
121 '''tell whether section exists in config.'''
122 return self.cdata.has_section(section)
122 return self.cdata.has_section(section)
123
123
124 def configitems(self, section):
124 def configitems(self, section):
125 items = {}
125 items = {}
126 if self.parentui is not None:
126 if self.parentui is not None:
127 items = dict(self.parentui.configitems(section))
127 items = dict(self.parentui.configitems(section))
128 if self.cdata.has_section(section):
128 if self.cdata.has_section(section):
129 try:
129 try:
130 items.update(dict(self.cdata.items(section)))
130 items.update(dict(self.cdata.items(section)))
131 except ConfigParser.InterpolationError, inst:
131 except ConfigParser.InterpolationError, inst:
132 raise util.Abort(_("Error in configuration:\n%s") % inst)
132 raise util.Abort(_("Error in configuration:\n%s") % inst)
133 x = items.items()
133 x = items.items()
134 x.sort()
134 x.sort()
135 return x
135 return x
136
136
137 def walkconfig(self, seen=None):
137 def walkconfig(self, seen=None):
138 if seen is None:
138 if seen is None:
139 seen = {}
139 seen = {}
140 for (section, name), value in self.overlay.iteritems():
140 for (section, name), value in self.overlay.iteritems():
141 yield section, name, value
141 yield section, name, value
142 seen[section, name] = 1
142 seen[section, name] = 1
143 for section in self.cdata.sections():
143 for section in self.cdata.sections():
144 for name, value in self.cdata.items(section):
144 for name, value in self.cdata.items(section):
145 if (section, name) in seen: continue
145 if (section, name) in seen: continue
146 yield section, name, value.replace('\n', '\\n')
146 yield section, name, value.replace('\n', '\\n')
147 seen[section, name] = 1
147 seen[section, name] = 1
148 if self.parentui is not None:
148 if self.parentui is not None:
149 for parent in self.parentui.walkconfig(seen):
149 for parent in self.parentui.walkconfig(seen):
150 yield parent
150 yield parent
151
151
152 def extensions(self):
152 def extensions(self):
153 result = self.configitems("extensions")
153 result = self.configitems("extensions")
154 for i, (key, value) in enumerate(result):
154 for i, (key, value) in enumerate(result):
155 if value:
155 if value:
156 result[i] = (key, os.path.expanduser(value))
156 result[i] = (key, os.path.expanduser(value))
157 return result
157 return result
158
158
159 def hgignorefiles(self):
159 def hgignorefiles(self):
160 result = []
160 result = []
161 for key, value in self.configitems("ui"):
161 for key, value in self.configitems("ui"):
162 if key == 'ignore' or key.startswith('ignore.'):
162 if key == 'ignore' or key.startswith('ignore.'):
163 result.append(os.path.expanduser(value))
163 result.append(os.path.expanduser(value))
164 return result
164 return result
165
165
166 def configrevlog(self):
166 def configrevlog(self):
167 result = {}
167 result = {}
168 for key, value in self.configitems("revlog"):
168 for key, value in self.configitems("revlog"):
169 result[key.lower()] = value
169 result[key.lower()] = value
170 return result
170 return result
171
171
172 def diffopts(self):
172 def diffopts(self):
173 if self.diffcache:
173 if self.diffcache:
174 return self.diffcache
174 return self.diffcache
175 result = {'showfunc': True, 'ignorews': False}
175 result = {'showfunc': True, 'ignorews': False}
176 for key, value in self.configitems("diff"):
176 for key, value in self.configitems("diff"):
177 if value:
177 if value:
178 result[key.lower()] = (value.lower() == 'true')
178 result[key.lower()] = (value.lower() == 'true')
179 self.diffcache = result
179 self.diffcache = result
180 return result
180 return result
181
181
182 def username(self):
182 def username(self):
183 """Return default username to be used in commits.
183 """Return default username to be used in commits.
184
184
185 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
185 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
186 and stop searching if one of these is set.
186 and stop searching if one of these is set.
187 Abort if found username is an empty string to force specifying
187 Abort if found username is an empty string to force specifying
188 the commit user elsewhere, e.g. with line option or repo hgrc.
188 the commit user elsewhere, e.g. with line option or repo hgrc.
189 If not found, use ($LOGNAME or $USER or $LNAME or
189 If not found, use ($LOGNAME or $USER or $LNAME or
190 $USERNAME) +"@full.hostname".
190 $USERNAME) +"@full.hostname".
191 """
191 """
192 user = os.environ.get("HGUSER")
192 user = os.environ.get("HGUSER")
193 if user is None:
193 if user is None:
194 user = self.config("ui", "username")
194 user = self.config("ui", "username")
195 if user is None:
195 if user is None:
196 user = os.environ.get("EMAIL")
196 user = os.environ.get("EMAIL")
197 if user is None:
197 if user is None:
198 try:
198 try:
199 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
199 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
200 except KeyError:
200 except KeyError:
201 raise util.Abort(_("Please specify a username."))
201 raise util.Abort(_("Please specify a username."))
202 return user
202 return user
203
203
204 def shortuser(self, user):
204 def shortuser(self, user):
205 """Return a short representation of a user name or email address."""
205 """Return a short representation of a user name or email address."""
206 if not self.verbose: user = util.shortuser(user)
206 if not self.verbose: user = util.shortuser(user)
207 return user
207 return user
208
208
209 def expandpath(self, loc, default=None):
209 def expandpath(self, loc, default=None):
210 """Return repository location relative to cwd or from [paths]"""
210 """Return repository location relative to cwd or from [paths]"""
211 if loc.find("://") != -1 or os.path.exists(loc):
211 if loc.find("://") != -1 or os.path.exists(loc):
212 return loc
212 return loc
213
213
214 path = self.config("paths", loc)
214 path = self.config("paths", loc)
215 if not path and default is not None:
215 if not path and default is not None:
216 path = self.config("paths", default)
216 path = self.config("paths", default)
217 return path or loc
217 return path or loc
218
218
219 def write(self, *args):
219 def write(self, *args):
220 if self.header:
220 if self.header:
221 if self.header != self.prev_header:
221 if self.header != self.prev_header:
222 self.prev_header = self.header
222 self.prev_header = self.header
223 self.write(*self.header)
223 self.write(*self.header)
224 self.header = []
224 self.header = []
225 for a in args:
225 for a in args:
226 sys.stdout.write(str(a))
226 sys.stdout.write(str(a))
227
227
228 def write_header(self, *args):
228 def write_header(self, *args):
229 for a in args:
229 for a in args:
230 self.header.append(str(a))
230 self.header.append(str(a))
231
231
232 def write_err(self, *args):
232 def write_err(self, *args):
233 try:
233 try:
234 if not sys.stdout.closed: sys.stdout.flush()
234 if not sys.stdout.closed: sys.stdout.flush()
235 for a in args:
235 for a in args:
236 sys.stderr.write(str(a))
236 sys.stderr.write(str(a))
237 except IOError, inst:
237 except IOError, inst:
238 if inst.errno != errno.EPIPE:
238 if inst.errno != errno.EPIPE:
239 raise
239 raise
240
240
241 def flush(self):
241 def flush(self):
242 try: sys.stdout.flush()
242 try: sys.stdout.flush()
243 except: pass
243 except: pass
244 try: sys.stderr.flush()
244 try: sys.stderr.flush()
245 except: pass
245 except: pass
246
246
247 def readline(self):
247 def readline(self):
248 return sys.stdin.readline()[:-1]
248 return sys.stdin.readline()[:-1]
249 def prompt(self, msg, pat=None, default="y"):
249 def prompt(self, msg, pat=None, default="y"):
250 if not self.interactive: return default
250 if not self.interactive: return default
251 while 1:
251 while 1:
252 self.write(msg, " ")
252 self.write(msg, " ")
253 r = self.readline()
253 r = self.readline()
254 if not pat or re.match(pat, r):
254 if not pat or re.match(pat, r):
255 return r
255 return r
256 else:
256 else:
257 self.write(_("unrecognized response\n"))
257 self.write(_("unrecognized response\n"))
258 def getpass(self, prompt=None, default=None):
258 def getpass(self, prompt=None, default=None):
259 if not self.interactive: return default
259 if not self.interactive: return default
260 return getpass.getpass(prompt or _('password: '))
260 return getpass.getpass(prompt or _('password: '))
261 def status(self, *msg):
261 def status(self, *msg):
262 if not self.quiet: self.write(*msg)
262 if not self.quiet: self.write(*msg)
263 def warn(self, *msg):
263 def warn(self, *msg):
264 self.write_err(*msg)
264 self.write_err(*msg)
265 def note(self, *msg):
265 def note(self, *msg):
266 if self.verbose: self.write(*msg)
266 if self.verbose: self.write(*msg)
267 def debug(self, *msg):
267 def debug(self, *msg):
268 if self.debugflag: self.write(*msg)
268 if self.debugflag: self.write(*msg)
269 def edit(self, text, user):
269 def edit(self, text, user):
270 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
270 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
271 text=True)
271 text=True)
272 try:
272 try:
273 f = os.fdopen(fd, "w")
273 f = os.fdopen(fd, "w")
274 f.write(text)
274 f.write(text)
275 f.close()
275 f.close()
276
276
277 editor = (os.environ.get("HGEDITOR") or
277 editor = (os.environ.get("HGEDITOR") or
278 self.config("ui", "editor") or
278 self.config("ui", "editor") or
279 os.environ.get("EDITOR", "vi"))
279 os.environ.get("EDITOR", "vi"))
280
280
281 util.system("%s \"%s\"" % (editor, name),
281 util.system("%s \"%s\"" % (editor, name),
282 environ={'HGUSER': user},
282 environ={'HGUSER': user},
283 onerr=util.Abort, errprefix=_("edit failed"))
283 onerr=util.Abort, errprefix=_("edit failed"))
284
284
285 f = open(name)
285 f = open(name)
286 t = f.read()
286 t = f.read()
287 f.close()
287 f.close()
288 t = re.sub("(?m)^HG:.*\n", "", t)
288 t = re.sub("(?m)^HG:.*\n", "", t)
289 finally:
289 finally:
290 os.unlink(name)
290 os.unlink(name)
291
291
292 return t
292 return t
293
293
294 def sendmail(self):
294 def sendmail(self):
295 '''send mail message. object returned has one method, sendmail.
295 '''send mail message. object returned has one method, sendmail.
296 call as sendmail(sender, list-of-recipients, msg).'''
296 call as sendmail(sender, list-of-recipients, msg).'''
297
297
298 def smtp():
298 def smtp():
299 '''send mail using smtp.'''
299 '''send mail using smtp.'''
300
300
301 s = smtplib.SMTP()
301 s = smtplib.SMTP()
302 mailhost = self.config('smtp', 'host')
302 mailhost = self.config('smtp', 'host')
303 if not mailhost:
303 if not mailhost:
304 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
304 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
305 mailport = int(self.config('smtp', 'port', 25))
305 mailport = int(self.config('smtp', 'port', 25))
306 self.note(_('sending mail: smtp host %s, port %s\n') %
306 self.note(_('sending mail: smtp host %s, port %s\n') %
307 (mailhost, mailport))
307 (mailhost, mailport))
308 s.connect(host=mailhost, port=mailport)
308 s.connect(host=mailhost, port=mailport)
309 if self.configbool('smtp', 'tls'):
309 if self.configbool('smtp', 'tls'):
310 self.note(_('(using tls)\n'))
310 self.note(_('(using tls)\n'))
311 s.ehlo()
311 s.ehlo()
312 s.starttls()
312 s.starttls()
313 s.ehlo()
313 s.ehlo()
314 username = self.config('smtp', 'username')
314 username = self.config('smtp', 'username')
315 password = self.config('smtp', 'password')
315 password = self.config('smtp', 'password')
316 if username and password:
316 if username and password:
317 self.note(_('(authenticating to mail server as %s)\n') %
317 self.note(_('(authenticating to mail server as %s)\n') %
318 (username))
318 (username))
319 s.login(username, password)
319 s.login(username, password)
320 return s
320 return s
321
321
322 class sendmail(object):
322 class sendmail(object):
323 '''send mail using sendmail.'''
323 '''send mail using sendmail.'''
324
324
325 def __init__(self, ui, program):
325 def __init__(self, ui, program):
326 self.ui = ui
326 self.ui = ui
327 self.program = program
327 self.program = program
328
328
329 def sendmail(self, sender, recipients, msg):
329 def sendmail(self, sender, recipients, msg):
330 cmdline = '%s -f %s %s' % (
330 cmdline = '%s -f %s %s' % (
331 self.program, templater.email(sender),
331 self.program, templater.email(sender),
332 ' '.join(map(templater.email, recipients)))
332 ' '.join(map(templater.email, recipients)))
333 self.ui.note(_('sending mail: %s\n') % cmdline)
333 self.ui.note(_('sending mail: %s\n') % cmdline)
334 fp = os.popen(cmdline, 'w')
334 fp = os.popen(cmdline, 'w')
335 fp.write(msg)
335 fp.write(msg)
336 ret = fp.close()
336 ret = fp.close()
337 if ret:
337 if ret:
338 raise util.Abort('%s %s' % (
338 raise util.Abort('%s %s' % (
339 os.path.basename(self.program.split(None, 1)[0]),
339 os.path.basename(self.program.split(None, 1)[0]),
340 util.explain_exit(ret)[0]))
340 util.explain_exit(ret)[0]))
341
341
342 method = self.config('email', 'method', 'smtp')
342 method = self.config('email', 'method', 'smtp')
343 if method == 'smtp':
343 if method == 'smtp':
344 mail = smtp()
344 mail = smtp()
345 else:
345 else:
346 mail = sendmail(self, method)
346 mail = sendmail(self, method)
347 return mail
347 return mail
348
348
349 def print_exc(self):
349 def print_exc(self):
350 '''print exception traceback if traceback printing enabled.
350 '''print exception traceback if traceback printing enabled.
351 only to call in exception handler. returns true if traceback
351 only to call in exception handler. returns true if traceback
352 printed.'''
352 printed.'''
353 if self.traceback:
353 if self.traceback:
354 traceback.print_exc()
354 traceback.print_exc()
355 return self.traceback
355 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now