41
41
each revision specifier supplied.
43
43
>>> _parse_revision_str('234')
44
[<RevisionSpec_dwim 234>]
44
[<RevisionSpec_revno 234>]
45
45
>>> _parse_revision_str('234..567')
46
[<RevisionSpec_dwim 234>, <RevisionSpec_dwim 567>]
46
[<RevisionSpec_revno 234>, <RevisionSpec_revno 567>]
47
47
>>> _parse_revision_str('..')
48
48
[<RevisionSpec None>, <RevisionSpec None>]
49
49
>>> _parse_revision_str('..234')
50
[<RevisionSpec None>, <RevisionSpec_dwim 234>]
50
[<RevisionSpec None>, <RevisionSpec_revno 234>]
51
51
>>> _parse_revision_str('234..')
52
[<RevisionSpec_dwim 234>, <RevisionSpec None>]
52
[<RevisionSpec_revno 234>, <RevisionSpec None>]
53
53
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
54
[<RevisionSpec_dwim 234>, <RevisionSpec_dwim 456>, <RevisionSpec_dwim 789>]
54
[<RevisionSpec_revno 234>, <RevisionSpec_revno 456>, <RevisionSpec_revno 789>]
55
55
>>> _parse_revision_str('234....789') #Error ?
56
[<RevisionSpec_dwim 234>, <RevisionSpec None>, <RevisionSpec_dwim 789>]
56
[<RevisionSpec_revno 234>, <RevisionSpec None>, <RevisionSpec_revno 789>]
57
57
>>> _parse_revision_str('revid:test@other.com-234234')
58
58
[<RevisionSpec_revid revid:test@other.com-234234>]
59
59
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
60
60
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
61
61
>>> _parse_revision_str('revid:test@other.com-234234..23')
62
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_dwim 23>]
62
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revno 23>]
63
63
>>> _parse_revision_str('date:2005-04-12')
64
64
[<RevisionSpec_date date:2005-04-12>]
65
65
>>> _parse_revision_str('date:2005-04-12 12:24:33')
69
69
>>> _parse_revision_str('date:2005-04-12,12:24:33')
70
70
[<RevisionSpec_date date:2005-04-12,12:24:33>]
71
71
>>> _parse_revision_str('-5..23')
72
[<RevisionSpec_dwim -5>, <RevisionSpec_dwim 23>]
72
[<RevisionSpec_revno -5>, <RevisionSpec_revno 23>]
73
73
>>> _parse_revision_str('-5')
74
[<RevisionSpec_dwim -5>]
74
[<RevisionSpec_revno -5>]
75
75
>>> _parse_revision_str('123a')
76
[<RevisionSpec_dwim 123a>]
76
Traceback (most recent call last):
78
NoSuchRevisionSpec: No namespace registered for string: '123a'
77
79
>>> _parse_revision_str('abc')
78
[<RevisionSpec_dwim abc>]
80
Traceback (most recent call last):
82
NoSuchRevisionSpec: No namespace registered for string: 'abc'
79
83
>>> _parse_revision_str('branch:../branch2')
80
84
[<RevisionSpec_branch branch:../branch2>]
81
85
>>> _parse_revision_str('branch:../../branch2')
82
86
[<RevisionSpec_branch branch:../../branch2>]
83
87
>>> _parse_revision_str('branch:../../branch2..23')
84
[<RevisionSpec_branch branch:../../branch2>, <RevisionSpec_dwim 23>]
85
>>> _parse_revision_str('branch:..\\\\branch2')
86
[<RevisionSpec_branch branch:..\\branch2>]
87
>>> _parse_revision_str('branch:..\\\\..\\\\branch2..23')
88
[<RevisionSpec_branch branch:..\\..\\branch2>, <RevisionSpec_dwim 23>]
88
[<RevisionSpec_branch branch:../../branch2>, <RevisionSpec_revno 23>]
90
90
# TODO: Maybe move this into revisionspec.py
92
# split on .. that is not followed by a / or \
93
sep = re.compile(r'\.\.(?![\\/])')
92
# split on the first .. that is not followed by a / ?
93
sep = re.compile("\\.\\.(?!/)")
94
94
for x in sep.split(revstr):
95
95
revs.append(revisionspec.RevisionSpec.from_string(x or None))
99
def _parse_change_str(revstr):
100
"""Parse the revision string and return a tuple with left-most
101
parent of the revision.
103
>>> _parse_change_str('123')
104
(<RevisionSpec_before before:123>, <RevisionSpec_dwim 123>)
105
>>> _parse_change_str('123..124')
106
Traceback (most recent call last):
108
RangeInChangeOption: Option --change does not accept revision ranges
110
revs = _parse_revision_str(revstr)
112
raise errors.RangeInChangeOption()
113
return (revisionspec.RevisionSpec.from_string('before:' + revstr),
117
99
def _parse_merge_type(typestring):
118
100
return get_merge_type(typestring)
134
116
class Option(object):
135
117
"""Description of a command line option
137
119
:ivar _short_name: If this option has a single-letter name, this is it.
141
# The dictionary of standard options. These are always legal.
123
# TODO: Some way to show in help a description of the option argument
144
# The dictionary of commonly used options. these are only legal
145
# if a command explicitly references them by name in the list
146
# of supported options.
149
127
def __init__(self, name, help='', type=None, argname=None,
150
short_name=None, param_name=None, custom_callback=None,
152
129
"""Make a new command option.
154
:param name: regular name of the command, used in the double-dash
155
form and also as the parameter to the command's run()
156
method (unless param_name is specified).
158
:param help: help message displayed in command help
160
:param type: function called to parse the option argument, or
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
161
138
None (default) if this option doesn't take an argument.
163
:param argname: name of option argument, if any
165
:param short_name: short option code for use with a single -, e.g.
166
short_name="v" to enable parsing of -v.
168
:param param_name: name of the parameter which will be passed to
169
the command's run() method.
171
:param custom_callback: a callback routine to be called after normal
172
processing. The signature of the callback routine is
173
(option, name, new_value, parser).
174
:param hidden: If True, the option should be hidden in help and
140
argname -- name of option argument, if any
180
145
self._short_name = short_name
183
raise ValueError('argname not valid for booleans')
147
assert argname is None
184
148
elif argname is None:
186
150
self.argname = argname
187
if param_name is None:
188
self._param_name = self.name.replace('-', '_')
190
self._param_name = param_name
191
self.custom_callback = custom_callback
194
152
def short_name(self):
195
153
if self._short_name:
196
154
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):
198
163
def set_short_name(self, short_name):
199
164
self._short_name = short_name
209
174
option_strings = ['--%s' % self.name]
210
175
if short_name is not None:
211
176
option_strings.append('-%s' % short_name)
213
help = optparse.SUPPRESS_HELP
216
177
optargfn = self.type
217
178
if optargfn is None:
218
parser.add_option(action='callback',
219
callback=self._optparse_bool_callback,
220
callback_args=(True,),
179
parser.add_option(action='store_true', dest=self.name,
181
default=OptionParser.DEFAULT_VALUE,
223
183
negation_strings = ['--%s' % self.get_negation_name()]
224
parser.add_option(action='callback',
225
callback=self._optparse_bool_callback,
226
callback_args=(False,),
184
parser.add_option(action='store_false', dest=self.name,
227
185
help=optparse.SUPPRESS_HELP, *negation_strings)
229
parser.add_option(action='callback',
230
callback=self._optparse_callback,
187
parser.add_option(action='callback',
188
callback=self._optparse_callback,
231
189
type='string', metavar=self.argname.upper(),
233
default=OptionParser.DEFAULT_VALUE,
191
default=OptionParser.DEFAULT_VALUE,
236
def _optparse_bool_callback(self, option, opt_str, value, parser, bool_v):
237
setattr(parser.values, self._param_name, bool_v)
238
if self.custom_callback is not None:
239
self.custom_callback(option, self._param_name, bool_v, parser)
241
194
def _optparse_callback(self, option, opt, value, parser):
243
setattr(parser.values, self._param_name, v)
244
if self.custom_callback is not None:
245
self.custom_callback(option, self.name, v, parser)
195
setattr(parser.values, self.name, self.type(value))
247
197
def iter_switches(self):
248
198
"""Iterate through the list of switches provided by the option
250
200
:return: an iterator of (name, short_name, argname, help)
252
202
argname = self.argname
254
204
argname = argname.upper()
255
205
yield self.name, self.short_name(), argname, self.help
257
def is_hidden(self, name):
261
class ListOption(Option):
262
"""Option used to provide a list of values.
264
On the command line, arguments are specified by a repeated use of the
265
option. '-' is a special argument that resets the list. For example,
267
sets the value of the 'foo' option to ['a', 'b'], and
268
--foo=a --foo=b --foo=- --foo=c
269
sets the value of the 'foo' option to ['c'].
272
def add_option(self, parser, short_name):
273
"""Add this option to an Optparse parser."""
274
option_strings = ['--%s' % self.name]
275
if short_name is not None:
276
option_strings.append('-%s' % short_name)
277
parser.add_option(action='callback',
278
callback=self._optparse_callback,
279
type='string', metavar=self.argname.upper(),
280
help=self.help, dest=self._param_name, default=[],
283
def _optparse_callback(self, option, opt, value, parser):
284
values = getattr(parser.values, self._param_name)
288
values.append(self.type(value))
289
if self.custom_callback is not None:
290
self.custom_callback(option, self._param_name, values, parser)
293
208
class RegistryOption(Option):
294
209
"""Option based on a registry
327
241
'--knit' can be used interchangeably.
328
242
:param enum_switch: If true, a switch is provided with the option name,
329
243
which takes a value.
330
:param lazy_registry: A tuple of (module name, attribute name) for a
331
registry to be lazily loaded.
332
:param short_name: The short name for the enum switch, if any
333
:param short_value_switches: A dict mapping values to short names
335
Option.__init__(self, name, help, type=self.convert, short_name=short_name)
336
self._registry = registry
338
if lazy_registry is None:
339
raise AssertionError(
340
'One of registry or lazy_registry must be given.')
341
self._lazy_registry = _mod_registry._LazyObjectGetter(
343
if registry is not None and lazy_registry is not None:
344
raise AssertionError(
345
'registry and lazy_registry are mutually exclusive')
245
Option.__init__(self, name, help, type=self.convert)
246
self.registry = registry
347
248
self.converter = converter
348
249
self.value_switches = value_switches
349
250
self.enum_switch = enum_switch
350
self.short_value_switches = short_value_switches
351
251
self.title = title
352
252
if self.title is None:
353
253
self.title = name
357
if self._registry is None:
358
self._registry = self._lazy_registry.get_obj()
359
return self._registry
362
256
def from_kwargs(name_, help=None, title=None, value_switches=False,
363
257
enum_switch=True, **kwargs):
366
260
name, help, value_switches and enum_switch are passed to the
367
261
RegistryOption constructor. Any other keyword arguments are treated
368
as values for the option, and their value is treated as the help.
262
as values for the option, and they value is treated as the help.
370
reg = _mod_registry.Registry()
371
for name, switch_help in sorted(kwargs.items()):
264
reg = registry.Registry()
265
for name, help in kwargs.iteritems():
372
266
name = name.replace('_', '-')
373
reg.register(name, name, help=switch_help)
374
if not value_switches:
375
help = help + ' "' + name + '": ' + switch_help
376
if not help.endswith("."):
267
reg.register(name, name, help=help)
378
268
return RegistryOption(name_, help, reg, title=title,
379
269
value_switches=value_switches, enum_switch=enum_switch)
419
302
for key in sorted(self.registry.keys()):
420
303
yield key, None, None, self.registry.get_help(key)
422
def is_hidden(self, name):
423
if name == self.name:
424
return Option.is_hidden(self, name)
425
return getattr(self.registry.get_info(name), 'hidden', False)
428
306
class OptionParser(optparse.OptionParser):
429
307
"""OptionParser that raises exceptions instead of exiting"""
431
309
DEFAULT_VALUE = object()
434
optparse.OptionParser.__init__(self)
435
self.formatter = GettextIndentedHelpFormatter()
437
311
def error(self, message):
438
312
raise errors.BzrCommandError(message)
440
class GettextIndentedHelpFormatter(optparse.IndentedHelpFormatter):
441
"""Adds gettext() call to format_option()"""
443
optparse.IndentedHelpFormatter.__init__(self)
445
def format_option(self, option):
446
"""code taken from Python's optparse.py"""
448
option.help = i18n.gettext(option.help)
449
return optparse.IndentedHelpFormatter.format_option(self, option)
451
315
def get_optparser(options):
452
316
"""Generate an optparse parser for bzrlib-style options"""
461
def custom_help(name, help):
462
"""Clone a common option overriding the help."""
464
o = copy.copy(Option.OPTIONS[name])
469
def _standard_option(name, **kwargs):
470
"""Register a standard option."""
471
# All standard options are implicitly 'global' ones
472
Option.STD_OPTIONS[name] = Option(name, **kwargs)
473
Option.OPTIONS[name] = Option.STD_OPTIONS[name]
476
325
def _global_option(name, **kwargs):
477
"""Register a global option."""
326
"""Register o as a global option."""
478
327
Option.OPTIONS[name] = Option(name, **kwargs)
481
def _global_registry_option(name, help, registry=None, **kwargs):
330
def _global_registry_option(name, help, registry, **kwargs):
482
331
Option.OPTIONS[name] = RegistryOption(name, help, registry, **kwargs)
485
# This is the verbosity level detected during command line parsing.
486
# Note that the final value is dependent on the order in which the
487
# various flags (verbose, quiet, no-verbose, no-quiet) are given.
488
# The final value will be one of the following:
496
def _verbosity_level_callback(option, opt_str, value, parser):
497
global _verbosity_level
499
# Either --no-verbose or --no-quiet was specified
501
elif opt_str == "verbose":
502
if _verbosity_level > 0:
503
_verbosity_level += 1
507
if _verbosity_level < 0:
508
_verbosity_level -= 1
510
_verbosity_level = -1
513
class MergeTypeRegistry(_mod_registry.Registry):
334
class MergeTypeRegistry(registry.Registry):
522
343
"Merge using external diff3")
523
344
_merge_type_registry.register_lazy('weave', 'bzrlib.merge', 'WeaveMerger',
524
345
"Weave-based merge")
525
_merge_type_registry.register_lazy('lca', 'bzrlib.merge', 'LCAMerger',
528
# Declare the standard options
529
_standard_option('help', short_name='h',
530
help='Show help message.')
531
_standard_option('usage',
532
help='Show usage message and options.')
533
_standard_option('verbose', short_name='v',
534
help='Display more information.',
535
custom_callback=_verbosity_level_callback)
536
_standard_option('quiet', short_name='q',
537
help="Only display errors and warnings.",
538
custom_callback=_verbosity_level_callback)
540
# Declare commonly used options
541
347
_global_option('all')
542
348
_global_option('overwrite', help='Ignore differences between branches and '
543
'overwrite unconditionally.')
349
'overwrite unconditionally')
544
350
_global_option('basis', type=str)
545
351
_global_option('bound')
546
352
_global_option('diff-options', type=str)
353
_global_option('help',
354
help='show help message',
547
356
_global_option('file', type=unicode, short_name='F')
548
357
_global_option('force')
549
358
_global_option('format', type=unicode)
550
359
_global_option('forward')
551
360
_global_option('message', type=unicode,
553
help='Message string.')
554
362
_global_option('no-recurse')
555
_global_option('null', short_name='0',
556
help='Use an ASCII NUL (\\0) separator rather than '
558
363
_global_option('profile',
559
help='Show performance profiling information.')
364
help='show performance profiling information')
560
365
_global_option('revision',
561
366
type=_parse_revision_str,
563
help='See "help revisionspec" for details.')
564
_global_option('change',
565
type=_parse_change_str,
567
param_name='revision',
568
help='Select changes introduced by the specified revision. See also "help revisionspec".')
569
_global_option('show-ids',
570
help='Show internal object ids.')
571
_global_option('timezone',
368
help='See \'help revisionspec\' for details')
369
_global_option('show-ids',
370
help='show internal object ids')
371
_global_option('timezone',
573
help='Display timezone as local, original, or utc.')
373
help='display timezone as local, original, or utc')
574
374
_global_option('unbound')
375
_global_option('verbose',
376
help='display more information',
575
378
_global_option('version')
576
379
_global_option('email')
577
380
_global_option('update')
578
_global_registry_option('log-format', "Use specified log format.",
579
lazy_registry=('bzrlib.log', 'log_formatter_registry'),
580
value_switches=True, title='Log format',
581
short_value_switches={'short': 'S'})
381
_global_registry_option('log-format', "Use this log format",
382
log.log_formatter_registry, value_switches=True,
582
384
_global_option('long', help='Use detailed log format. Same as --log-format long',
584
386
_global_option('short', help='Use moderately short log format. Same as --log-format short')
585
387
_global_option('line', help='Use log format with one line per revision. Same as --log-format line')
586
388
_global_option('root', type=str)
587
389
_global_option('no-backup')
588
_global_registry_option('merge-type', 'Select a particular merge algorithm.',
390
_global_registry_option('merge-type', 'Select a particular merge algorithm',
589
391
_merge_type_registry, value_switches=True,
590
392
title='Merge algorithm')
591
393
_global_option('pattern', type=str)
394
_global_option('quiet', short_name='q')
592
395
_global_option('remember', help='Remember the specified location as a'
594
_global_option('reprocess', help='Reprocess to reduce spurious conflicts.')
397
_global_option('reprocess', help='Reprocess to reduce spurious conflicts')
595
398
_global_option('kind', type=str)
596
399
_global_option('dry-run',
597
help="Show what would be done, but don't actually do anything.")
400
help="show what would be done, but don't actually do anything")
598
401
_global_option('name-from-revision', help='The path name in the old tree.')
599
_global_option('directory', short_name='d', type=unicode,
600
help='Branch to operate on, instead of working directory')
602
diff_writer_registry = _mod_registry.Registry()
603
diff_writer_registry.register('plain', lambda x: x, 'Plaintext diff output.')
604
diff_writer_registry.default_key = 'plain'
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.',