##// END OF EJS Templates
Fix error on Windows if "hg log | more" exits.
Eung-Ju Park -
r2013:65634e10 default
parent child Browse files
Show More
@@ -1,246 +1,246
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(), "errno os re socket sys tempfile util")
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 hgignorefiles(self):
126 def hgignorefiles(self):
127 result = []
127 result = []
128 cfgitems = self.configitems("ui")
128 cfgitems = self.configitems("ui")
129 for key, value in cfgitems:
129 for key, value in cfgitems:
130 if key == 'ignore' or key.startswith('ignore.'):
130 if key == 'ignore' or key.startswith('ignore.'):
131 path = os.path.expanduser(value)
131 path = os.path.expanduser(value)
132 result.append(path)
132 result.append(path)
133 return result
133 return result
134
134
135 def diffopts(self):
135 def diffopts(self):
136 if self.diffcache:
136 if self.diffcache:
137 return self.diffcache
137 return self.diffcache
138 ret = { 'showfunc' : True, 'ignorews' : False}
138 ret = { 'showfunc' : True, 'ignorews' : False}
139 for x in self.configitems("diff"):
139 for x in self.configitems("diff"):
140 k = x[0].lower()
140 k = x[0].lower()
141 v = x[1]
141 v = x[1]
142 if v:
142 if v:
143 v = v.lower()
143 v = v.lower()
144 if v == 'true':
144 if v == 'true':
145 value = True
145 value = True
146 else:
146 else:
147 value = False
147 value = False
148 ret[k] = value
148 ret[k] = value
149 self.diffcache = ret
149 self.diffcache = ret
150 return ret
150 return ret
151
151
152 def username(self):
152 def username(self):
153 """Return default username to be used in commits.
153 """Return default username to be used in commits.
154
154
155 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
155 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
156 and stop searching if one of these is set.
156 and stop searching if one of these is set.
157 Abort if found username is an empty string to force specifying
157 Abort if found username is an empty string to force specifying
158 the commit user elsewhere, e.g. with line option or repo hgrc.
158 the commit user elsewhere, e.g. with line option or repo hgrc.
159 If not found, use $LOGNAME or $USERNAME +"@full.hostname".
159 If not found, use $LOGNAME or $USERNAME +"@full.hostname".
160 """
160 """
161 user = os.environ.get("HGUSER")
161 user = os.environ.get("HGUSER")
162 if user is None:
162 if user is None:
163 user = self.config("ui", "username")
163 user = self.config("ui", "username")
164 if user is None:
164 if user is None:
165 user = os.environ.get("EMAIL")
165 user = os.environ.get("EMAIL")
166 if user is None:
166 if user is None:
167 user = os.environ.get("LOGNAME") or os.environ.get("USERNAME")
167 user = os.environ.get("LOGNAME") or os.environ.get("USERNAME")
168 if user:
168 if user:
169 user = "%s@%s" % (user, socket.getfqdn())
169 user = "%s@%s" % (user, socket.getfqdn())
170 if not user:
170 if not user:
171 raise util.Abort(_("Please specify a username."))
171 raise util.Abort(_("Please specify a username."))
172 return user
172 return user
173
173
174 def shortuser(self, user):
174 def shortuser(self, user):
175 """Return a short representation of a user name or email address."""
175 """Return a short representation of a user name or email address."""
176 if not self.verbose: user = util.shortuser(user)
176 if not self.verbose: user = util.shortuser(user)
177 return user
177 return user
178
178
179 def expandpath(self, loc):
179 def expandpath(self, loc):
180 """Return repository location relative to cwd or from [paths]"""
180 """Return repository location relative to cwd or from [paths]"""
181 if loc.find("://") != -1 or os.path.exists(loc):
181 if loc.find("://") != -1 or os.path.exists(loc):
182 return loc
182 return loc
183
183
184 return self.config("paths", loc, loc)
184 return self.config("paths", loc, loc)
185
185
186 def write(self, *args):
186 def write(self, *args):
187 for a in args:
187 for a in args:
188 sys.stdout.write(str(a))
188 sys.stdout.write(str(a))
189
189
190 def write_err(self, *args):
190 def write_err(self, *args):
191 try:
191 try:
192 if not sys.stdout.closed: sys.stdout.flush()
192 if not sys.stdout.closed: sys.stdout.flush()
193 for a in args:
193 for a in args:
194 sys.stderr.write(str(a))
194 sys.stderr.write(str(a))
195 except IOError, inst:
195 except IOError, inst:
196 if inst.errno != errno.EPIPE:
196 if inst.errno != errno.EPIPE:
197 raise
197 raise
198
198
199 def flush(self):
199 def flush(self):
200 try:
200 try: sys.stdout.flush()
201 sys.stdout.flush()
201 except: pass
202 finally:
202 try: sys.stderr.flush()
203 sys.stderr.flush()
203 except: pass
204
204
205 def readline(self):
205 def readline(self):
206 return sys.stdin.readline()[:-1]
206 return sys.stdin.readline()[:-1]
207 def prompt(self, msg, pat, default="y"):
207 def prompt(self, msg, pat, default="y"):
208 if not self.interactive: return default
208 if not self.interactive: return default
209 while 1:
209 while 1:
210 self.write(msg, " ")
210 self.write(msg, " ")
211 r = self.readline()
211 r = self.readline()
212 if re.match(pat, r):
212 if re.match(pat, r):
213 return r
213 return r
214 else:
214 else:
215 self.write(_("unrecognized response\n"))
215 self.write(_("unrecognized response\n"))
216 def status(self, *msg):
216 def status(self, *msg):
217 if not self.quiet: self.write(*msg)
217 if not self.quiet: self.write(*msg)
218 def warn(self, *msg):
218 def warn(self, *msg):
219 self.write_err(*msg)
219 self.write_err(*msg)
220 def note(self, *msg):
220 def note(self, *msg):
221 if self.verbose: self.write(*msg)
221 if self.verbose: self.write(*msg)
222 def debug(self, *msg):
222 def debug(self, *msg):
223 if self.debugflag: self.write(*msg)
223 if self.debugflag: self.write(*msg)
224 def edit(self, text, user):
224 def edit(self, text, user):
225 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt")
225 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt")
226 try:
226 try:
227 f = os.fdopen(fd, "w")
227 f = os.fdopen(fd, "w")
228 f.write(text)
228 f.write(text)
229 f.close()
229 f.close()
230
230
231 editor = (os.environ.get("HGEDITOR") or
231 editor = (os.environ.get("HGEDITOR") or
232 self.config("ui", "editor") or
232 self.config("ui", "editor") or
233 os.environ.get("EDITOR", "vi"))
233 os.environ.get("EDITOR", "vi"))
234
234
235 util.system("%s \"%s\"" % (editor, name),
235 util.system("%s \"%s\"" % (editor, name),
236 environ={'HGUSER': user},
236 environ={'HGUSER': user},
237 onerr=util.Abort, errprefix=_("edit failed"))
237 onerr=util.Abort, errprefix=_("edit failed"))
238
238
239 f = open(name)
239 f = open(name)
240 t = f.read()
240 t = f.read()
241 f.close()
241 f.close()
242 t = re.sub("(?m)^HG:.*\n", "", t)
242 t = re.sub("(?m)^HG:.*\n", "", t)
243 finally:
243 finally:
244 os.unlink(name)
244 os.unlink(name)
245
245
246 return t
246 return t
General Comments 0
You need to be logged in to leave comments. Login now