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