bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
|
329
by Martin Pool
- refactor command functions into command classes |
1 |
# Copyright (C) 2004, 2005 by Canonical Ltd
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
2 |
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
||
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
||
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
17 |
||
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
18 |
# TODO: probably should say which arguments are candidates for glob
|
19 |
# expansion on windows and do that at the command level.
|
|
20 |
||
|
1095
by Martin Pool
todo |
21 |
# TODO: Help messages for options.
|
22 |
||
23 |
# TODO: Define arguments by objects, rather than just using names.
|
|
24 |
# Those objects can specify the expected type of the argument, which
|
|
25 |
# would help with validation and shell completion.
|
|
26 |
||
27 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
28 |
|
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
29 |
import sys |
30 |
import os |
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
31 |
from warnings import warn |
32 |
from inspect import getdoc |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
33 |
|
34 |
import bzrlib |
|
|
1112
by Martin Pool
- disable standard logging to .bzr.log and stderr while running |
35 |
import bzrlib.trace |
|
897
by Martin Pool
- merge john's revision-naming code |
36 |
from bzrlib.trace import mutter, note, log_error, warning |
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
37 |
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError |
|
800
by Martin Pool
Merge John's import-speedup branch: |
38 |
from bzrlib.branch import find_branch |
39 |
from bzrlib import BZRDIR |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
40 |
|
41 |
||
|
731
by Martin Pool
- merge plugin patch from john |
42 |
plugin_cmds = {} |
43 |
||
44 |
||
|
759
by Martin Pool
- fix up register_command() names |
45 |
def register_command(cmd): |
|
731
by Martin Pool
- merge plugin patch from john |
46 |
"Utility function to help register a command"
|
47 |
global plugin_cmds |
|
48 |
k = cmd.__name__ |
|
49 |
if k.startswith("cmd_"): |
|
50 |
k_unsquished = _unsquish_command_name(k) |
|
51 |
else: |
|
52 |
k_unsquished = k |
|
53 |
if not plugin_cmds.has_key(k_unsquished): |
|
54 |
plugin_cmds[k_unsquished] = cmd |
|
|
1137
by Martin Pool
- additional trace messages for plugins |
55 |
mutter('registered plugin command %s', k_unsquished) |
|
731
by Martin Pool
- merge plugin patch from john |
56 |
else: |
57 |
log_error('Two plugins defined the same command: %r' % k) |
|
58 |
log_error('Not loading the one in %r' % sys.modules[cmd.__module__]) |
|
59 |
||
60 |
||
|
350
by Martin Pool
- refactor command aliases into command classes |
61 |
def _squish_command_name(cmd): |
62 |
return 'cmd_' + cmd.replace('-', '_') |
|
63 |
||
64 |
||
65 |
def _unsquish_command_name(cmd): |
|
66 |
assert cmd.startswith("cmd_") |
|
67 |
return cmd[4:].replace('_','-') |
|
68 |
||
|
914
by Martin Pool
- fix up breakage of 'bzr log -v' by root_id patch |
69 |
|
|
567
by Martin Pool
- New form 'bzr log -r FROM:TO' |
70 |
def _parse_revision_str(revstr): |
|
914
by Martin Pool
- fix up breakage of 'bzr log -v' by root_id patch |
71 |
"""This handles a revision string -> revno. |
72 |
||
73 |
This always returns a list. The list will have one element for
|
|
|
567
by Martin Pool
- New form 'bzr log -r FROM:TO' |
74 |
|
|
897
by Martin Pool
- merge john's revision-naming code |
75 |
It supports integers directly, but everything else it
|
76 |
defers for passing to Branch.get_revision_info()
|
|
77 |
||
78 |
>>> _parse_revision_str('234')
|
|
79 |
[234]
|
|
80 |
>>> _parse_revision_str('234..567')
|
|
81 |
[234, 567]
|
|
82 |
>>> _parse_revision_str('..')
|
|
83 |
[None, None]
|
|
84 |
>>> _parse_revision_str('..234')
|
|
85 |
[None, 234]
|
|
86 |
>>> _parse_revision_str('234..')
|
|
87 |
[234, None]
|
|
88 |
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
|
|
89 |
[234, 456, 789]
|
|
90 |
>>> _parse_revision_str('234....789') # Error?
|
|
91 |
[234, None, 789]
|
|
92 |
>>> _parse_revision_str('revid:test@other.com-234234')
|
|
93 |
['revid:test@other.com-234234']
|
|
94 |
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
|
|
95 |
['revid:test@other.com-234234', 'revid:test@other.com-234235']
|
|
96 |
>>> _parse_revision_str('revid:test@other.com-234234..23')
|
|
97 |
['revid:test@other.com-234234', 23]
|
|
98 |
>>> _parse_revision_str('date:2005-04-12')
|
|
99 |
['date:2005-04-12']
|
|
100 |
>>> _parse_revision_str('date:2005-04-12 12:24:33')
|
|
101 |
['date:2005-04-12 12:24:33']
|
|
102 |
>>> _parse_revision_str('date:2005-04-12T12:24:33')
|
|
103 |
['date:2005-04-12T12:24:33']
|
|
104 |
>>> _parse_revision_str('date:2005-04-12,12:24:33')
|
|
105 |
['date:2005-04-12,12:24:33']
|
|
106 |
>>> _parse_revision_str('-5..23')
|
|
107 |
[-5, 23]
|
|
108 |
>>> _parse_revision_str('-5')
|
|
109 |
[-5]
|
|
110 |
>>> _parse_revision_str('123a')
|
|
111 |
['123a']
|
|
112 |
>>> _parse_revision_str('abc')
|
|
113 |
['abc']
|
|
|
567
by Martin Pool
- New form 'bzr log -r FROM:TO' |
114 |
"""
|
|
897
by Martin Pool
- merge john's revision-naming code |
115 |
import re |
116 |
old_format_re = re.compile('\d*:\d*') |
|
117 |
m = old_format_re.match(revstr) |
|
118 |
if m: |
|
119 |
warning('Colon separator for revision numbers is deprecated.' |
|
120 |
' Use .. instead') |
|
121 |
revs = [] |
|
122 |
for rev in revstr.split(':'): |
|
123 |
if rev: |
|
124 |
revs.append(int(rev)) |
|
125 |
else: |
|
126 |
revs.append(None) |
|
127 |
return revs |
|
128 |
revs = [] |
|
129 |
for x in revstr.split('..'): |
|
130 |
if not x: |
|
131 |
revs.append(None) |
|
132 |
else: |
|
133 |
try: |
|
134 |
revs.append(int(x)) |
|
135 |
except ValueError: |
|
136 |
revs.append(x) |
|
|
567
by Martin Pool
- New form 'bzr log -r FROM:TO' |
137 |
return revs |
138 |
||
|
731
by Martin Pool
- merge plugin patch from john |
139 |
|
|
974.1.9
by Aaron Bentley
Added merge-type parameter to merge. |
140 |
def get_merge_type(typestring): |
141 |
"""Attempt to find the merge class/factory associated with a string.""" |
|
142 |
from merge import merge_types |
|
143 |
try: |
|
144 |
return merge_types[typestring][0] |
|
145 |
except KeyError: |
|
146 |
templ = '%s%%7s: %%s' % (' '*12) |
|
147 |
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()] |
|
148 |
type_list = '\n'.join(lines) |
|
149 |
msg = "No known merge type %s. Supported types are:\n%s" %\ |
|
150 |
(typestring, type_list) |
|
151 |
raise BzrCommandError(msg) |
|
152 |
||
153 |
||
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
154 |
def get_merge_type(typestring): |
155 |
"""Attempt to find the merge class/factory associated with a string.""" |
|
156 |
from merge import merge_types |
|
157 |
try: |
|
158 |
return merge_types[typestring][0] |
|
159 |
except KeyError: |
|
160 |
templ = '%s%%7s: %%s' % (' '*12) |
|
161 |
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()] |
|
162 |
type_list = '\n'.join(lines) |
|
163 |
msg = "No known merge type %s. Supported types are:\n%s" %\ |
|
164 |
(typestring, type_list) |
|
165 |
raise BzrCommandError(msg) |
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
166 |
|
167 |
||
168 |
def _builtin_commands(): |
|
|
1147
by Martin Pool
- split builtin commands into separate module bzrlib.builtins; |
169 |
import bzrlib.builtins |
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
170 |
r = {} |
|
1147
by Martin Pool
- split builtin commands into separate module bzrlib.builtins; |
171 |
builtins = bzrlib.builtins.__dict__ |
172 |
for name in builtins: |
|
173 |
if name.startswith("cmd_"): |
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
174 |
real_name = _unsquish_command_name(name) |
175 |
r[real_name] = builtins[name] |
|
176 |
return r |
|
177 |
||
178 |
||
179 |
||
180 |
def builtin_command_names(): |
|
181 |
"""Return list of builtin command names.""" |
|
182 |
return _builtin_commands().keys() |
|
183 |
||
184 |
||
185 |
def plugin_command_names(): |
|
186 |
return plugin_cmds.keys() |
|
187 |
||
188 |
||
189 |
def _get_cmd_dict(plugins_override=True): |
|
190 |
"""Return name->class mapping for all commands.""" |
|
191 |
d = _builtin_commands() |
|
|
731
by Martin Pool
- merge plugin patch from john |
192 |
if plugins_override: |
193 |
d.update(plugin_cmds) |
|
|
641
by Martin Pool
- improved external-command patch from john |
194 |
return d |
|
731
by Martin Pool
- merge plugin patch from john |
195 |
|
|
641
by Martin Pool
- improved external-command patch from john |
196 |
|
|
731
by Martin Pool
- merge plugin patch from john |
197 |
def get_all_cmds(plugins_override=True): |
|
641
by Martin Pool
- improved external-command patch from john |
198 |
"""Return canonical name and class for all registered commands.""" |
|
731
by Martin Pool
- merge plugin patch from john |
199 |
for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems(): |
|
641
by Martin Pool
- improved external-command patch from john |
200 |
yield k,v |
201 |
||
202 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
203 |
def get_cmd_object(cmd_name, plugins_override=True): |
|
350
by Martin Pool
- refactor command aliases into command classes |
204 |
"""Return the canonical name and command class for a command. |
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
205 |
|
206 |
plugins_override
|
|
207 |
If true, plugin commands can override builtins.
|
|
|
350
by Martin Pool
- refactor command aliases into command classes |
208 |
"""
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
209 |
cmd_name = str(cmd_name) # not unicode |
|
350
by Martin Pool
- refactor command aliases into command classes |
210 |
|
211 |
# first look up this command under the specified name
|
|
|
731
by Martin Pool
- merge plugin patch from john |
212 |
cmds = _get_cmd_dict(plugins_override=plugins_override) |
|
272
by Martin Pool
- Add command aliases |
213 |
try: |
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
214 |
return cmds[cmd_name]() |
|
272
by Martin Pool
- Add command aliases |
215 |
except KeyError: |
|
350
by Martin Pool
- refactor command aliases into command classes |
216 |
pass
|
217 |
||
218 |
# look for any command which claims this as an alias
|
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
219 |
for real_cmd_name, cmd_class in cmds.iteritems(): |
220 |
if cmd_name in cmd_class.aliases: |
|
221 |
return cmd_class() |
|
222 |
||
223 |
cmd_obj = ExternalCommand.find_command(cmd_name) |
|
224 |
if cmd_obj: |
|
225 |
return cmd_obj |
|
226 |
||
227 |
raise BzrCommandError("unknown command %r" % cmd_name) |
|
|
272
by Martin Pool
- Add command aliases |
228 |
|
|
329
by Martin Pool
- refactor command functions into command classes |
229 |
|
|
558
by Martin Pool
- All top-level classes inherit from object |
230 |
class Command(object): |
|
329
by Martin Pool
- refactor command functions into command classes |
231 |
"""Base class for commands. |
232 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
233 |
Commands are the heart of the command-line bzr interface.
|
234 |
||
235 |
The command object mostly handles the mapping of command-line
|
|
236 |
parameters into one or more bzrlib operations, and of the results
|
|
237 |
into textual output.
|
|
238 |
||
239 |
Commands normally don't have any state. All their arguments are
|
|
240 |
passed in to the run method. (Subclasses may take a different
|
|
241 |
policy if the behaviour of the instance needs to depend on e.g. a
|
|
242 |
shell plugin and not just its Python class.)
|
|
243 |
||
|
329
by Martin Pool
- refactor command functions into command classes |
244 |
The docstring for an actual command should give a single-line
|
245 |
summary, then a complete description of the command. A grammar
|
|
246 |
description will be inserted.
|
|
247 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
248 |
aliases
|
249 |
Other accepted names for this command.
|
|
250 |
||
|
329
by Martin Pool
- refactor command functions into command classes |
251 |
takes_args
|
252 |
List of argument forms, marked with whether they are optional,
|
|
253 |
repeated, etc.
|
|
254 |
||
255 |
takes_options
|
|
256 |
List of options that may be given for this command.
|
|
257 |
||
258 |
hidden
|
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
259 |
If true, this command isn't advertised. This is typically
|
260 |
for commands intended for expert users.
|
|
|
329
by Martin Pool
- refactor command functions into command classes |
261 |
"""
|
262 |
aliases = [] |
|
263 |
||
264 |
takes_args = [] |
|
265 |
takes_options = [] |
|
266 |
||
267 |
hidden = False |
|
268 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
269 |
def __init__(self): |
270 |
"""Construct an instance of this command.""" |
|
|
973
by Martin Pool
- various refactorings of command interpreter |
271 |
if self.__doc__ == Command.__doc__: |
272 |
warn("No help message set for %r" % self) |
|
|
329
by Martin Pool
- refactor command functions into command classes |
273 |
|
274 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
275 |
def run(self): |
276 |
"""Actually run the command. |
|
|
329
by Martin Pool
- refactor command functions into command classes |
277 |
|
278 |
This is invoked with the options and arguments bound to
|
|
279 |
keyword parameters.
|
|
280 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
281 |
Return 0 or None if the command was successful, or a non-zero
|
282 |
shell error code if not. It's OK for this method to allow
|
|
283 |
an exception to raise up.
|
|
|
329
by Martin Pool
- refactor command functions into command classes |
284 |
"""
|
|
1147
by Martin Pool
- split builtin commands into separate module bzrlib.builtins; |
285 |
raise NotImplementedError() |
|
329
by Martin Pool
- refactor command functions into command classes |
286 |
|
287 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
288 |
def help(self): |
289 |
"""Return help message for this class.""" |
|
290 |
if self.__doc__ is Command.__doc__: |
|
291 |
return None |
|
292 |
return getdoc(self) |
|
293 |
||
294 |
def name(self): |
|
295 |
return _unsquish_command_name(self.__class__.__name__) |
|
296 |
||
297 |
||
|
422
by Martin Pool
- External-command patch from mpe |
298 |
class ExternalCommand(Command): |
299 |
"""Class to wrap external commands. |
|
300 |
||
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
301 |
We cheat a little here, when get_cmd_class() calls us we actually
|
302 |
give it back an object we construct that has the appropriate path,
|
|
303 |
help, options etc for the specified command.
|
|
304 |
||
305 |
When run_bzr() tries to instantiate that 'class' it gets caught by
|
|
306 |
the __call__ method, which we override to call the Command.__init__
|
|
307 |
method. That then calls our run method which is pretty straight
|
|
308 |
forward.
|
|
309 |
||
310 |
The only wrinkle is that we have to map bzr's dictionary of options
|
|
311 |
and arguments back into command line options and arguments for the
|
|
312 |
script.
|
|
|
422
by Martin Pool
- External-command patch from mpe |
313 |
"""
|
314 |
||
315 |
def find_command(cls, cmd): |
|
|
572
by Martin Pool
- trim imports |
316 |
import os.path |
|
422
by Martin Pool
- External-command patch from mpe |
317 |
bzrpath = os.environ.get('BZRPATH', '') |
318 |
||
|
641
by Martin Pool
- improved external-command patch from john |
319 |
for dir in bzrpath.split(os.pathsep): |
|
422
by Martin Pool
- External-command patch from mpe |
320 |
path = os.path.join(dir, cmd) |
321 |
if os.path.isfile(path): |
|
322 |
return ExternalCommand(path) |
|
323 |
||
324 |
return None |
|
325 |
||
326 |
find_command = classmethod(find_command) |
|
327 |
||
328 |
def __init__(self, path): |
|
329 |
self.path = path |
|
330 |
||
331 |
pipe = os.popen('%s --bzr-usage' % path, 'r') |
|
332 |
self.takes_options = pipe.readline().split() |
|
|
687
by Martin Pool
- trap more errors from external commands |
333 |
|
334 |
for opt in self.takes_options: |
|
335 |
if not opt in OPTIONS: |
|
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
336 |
raise BzrError("Unknown option '%s' returned by external command %s" |
337 |
% (opt, path)) |
|
|
687
by Martin Pool
- trap more errors from external commands |
338 |
|
339 |
# TODO: Is there any way to check takes_args is valid here?
|
|
|
422
by Martin Pool
- External-command patch from mpe |
340 |
self.takes_args = pipe.readline().split() |
|
687
by Martin Pool
- trap more errors from external commands |
341 |
|
342 |
if pipe.close() is not None: |
|
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
343 |
raise BzrError("Failed funning '%s --bzr-usage'" % path) |
|
422
by Martin Pool
- External-command patch from mpe |
344 |
|
345 |
pipe = os.popen('%s --bzr-help' % path, 'r') |
|
346 |
self.__doc__ = pipe.read() |
|
|
687
by Martin Pool
- trap more errors from external commands |
347 |
if pipe.close() is not None: |
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
348 |
raise BzrError("Failed funning '%s --bzr-help'" % path) |
|
422
by Martin Pool
- External-command patch from mpe |
349 |
|
350 |
def __call__(self, options, arguments): |
|
351 |
Command.__init__(self, options, arguments) |
|
352 |
return self |
|
353 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
354 |
def name(self): |
355 |
raise NotImplementedError() |
|
356 |
||
|
422
by Martin Pool
- External-command patch from mpe |
357 |
def run(self, **kargs): |
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
358 |
raise NotImplementedError() |
359 |
||
|
422
by Martin Pool
- External-command patch from mpe |
360 |
opts = [] |
361 |
args = [] |
|
362 |
||
363 |
keys = kargs.keys() |
|
364 |
keys.sort() |
|
365 |
for name in keys: |
|
|
689
by Martin Pool
- make options with - work with external commands |
366 |
optname = name.replace('_','-') |
|
422
by Martin Pool
- External-command patch from mpe |
367 |
value = kargs[name] |
|
689
by Martin Pool
- make options with - work with external commands |
368 |
if OPTIONS.has_key(optname): |
|
422
by Martin Pool
- External-command patch from mpe |
369 |
# it's an option
|
|
689
by Martin Pool
- make options with - work with external commands |
370 |
opts.append('--%s' % optname) |
|
422
by Martin Pool
- External-command patch from mpe |
371 |
if value is not None and value is not True: |
372 |
opts.append(str(value)) |
|
373 |
else: |
|
374 |
# it's an arg, or arg list
|
|
375 |
if type(value) is not list: |
|
376 |
value = [value] |
|
377 |
for v in value: |
|
378 |
if v is not None: |
|
379 |
args.append(str(v)) |
|
380 |
||
381 |
self.status = os.spawnv(os.P_WAIT, self.path, [self.path] + opts + args) |
|
382 |
return self.status |
|
383 |
||
|
329
by Martin Pool
- refactor command functions into command classes |
384 |
|
385 |
||
|
493
by Martin Pool
- Merge aaron's merge command |
386 |
def parse_spec(spec): |
|
622
by Martin Pool
Updated merge patch from Aaron |
387 |
""" |
388 |
>>> parse_spec(None)
|
|
389 |
[None, None]
|
|
390 |
>>> parse_spec("./")
|
|
391 |
['./', None]
|
|
392 |
>>> parse_spec("../@")
|
|
393 |
['..', -1]
|
|
394 |
>>> parse_spec("../f/@35")
|
|
395 |
['../f', 35]
|
|
|
897
by Martin Pool
- merge john's revision-naming code |
396 |
>>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
|
397 |
['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
|
|
|
622
by Martin Pool
Updated merge patch from Aaron |
398 |
"""
|
399 |
if spec is None: |
|
400 |
return [None, None] |
|
|
493
by Martin Pool
- Merge aaron's merge command |
401 |
if '/@' in spec: |
402 |
parsed = spec.split('/@') |
|
403 |
assert len(parsed) == 2 |
|
404 |
if parsed[1] == "": |
|
405 |
parsed[1] = -1 |
|
406 |
else: |
|
|
897
by Martin Pool
- merge john's revision-naming code |
407 |
try: |
408 |
parsed[1] = int(parsed[1]) |
|
409 |
except ValueError: |
|
410 |
pass # We can allow stuff like ./@revid:blahblahblah |
|
411 |
else: |
|
412 |
assert parsed[1] >=0 |
|
|
493
by Martin Pool
- Merge aaron's merge command |
413 |
else: |
414 |
parsed = [spec, None] |
|
415 |
return parsed |
|
416 |
||
|
628
by Martin Pool
- merge aaron's updated merge/pull code |
417 |
|
418 |
||
|
755
by Martin Pool
- new 'plugins' command |
419 |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
420 |
# list of all available options; the rhs can be either None for an
|
421 |
# option that takes no argument, or a constructor function that checks
|
|
422 |
# the type.
|
|
423 |
OPTIONS = { |
|
424 |
'all': None, |
|
|
571
by Martin Pool
- new --diff-options to pass options through to external |
425 |
'diff-options': str, |
|
1
by mbp at sourcefrog
import from baz patch-364 |
426 |
'help': None, |
|
389
by Martin Pool
- new commit --file option! |
427 |
'file': unicode, |
|
628
by Martin Pool
- merge aaron's updated merge/pull code |
428 |
'force': None, |
|
678
by Martin Pool
- export to tarballs |
429 |
'format': unicode, |
|
545
by Martin Pool
- --forward option for log |
430 |
'forward': None, |
|
1
by mbp at sourcefrog
import from baz patch-364 |
431 |
'message': unicode, |
|
594
by Martin Pool
- add --no-recurse option for add command |
432 |
'no-recurse': None, |
|
137
by mbp at sourcefrog
new --profile option |
433 |
'profile': None, |
|
567
by Martin Pool
- New form 'bzr log -r FROM:TO' |
434 |
'revision': _parse_revision_str, |
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
435 |
'short': None, |
|
1
by mbp at sourcefrog
import from baz patch-364 |
436 |
'show-ids': None, |
|
12
by mbp at sourcefrog
new --timezone option for bzr log |
437 |
'timezone': str, |
|
1
by mbp at sourcefrog
import from baz patch-364 |
438 |
'verbose': None, |
439 |
'version': None, |
|
|
286
by Martin Pool
- New bzr whoami --email option |
440 |
'email': None, |
|
885
by Martin Pool
- commit command refuses unless something is changed or --unchanged is given |
441 |
'unchanged': None, |
|
674
by Martin Pool
- check command now also checks new inventory_sha1 and |
442 |
'update': None, |
|
807
by Martin Pool
- New log --long option |
443 |
'long': None, |
|
849
by Martin Pool
- Put files inside an exported tarball into a top-level directory rather than |
444 |
'root': str, |
|
974.1.8
by Aaron Bentley
Added default backups for merge-revert |
445 |
'no-backup': None, |
|
974.1.9
by Aaron Bentley
Added merge-type parameter to merge. |
446 |
'merge-type': get_merge_type, |
|
1092.1.20
by Robert Collins
import and use TestUtil to do regex based partial test runs |
447 |
'pattern': str, |
|
1
by mbp at sourcefrog
import from baz patch-364 |
448 |
}
|
449 |
||
450 |
SHORT_OPTIONS = { |
|
|
583
by Martin Pool
- add -h as short name for --help |
451 |
'F': 'file', |
452 |
'h': 'help', |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
453 |
'm': 'message', |
454 |
'r': 'revision', |
|
455 |
'v': 'verbose', |
|
|
807
by Martin Pool
- New log --long option |
456 |
'l': 'long', |
|
1
by mbp at sourcefrog
import from baz patch-364 |
457 |
}
|
458 |
||
459 |
||
460 |
def parse_args(argv): |
|
461 |
"""Parse command line. |
|
462 |
|
|
463 |
Arguments and options are parsed at this level before being passed
|
|
464 |
down to specific command handlers. This routine knows, from a
|
|
465 |
lookup table, something about the available options, what optargs
|
|
466 |
they take, and which commands will accept them.
|
|
467 |
||
|
31
by Martin Pool
fix up parse_args doctest |
468 |
>>> parse_args('--help'.split())
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
469 |
([], {'help': True})
|
|
1144
by Martin Pool
- accept -- to terminate options |
470 |
>>> parse_args('help -- --invalidcmd'.split())
|
471 |
(['help', '--invalidcmd'], {})
|
|
|
31
by Martin Pool
fix up parse_args doctest |
472 |
>>> parse_args('--version'.split())
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
473 |
([], {'version': True})
|
|
31
by Martin Pool
fix up parse_args doctest |
474 |
>>> parse_args('status --all'.split())
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
475 |
(['status'], {'all': True})
|
|
31
by Martin Pool
fix up parse_args doctest |
476 |
>>> parse_args('commit --message=biter'.split())
|
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
477 |
(['commit'], {'message': u'biter'})
|
|
683
by Martin Pool
- short option stacking patch from John A Meinel |
478 |
>>> parse_args('log -r 500'.split())
|
|
897
by Martin Pool
- merge john's revision-naming code |
479 |
(['log'], {'revision': [500]})
|
480 |
>>> parse_args('log -r500..600'.split())
|
|
|
683
by Martin Pool
- short option stacking patch from John A Meinel |
481 |
(['log'], {'revision': [500, 600]})
|
|
897
by Martin Pool
- merge john's revision-naming code |
482 |
>>> parse_args('log -vr500..600'.split())
|
|
683
by Martin Pool
- short option stacking patch from John A Meinel |
483 |
(['log'], {'verbose': True, 'revision': [500, 600]})
|
|
897
by Martin Pool
- merge john's revision-naming code |
484 |
>>> parse_args('log -rv500..600'.split()) #the r takes an argument
|
485 |
(['log'], {'revision': ['v500', 600]})
|
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
486 |
"""
|
487 |
args = [] |
|
488 |
opts = {} |
|
489 |
||
|
1144
by Martin Pool
- accept -- to terminate options |
490 |
argsover = False |
|
26
by mbp at sourcefrog
fix StopIteration error on python2.3(?) |
491 |
while argv: |
492 |
a = argv.pop(0) |
|
|
1144
by Martin Pool
- accept -- to terminate options |
493 |
if not argsover and a[0] == '-': |
|
264
by Martin Pool
parse_args: option names must be ascii |
494 |
# option names must not be unicode
|
495 |
a = str(a) |
|
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
496 |
optarg = None |
|
1
by mbp at sourcefrog
import from baz patch-364 |
497 |
if a[1] == '-': |
|
1144
by Martin Pool
- accept -- to terminate options |
498 |
if a == '--': |
499 |
# We've received a standalone -- No more flags
|
|
500 |
argsover = True |
|
501 |
continue
|
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
502 |
mutter(" got option %r" % a) |
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
503 |
if '=' in a: |
504 |
optname, optarg = a[2:].split('=', 1) |
|
505 |
else: |
|
506 |
optname = a[2:] |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
507 |
if optname not in OPTIONS: |
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
508 |
raise BzrError('unknown long option %r' % a) |
|
1
by mbp at sourcefrog
import from baz patch-364 |
509 |
else: |
510 |
shortopt = a[1:] |
|
|
683
by Martin Pool
- short option stacking patch from John A Meinel |
511 |
if shortopt in SHORT_OPTIONS: |
512 |
# Multi-character options must have a space to delimit
|
|
513 |
# their value
|
|
514 |
optname = SHORT_OPTIONS[shortopt] |
|
515 |
else: |
|
516 |
# Single character short options, can be chained,
|
|
517 |
# and have their value appended to their name
|
|
518 |
shortopt = a[1:2] |
|
519 |
if shortopt not in SHORT_OPTIONS: |
|
520 |
# We didn't find the multi-character name, and we
|
|
521 |
# didn't find the single char name
|
|
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
522 |
raise BzrError('unknown short option %r' % a) |
|
683
by Martin Pool
- short option stacking patch from John A Meinel |
523 |
optname = SHORT_OPTIONS[shortopt] |
524 |
||
525 |
if a[2:]: |
|
526 |
# There are extra things on this option
|
|
527 |
# see if it is the value, or if it is another
|
|
528 |
# short option
|
|
529 |
optargfn = OPTIONS[optname] |
|
530 |
if optargfn is None: |
|
531 |
# This option does not take an argument, so the
|
|
532 |
# next entry is another short option, pack it back
|
|
533 |
# into the list
|
|
534 |
argv.insert(0, '-' + a[2:]) |
|
535 |
else: |
|
536 |
# This option takes an argument, so pack it
|
|
537 |
# into the array
|
|
538 |
optarg = a[2:] |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
539 |
|
540 |
if optname in opts: |
|
541 |
# XXX: Do we ever want to support this, e.g. for -r?
|
|
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
542 |
raise BzrError('repeated option %r' % a) |
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
543 |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
544 |
optargfn = OPTIONS[optname] |
545 |
if optargfn: |
|
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
546 |
if optarg == None: |
|
26
by mbp at sourcefrog
fix StopIteration error on python2.3(?) |
547 |
if not argv: |
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
548 |
raise BzrError('option %r needs an argument' % a) |
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
549 |
else: |
|
26
by mbp at sourcefrog
fix StopIteration error on python2.3(?) |
550 |
optarg = argv.pop(0) |
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
551 |
opts[optname] = optargfn(optarg) |
|
1
by mbp at sourcefrog
import from baz patch-364 |
552 |
else: |
|
17
by mbp at sourcefrog
allow --option=ARG syntax |
553 |
if optarg != None: |
|
694
by Martin Pool
- weed out all remaining calls to bailout() and remove the function |
554 |
raise BzrError('option %r takes no argument' % optname) |
|
1
by mbp at sourcefrog
import from baz patch-364 |
555 |
opts[optname] = True |
556 |
else: |
|
557 |
args.append(a) |
|
558 |
||
559 |
return args, opts |
|
560 |
||
561 |
||
562 |
||
563 |
||
|
329
by Martin Pool
- refactor command functions into command classes |
564 |
def _match_argform(cmd, takes_args, args): |
|
1
by mbp at sourcefrog
import from baz patch-364 |
565 |
argdict = {} |
|
26
by mbp at sourcefrog
fix StopIteration error on python2.3(?) |
566 |
|
|
329
by Martin Pool
- refactor command functions into command classes |
567 |
# step through args and takes_args, allowing appropriate 0-many matches
|
568 |
for ap in takes_args: |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
569 |
argname = ap[:-1] |
570 |
if ap[-1] == '?': |
|
|
62
by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron |
571 |
if args: |
572 |
argdict[argname] = args.pop(0) |
|
|
196
by mbp at sourcefrog
selected-file diff |
573 |
elif ap[-1] == '*': # all remaining arguments |
574 |
if args: |
|
575 |
argdict[argname + '_list'] = args[:] |
|
576 |
args = [] |
|
577 |
else: |
|
578 |
argdict[argname + '_list'] = None |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
579 |
elif ap[-1] == '+': |
580 |
if not args: |
|
|
329
by Martin Pool
- refactor command functions into command classes |
581 |
raise BzrCommandError("command %r needs one or more %s" |
|
1
by mbp at sourcefrog
import from baz patch-364 |
582 |
% (cmd, argname.upper())) |
583 |
else: |
|
584 |
argdict[argname + '_list'] = args[:] |
|
585 |
args = [] |
|
|
160
by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think |
586 |
elif ap[-1] == '$': # all but one |
587 |
if len(args) < 2: |
|
|
329
by Martin Pool
- refactor command functions into command classes |
588 |
raise BzrCommandError("command %r needs one or more %s" |
|
160
by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think |
589 |
% (cmd, argname.upper())) |
590 |
argdict[argname + '_list'] = args[:-1] |
|
591 |
args[:-1] = [] |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
592 |
else: |
593 |
# just a plain arg
|
|
594 |
argname = ap |
|
595 |
if not args: |
|
|
329
by Martin Pool
- refactor command functions into command classes |
596 |
raise BzrCommandError("command %r requires argument %s" |
|
1
by mbp at sourcefrog
import from baz patch-364 |
597 |
% (cmd, argname.upper())) |
598 |
else: |
|
599 |
argdict[argname] = args.pop(0) |
|
600 |
||
601 |
if args: |
|
|
329
by Martin Pool
- refactor command functions into command classes |
602 |
raise BzrCommandError("extra argument to command %s: %s" |
603 |
% (cmd, args[0])) |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
604 |
|
605 |
return argdict |
|
606 |
||
607 |
||
608 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
609 |
def apply_profiled(the_callable, *args, **kwargs): |
610 |
import hotshot |
|
611 |
import tempfile |
|
612 |
pffileno, pfname = tempfile.mkstemp() |
|
613 |
try: |
|
614 |
prof = hotshot.Profile(pfname) |
|
615 |
try: |
|
616 |
ret = prof.runcall(the_callable, *args, **kwargs) or 0 |
|
617 |
finally: |
|
618 |
prof.close() |
|
619 |
||
620 |
import hotshot.stats |
|
621 |
stats = hotshot.stats.load(pfname) |
|
622 |
#stats.strip_dirs()
|
|
623 |
stats.sort_stats('time') |
|
624 |
## XXX: Might like to write to stderr or the trace file instead but
|
|
625 |
## print_stats seems hardcoded to stdout
|
|
626 |
stats.print_stats(20) |
|
627 |
||
628 |
return ret |
|
629 |
finally: |
|
630 |
os.close(pffileno) |
|
631 |
os.remove(pfname) |
|
632 |
||
633 |
||
|
1
by mbp at sourcefrog
import from baz patch-364 |
634 |
def run_bzr(argv): |
635 |
"""Execute a command. |
|
636 |
||
637 |
This is similar to main(), but without all the trappings for
|
|
|
245
by mbp at sourcefrog
- control files always in utf-8-unix format |
638 |
logging and error handling.
|
|
973
by Martin Pool
- various refactorings of command interpreter |
639 |
|
640 |
argv
|
|
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
641 |
The command-line arguments, without the program name from argv[0]
|
|
973
by Martin Pool
- various refactorings of command interpreter |
642 |
|
643 |
Returns a command status or raises an exception.
|
|
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
644 |
|
645 |
Special master options: these must come before the command because
|
|
646 |
they control how the command is interpreted.
|
|
647 |
||
648 |
--no-plugins
|
|
649 |
Do not load plugin modules at all
|
|
650 |
||
651 |
--builtin
|
|
652 |
Only use builtin commands. (Plugins are still allowed to change
|
|
653 |
other behaviour.)
|
|
654 |
||
655 |
--profile
|
|
656 |
Run under the Python profiler.
|
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
657 |
"""
|
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
658 |
|
|
251
by mbp at sourcefrog
- factor out locale.getpreferredencoding() |
659 |
argv = [a.decode(bzrlib.user_encoding) for a in argv] |
|
973
by Martin Pool
- various refactorings of command interpreter |
660 |
|
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
661 |
opt_profile = opt_no_plugins = opt_builtin = False |
662 |
||
663 |
# --no-plugins is handled specially at a very early stage. We need
|
|
664 |
# to load plugins before doing other command parsing so that they
|
|
665 |
# can override commands, but this needs to happen first.
|
|
666 |
||
667 |
for a in argv[:]: |
|
668 |
if a == '--profile': |
|
669 |
opt_profile = True |
|
670 |
elif a == '--no-plugins': |
|
671 |
opt_no_plugins = True |
|
672 |
elif a == '--builtin': |
|
673 |
opt_builtin = True |
|
674 |
else: |
|
675 |
break
|
|
676 |
argv.remove(a) |
|
677 |
||
678 |
if not opt_no_plugins: |
|
|
973
by Martin Pool
- various refactorings of command interpreter |
679 |
from bzrlib.plugin import load_plugins |
680 |
load_plugins() |
|
681 |
||
682 |
args, opts = parse_args(argv) |
|
683 |
||
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
684 |
if 'help' in opts: |
|
973
by Martin Pool
- various refactorings of command interpreter |
685 |
from bzrlib.help import help |
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
686 |
if args: |
687 |
help(args[0]) |
|
|
973
by Martin Pool
- various refactorings of command interpreter |
688 |
else: |
689 |
help() |
|
690 |
return 0 |
|
691 |
||
692 |
if 'version' in opts: |
|
|
1147
by Martin Pool
- split builtin commands into separate module bzrlib.builtins; |
693 |
from bzrlib.builtins import show_version |
|
973
by Martin Pool
- various refactorings of command interpreter |
694 |
show_version() |
695 |
return 0 |
|
696 |
||
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
697 |
if not args: |
|
1099
by Martin Pool
- 'bzr' with no arguments shows the summary help. |
698 |
from bzrlib.help import help |
699 |
help(None) |
|
700 |
return 0 |
|
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
701 |
|
702 |
cmd = str(args.pop(0)) |
|
703 |
||
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
704 |
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin) |
|
1
by mbp at sourcefrog
import from baz patch-364 |
705 |
|
706 |
# check options are reasonable
|
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
707 |
allowed = cmd_obj.takes_options |
|
1
by mbp at sourcefrog
import from baz patch-364 |
708 |
for oname in opts: |
709 |
if oname not in allowed: |
|
|
381
by Martin Pool
- Better message when a wrong argument is given |
710 |
raise BzrCommandError("option '--%s' is not allowed for command %r" |
|
329
by Martin Pool
- refactor command functions into command classes |
711 |
% (oname, cmd)) |
|
176
by mbp at sourcefrog
New cat command contributed by janmar. |
712 |
|
|
137
by mbp at sourcefrog
new --profile option |
713 |
# mix arguments and options into one dictionary
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
714 |
cmdargs = _match_argform(cmd, cmd_obj.takes_args, args) |
|
329
by Martin Pool
- refactor command functions into command classes |
715 |
cmdopts = {} |
|
136
by mbp at sourcefrog
new --show-ids option for 'deleted' command |
716 |
for k, v in opts.items(): |
|
329
by Martin Pool
- refactor command functions into command classes |
717 |
cmdopts[k.replace('-', '_')] = v |
|
1
by mbp at sourcefrog
import from baz patch-364 |
718 |
|
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
719 |
all_cmd_args = cmdargs.copy() |
720 |
all_cmd_args.update(cmdopts) |
|
721 |
||
|
974.1.26
by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 |
722 |
if opt_profile: |
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
723 |
ret = apply_profiled(cmd_obj.run, **all_cmd_args) |
|
137
by mbp at sourcefrog
new --profile option |
724 |
else: |
|
1162
by Martin Pool
- change Command infrastructure to use (mostly stateless) objects to |
725 |
ret = cmd_obj.run(**all_cmd_args) |
726 |
||
727 |
if ret is None: |
|
728 |
ret = 0 |
|
729 |
return ret |
|
|
1
by mbp at sourcefrog
import from baz patch-364 |
730 |
|
731 |
||
732 |
def main(argv): |
|
|
1104
by Martin Pool
- Add a simple UIFactory |
733 |
import bzrlib.ui |
|
1111
by Martin Pool
- add functions to enable and disable default logging, so that we can |
734 |
bzrlib.trace.log_startup(argv) |
|
1104
by Martin Pool
- Add a simple UIFactory |
735 |
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory() |
736 |
||
|
1
by mbp at sourcefrog
import from baz patch-364 |
737 |
try: |
|
260
by Martin Pool
- remove atexit() dependency for writing out execution times |
738 |
try: |
|
1097
by Martin Pool
- send trace messages out through python logging module |
739 |
return run_bzr(argv[1:]) |
740 |
finally: |
|
741 |
# do this here inside the exception wrappers to catch EPIPE
|
|
742 |
sys.stdout.flush() |
|
743 |
except BzrCommandError, e: |
|
744 |
# command line syntax error, etc
|
|
745 |
log_error(str(e)) |
|
746 |
return 1 |
|
747 |
except BzrError, e: |
|
748 |
bzrlib.trace.log_exception() |
|
749 |
return 1 |
|
750 |
except AssertionError, e: |
|
751 |
bzrlib.trace.log_exception('assertion failed: ' + str(e)) |
|
752 |
return 3 |
|
753 |
except KeyboardInterrupt, e: |
|
754 |
bzrlib.trace.note('interrupted') |
|
755 |
return 2 |
|
756 |
except Exception, e: |
|
757 |
import errno |
|
758 |
if (isinstance(e, IOError) |
|
759 |
and hasattr(e, 'errno') |
|
760 |
and e.errno == errno.EPIPE): |
|
761 |
bzrlib.trace.note('broken pipe') |
|
762 |
return 2 |
|
763 |
else: |
|
|
1108
by Martin Pool
- more cleanups of error reporting |
764 |
bzrlib.trace.log_exception() |
|
1097
by Martin Pool
- send trace messages out through python logging module |
765 |
return 2 |
|
1
by mbp at sourcefrog
import from baz patch-364 |
766 |
|
767 |
||
768 |
if __name__ == '__main__': |
|
769 |
sys.exit(main(sys.argv)) |