##// END OF EJS Templates
Merge with crew-stable
Martin Geisler -
r9471:bccf780f merge default
parent child Browse files
Show More
@@ -1,137 +1,138 b''
1 # config.py - configuration parsing for Mercurial
1 # config.py - configuration parsing for Mercurial
2 #
2 #
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 from i18n import _
8 from i18n import _
9 import error
9 import error
10 import re, os
10 import re, os
11
11
12 class sortdict(dict):
12 class sortdict(dict):
13 'a simple sorted dictionary'
13 'a simple sorted dictionary'
14 def __init__(self, data=None):
14 def __init__(self, data=None):
15 self._list = []
15 self._list = []
16 if data:
16 if data:
17 self.update(data)
17 self.update(data)
18 def copy(self):
18 def copy(self):
19 return sortdict(self)
19 return sortdict(self)
20 def __setitem__(self, key, val):
20 def __setitem__(self, key, val):
21 if key in self:
21 if key in self:
22 self._list.remove(key)
22 self._list.remove(key)
23 self._list.append(key)
23 self._list.append(key)
24 dict.__setitem__(self, key, val)
24 dict.__setitem__(self, key, val)
25 def __iter__(self):
25 def __iter__(self):
26 return self._list.__iter__()
26 return self._list.__iter__()
27 def update(self, src):
27 def update(self, src):
28 for k in src:
28 for k in src:
29 self[k] = src[k]
29 self[k] = src[k]
30 def items(self):
30 def items(self):
31 return [(k, self[k]) for k in self._list]
31 return [(k, self[k]) for k in self._list]
32 def __delitem__(self, key):
32 def __delitem__(self, key):
33 dict.__delitem__(self, key)
33 dict.__delitem__(self, key)
34 self._list.remove(key)
34 self._list.remove(key)
35
35
36 class config(object):
36 class config(object):
37 def __init__(self, data=None):
37 def __init__(self, data=None):
38 self._data = {}
38 self._data = {}
39 self._source = {}
39 self._source = {}
40 if data:
40 if data:
41 for k in data._data:
41 for k in data._data:
42 self._data[k] = data[k].copy()
42 self._data[k] = data[k].copy()
43 self._source = data._source.copy()
43 self._source = data._source.copy()
44 def copy(self):
44 def copy(self):
45 return config(self)
45 return config(self)
46 def __contains__(self, section):
46 def __contains__(self, section):
47 return section in self._data
47 return section in self._data
48 def __getitem__(self, section):
48 def __getitem__(self, section):
49 return self._data.get(section, {})
49 return self._data.get(section, {})
50 def __iter__(self):
50 def __iter__(self):
51 for d in self.sections():
51 for d in self.sections():
52 yield d
52 yield d
53 def update(self, src):
53 def update(self, src):
54 for s in src:
54 for s in src:
55 if s not in self:
55 if s not in self:
56 self._data[s] = sortdict()
56 self._data[s] = sortdict()
57 self._data[s].update(src._data[s])
57 self._data[s].update(src._data[s])
58 self._source.update(src._source)
58 self._source.update(src._source)
59 def get(self, section, item, default=None):
59 def get(self, section, item, default=None):
60 return self._data.get(section, {}).get(item, default)
60 return self._data.get(section, {}).get(item, default)
61 def source(self, section, item):
61 def source(self, section, item):
62 return self._source.get((section, item), "")
62 return self._source.get((section, item), "")
63 def sections(self):
63 def sections(self):
64 return sorted(self._data.keys())
64 return sorted(self._data.keys())
65 def items(self, section):
65 def items(self, section):
66 return self._data.get(section, {}).items()
66 return self._data.get(section, {}).items()
67 def set(self, section, item, value, source=""):
67 def set(self, section, item, value, source=""):
68 if section not in self:
68 if section not in self:
69 self._data[section] = sortdict()
69 self._data[section] = sortdict()
70 self._data[section][item] = value
70 self._data[section][item] = value
71 self._source[(section, item)] = source
71 self._source[(section, item)] = source
72
72
73 def parse(self, src, data, sections=None, remap=None, include=None):
73 def parse(self, src, data, sections=None, remap=None, include=None):
74 sectionre = re.compile(r'\[([^\[]+)\]')
74 sectionre = re.compile(r'\[([^\[]+)\]')
75 itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
75 itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
76 contre = re.compile(r'\s+(\S.*\S)')
76 contre = re.compile(r'\s+(\S.*\S)')
77 emptyre = re.compile(r'(;|#|\s*$)')
77 emptyre = re.compile(r'(;|#|\s*$)')
78 unsetre = re.compile(r'%unset\s+(\S+)')
78 unsetre = re.compile(r'%unset\s+(\S+)')
79 includere = re.compile(r'%include\s+(\S.*\S)')
79 includere = re.compile(r'%include\s+(\S.*\S)')
80 section = ""
80 section = ""
81 item = None
81 item = None
82 line = 0
82 line = 0
83 cont = False
83 cont = False
84
84
85 for l in data.splitlines(True):
85 for l in data.splitlines(True):
86 line += 1
86 line += 1
87 if cont:
87 if cont:
88 m = contre.match(l)
88 m = contre.match(l)
89 if m:
89 if m:
90 if sections and section not in sections:
90 if sections and section not in sections:
91 continue
91 continue
92 v = self.get(section, item) + "\n" + m.group(1)
92 v = self.get(section, item) + "\n" + m.group(1)
93 self.set(section, item, v, "%s:%d" % (src, line))
93 self.set(section, item, v, "%s:%d" % (src, line))
94 continue
94 continue
95 item = None
95 item = None
96 cont = False
96 m = includere.match(l)
97 m = includere.match(l)
97 if m:
98 if m:
98 inc = m.group(1)
99 inc = m.group(1)
99 base = os.path.dirname(src)
100 base = os.path.dirname(src)
100 inc = os.path.normpath(os.path.join(base, inc))
101 inc = os.path.normpath(os.path.join(base, inc))
101 if include:
102 if include:
102 include(inc, remap=remap, sections=sections)
103 include(inc, remap=remap, sections=sections)
103 continue
104 continue
104 if emptyre.match(l):
105 if emptyre.match(l):
105 continue
106 continue
106 m = sectionre.match(l)
107 m = sectionre.match(l)
107 if m:
108 if m:
108 section = m.group(1)
109 section = m.group(1)
109 if remap:
110 if remap:
110 section = remap.get(section, section)
111 section = remap.get(section, section)
111 if section not in self:
112 if section not in self:
112 self._data[section] = sortdict()
113 self._data[section] = sortdict()
113 continue
114 continue
114 m = itemre.match(l)
115 m = itemre.match(l)
115 if m:
116 if m:
116 item = m.group(1)
117 item = m.group(1)
117 cont = True
118 cont = True
118 if sections and section not in sections:
119 if sections and section not in sections:
119 continue
120 continue
120 self.set(section, item, m.group(2), "%s:%d" % (src, line))
121 self.set(section, item, m.group(2), "%s:%d" % (src, line))
121 continue
122 continue
122 m = unsetre.match(l)
123 m = unsetre.match(l)
123 if m:
124 if m:
124 name = m.group(1)
125 name = m.group(1)
125 if sections and section not in sections:
126 if sections and section not in sections:
126 continue
127 continue
127 if self.get(section, name) != None:
128 if self.get(section, name) != None:
128 del self._data[section][name]
129 del self._data[section][name]
129 continue
130 continue
130
131
131 raise error.ConfigError(_("config error at %s:%d: '%s'")
132 raise error.ConfigError(_("config error at %s:%d: '%s'")
132 % (src, line, l.rstrip()))
133 % (src, line, l.rstrip()))
133
134
134 def read(self, path, fp=None, sections=None, remap=None):
135 def read(self, path, fp=None, sections=None, remap=None):
135 if not fp:
136 if not fp:
136 fp = open(path)
137 fp = open(path)
137 self.parse(path, fp.read(), sections, remap, self.read)
138 self.parse(path, fp.read(), sections, remap, self.read)
@@ -1,509 +1,512 b''
1 # dispatch.py - command dispatching for mercurial
1 # dispatch.py - command dispatching for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 from i18n import _
8 from i18n import _
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
10 import util, commands, hg, fancyopts, extensions, hook, error
10 import util, commands, hg, fancyopts, extensions, hook, error
11 import cmdutil, encoding
11 import cmdutil, encoding
12 import ui as _ui
12 import ui as _ui
13
13
14 def run():
14 def run():
15 "run the command in sys.argv"
15 "run the command in sys.argv"
16 sys.exit(dispatch(sys.argv[1:]))
16 sys.exit(dispatch(sys.argv[1:]))
17
17
18 def dispatch(args):
18 def dispatch(args):
19 "run the command specified in args"
19 "run the command specified in args"
20 try:
20 try:
21 u = _ui.ui()
21 u = _ui.ui()
22 if '--traceback' in args:
22 if '--traceback' in args:
23 u.setconfig('ui', 'traceback', 'on')
23 u.setconfig('ui', 'traceback', 'on')
24 except util.Abort, inst:
24 except util.Abort, inst:
25 sys.stderr.write(_("abort: %s\n") % inst)
25 sys.stderr.write(_("abort: %s\n") % inst)
26 return -1
26 return -1
27 except error.ConfigError, inst:
28 sys.stderr.write(_("hg: %s\n") % inst)
29 return -1
27 return _runcatch(u, args)
30 return _runcatch(u, args)
28
31
29 def _runcatch(ui, args):
32 def _runcatch(ui, args):
30 def catchterm(*args):
33 def catchterm(*args):
31 raise error.SignalInterrupt
34 raise error.SignalInterrupt
32
35
33 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
36 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
34 num = getattr(signal, name, None)
37 num = getattr(signal, name, None)
35 if num: signal.signal(num, catchterm)
38 if num: signal.signal(num, catchterm)
36
39
37 try:
40 try:
38 try:
41 try:
39 # enter the debugger before command execution
42 # enter the debugger before command execution
40 if '--debugger' in args:
43 if '--debugger' in args:
41 pdb.set_trace()
44 pdb.set_trace()
42 try:
45 try:
43 return _dispatch(ui, args)
46 return _dispatch(ui, args)
44 finally:
47 finally:
45 ui.flush()
48 ui.flush()
46 except:
49 except:
47 # enter the debugger when we hit an exception
50 # enter the debugger when we hit an exception
48 if '--debugger' in args:
51 if '--debugger' in args:
49 pdb.post_mortem(sys.exc_info()[2])
52 pdb.post_mortem(sys.exc_info()[2])
50 ui.traceback()
53 ui.traceback()
51 raise
54 raise
52
55
53 # Global exception handling, alphabetically
56 # Global exception handling, alphabetically
54 # Mercurial-specific first, followed by built-in and library exceptions
57 # Mercurial-specific first, followed by built-in and library exceptions
55 except error.AmbiguousCommand, inst:
58 except error.AmbiguousCommand, inst:
56 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
59 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
57 (inst.args[0], " ".join(inst.args[1])))
60 (inst.args[0], " ".join(inst.args[1])))
58 except error.ConfigError, inst:
61 except error.ConfigError, inst:
59 ui.warn(_("hg: %s\n") % inst.args[0])
62 ui.warn(_("hg: %s\n") % inst.args[0])
60 except error.LockHeld, inst:
63 except error.LockHeld, inst:
61 if inst.errno == errno.ETIMEDOUT:
64 if inst.errno == errno.ETIMEDOUT:
62 reason = _('timed out waiting for lock held by %s') % inst.locker
65 reason = _('timed out waiting for lock held by %s') % inst.locker
63 else:
66 else:
64 reason = _('lock held by %s') % inst.locker
67 reason = _('lock held by %s') % inst.locker
65 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
68 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
66 except error.LockUnavailable, inst:
69 except error.LockUnavailable, inst:
67 ui.warn(_("abort: could not lock %s: %s\n") %
70 ui.warn(_("abort: could not lock %s: %s\n") %
68 (inst.desc or inst.filename, inst.strerror))
71 (inst.desc or inst.filename, inst.strerror))
69 except error.ParseError, inst:
72 except error.ParseError, inst:
70 if inst.args[0]:
73 if inst.args[0]:
71 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
74 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
72 commands.help_(ui, inst.args[0])
75 commands.help_(ui, inst.args[0])
73 else:
76 else:
74 ui.warn(_("hg: %s\n") % inst.args[1])
77 ui.warn(_("hg: %s\n") % inst.args[1])
75 commands.help_(ui, 'shortlist')
78 commands.help_(ui, 'shortlist')
76 except error.RepoError, inst:
79 except error.RepoError, inst:
77 ui.warn(_("abort: %s!\n") % inst)
80 ui.warn(_("abort: %s!\n") % inst)
78 except error.ResponseError, inst:
81 except error.ResponseError, inst:
79 ui.warn(_("abort: %s") % inst.args[0])
82 ui.warn(_("abort: %s") % inst.args[0])
80 if not isinstance(inst.args[1], basestring):
83 if not isinstance(inst.args[1], basestring):
81 ui.warn(" %r\n" % (inst.args[1],))
84 ui.warn(" %r\n" % (inst.args[1],))
82 elif not inst.args[1]:
85 elif not inst.args[1]:
83 ui.warn(_(" empty string\n"))
86 ui.warn(_(" empty string\n"))
84 else:
87 else:
85 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
88 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
86 except error.RevlogError, inst:
89 except error.RevlogError, inst:
87 ui.warn(_("abort: %s!\n") % inst)
90 ui.warn(_("abort: %s!\n") % inst)
88 except error.SignalInterrupt:
91 except error.SignalInterrupt:
89 ui.warn(_("killed!\n"))
92 ui.warn(_("killed!\n"))
90 except error.UnknownCommand, inst:
93 except error.UnknownCommand, inst:
91 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
94 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
92 commands.help_(ui, 'shortlist')
95 commands.help_(ui, 'shortlist')
93 except util.Abort, inst:
96 except util.Abort, inst:
94 ui.warn(_("abort: %s\n") % inst)
97 ui.warn(_("abort: %s\n") % inst)
95 except ImportError, inst:
98 except ImportError, inst:
96 m = str(inst).split()[-1]
99 m = str(inst).split()[-1]
97 ui.warn(_("abort: could not import module %s!\n") % m)
100 ui.warn(_("abort: could not import module %s!\n") % m)
98 if m in "mpatch bdiff".split():
101 if m in "mpatch bdiff".split():
99 ui.warn(_("(did you forget to compile extensions?)\n"))
102 ui.warn(_("(did you forget to compile extensions?)\n"))
100 elif m in "zlib".split():
103 elif m in "zlib".split():
101 ui.warn(_("(is your Python install correct?)\n"))
104 ui.warn(_("(is your Python install correct?)\n"))
102 except IOError, inst:
105 except IOError, inst:
103 if hasattr(inst, "code"):
106 if hasattr(inst, "code"):
104 ui.warn(_("abort: %s\n") % inst)
107 ui.warn(_("abort: %s\n") % inst)
105 elif hasattr(inst, "reason"):
108 elif hasattr(inst, "reason"):
106 try: # usually it is in the form (errno, strerror)
109 try: # usually it is in the form (errno, strerror)
107 reason = inst.reason.args[1]
110 reason = inst.reason.args[1]
108 except: # it might be anything, for example a string
111 except: # it might be anything, for example a string
109 reason = inst.reason
112 reason = inst.reason
110 ui.warn(_("abort: error: %s\n") % reason)
113 ui.warn(_("abort: error: %s\n") % reason)
111 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
114 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
112 if ui.debugflag:
115 if ui.debugflag:
113 ui.warn(_("broken pipe\n"))
116 ui.warn(_("broken pipe\n"))
114 elif getattr(inst, "strerror", None):
117 elif getattr(inst, "strerror", None):
115 if getattr(inst, "filename", None):
118 if getattr(inst, "filename", None):
116 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
119 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
117 else:
120 else:
118 ui.warn(_("abort: %s\n") % inst.strerror)
121 ui.warn(_("abort: %s\n") % inst.strerror)
119 else:
122 else:
120 raise
123 raise
121 except OSError, inst:
124 except OSError, inst:
122 if getattr(inst, "filename", None):
125 if getattr(inst, "filename", None):
123 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
126 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
124 else:
127 else:
125 ui.warn(_("abort: %s\n") % inst.strerror)
128 ui.warn(_("abort: %s\n") % inst.strerror)
126 except KeyboardInterrupt:
129 except KeyboardInterrupt:
127 try:
130 try:
128 ui.warn(_("interrupted!\n"))
131 ui.warn(_("interrupted!\n"))
129 except IOError, inst:
132 except IOError, inst:
130 if inst.errno == errno.EPIPE:
133 if inst.errno == errno.EPIPE:
131 if ui.debugflag:
134 if ui.debugflag:
132 ui.warn(_("\nbroken pipe\n"))
135 ui.warn(_("\nbroken pipe\n"))
133 else:
136 else:
134 raise
137 raise
135 except MemoryError:
138 except MemoryError:
136 ui.warn(_("abort: out of memory\n"))
139 ui.warn(_("abort: out of memory\n"))
137 except SystemExit, inst:
140 except SystemExit, inst:
138 # Commands shouldn't sys.exit directly, but give a return code.
141 # Commands shouldn't sys.exit directly, but give a return code.
139 # Just in case catch this and and pass exit code to caller.
142 # Just in case catch this and and pass exit code to caller.
140 return inst.code
143 return inst.code
141 except socket.error, inst:
144 except socket.error, inst:
142 ui.warn(_("abort: %s\n") % inst.args[-1])
145 ui.warn(_("abort: %s\n") % inst.args[-1])
143 except:
146 except:
144 ui.warn(_("** unknown exception encountered, details follow\n"))
147 ui.warn(_("** unknown exception encountered, details follow\n"))
145 ui.warn(_("** report bug details to "
148 ui.warn(_("** report bug details to "
146 "http://mercurial.selenic.com/bts/\n"))
149 "http://mercurial.selenic.com/bts/\n"))
147 ui.warn(_("** or mercurial@selenic.com\n"))
150 ui.warn(_("** or mercurial@selenic.com\n"))
148 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
151 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
149 % util.version())
152 % util.version())
150 ui.warn(_("** Extensions loaded: %s\n")
153 ui.warn(_("** Extensions loaded: %s\n")
151 % ", ".join([x[0] for x in extensions.extensions()]))
154 % ", ".join([x[0] for x in extensions.extensions()]))
152 raise
155 raise
153
156
154 return -1
157 return -1
155
158
156 def _findrepo(p):
159 def _findrepo(p):
157 while not os.path.isdir(os.path.join(p, ".hg")):
160 while not os.path.isdir(os.path.join(p, ".hg")):
158 oldp, p = p, os.path.dirname(p)
161 oldp, p = p, os.path.dirname(p)
159 if p == oldp:
162 if p == oldp:
160 return None
163 return None
161
164
162 return p
165 return p
163
166
164 def aliasargs(fn):
167 def aliasargs(fn):
165 if hasattr(fn, 'args'):
168 if hasattr(fn, 'args'):
166 return fn.args
169 return fn.args
167 return []
170 return []
168
171
169 class cmdalias(object):
172 class cmdalias(object):
170 def __init__(self, name, definition, cmdtable):
173 def __init__(self, name, definition, cmdtable):
171 self.name = name
174 self.name = name
172 self.definition = definition
175 self.definition = definition
173 self.args = []
176 self.args = []
174 self.opts = []
177 self.opts = []
175 self.help = ''
178 self.help = ''
176 self.norepo = True
179 self.norepo = True
177
180
178 try:
181 try:
179 cmdutil.findcmd(self.name, cmdtable, True)
182 cmdutil.findcmd(self.name, cmdtable, True)
180 self.shadows = True
183 self.shadows = True
181 except error.UnknownCommand:
184 except error.UnknownCommand:
182 self.shadows = False
185 self.shadows = False
183
186
184 if not self.definition:
187 if not self.definition:
185 def fn(ui, *args):
188 def fn(ui, *args):
186 ui.warn(_("no definition for alias '%s'\n") % self.name)
189 ui.warn(_("no definition for alias '%s'\n") % self.name)
187 return 1
190 return 1
188 self.fn = fn
191 self.fn = fn
189
192
190 return
193 return
191
194
192 args = shlex.split(self.definition)
195 args = shlex.split(self.definition)
193 cmd = args.pop(0)
196 cmd = args.pop(0)
194 opts = []
197 opts = []
195 help = ''
198 help = ''
196
199
197 try:
200 try:
198 self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
201 self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
199 self.args = aliasargs(self.fn) + args
202 self.args = aliasargs(self.fn) + args
200 if cmd not in commands.norepo.split(' '):
203 if cmd not in commands.norepo.split(' '):
201 self.norepo = False
204 self.norepo = False
202 except error.UnknownCommand:
205 except error.UnknownCommand:
203 def fn(ui, *args):
206 def fn(ui, *args):
204 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
207 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
205 % (self.name, cmd))
208 % (self.name, cmd))
206 return 1
209 return 1
207 self.fn = fn
210 self.fn = fn
208 except error.AmbiguousCommand:
211 except error.AmbiguousCommand:
209 def fn(ui, *args):
212 def fn(ui, *args):
210 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
213 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
211 % (self.name, cmd))
214 % (self.name, cmd))
212 return 1
215 return 1
213 self.fn = fn
216 self.fn = fn
214
217
215 def __call__(self, ui, *args, **opts):
218 def __call__(self, ui, *args, **opts):
216 if self.shadows:
219 if self.shadows:
217 ui.debug("alias '%s' shadows command\n" % self.name)
220 ui.debug("alias '%s' shadows command\n" % self.name)
218
221
219 return self.fn(ui, *args, **opts)
222 return self.fn(ui, *args, **opts)
220
223
221 def addaliases(ui, cmdtable):
224 def addaliases(ui, cmdtable):
222 # aliases are processed after extensions have been loaded, so they
225 # aliases are processed after extensions have been loaded, so they
223 # may use extension commands. Aliases can also use other alias definitions,
226 # may use extension commands. Aliases can also use other alias definitions,
224 # but only if they have been defined prior to the current definition.
227 # but only if they have been defined prior to the current definition.
225 for alias, definition in ui.configitems('alias'):
228 for alias, definition in ui.configitems('alias'):
226 aliasdef = cmdalias(alias, definition, cmdtable)
229 aliasdef = cmdalias(alias, definition, cmdtable)
227 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
230 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
228 if aliasdef.norepo:
231 if aliasdef.norepo:
229 commands.norepo += ' %s' % alias
232 commands.norepo += ' %s' % alias
230
233
231 def _parse(ui, args):
234 def _parse(ui, args):
232 options = {}
235 options = {}
233 cmdoptions = {}
236 cmdoptions = {}
234
237
235 try:
238 try:
236 args = fancyopts.fancyopts(args, commands.globalopts, options)
239 args = fancyopts.fancyopts(args, commands.globalopts, options)
237 except fancyopts.getopt.GetoptError, inst:
240 except fancyopts.getopt.GetoptError, inst:
238 raise error.ParseError(None, inst)
241 raise error.ParseError(None, inst)
239
242
240 if args:
243 if args:
241 cmd, args = args[0], args[1:]
244 cmd, args = args[0], args[1:]
242 aliases, i = cmdutil.findcmd(cmd, commands.table,
245 aliases, i = cmdutil.findcmd(cmd, commands.table,
243 ui.config("ui", "strict"))
246 ui.config("ui", "strict"))
244 cmd = aliases[0]
247 cmd = aliases[0]
245 args = aliasargs(i[0]) + args
248 args = aliasargs(i[0]) + args
246 defaults = ui.config("defaults", cmd)
249 defaults = ui.config("defaults", cmd)
247 if defaults:
250 if defaults:
248 args = shlex.split(defaults) + args
251 args = shlex.split(defaults) + args
249 c = list(i[1])
252 c = list(i[1])
250 else:
253 else:
251 cmd = None
254 cmd = None
252 c = []
255 c = []
253
256
254 # combine global options into local
257 # combine global options into local
255 for o in commands.globalopts:
258 for o in commands.globalopts:
256 c.append((o[0], o[1], options[o[1]], o[3]))
259 c.append((o[0], o[1], options[o[1]], o[3]))
257
260
258 try:
261 try:
259 args = fancyopts.fancyopts(args, c, cmdoptions, True)
262 args = fancyopts.fancyopts(args, c, cmdoptions, True)
260 except fancyopts.getopt.GetoptError, inst:
263 except fancyopts.getopt.GetoptError, inst:
261 raise error.ParseError(cmd, inst)
264 raise error.ParseError(cmd, inst)
262
265
263 # separate global options back out
266 # separate global options back out
264 for o in commands.globalopts:
267 for o in commands.globalopts:
265 n = o[1]
268 n = o[1]
266 options[n] = cmdoptions[n]
269 options[n] = cmdoptions[n]
267 del cmdoptions[n]
270 del cmdoptions[n]
268
271
269 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
272 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
270
273
271 def _parseconfig(ui, config):
274 def _parseconfig(ui, config):
272 """parse the --config options from the command line"""
275 """parse the --config options from the command line"""
273 for cfg in config:
276 for cfg in config:
274 try:
277 try:
275 name, value = cfg.split('=', 1)
278 name, value = cfg.split('=', 1)
276 section, name = name.split('.', 1)
279 section, name = name.split('.', 1)
277 if not section or not name:
280 if not section or not name:
278 raise IndexError
281 raise IndexError
279 ui.setconfig(section, name, value)
282 ui.setconfig(section, name, value)
280 except (IndexError, ValueError):
283 except (IndexError, ValueError):
281 raise util.Abort(_('malformed --config option: %s') % cfg)
284 raise util.Abort(_('malformed --config option: %s') % cfg)
282
285
283 def _earlygetopt(aliases, args):
286 def _earlygetopt(aliases, args):
284 """Return list of values for an option (or aliases).
287 """Return list of values for an option (or aliases).
285
288
286 The values are listed in the order they appear in args.
289 The values are listed in the order they appear in args.
287 The options and values are removed from args.
290 The options and values are removed from args.
288 """
291 """
289 try:
292 try:
290 argcount = args.index("--")
293 argcount = args.index("--")
291 except ValueError:
294 except ValueError:
292 argcount = len(args)
295 argcount = len(args)
293 shortopts = [opt for opt in aliases if len(opt) == 2]
296 shortopts = [opt for opt in aliases if len(opt) == 2]
294 values = []
297 values = []
295 pos = 0
298 pos = 0
296 while pos < argcount:
299 while pos < argcount:
297 if args[pos] in aliases:
300 if args[pos] in aliases:
298 if pos + 1 >= argcount:
301 if pos + 1 >= argcount:
299 # ignore and let getopt report an error if there is no value
302 # ignore and let getopt report an error if there is no value
300 break
303 break
301 del args[pos]
304 del args[pos]
302 values.append(args.pop(pos))
305 values.append(args.pop(pos))
303 argcount -= 2
306 argcount -= 2
304 elif args[pos][:2] in shortopts:
307 elif args[pos][:2] in shortopts:
305 # short option can have no following space, e.g. hg log -Rfoo
308 # short option can have no following space, e.g. hg log -Rfoo
306 values.append(args.pop(pos)[2:])
309 values.append(args.pop(pos)[2:])
307 argcount -= 1
310 argcount -= 1
308 else:
311 else:
309 pos += 1
312 pos += 1
310 return values
313 return values
311
314
312 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
315 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
313 # run pre-hook, and abort if it fails
316 # run pre-hook, and abort if it fails
314 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
317 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
315 if ret:
318 if ret:
316 return ret
319 return ret
317 ret = _runcommand(ui, options, cmd, d)
320 ret = _runcommand(ui, options, cmd, d)
318 # run post-hook, passing command result
321 # run post-hook, passing command result
319 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
322 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
320 result = ret)
323 result = ret)
321 return ret
324 return ret
322
325
323 _loaded = set()
326 _loaded = set()
324 def _dispatch(ui, args):
327 def _dispatch(ui, args):
325 # read --config before doing anything else
328 # read --config before doing anything else
326 # (e.g. to change trust settings for reading .hg/hgrc)
329 # (e.g. to change trust settings for reading .hg/hgrc)
327 _parseconfig(ui, _earlygetopt(['--config'], args))
330 _parseconfig(ui, _earlygetopt(['--config'], args))
328
331
329 # check for cwd
332 # check for cwd
330 cwd = _earlygetopt(['--cwd'], args)
333 cwd = _earlygetopt(['--cwd'], args)
331 if cwd:
334 if cwd:
332 os.chdir(cwd[-1])
335 os.chdir(cwd[-1])
333
336
334 # read the local repository .hgrc into a local ui object
337 # read the local repository .hgrc into a local ui object
335 path = _findrepo(os.getcwd()) or ""
338 path = _findrepo(os.getcwd()) or ""
336 if not path:
339 if not path:
337 lui = ui
340 lui = ui
338 else:
341 else:
339 try:
342 try:
340 lui = ui.copy()
343 lui = ui.copy()
341 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
344 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
342 except IOError:
345 except IOError:
343 pass
346 pass
344
347
345 # now we can expand paths, even ones in .hg/hgrc
348 # now we can expand paths, even ones in .hg/hgrc
346 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
349 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
347 if rpath:
350 if rpath:
348 path = lui.expandpath(rpath[-1])
351 path = lui.expandpath(rpath[-1])
349 lui = ui.copy()
352 lui = ui.copy()
350 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
353 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
351
354
352 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
355 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
353 # reposetup. Programs like TortoiseHg will call _dispatch several
356 # reposetup. Programs like TortoiseHg will call _dispatch several
354 # times so we keep track of configured extensions in _loaded.
357 # times so we keep track of configured extensions in _loaded.
355 extensions.loadall(lui)
358 extensions.loadall(lui)
356 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
359 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
357
360
358 # (uisetup is handled in extensions.loadall)
361 # (uisetup is handled in extensions.loadall)
359
362
360 for name, module in exts:
363 for name, module in exts:
361 extsetup = getattr(module, 'extsetup', None)
364 extsetup = getattr(module, 'extsetup', None)
362 if extsetup:
365 if extsetup:
363 try:
366 try:
364 extsetup(ui)
367 extsetup(ui)
365 except TypeError:
368 except TypeError:
366 if extsetup.func_code.co_argcount != 0:
369 if extsetup.func_code.co_argcount != 0:
367 raise
370 raise
368 extsetup() # old extsetup with no ui argument
371 extsetup() # old extsetup with no ui argument
369
372
370 for name, module in exts:
373 for name, module in exts:
371 cmdtable = getattr(module, 'cmdtable', {})
374 cmdtable = getattr(module, 'cmdtable', {})
372 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
375 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
373 if overrides:
376 if overrides:
374 ui.warn(_("extension '%s' overrides commands: %s\n")
377 ui.warn(_("extension '%s' overrides commands: %s\n")
375 % (name, " ".join(overrides)))
378 % (name, " ".join(overrides)))
376 commands.table.update(cmdtable)
379 commands.table.update(cmdtable)
377 _loaded.add(name)
380 _loaded.add(name)
378
381
379 # (reposetup is handled in hg.repository)
382 # (reposetup is handled in hg.repository)
380
383
381 addaliases(lui, commands.table)
384 addaliases(lui, commands.table)
382
385
383 # check for fallback encoding
386 # check for fallback encoding
384 fallback = lui.config('ui', 'fallbackencoding')
387 fallback = lui.config('ui', 'fallbackencoding')
385 if fallback:
388 if fallback:
386 encoding.fallbackencoding = fallback
389 encoding.fallbackencoding = fallback
387
390
388 fullargs = args
391 fullargs = args
389 cmd, func, args, options, cmdoptions = _parse(lui, args)
392 cmd, func, args, options, cmdoptions = _parse(lui, args)
390
393
391 if options["config"]:
394 if options["config"]:
392 raise util.Abort(_("Option --config may not be abbreviated!"))
395 raise util.Abort(_("Option --config may not be abbreviated!"))
393 if options["cwd"]:
396 if options["cwd"]:
394 raise util.Abort(_("Option --cwd may not be abbreviated!"))
397 raise util.Abort(_("Option --cwd may not be abbreviated!"))
395 if options["repository"]:
398 if options["repository"]:
396 raise util.Abort(_(
399 raise util.Abort(_(
397 "Option -R has to be separated from other options (e.g. not -qR) "
400 "Option -R has to be separated from other options (e.g. not -qR) "
398 "and --repository may only be abbreviated as --repo!"))
401 "and --repository may only be abbreviated as --repo!"))
399
402
400 if options["encoding"]:
403 if options["encoding"]:
401 encoding.encoding = options["encoding"]
404 encoding.encoding = options["encoding"]
402 if options["encodingmode"]:
405 if options["encodingmode"]:
403 encoding.encodingmode = options["encodingmode"]
406 encoding.encodingmode = options["encodingmode"]
404 if options["time"]:
407 if options["time"]:
405 def get_times():
408 def get_times():
406 t = os.times()
409 t = os.times()
407 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
410 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
408 t = (t[0], t[1], t[2], t[3], time.clock())
411 t = (t[0], t[1], t[2], t[3], time.clock())
409 return t
412 return t
410 s = get_times()
413 s = get_times()
411 def print_time():
414 def print_time():
412 t = get_times()
415 t = get_times()
413 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
416 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
414 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
417 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
415 atexit.register(print_time)
418 atexit.register(print_time)
416
419
417 if options['verbose'] or options['debug'] or options['quiet']:
420 if options['verbose'] or options['debug'] or options['quiet']:
418 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
421 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
419 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
422 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
420 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
423 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
421 if options['traceback']:
424 if options['traceback']:
422 ui.setconfig('ui', 'traceback', 'on')
425 ui.setconfig('ui', 'traceback', 'on')
423 if options['noninteractive']:
426 if options['noninteractive']:
424 ui.setconfig('ui', 'interactive', 'off')
427 ui.setconfig('ui', 'interactive', 'off')
425
428
426 if options['help']:
429 if options['help']:
427 return commands.help_(ui, cmd, options['version'])
430 return commands.help_(ui, cmd, options['version'])
428 elif options['version']:
431 elif options['version']:
429 return commands.version_(ui)
432 return commands.version_(ui)
430 elif not cmd:
433 elif not cmd:
431 return commands.help_(ui, 'shortlist')
434 return commands.help_(ui, 'shortlist')
432
435
433 repo = None
436 repo = None
434 if cmd not in commands.norepo.split():
437 if cmd not in commands.norepo.split():
435 try:
438 try:
436 repo = hg.repository(ui, path=path)
439 repo = hg.repository(ui, path=path)
437 ui = repo.ui
440 ui = repo.ui
438 if not repo.local():
441 if not repo.local():
439 raise util.Abort(_("repository '%s' is not local") % path)
442 raise util.Abort(_("repository '%s' is not local") % path)
440 ui.setconfig("bundle", "mainreporoot", repo.root)
443 ui.setconfig("bundle", "mainreporoot", repo.root)
441 except error.RepoError:
444 except error.RepoError:
442 if cmd not in commands.optionalrepo.split():
445 if cmd not in commands.optionalrepo.split():
443 if args and not path: # try to infer -R from command args
446 if args and not path: # try to infer -R from command args
444 repos = map(_findrepo, args)
447 repos = map(_findrepo, args)
445 guess = repos[0]
448 guess = repos[0]
446 if guess and repos.count(guess) == len(repos):
449 if guess and repos.count(guess) == len(repos):
447 return _dispatch(ui, ['--repository', guess] + fullargs)
450 return _dispatch(ui, ['--repository', guess] + fullargs)
448 if not path:
451 if not path:
449 raise error.RepoError(_("There is no Mercurial repository"
452 raise error.RepoError(_("There is no Mercurial repository"
450 " here (.hg not found)"))
453 " here (.hg not found)"))
451 raise
454 raise
452 args.insert(0, repo)
455 args.insert(0, repo)
453 elif rpath:
456 elif rpath:
454 ui.warn("warning: --repository ignored\n")
457 ui.warn("warning: --repository ignored\n")
455
458
456 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
459 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
457 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
460 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
458
461
459 def _runcommand(ui, options, cmd, cmdfunc):
462 def _runcommand(ui, options, cmd, cmdfunc):
460 def checkargs():
463 def checkargs():
461 try:
464 try:
462 return cmdfunc()
465 return cmdfunc()
463 except error.SignatureError:
466 except error.SignatureError:
464 raise error.ParseError(cmd, _("invalid arguments"))
467 raise error.ParseError(cmd, _("invalid arguments"))
465
468
466 if options['profile']:
469 if options['profile']:
467 format = ui.config('profiling', 'format', default='text')
470 format = ui.config('profiling', 'format', default='text')
468
471
469 if not format in ['text', 'kcachegrind']:
472 if not format in ['text', 'kcachegrind']:
470 ui.warn(_("unrecognized profiling format '%s'"
473 ui.warn(_("unrecognized profiling format '%s'"
471 " - Ignored\n") % format)
474 " - Ignored\n") % format)
472 format = 'text'
475 format = 'text'
473
476
474 output = ui.config('profiling', 'output')
477 output = ui.config('profiling', 'output')
475
478
476 if output:
479 if output:
477 path = os.path.expanduser(output)
480 path = os.path.expanduser(output)
478 path = ui.expandpath(path)
481 path = ui.expandpath(path)
479 ostream = open(path, 'wb')
482 ostream = open(path, 'wb')
480 else:
483 else:
481 ostream = sys.stderr
484 ostream = sys.stderr
482
485
483 try:
486 try:
484 from mercurial import lsprof
487 from mercurial import lsprof
485 except ImportError:
488 except ImportError:
486 raise util.Abort(_(
489 raise util.Abort(_(
487 'lsprof not available - install from '
490 'lsprof not available - install from '
488 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
491 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
489 p = lsprof.Profiler()
492 p = lsprof.Profiler()
490 p.enable(subcalls=True)
493 p.enable(subcalls=True)
491 try:
494 try:
492 return checkargs()
495 return checkargs()
493 finally:
496 finally:
494 p.disable()
497 p.disable()
495
498
496 if format == 'kcachegrind':
499 if format == 'kcachegrind':
497 import lsprofcalltree
500 import lsprofcalltree
498 calltree = lsprofcalltree.KCacheGrind(p)
501 calltree = lsprofcalltree.KCacheGrind(p)
499 calltree.output(ostream)
502 calltree.output(ostream)
500 else:
503 else:
501 # format == 'text'
504 # format == 'text'
502 stats = lsprof.Stats(p.getstats())
505 stats = lsprof.Stats(p.getstats())
503 stats.sort()
506 stats.sort()
504 stats.pprint(top=10, file=ostream, climit=5)
507 stats.pprint(top=10, file=ostream, climit=5)
505
508
506 if output:
509 if output:
507 ostream.close()
510 ostream.close()
508 else:
511 else:
509 return checkargs()
512 return checkargs()
@@ -1,18 +1,24 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 mkdir t
3 mkdir t
4 cd t
4 cd t
5 hg init
5 hg init
6 echo "invalid" > .hg/hgrc
6 echo "invalid" > .hg/hgrc
7 hg status 2>&1 |sed -e "s:/.*\(/t/.*\):...\1:"
7 hg status 2>&1 |sed -e "s:/.*\(/t/.*\):...\1:"
8
8
9 #issue 1199, escaping
9 #issue 1199, escaping
10
10
11 cd ..
11 cd ..
12 hg init "foo%bar"
12 hg init "foo%bar"
13 hg clone "foo%bar" foobar
13 hg clone "foo%bar" foobar
14 p=`pwd`
14 p=`pwd`
15 cd foobar
15 cd foobar
16 cat .hg/hgrc |sed -e "s:$p:...:"
16 cat .hg/hgrc |sed -e "s:$p:...:"
17 hg paths |sed -e "s:$p:...:"
17 hg paths |sed -e "s:$p:...:"
18 hg showconfig |sed -e "s:$p:...:"
18 hg showconfig |sed -e "s:$p:...:"
19
20 # issue1829: wrong indentation
21 cd ..
22 echo '[foo]' >> $HGRCPATH
23 echo ' x = y' >> $HGRCPATH
24 hg version 2>&1 | sed -e "s|$HGRCPATH|\$HGRCPATH|"
@@ -1,12 +1,13 b''
1 hg: config error at .../t/.hg/hgrc:1: 'invalid'
1 hg: config error at .../t/.hg/hgrc:1: 'invalid'
2 updating working directory
2 updating working directory
3 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 [paths]
4 [paths]
5 default = .../foo%bar
5 default = .../foo%bar
6 default = .../foo%bar
6 default = .../foo%bar
7 bundle.mainreporoot=.../foobar
7 bundle.mainreporoot=.../foobar
8 defaults.backout=-d "0 0"
8 defaults.backout=-d "0 0"
9 defaults.commit=-d "0 0"
9 defaults.commit=-d "0 0"
10 defaults.tag=-d "0 0"
10 defaults.tag=-d "0 0"
11 paths.default=.../foo%bar
11 paths.default=.../foo%bar
12 ui.slash=True
12 ui.slash=True
13 hg: config error at $HGRCPATH:8: ' x = y'
General Comments 0
You need to be logged in to leave comments. Login now