41
40
each revision specifier supplied.
43
42
>>> _parse_revision_str('234')
44
[<RevisionSpec_revno 234>]
43
[<RevisionSpec_dwim 234>]
45
44
>>> _parse_revision_str('234..567')
46
[<RevisionSpec_revno 234>, <RevisionSpec_revno 567>]
45
[<RevisionSpec_dwim 234>, <RevisionSpec_dwim 567>]
47
46
>>> _parse_revision_str('..')
48
47
[<RevisionSpec None>, <RevisionSpec None>]
49
48
>>> _parse_revision_str('..234')
50
[<RevisionSpec None>, <RevisionSpec_revno 234>]
49
[<RevisionSpec None>, <RevisionSpec_dwim 234>]
51
50
>>> _parse_revision_str('234..')
52
[<RevisionSpec_revno 234>, <RevisionSpec None>]
51
[<RevisionSpec_dwim 234>, <RevisionSpec None>]
53
52
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
54
[<RevisionSpec_revno 234>, <RevisionSpec_revno 456>, <RevisionSpec_revno 789>]
53
[<RevisionSpec_dwim 234>, <RevisionSpec_dwim 456>, <RevisionSpec_dwim 789>]
55
54
>>> _parse_revision_str('234....789') #Error ?
56
[<RevisionSpec_revno 234>, <RevisionSpec None>, <RevisionSpec_revno 789>]
55
[<RevisionSpec_dwim 234>, <RevisionSpec None>, <RevisionSpec_dwim 789>]
57
56
>>> _parse_revision_str('revid:test@other.com-234234')
58
57
[<RevisionSpec_revid revid:test@other.com-234234>]
59
58
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
60
59
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
61
60
>>> _parse_revision_str('revid:test@other.com-234234..23')
62
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revno 23>]
61
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_dwim 23>]
63
62
>>> _parse_revision_str('date:2005-04-12')
64
63
[<RevisionSpec_date date:2005-04-12>]
65
64
>>> _parse_revision_str('date:2005-04-12 12:24:33')
69
68
>>> _parse_revision_str('date:2005-04-12,12:24:33')
70
69
[<RevisionSpec_date date:2005-04-12,12:24:33>]
71
70
>>> _parse_revision_str('-5..23')
72
[<RevisionSpec_revno -5>, <RevisionSpec_revno 23>]
71
[<RevisionSpec_dwim -5>, <RevisionSpec_dwim 23>]
73
72
>>> _parse_revision_str('-5')
74
[<RevisionSpec_revno -5>]
73
[<RevisionSpec_dwim -5>]
75
74
>>> _parse_revision_str('123a')
76
Traceback (most recent call last):
78
NoSuchRevisionSpec: No namespace registered for string: '123a'
75
[<RevisionSpec_dwim 123a>]
79
76
>>> _parse_revision_str('abc')
80
Traceback (most recent call last):
82
NoSuchRevisionSpec: No namespace registered for string: 'abc'
77
[<RevisionSpec_dwim abc>]
83
78
>>> _parse_revision_str('branch:../branch2')
84
79
[<RevisionSpec_branch branch:../branch2>]
85
80
>>> _parse_revision_str('branch:../../branch2')
86
81
[<RevisionSpec_branch branch:../../branch2>]
87
82
>>> _parse_revision_str('branch:../../branch2..23')
88
[<RevisionSpec_branch branch:../../branch2>, <RevisionSpec_revno 23>]
83
[<RevisionSpec_branch branch:../../branch2>, <RevisionSpec_dwim 23>]
84
>>> _parse_revision_str('branch:..\\\\branch2')
85
[<RevisionSpec_branch branch:..\\branch2>]
86
>>> _parse_revision_str('branch:..\\\\..\\\\branch2..23')
87
[<RevisionSpec_branch branch:..\\..\\branch2>, <RevisionSpec_dwim 23>]
90
89
# TODO: Maybe move this into revisionspec.py
92
# split on the first .. that is not followed by a / ?
93
sep = re.compile("\\.\\.(?!/)")
91
# split on .. that is not followed by a / or \
92
sep = re.compile(r'\.\.(?![\\/])')
94
93
for x in sep.split(revstr):
95
94
revs.append(revisionspec.RevisionSpec.from_string(x or None))
98
def _parse_change_str(revstr):
99
"""Parse the revision string and return a tuple with left-most
100
parent of the revision.
102
>>> _parse_change_str('123')
103
(<RevisionSpec_before before:123>, <RevisionSpec_dwim 123>)
104
>>> _parse_change_str('123..124')
105
Traceback (most recent call last):
107
RangeInChangeOption: Option --change does not accept revision ranges
109
revs = _parse_revision_str(revstr)
111
raise errors.RangeInChangeOption()
112
return (revisionspec.RevisionSpec.from_string('before:' + revstr),
99
116
def _parse_merge_type(typestring):
100
117
return get_merge_type(typestring)
116
133
class Option(object):
117
134
"""Description of a command line option
119
136
:ivar _short_name: If this option has a single-letter name, this is it.
123
# TODO: Some way to show in help a description of the option argument
140
# The dictionary of standard options. These are always legal.
143
# The dictionary of commonly used options. these are only legal
144
# if a command explicitly references them by name in the list
145
# of supported options.
127
148
def __init__(self, name, help='', type=None, argname=None,
149
short_name=None, param_name=None, custom_callback=None,
129
151
"""Make a new command option.
131
name -- regular name of the command, used in the double-dash
132
form and also as the parameter to the command's run()
135
help -- help message displayed in command help
137
type -- function called to parse the option argument, or
153
:param name: regular name of the command, used in the double-dash
154
form and also as the parameter to the command's run()
155
method (unless param_name is specified).
157
:param help: help message displayed in command help
159
:param type: function called to parse the option argument, or
138
160
None (default) if this option doesn't take an argument.
140
argname -- name of option argument, if any
162
:param argname: name of option argument, if any
164
:param short_name: short option code for use with a single -, e.g.
165
short_name="v" to enable parsing of -v.
167
:param param_name: name of the parameter which will be passed to
168
the command's run() method.
170
:param custom_callback: a callback routine to be called after normal
171
processing. The signature of the callback routine is
172
(option, name, new_value, parser).
173
:param hidden: If True, the option should be hidden in help and
145
179
self._short_name = short_name
147
assert argname is None
182
raise ValueError('argname not valid for booleans')
148
183
elif argname is None:
150
185
self.argname = argname
186
if param_name is None:
187
self._param_name = self.name.replace('-', '_')
189
self._param_name = param_name
190
self.custom_callback = custom_callback
152
193
def short_name(self):
153
194
if self._short_name:
154
195
return self._short_name
156
# remove this when SHORT_OPTIONS is removed
157
# XXX: This is accessing a DeprecatedDict, so we call the super
158
# method to avoid warnings
159
for (k, v) in dict.iteritems(Option.SHORT_OPTIONS):
163
197
def set_short_name(self, short_name):
164
198
self._short_name = short_name
174
208
option_strings = ['--%s' % self.name]
175
209
if short_name is not None:
176
210
option_strings.append('-%s' % short_name)
212
help = optparse.SUPPRESS_HELP
177
215
optargfn = self.type
178
216
if optargfn is None:
179
parser.add_option(action='store_true', dest=self.name,
181
default=OptionParser.DEFAULT_VALUE,
217
parser.add_option(action='callback',
218
callback=self._optparse_bool_callback,
219
callback_args=(True,),
183
222
negation_strings = ['--%s' % self.get_negation_name()]
184
parser.add_option(action='store_false', dest=self.name,
223
parser.add_option(action='callback',
224
callback=self._optparse_bool_callback,
225
callback_args=(False,),
185
226
help=optparse.SUPPRESS_HELP, *negation_strings)
187
parser.add_option(action='callback',
188
callback=self._optparse_callback,
228
parser.add_option(action='callback',
229
callback=self._optparse_callback,
189
230
type='string', metavar=self.argname.upper(),
191
default=OptionParser.DEFAULT_VALUE,
232
default=OptionParser.DEFAULT_VALUE,
235
def _optparse_bool_callback(self, option, opt_str, value, parser, bool_v):
236
setattr(parser.values, self._param_name, bool_v)
237
if self.custom_callback is not None:
238
self.custom_callback(option, self._param_name, bool_v, parser)
194
240
def _optparse_callback(self, option, opt, value, parser):
195
setattr(parser.values, self.name, self.type(value))
242
setattr(parser.values, self._param_name, v)
243
if self.custom_callback is not None:
244
self.custom_callback(option, self.name, v, parser)
197
246
def iter_switches(self):
198
247
"""Iterate through the list of switches provided by the option
200
249
:return: an iterator of (name, short_name, argname, help)
202
251
argname = self.argname
204
253
argname = argname.upper()
205
254
yield self.name, self.short_name(), argname, self.help
256
def is_hidden(self, name):
260
class ListOption(Option):
261
"""Option used to provide a list of values.
263
On the command line, arguments are specified by a repeated use of the
264
option. '-' is a special argument that resets the list. For example,
266
sets the value of the 'foo' option to ['a', 'b'], and
267
--foo=a --foo=b --foo=- --foo=c
268
sets the value of the 'foo' option to ['c'].
271
def add_option(self, parser, short_name):
272
"""Add this option to an Optparse parser."""
273
option_strings = ['--%s' % self.name]
274
if short_name is not None:
275
option_strings.append('-%s' % short_name)
276
parser.add_option(action='callback',
277
callback=self._optparse_callback,
278
type='string', metavar=self.argname.upper(),
279
help=self.help, dest=self._param_name, default=[],
282
def _optparse_callback(self, option, opt, value, parser):
283
values = getattr(parser.values, self._param_name)
287
values.append(self.type(value))
288
if self.custom_callback is not None:
289
self.custom_callback(option, self._param_name, values, parser)
208
292
class RegistryOption(Option):
209
293
"""Option based on a registry
260
362
name, help, value_switches and enum_switch are passed to the
261
363
RegistryOption constructor. Any other keyword arguments are treated
262
as values for the option, and they value is treated as the help.
364
as values for the option, and their value is treated as the help.
264
reg = registry.Registry()
265
for name, help in kwargs.iteritems():
366
reg = _mod_registry.Registry()
367
for name, switch_help in sorted(kwargs.items()):
266
368
name = name.replace('_', '-')
267
reg.register(name, name, help=help)
369
reg.register(name, name, help=switch_help)
370
if not value_switches:
371
help = help + ' "' + name + '": ' + switch_help
372
if not help.endswith("."):
268
374
return RegistryOption(name_, help, reg, title=title,
269
375
value_switches=value_switches, enum_switch=enum_switch)
439
def custom_help(name, help):
440
"""Clone a common option overriding the help."""
442
o = copy.copy(Option.OPTIONS[name])
447
def _standard_option(name, **kwargs):
448
"""Register a standard option."""
449
# All standard options are implicitly 'global' ones
450
Option.STD_OPTIONS[name] = Option(name, **kwargs)
451
Option.OPTIONS[name] = Option.STD_OPTIONS[name]
325
454
def _global_option(name, **kwargs):
326
"""Register o as a global option."""
455
"""Register a global option."""
327
456
Option.OPTIONS[name] = Option(name, **kwargs)
330
def _global_registry_option(name, help, registry, **kwargs):
459
def _global_registry_option(name, help, registry=None, **kwargs):
331
460
Option.OPTIONS[name] = RegistryOption(name, help, registry, **kwargs)
334
class MergeTypeRegistry(registry.Registry):
463
# This is the verbosity level detected during command line parsing.
464
# Note that the final value is dependent on the order in which the
465
# various flags (verbose, quiet, no-verbose, no-quiet) are given.
466
# The final value will be one of the following:
474
def _verbosity_level_callback(option, opt_str, value, parser):
475
global _verbosity_level
477
# Either --no-verbose or --no-quiet was specified
479
elif opt_str == "verbose":
480
if _verbosity_level > 0:
481
_verbosity_level += 1
485
if _verbosity_level < 0:
486
_verbosity_level -= 1
488
_verbosity_level = -1
491
class MergeTypeRegistry(_mod_registry.Registry):
343
500
"Merge using external diff3")
344
501
_merge_type_registry.register_lazy('weave', 'bzrlib.merge', 'WeaveMerger',
345
502
"Weave-based merge")
503
_merge_type_registry.register_lazy('lca', 'bzrlib.merge', 'LCAMerger',
506
# Declare the standard options
507
_standard_option('help', short_name='h',
508
help='Show help message.')
509
_standard_option('usage',
510
help='Show usage message and options.')
511
_standard_option('verbose', short_name='v',
512
help='Display more information.',
513
custom_callback=_verbosity_level_callback)
514
_standard_option('quiet', short_name='q',
515
help="Only display errors and warnings.",
516
custom_callback=_verbosity_level_callback)
518
# Declare commonly used options
347
519
_global_option('all')
348
520
_global_option('overwrite', help='Ignore differences between branches and '
349
'overwrite unconditionally')
521
'overwrite unconditionally.')
350
522
_global_option('basis', type=str)
351
523
_global_option('bound')
352
524
_global_option('diff-options', type=str)
353
_global_option('help',
354
help='show help message',
356
525
_global_option('file', type=unicode, short_name='F')
357
526
_global_option('force')
358
527
_global_option('format', type=unicode)
359
528
_global_option('forward')
360
529
_global_option('message', type=unicode,
531
help='Message string.')
362
532
_global_option('no-recurse')
363
533
_global_option('profile',
364
help='show performance profiling information')
534
help='Show performance profiling information.')
365
535
_global_option('revision',
366
536
type=_parse_revision_str,
368
help='See \'help revisionspec\' for details')
369
_global_option('show-ids',
370
help='show internal object ids')
371
_global_option('timezone',
538
help='See "help revisionspec" for details.')
539
_global_option('change',
540
type=_parse_change_str,
542
param_name='revision',
543
help='Select changes introduced by the specified revision. See also "help revisionspec".')
544
_global_option('show-ids',
545
help='Show internal object ids.')
546
_global_option('timezone',
373
help='display timezone as local, original, or utc')
548
help='Display timezone as local, original, or utc.')
374
549
_global_option('unbound')
375
_global_option('verbose',
376
help='display more information',
378
550
_global_option('version')
379
551
_global_option('email')
380
552
_global_option('update')
381
_global_registry_option('log-format', "Use this log format",
382
log.log_formatter_registry, value_switches=True,
553
_global_registry_option('log-format', "Use specified log format.",
554
lazy_registry=('bzrlib.log', 'log_formatter_registry'),
555
value_switches=True, title='Log format')
384
556
_global_option('long', help='Use detailed log format. Same as --log-format long',
386
558
_global_option('short', help='Use moderately short log format. Same as --log-format short')
387
559
_global_option('line', help='Use log format with one line per revision. Same as --log-format line')
388
560
_global_option('root', type=str)
389
561
_global_option('no-backup')
390
_global_registry_option('merge-type', 'Select a particular merge algorithm',
562
_global_registry_option('merge-type', 'Select a particular merge algorithm.',
391
563
_merge_type_registry, value_switches=True,
392
564
title='Merge algorithm')
393
565
_global_option('pattern', type=str)
394
_global_option('quiet', short_name='q')
395
566
_global_option('remember', help='Remember the specified location as a'
397
_global_option('reprocess', help='Reprocess to reduce spurious conflicts')
568
_global_option('reprocess', help='Reprocess to reduce spurious conflicts.')
398
569
_global_option('kind', type=str)
399
570
_global_option('dry-run',
400
help="show what would be done, but don't actually do anything")
571
help="Show what would be done, but don't actually do anything.")
401
572
_global_option('name-from-revision', help='The path name in the old tree.')
404
# prior to 0.14 these were always globally registered; the old dict is
405
# available for plugins that use it but it should not be used.
406
Option.SHORT_OPTIONS = symbol_versioning.DeprecatedDict(
407
symbol_versioning.zero_fourteen,
410
'F': Option.OPTIONS['file'],
411
'h': Option.OPTIONS['help'],
412
'm': Option.OPTIONS['message'],
413
'r': Option.OPTIONS['revision'],
414
'v': Option.OPTIONS['verbose'],
415
'l': Option.OPTIONS['long'],
416
'q': Option.OPTIONS['quiet'],
418
'Set the short option name when constructing the Option.',
574
diff_writer_registry = _mod_registry.Registry()
575
diff_writer_registry.register('plain', lambda x: x, 'Plaintext diff output.')
576
diff_writer_registry.default_key = 'plain'