/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/option.py

  • Committer: Jelmer Vernooij
  • Date: 2017-07-21 13:20:17 UTC
  • mfrom: (6733.1.1 move-errors-config)
  • Revision ID: jelmer@jelmer.uk-20170721132017-oratmmxasovq4r1q
Merge lp:~jelmer/brz/move-errors-config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005-2010 Canonical Ltd
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
# TODO: For things like --diff-prefix, we want a way to customize the display
 
18
# of the option argument.
 
19
 
 
20
from __future__ import absolute_import
 
21
 
 
22
import optparse
 
23
import re
 
24
 
 
25
from .lazy_import import lazy_import
 
26
lazy_import(globals(), """
 
27
from breezy import (
 
28
    revisionspec,
 
29
    i18n,
 
30
    )
 
31
""")
 
32
 
 
33
from . import (
 
34
    errors,
 
35
    registry as _mod_registry,
 
36
    )
 
37
from .sixish import (
 
38
    text_type,
 
39
    )
 
40
 
 
41
 
 
42
class BadOptionValue(errors.BzrError):
 
43
 
 
44
    _fmt = """Bad value "%(value)s" for option "%(name)s"."""
 
45
 
 
46
    def __init__(self, name, value):
 
47
        errors.BzrError.__init__(self, name=name, value=value)
 
48
 
 
49
 
 
50
def _parse_revision_str(revstr):
 
51
    """This handles a revision string -> revno.
 
52
 
 
53
    This always returns a list.  The list will have one element for
 
54
    each revision specifier supplied.
 
55
 
 
56
    >>> _parse_revision_str('234')
 
57
    [<RevisionSpec_dwim 234>]
 
58
    >>> _parse_revision_str('234..567')
 
59
    [<RevisionSpec_dwim 234>, <RevisionSpec_dwim 567>]
 
60
    >>> _parse_revision_str('..')
 
61
    [<RevisionSpec None>, <RevisionSpec None>]
 
62
    >>> _parse_revision_str('..234')
 
63
    [<RevisionSpec None>, <RevisionSpec_dwim 234>]
 
64
    >>> _parse_revision_str('234..')
 
65
    [<RevisionSpec_dwim 234>, <RevisionSpec None>]
 
66
    >>> _parse_revision_str('234..456..789') # Maybe this should be an error
 
67
    [<RevisionSpec_dwim 234>, <RevisionSpec_dwim 456>, <RevisionSpec_dwim 789>]
 
68
    >>> _parse_revision_str('234....789') #Error ?
 
69
    [<RevisionSpec_dwim 234>, <RevisionSpec None>, <RevisionSpec_dwim 789>]
 
70
    >>> _parse_revision_str('revid:test@other.com-234234')
 
71
    [<RevisionSpec_revid revid:test@other.com-234234>]
 
72
    >>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
 
73
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
 
74
    >>> _parse_revision_str('revid:test@other.com-234234..23')
 
75
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_dwim 23>]
 
76
    >>> _parse_revision_str('date:2005-04-12')
 
77
    [<RevisionSpec_date date:2005-04-12>]
 
78
    >>> _parse_revision_str('date:2005-04-12 12:24:33')
 
79
    [<RevisionSpec_date date:2005-04-12 12:24:33>]
 
80
    >>> _parse_revision_str('date:2005-04-12T12:24:33')
 
81
    [<RevisionSpec_date date:2005-04-12T12:24:33>]
 
82
    >>> _parse_revision_str('date:2005-04-12,12:24:33')
 
83
    [<RevisionSpec_date date:2005-04-12,12:24:33>]
 
84
    >>> _parse_revision_str('-5..23')
 
85
    [<RevisionSpec_dwim -5>, <RevisionSpec_dwim 23>]
 
86
    >>> _parse_revision_str('-5')
 
87
    [<RevisionSpec_dwim -5>]
 
88
    >>> _parse_revision_str('123a')
 
89
    [<RevisionSpec_dwim 123a>]
 
90
    >>> _parse_revision_str('abc')
 
91
    [<RevisionSpec_dwim abc>]
 
92
    >>> _parse_revision_str('branch:../branch2')
 
93
    [<RevisionSpec_branch branch:../branch2>]
 
94
    >>> _parse_revision_str('branch:../../branch2')
 
95
    [<RevisionSpec_branch branch:../../branch2>]
 
96
    >>> _parse_revision_str('branch:../../branch2..23')
 
97
    [<RevisionSpec_branch branch:../../branch2>, <RevisionSpec_dwim 23>]
 
98
    >>> _parse_revision_str('branch:..\\\\branch2')
 
99
    [<RevisionSpec_branch branch:..\\branch2>]
 
100
    >>> _parse_revision_str('branch:..\\\\..\\\\branch2..23')
 
101
    [<RevisionSpec_branch branch:..\\..\\branch2>, <RevisionSpec_dwim 23>]
 
102
    """
 
103
    # TODO: Maybe move this into revisionspec.py
 
104
    revs = []
 
105
    # split on .. that is not followed by a / or \
 
106
    sep = re.compile(r'\.\.(?![\\/])')
 
107
    for x in sep.split(revstr):
 
108
        revs.append(revisionspec.RevisionSpec.from_string(x or None))
 
109
    return revs
 
110
 
 
111
 
 
112
def _parse_change_str(revstr):
 
113
    """Parse the revision string and return a tuple with left-most
 
114
    parent of the revision.
 
115
 
 
116
    >>> _parse_change_str('123')
 
117
    (<RevisionSpec_before before:123>, <RevisionSpec_dwim 123>)
 
118
    >>> _parse_change_str('123..124')
 
119
    Traceback (most recent call last):
 
120
      ...
 
121
    RangeInChangeOption: Option --change does not accept revision ranges
 
122
    """
 
123
    revs = _parse_revision_str(revstr)
 
124
    if len(revs) > 1:
 
125
        raise errors.RangeInChangeOption()
 
126
    return (revisionspec.RevisionSpec.from_string('before:' + revstr),
 
127
            revs[0])
 
128
 
 
129
 
 
130
def _parse_merge_type(typestring):
 
131
    return get_merge_type(typestring)
 
132
 
 
133
def get_merge_type(typestring):
 
134
    """Attempt to find the merge class/factory associated with a string."""
 
135
    from merge import merge_types
 
136
    try:
 
137
        return merge_types[typestring][0]
 
138
    except KeyError:
 
139
        templ = '%s%%7s: %%s' % (' '*12)
 
140
        lines = [templ % (f[0], f[1][1]) for f in merge_types.items()]
 
141
        type_list = '\n'.join(lines)
 
142
        msg = "No known merge type %s. Supported types are:\n%s" %\
 
143
            (typestring, type_list)
 
144
        raise errors.BzrCommandError(msg)
 
145
 
 
146
 
 
147
class Option(object):
 
148
    """Description of a command line option
 
149
 
 
150
    :ivar _short_name: If this option has a single-letter name, this is it.
 
151
    Otherwise None.
 
152
    """
 
153
 
 
154
    # The dictionary of standard options. These are always legal.
 
155
    STD_OPTIONS = {}
 
156
 
 
157
    # The dictionary of commonly used options. these are only legal
 
158
    # if a command explicitly references them by name in the list
 
159
    # of supported options.
 
160
    OPTIONS = {}
 
161
 
 
162
    def __init__(self, name, help='', type=None, argname=None,
 
163
                 short_name=None, param_name=None, custom_callback=None,
 
164
                 hidden=False):
 
165
        """Make a new command option.
 
166
 
 
167
        :param name: regular name of the command, used in the double-dash
 
168
            form and also as the parameter to the command's run()
 
169
            method (unless param_name is specified).
 
170
 
 
171
        :param help: help message displayed in command help
 
172
 
 
173
        :param type: function called to parse the option argument, or
 
174
            None (default) if this option doesn't take an argument.
 
175
 
 
176
        :param argname: name of option argument, if any
 
177
 
 
178
        :param short_name: short option code for use with a single -, e.g.
 
179
            short_name="v" to enable parsing of -v.
 
180
 
 
181
        :param param_name: name of the parameter which will be passed to
 
182
            the command's run() method.
 
183
 
 
184
        :param custom_callback: a callback routine to be called after normal
 
185
            processing. The signature of the callback routine is
 
186
            (option, name, new_value, parser).
 
187
        :param hidden: If True, the option should be hidden in help and
 
188
            documentation.
 
189
        """
 
190
        self.name = name
 
191
        self.help = help
 
192
        self.type = type
 
193
        self._short_name = short_name
 
194
        if type is None:
 
195
            if argname:
 
196
                raise ValueError('argname not valid for booleans')
 
197
        elif argname is None:
 
198
            argname = 'ARG'
 
199
        self.argname = argname
 
200
        if param_name is None:
 
201
            self._param_name = self.name.replace('-', '_')
 
202
        else:
 
203
            self._param_name = param_name
 
204
        self.custom_callback = custom_callback
 
205
        self.hidden = hidden
 
206
 
 
207
    def short_name(self):
 
208
        if self._short_name:
 
209
            return self._short_name
 
210
 
 
211
    def set_short_name(self, short_name):
 
212
        self._short_name = short_name
 
213
 
 
214
    def get_negation_name(self):
 
215
        if self.name.startswith('no-'):
 
216
            return self.name[3:]
 
217
        else:
 
218
            return 'no-' + self.name
 
219
 
 
220
    def add_option(self, parser, short_name):
 
221
        """Add this option to an Optparse parser"""
 
222
        option_strings = ['--%s' % self.name]
 
223
        if short_name is not None:
 
224
            option_strings.append('-%s' % short_name)
 
225
        if self.hidden:
 
226
            help = optparse.SUPPRESS_HELP
 
227
        else:
 
228
            help = self.help
 
229
        optargfn = self.type
 
230
        if optargfn is None:
 
231
            parser.add_option(action='callback',
 
232
                              callback=self._optparse_bool_callback,
 
233
                              callback_args=(True,),
 
234
                              help=help,
 
235
                              *option_strings)
 
236
            negation_strings = ['--%s' % self.get_negation_name()]
 
237
            parser.add_option(action='callback',
 
238
                              callback=self._optparse_bool_callback,
 
239
                              callback_args=(False,),
 
240
                              help=optparse.SUPPRESS_HELP, *negation_strings)
 
241
        else:
 
242
            parser.add_option(action='callback',
 
243
                              callback=self._optparse_callback,
 
244
                              type='string', metavar=self.argname.upper(),
 
245
                              help=help,
 
246
                              default=OptionParser.DEFAULT_VALUE,
 
247
                              *option_strings)
 
248
 
 
249
    def _optparse_bool_callback(self, option, opt_str, value, parser, bool_v):
 
250
        setattr(parser.values, self._param_name, bool_v)
 
251
        if self.custom_callback is not None:
 
252
            self.custom_callback(option, self._param_name, bool_v, parser)
 
253
 
 
254
    def _optparse_callback(self, option, opt, value, parser):
 
255
        v = self.type(value)
 
256
        setattr(parser.values, self._param_name, v)
 
257
        if self.custom_callback is not None:
 
258
            self.custom_callback(option, self.name, v, parser)
 
259
 
 
260
    def iter_switches(self):
 
261
        """Iterate through the list of switches provided by the option
 
262
 
 
263
        :return: an iterator of (name, short_name, argname, help)
 
264
        """
 
265
        argname =  self.argname
 
266
        if argname is not None:
 
267
            argname = argname.upper()
 
268
        yield self.name, self.short_name(), argname, self.help
 
269
 
 
270
    def is_hidden(self, name):
 
271
        return self.hidden
 
272
 
 
273
 
 
274
class ListOption(Option):
 
275
    """Option used to provide a list of values.
 
276
 
 
277
    On the command line, arguments are specified by a repeated use of the
 
278
    option. '-' is a special argument that resets the list. For example,
 
279
      --foo=a --foo=b
 
280
    sets the value of the 'foo' option to ['a', 'b'], and
 
281
      --foo=a --foo=b --foo=- --foo=c
 
282
    sets the value of the 'foo' option to ['c'].
 
283
    """
 
284
 
 
285
    def add_option(self, parser, short_name):
 
286
        """Add this option to an Optparse parser."""
 
287
        option_strings = ['--%s' % self.name]
 
288
        if short_name is not None:
 
289
            option_strings.append('-%s' % short_name)
 
290
        parser.add_option(action='callback',
 
291
                          callback=self._optparse_callback,
 
292
                          type='string', metavar=self.argname.upper(),
 
293
                          help=self.help, dest=self._param_name, default=[],
 
294
                          *option_strings)
 
295
 
 
296
    def _optparse_callback(self, option, opt, value, parser):
 
297
        values = getattr(parser.values, self._param_name)
 
298
        if value == '-':
 
299
            del values[:]
 
300
        else:
 
301
            values.append(self.type(value))
 
302
        if self.custom_callback is not None:
 
303
            self.custom_callback(option, self._param_name, values, parser)
 
304
 
 
305
 
 
306
class RegistryOption(Option):
 
307
    """Option based on a registry
 
308
 
 
309
    The values for the options correspond to entries in the registry.  Input
 
310
    must be a registry key.  After validation, it is converted into an object
 
311
    using Registry.get or a caller-provided converter.
 
312
    """
 
313
 
 
314
    def validate_value(self, value):
 
315
        """Validate a value name"""
 
316
        if value not in self.registry:
 
317
            raise BadOptionValue(self.name, value)
 
318
 
 
319
    def convert(self, value):
 
320
        """Convert a value name into an output type"""
 
321
        self.validate_value(value)
 
322
        if self.converter is None:
 
323
            return self.registry.get(value)
 
324
        else:
 
325
            return self.converter(value)
 
326
 
 
327
    def __init__(self, name, help, registry=None, converter=None,
 
328
        value_switches=False, title=None, enum_switch=True,
 
329
        lazy_registry=None, short_name=None, short_value_switches=None):
 
330
        """
 
331
        Constructor.
 
332
 
 
333
        :param name: The option name.
 
334
        :param help: Help for the option.
 
335
        :param registry: A Registry containing the values
 
336
        :param converter: Callable to invoke with the value name to produce
 
337
            the value.  If not supplied, self.registry.get is used.
 
338
        :param value_switches: If true, each possible value is assigned its
 
339
            own switch.  For example, instead of '--format knit',
 
340
            '--knit' can be used interchangeably.
 
341
        :param enum_switch: If true, a switch is provided with the option name,
 
342
            which takes a value.
 
343
        :param lazy_registry: A tuple of (module name, attribute name) for a
 
344
            registry to be lazily loaded.
 
345
        :param short_name: The short name for the enum switch, if any
 
346
        :param short_value_switches: A dict mapping values to short names
 
347
        """
 
348
        Option.__init__(self, name, help, type=self.convert,
 
349
                        short_name=short_name)
 
350
        self._registry = registry
 
351
        if registry is None:
 
352
            if lazy_registry is None:
 
353
                raise AssertionError(
 
354
                    'One of registry or lazy_registry must be given.')
 
355
            self._lazy_registry = _mod_registry._LazyObjectGetter(
 
356
                *lazy_registry)
 
357
        if registry is not None and lazy_registry is not None:
 
358
            raise AssertionError(
 
359
                'registry and lazy_registry are mutually exclusive')
 
360
        self.name = name
 
361
        self.converter = converter
 
362
        self.value_switches = value_switches
 
363
        self.enum_switch = enum_switch
 
364
        self.short_value_switches = short_value_switches
 
365
        self.title = title
 
366
        if self.title is None:
 
367
            self.title = name
 
368
 
 
369
    @property
 
370
    def registry(self):
 
371
        if self._registry is None:
 
372
            self._registry = self._lazy_registry.get_obj()
 
373
        return self._registry
 
374
 
 
375
    @staticmethod
 
376
    def from_kwargs(name_, help=None, title=None, value_switches=False,
 
377
                    enum_switch=True, **kwargs):
 
378
        """Convenience method to generate string-map registry options
 
379
 
 
380
        name, help, value_switches and enum_switch are passed to the
 
381
        RegistryOption constructor.  Any other keyword arguments are treated
 
382
        as values for the option, and their value is treated as the help.
 
383
        """
 
384
        reg = _mod_registry.Registry()
 
385
        for name, switch_help in sorted(kwargs.items()):
 
386
            name = name.replace('_', '-')
 
387
            reg.register(name, name, help=switch_help)
 
388
            if not value_switches:
 
389
                help = help + '  "' + name + '": ' + switch_help
 
390
                if not help.endswith("."):
 
391
                    help = help + "."
 
392
        return RegistryOption(name_, help, reg, title=title,
 
393
            value_switches=value_switches, enum_switch=enum_switch)
 
394
 
 
395
    def add_option(self, parser, short_name):
 
396
        """Add this option to an Optparse parser"""
 
397
        if self.value_switches:
 
398
            parser = parser.add_option_group(self.title)
 
399
        if self.enum_switch:
 
400
            Option.add_option(self, parser, short_name)
 
401
        if self.value_switches:
 
402
            for key in self.registry.keys():
 
403
                option_strings = ['--%s' % key]
 
404
                if self.is_hidden(key):
 
405
                    help = optparse.SUPPRESS_HELP
 
406
                else:
 
407
                    help = self.registry.get_help(key)
 
408
                if (self.short_value_switches and
 
409
                    key in self.short_value_switches):
 
410
                    option_strings.append('-%s' %
 
411
                                          self.short_value_switches[key])
 
412
                parser.add_option(action='callback',
 
413
                              callback=self._optparse_value_callback(key),
 
414
                                  help=help,
 
415
                                  *option_strings)
 
416
 
 
417
    def _optparse_value_callback(self, cb_value):
 
418
        def cb(option, opt, value, parser):
 
419
            v = self.type(cb_value)
 
420
            setattr(parser.values, self._param_name, v)
 
421
            if self.custom_callback is not None:
 
422
                self.custom_callback(option, self._param_name, v, parser)
 
423
        return cb
 
424
 
 
425
    def iter_switches(self):
 
426
        """Iterate through the list of switches provided by the option
 
427
 
 
428
        :return: an iterator of (name, short_name, argname, help)
 
429
        """
 
430
        for value in Option.iter_switches(self):
 
431
            yield value
 
432
        if self.value_switches:
 
433
            for key in sorted(self.registry.keys()):
 
434
                yield key, None, None, self.registry.get_help(key)
 
435
 
 
436
    def is_hidden(self, name):
 
437
        if name == self.name:
 
438
            return Option.is_hidden(self, name)
 
439
        return getattr(self.registry.get_info(name), 'hidden', False)
 
440
 
 
441
 
 
442
class OptionParser(optparse.OptionParser):
 
443
    """OptionParser that raises exceptions instead of exiting"""
 
444
 
 
445
    DEFAULT_VALUE = object()
 
446
 
 
447
    def __init__(self):
 
448
        optparse.OptionParser.__init__(self)
 
449
        self.formatter = GettextIndentedHelpFormatter()
 
450
 
 
451
    def error(self, message):
 
452
        raise errors.BzrCommandError(message)
 
453
 
 
454
 
 
455
class GettextIndentedHelpFormatter(optparse.IndentedHelpFormatter):
 
456
    """Adds gettext() call to format_option()"""
 
457
    def __init__(self):
 
458
        optparse.IndentedHelpFormatter.__init__(self)
 
459
 
 
460
    def format_option(self, option):
 
461
        """code taken from Python's optparse.py"""
 
462
        if option.help:
 
463
            option.help = i18n.gettext(option.help)
 
464
        return optparse.IndentedHelpFormatter.format_option(self, option)
 
465
 
 
466
 
 
467
def get_optparser(options):
 
468
    """Generate an optparse parser for breezy-style options"""
 
469
 
 
470
    parser = OptionParser()
 
471
    parser.remove_option('--help')
 
472
    for option in options.values():
 
473
        option.add_option(parser, option.short_name())
 
474
    return parser
 
475
 
 
476
 
 
477
def custom_help(name, help):
 
478
    """Clone a common option overriding the help."""
 
479
    import copy
 
480
    o = copy.copy(Option.OPTIONS[name])
 
481
    o.help = help
 
482
    return o
 
483
 
 
484
 
 
485
def _standard_option(name, **kwargs):
 
486
    """Register a standard option."""
 
487
    # All standard options are implicitly 'global' ones
 
488
    Option.STD_OPTIONS[name] = Option(name, **kwargs)
 
489
    Option.OPTIONS[name] = Option.STD_OPTIONS[name]
 
490
 
 
491
def _standard_list_option(name, **kwargs):
 
492
    """Register a standard option."""
 
493
    # All standard options are implicitly 'global' ones
 
494
    Option.STD_OPTIONS[name] = ListOption(name, **kwargs)
 
495
    Option.OPTIONS[name] = Option.STD_OPTIONS[name]
 
496
 
 
497
 
 
498
def _global_option(name, **kwargs):
 
499
    """Register a global option."""
 
500
    Option.OPTIONS[name] = Option(name, **kwargs)
 
501
 
 
502
 
 
503
def _global_registry_option(name, help, registry=None, **kwargs):
 
504
    Option.OPTIONS[name] = RegistryOption(name, help, registry, **kwargs)
 
505
 
 
506
 
 
507
# This is the verbosity level detected during command line parsing.
 
508
# Note that the final value is dependent on the order in which the
 
509
# various flags (verbose, quiet, no-verbose, no-quiet) are given.
 
510
# The final value will be one of the following:
 
511
#
 
512
# * -ve for quiet
 
513
# * 0 for normal
 
514
# * +ve for verbose
 
515
_verbosity_level = 0
 
516
 
 
517
 
 
518
def _verbosity_level_callback(option, opt_str, value, parser):
 
519
    global _verbosity_level
 
520
    if not value:
 
521
        # Either --no-verbose or --no-quiet was specified
 
522
        _verbosity_level = 0
 
523
    elif opt_str == "verbose":
 
524
        if _verbosity_level > 0:
 
525
            _verbosity_level += 1
 
526
        else:
 
527
            _verbosity_level = 1
 
528
    else:
 
529
        if _verbosity_level < 0:
 
530
            _verbosity_level -= 1
 
531
        else:
 
532
            _verbosity_level = -1
 
533
 
 
534
 
 
535
# Declare the standard options
 
536
_standard_option('help', short_name='h',
 
537
                 help='Show help message.')
 
538
_standard_option('quiet', short_name='q',
 
539
                 help="Only display errors and warnings.",
 
540
                 custom_callback=_verbosity_level_callback)
 
541
_standard_option('usage',
 
542
                 help='Show usage message and options.')
 
543
_standard_option('verbose', short_name='v',
 
544
                 help='Display more information.',
 
545
                 custom_callback=_verbosity_level_callback)
 
546
 
 
547
# Declare commonly used options
 
548
_global_option('change',
 
549
               type=_parse_change_str,
 
550
               short_name='c',
 
551
               param_name='revision',
 
552
               help='Select changes introduced by the specified revision. See also "help revisionspec".')
 
553
_global_option('directory', short_name='d', type=text_type,
 
554
               help='Branch to operate on, instead of working directory.')
 
555
_global_option('file', type=text_type, short_name='F')
 
556
_global_registry_option('log-format', "Use specified log format.",
 
557
                        lazy_registry=('breezy.log', 'log_formatter_registry'),
 
558
                        value_switches=True, title='Log format',
 
559
                        short_value_switches={'short': 'S'})
 
560
_global_registry_option('merge-type', 'Select a particular merge algorithm.',
 
561
                        lazy_registry=('breezy.merge', 'merge_type_registry'),
 
562
                        value_switches=True, title='Merge algorithm')
 
563
_global_option('message', type=text_type,
 
564
               short_name='m',
 
565
               help='Message string.')
 
566
_global_option('null', short_name='0',
 
567
                 help='Use an ASCII NUL (\\0) separator rather than '
 
568
                      'a newline.')
 
569
_global_option('overwrite', help='Ignore differences between branches and '
 
570
               'overwrite unconditionally.')
 
571
_global_option('remember', help='Remember the specified location as a'
 
572
               ' default.')
 
573
_global_option('reprocess', help='Reprocess to reduce spurious conflicts.')
 
574
_global_option('revision',
 
575
               type=_parse_revision_str,
 
576
               short_name='r',
 
577
               help='See "help revisionspec" for details.')
 
578
_global_option('show-ids',
 
579
               help='Show internal object ids.')
 
580
_global_option('timezone',
 
581
               type=str,
 
582
               help='Display timezone as local, original, or utc.')
 
583
 
 
584
diff_writer_registry = _mod_registry.Registry()
 
585
diff_writer_registry.register('plain', lambda x: x, 'Plaintext diff output.')
 
586
diff_writer_registry.default_key = 'plain'