##// END OF EJS Templates
ignore EPIPE in ui.err_write...
Benoit Boissinot -
r1989:0541768f default
parent child Browse files
Show More
@@ -1,233 +1,237
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 import ConfigParser
8 import ConfigParser
9 from i18n import gettext as _
9 from i18n import gettext as _
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "os re socket sys util tempfile")
11 demandload(globals(), "errno os re socket sys tempfile 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, parentui=None):
15 interactive=True, 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
27
28 self.updateopts(verbose, debug, quiet, interactive)
28 self.updateopts(verbose, debug, quiet, interactive)
29 self.diffcache = None
29 self.diffcache = None
30 else:
30 else:
31 # parentui may point to an ui object which is already a child
31 # parentui may point to an ui object which is already a child
32 self.parentui = parentui.parentui or parentui
32 self.parentui = parentui.parentui or parentui
33 parent_cdata = self.parentui.cdata
33 parent_cdata = self.parentui.cdata
34 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
34 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
35 # make interpolation work
35 # make interpolation work
36 for section in parent_cdata.sections():
36 for section in parent_cdata.sections():
37 self.cdata.add_section(section)
37 self.cdata.add_section(section)
38 for name, value in parent_cdata.items(section, raw=True):
38 for name, value in parent_cdata.items(section, raw=True):
39 self.cdata.set(section, name, value)
39 self.cdata.set(section, name, value)
40
40
41 def __getattr__(self, key):
41 def __getattr__(self, key):
42 return getattr(self.parentui, key)
42 return getattr(self.parentui, key)
43
43
44 def updateopts(self, verbose=False, debug=False, quiet=False,
44 def updateopts(self, verbose=False, debug=False, quiet=False,
45 interactive=True):
45 interactive=True):
46 self.quiet = (self.quiet or quiet) and not verbose and not debug
46 self.quiet = (self.quiet or quiet) and not verbose and not debug
47 self.verbose = (self.verbose or verbose) or debug
47 self.verbose = (self.verbose or verbose) or debug
48 self.debugflag = (self.debugflag or debug)
48 self.debugflag = (self.debugflag or debug)
49 self.interactive = (self.interactive and interactive)
49 self.interactive = (self.interactive and interactive)
50
50
51 def readconfig(self, fn, root=None):
51 def readconfig(self, fn, root=None):
52 if isinstance(fn, basestring):
52 if isinstance(fn, basestring):
53 fn = [fn]
53 fn = [fn]
54 for f in fn:
54 for f in fn:
55 try:
55 try:
56 self.cdata.read(f)
56 self.cdata.read(f)
57 except ConfigParser.ParsingError, inst:
57 except ConfigParser.ParsingError, inst:
58 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
58 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
59 # translate paths relative to root (or home) into absolute paths
59 # translate paths relative to root (or home) into absolute paths
60 if root is None:
60 if root is None:
61 root = os.path.expanduser('~')
61 root = os.path.expanduser('~')
62 for name, path in self.configitems("paths"):
62 for name, path in self.configitems("paths"):
63 if path and path.find("://") == -1 and not os.path.isabs(path):
63 if path and path.find("://") == -1 and not os.path.isabs(path):
64 self.cdata.set("paths", name, os.path.join(root, path))
64 self.cdata.set("paths", name, os.path.join(root, path))
65
65
66 def setconfig(self, section, name, val):
66 def setconfig(self, section, name, val):
67 self.overlay[(section, name)] = val
67 self.overlay[(section, name)] = val
68
68
69 def config(self, section, name, default=None):
69 def config(self, section, name, default=None):
70 if self.overlay.has_key((section, name)):
70 if self.overlay.has_key((section, name)):
71 return self.overlay[(section, name)]
71 return self.overlay[(section, name)]
72 if self.cdata.has_option(section, name):
72 if self.cdata.has_option(section, name):
73 try:
73 try:
74 return self.cdata.get(section, name)
74 return self.cdata.get(section, name)
75 except ConfigParser.InterpolationError, inst:
75 except ConfigParser.InterpolationError, inst:
76 raise util.Abort(_("Error in configuration:\n%s") % inst)
76 raise util.Abort(_("Error in configuration:\n%s") % inst)
77 if self.parentui is None:
77 if self.parentui is None:
78 return default
78 return default
79 else:
79 else:
80 return self.parentui.config(section, name, default)
80 return self.parentui.config(section, name, default)
81
81
82 def configbool(self, section, name, default=False):
82 def configbool(self, section, name, default=False):
83 if self.overlay.has_key((section, name)):
83 if self.overlay.has_key((section, name)):
84 return self.overlay[(section, name)]
84 return self.overlay[(section, name)]
85 if self.cdata.has_option(section, name):
85 if self.cdata.has_option(section, name):
86 try:
86 try:
87 return self.cdata.getboolean(section, name)
87 return self.cdata.getboolean(section, name)
88 except ConfigParser.InterpolationError, inst:
88 except ConfigParser.InterpolationError, inst:
89 raise util.Abort(_("Error in configuration:\n%s") % inst)
89 raise util.Abort(_("Error in configuration:\n%s") % inst)
90 if self.parentui is None:
90 if self.parentui is None:
91 return default
91 return default
92 else:
92 else:
93 return self.parentui.configbool(section, name, default)
93 return self.parentui.configbool(section, name, default)
94
94
95 def configitems(self, section):
95 def configitems(self, section):
96 items = {}
96 items = {}
97 if self.parentui is not None:
97 if self.parentui is not None:
98 items = dict(self.parentui.configitems(section))
98 items = dict(self.parentui.configitems(section))
99 if self.cdata.has_section(section):
99 if self.cdata.has_section(section):
100 try:
100 try:
101 items.update(dict(self.cdata.items(section)))
101 items.update(dict(self.cdata.items(section)))
102 except ConfigParser.InterpolationError, inst:
102 except ConfigParser.InterpolationError, inst:
103 raise util.Abort(_("Error in configuration:\n%s") % inst)
103 raise util.Abort(_("Error in configuration:\n%s") % inst)
104 x = items.items()
104 x = items.items()
105 x.sort()
105 x.sort()
106 return x
106 return x
107
107
108 def walkconfig(self, seen=None):
108 def walkconfig(self, seen=None):
109 if seen is None:
109 if seen is None:
110 seen = {}
110 seen = {}
111 for (section, name), value in self.overlay.iteritems():
111 for (section, name), value in self.overlay.iteritems():
112 yield section, name, value
112 yield section, name, value
113 seen[section, name] = 1
113 seen[section, name] = 1
114 for section in self.cdata.sections():
114 for section in self.cdata.sections():
115 for name, value in self.cdata.items(section):
115 for name, value in self.cdata.items(section):
116 if (section, name) in seen: continue
116 if (section, name) in seen: continue
117 yield section, name, value.replace('\n', '\\n')
117 yield section, name, value.replace('\n', '\\n')
118 seen[section, name] = 1
118 seen[section, name] = 1
119 if self.parentui is not None:
119 if self.parentui is not None:
120 for parent in self.parentui.walkconfig(seen):
120 for parent in self.parentui.walkconfig(seen):
121 yield parent
121 yield parent
122
122
123 def extensions(self):
123 def extensions(self):
124 return self.configitems("extensions")
124 return self.configitems("extensions")
125
125
126 def diffopts(self):
126 def diffopts(self):
127 if self.diffcache:
127 if self.diffcache:
128 return self.diffcache
128 return self.diffcache
129 ret = { 'showfunc' : True, 'ignorews' : False}
129 ret = { 'showfunc' : True, 'ignorews' : False}
130 for x in self.configitems("diff"):
130 for x in self.configitems("diff"):
131 k = x[0].lower()
131 k = x[0].lower()
132 v = x[1]
132 v = x[1]
133 if v:
133 if v:
134 v = v.lower()
134 v = v.lower()
135 if v == 'true':
135 if v == 'true':
136 value = True
136 value = True
137 else:
137 else:
138 value = False
138 value = False
139 ret[k] = value
139 ret[k] = value
140 self.diffcache = ret
140 self.diffcache = ret
141 return ret
141 return ret
142
142
143 def username(self):
143 def username(self):
144 """Return default username to be used in commits.
144 """Return default username to be used in commits.
145
145
146 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
146 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
147 and stop searching if one of these is set.
147 and stop searching if one of these is set.
148 Abort if found username is an empty string to force specifying
148 Abort if found username is an empty string to force specifying
149 the commit user elsewhere, e.g. with line option or repo hgrc.
149 the commit user elsewhere, e.g. with line option or repo hgrc.
150 If not found, use $LOGNAME or $USERNAME +"@full.hostname".
150 If not found, use $LOGNAME or $USERNAME +"@full.hostname".
151 """
151 """
152 user = os.environ.get("HGUSER")
152 user = os.environ.get("HGUSER")
153 if user is None:
153 if user is None:
154 user = self.config("ui", "username")
154 user = self.config("ui", "username")
155 if user is None:
155 if user is None:
156 user = os.environ.get("EMAIL")
156 user = os.environ.get("EMAIL")
157 if user is None:
157 if user is None:
158 user = os.environ.get("LOGNAME") or os.environ.get("USERNAME")
158 user = os.environ.get("LOGNAME") or os.environ.get("USERNAME")
159 if user:
159 if user:
160 user = "%s@%s" % (user, socket.getfqdn())
160 user = "%s@%s" % (user, socket.getfqdn())
161 if not user:
161 if not user:
162 raise util.Abort(_("Please specify a username."))
162 raise util.Abort(_("Please specify a username."))
163 return user
163 return user
164
164
165 def shortuser(self, user):
165 def shortuser(self, user):
166 """Return a short representation of a user name or email address."""
166 """Return a short representation of a user name or email address."""
167 if not self.verbose: user = util.shortuser(user)
167 if not self.verbose: user = util.shortuser(user)
168 return user
168 return user
169
169
170 def expandpath(self, loc):
170 def expandpath(self, loc):
171 """Return repository location relative to cwd or from [paths]"""
171 """Return repository location relative to cwd or from [paths]"""
172 if loc.find("://") != -1 or os.path.exists(loc):
172 if loc.find("://") != -1 or os.path.exists(loc):
173 return loc
173 return loc
174
174
175 return self.config("paths", loc, loc)
175 return self.config("paths", loc, loc)
176
176
177 def write(self, *args):
177 def write(self, *args):
178 for a in args:
178 for a in args:
179 sys.stdout.write(str(a))
179 sys.stdout.write(str(a))
180
180
181 def write_err(self, *args):
181 def write_err(self, *args):
182 if not sys.stdout.closed: sys.stdout.flush()
182 try:
183 for a in args:
183 if not sys.stdout.closed: sys.stdout.flush()
184 sys.stderr.write(str(a))
184 for a in args:
185 sys.stderr.write(str(a))
186 except IOError, inst:
187 if inst.errno != errno.EPIPE:
188 raise
185
189
186 def flush(self):
190 def flush(self):
187 try:
191 try:
188 sys.stdout.flush()
192 sys.stdout.flush()
189 finally:
193 finally:
190 sys.stderr.flush()
194 sys.stderr.flush()
191
195
192 def readline(self):
196 def readline(self):
193 return sys.stdin.readline()[:-1]
197 return sys.stdin.readline()[:-1]
194 def prompt(self, msg, pat, default="y"):
198 def prompt(self, msg, pat, default="y"):
195 if not self.interactive: return default
199 if not self.interactive: return default
196 while 1:
200 while 1:
197 self.write(msg, " ")
201 self.write(msg, " ")
198 r = self.readline()
202 r = self.readline()
199 if re.match(pat, r):
203 if re.match(pat, r):
200 return r
204 return r
201 else:
205 else:
202 self.write(_("unrecognized response\n"))
206 self.write(_("unrecognized response\n"))
203 def status(self, *msg):
207 def status(self, *msg):
204 if not self.quiet: self.write(*msg)
208 if not self.quiet: self.write(*msg)
205 def warn(self, *msg):
209 def warn(self, *msg):
206 self.write_err(*msg)
210 self.write_err(*msg)
207 def note(self, *msg):
211 def note(self, *msg):
208 if self.verbose: self.write(*msg)
212 if self.verbose: self.write(*msg)
209 def debug(self, *msg):
213 def debug(self, *msg):
210 if self.debugflag: self.write(*msg)
214 if self.debugflag: self.write(*msg)
211 def edit(self, text, user):
215 def edit(self, text, user):
212 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt")
216 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt")
213 try:
217 try:
214 f = os.fdopen(fd, "w")
218 f = os.fdopen(fd, "w")
215 f.write(text)
219 f.write(text)
216 f.close()
220 f.close()
217
221
218 editor = (os.environ.get("HGEDITOR") or
222 editor = (os.environ.get("HGEDITOR") or
219 self.config("ui", "editor") or
223 self.config("ui", "editor") or
220 os.environ.get("EDITOR", "vi"))
224 os.environ.get("EDITOR", "vi"))
221
225
222 util.system("%s \"%s\"" % (editor, name),
226 util.system("%s \"%s\"" % (editor, name),
223 environ={'HGUSER': user},
227 environ={'HGUSER': user},
224 onerr=util.Abort, errprefix=_("edit failed"))
228 onerr=util.Abort, errprefix=_("edit failed"))
225
229
226 f = open(name)
230 f = open(name)
227 t = f.read()
231 t = f.read()
228 f.close()
232 f.close()
229 t = re.sub("(?m)^HG:.*\n", "", t)
233 t = re.sub("(?m)^HG:.*\n", "", t)
230 finally:
234 finally:
231 os.unlink(name)
235 os.unlink(name)
232
236
233 return t
237 return t
General Comments 0
You need to be logged in to leave comments. Login now