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