~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Martin Pool
  • Date: 2005-09-05 05:35:25 UTC
  • mfrom: (974.1.55)
  • Revision ID: mbp@sourcefrog.net-20050905053525-2112bac069dbe331
- merge various bug fixes from aaron

aaron.bentley@utoronto.ca-20050905020131-a2d5b7711dd6cd98

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
# Those objects can specify the expected type of the argument, which
25
25
# would help with validation and shell completion.
26
26
 
27
 
# TODO: "--profile=cum", to change sort order.  Is there any value in leaving
28
 
# the profile output behind so it can be interactively examined?
 
27
 
29
28
 
30
29
import sys
31
30
import os
35
34
import bzrlib
36
35
import bzrlib.trace
37
36
from bzrlib.trace import mutter, note, log_error, warning
38
 
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
39
 
from bzrlib.revisionspec import RevisionSpec
 
37
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
 
38
from bzrlib.branch import find_branch
40
39
from bzrlib import BZRDIR
41
40
 
42
41
plugin_cmds = {}
70
69
def _parse_revision_str(revstr):
71
70
    """This handles a revision string -> revno.
72
71
 
73
 
    This always returns a list.  The list will have one element for
74
 
    each revision specifier supplied.
 
72
    This always returns a list.  The list will have one element for 
 
73
 
 
74
    It supports integers directly, but everything else it
 
75
    defers for passing to Branch.get_revision_info()
75
76
 
76
77
    >>> _parse_revision_str('234')
77
 
    [<RevisionSpec_int 234>]
 
78
    [234]
78
79
    >>> _parse_revision_str('234..567')
79
 
    [<RevisionSpec_int 234>, <RevisionSpec_int 567>]
 
80
    [234, 567]
80
81
    >>> _parse_revision_str('..')
81
 
    [<RevisionSpec None>, <RevisionSpec None>]
 
82
    [None, None]
82
83
    >>> _parse_revision_str('..234')
83
 
    [<RevisionSpec None>, <RevisionSpec_int 234>]
 
84
    [None, 234]
84
85
    >>> _parse_revision_str('234..')
85
 
    [<RevisionSpec_int 234>, <RevisionSpec None>]
 
86
    [234, None]
86
87
    >>> _parse_revision_str('234..456..789') # Maybe this should be an error
87
 
    [<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
88
 
    >>> _parse_revision_str('234....789') #Error ?
89
 
    [<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
 
88
    [234, 456, 789]
 
89
    >>> _parse_revision_str('234....789') # Error?
 
90
    [234, None, 789]
90
91
    >>> _parse_revision_str('revid:test@other.com-234234')
91
 
    [<RevisionSpec_revid revid:test@other.com-234234>]
 
92
    ['revid:test@other.com-234234']
92
93
    >>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
93
 
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
 
94
    ['revid:test@other.com-234234', 'revid:test@other.com-234235']
94
95
    >>> _parse_revision_str('revid:test@other.com-234234..23')
95
 
    [<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
 
96
    ['revid:test@other.com-234234', 23]
96
97
    >>> _parse_revision_str('date:2005-04-12')
97
 
    [<RevisionSpec_date date:2005-04-12>]
 
98
    ['date:2005-04-12']
98
99
    >>> _parse_revision_str('date:2005-04-12 12:24:33')
99
 
    [<RevisionSpec_date date:2005-04-12 12:24:33>]
 
100
    ['date:2005-04-12 12:24:33']
100
101
    >>> _parse_revision_str('date:2005-04-12T12:24:33')
101
 
    [<RevisionSpec_date date:2005-04-12T12:24:33>]
 
102
    ['date:2005-04-12T12:24:33']
102
103
    >>> _parse_revision_str('date:2005-04-12,12:24:33')
103
 
    [<RevisionSpec_date date:2005-04-12,12:24:33>]
 
104
    ['date:2005-04-12,12:24:33']
104
105
    >>> _parse_revision_str('-5..23')
105
 
    [<RevisionSpec_int -5>, <RevisionSpec_int 23>]
 
106
    [-5, 23]
106
107
    >>> _parse_revision_str('-5')
107
 
    [<RevisionSpec_int -5>]
 
108
    [-5]
108
109
    >>> _parse_revision_str('123a')
109
 
    Traceback (most recent call last):
110
 
      ...
111
 
    BzrError: No namespace registered for string: '123a'
 
110
    ['123a']
112
111
    >>> _parse_revision_str('abc')
113
 
    Traceback (most recent call last):
114
 
      ...
115
 
    BzrError: No namespace registered for string: 'abc'
116
 
    >>> _parse_revision_str('branch:../branch2')
117
 
    [<RevisionSpec_branch branch:../branch2>]
 
112
    ['abc']
118
113
    """
119
114
    import re
120
115
    old_format_re = re.compile('\d*:\d*')
121
116
    m = old_format_re.match(revstr)
122
 
    revs = []
123
117
    if m:
124
118
        warning('Colon separator for revision numbers is deprecated.'
125
119
                ' Use .. instead')
 
120
        revs = []
126
121
        for rev in revstr.split(':'):
127
122
            if rev:
128
 
                revs.append(RevisionSpec(int(rev)))
129
 
            else:
130
 
                revs.append(RevisionSpec(None))
131
 
    else:
132
 
        next_prefix = None
133
 
        for x in revstr.split('..'):
134
 
            if not x:
135
 
                revs.append(RevisionSpec(None))
136
 
            elif x[-1] == ':':
137
 
                # looks like a namespace:.. has happened
138
 
                next_prefix = x + '..'
139
 
            else:
140
 
                if next_prefix is not None:
141
 
                    x = next_prefix + x
142
 
                revs.append(RevisionSpec(x))
143
 
                next_prefix = None
144
 
        if next_prefix is not None:
145
 
            revs.append(RevisionSpec(next_prefix))
 
123
                revs.append(int(rev))
 
124
            else:
 
125
                revs.append(None)
 
126
        return revs
 
127
    revs = []
 
128
    for x in revstr.split('..'):
 
129
        if not x:
 
130
            revs.append(None)
 
131
        else:
 
132
            try:
 
133
                revs.append(int(x))
 
134
            except ValueError:
 
135
                revs.append(x)
146
136
    return revs
147
137
 
148
138
 
 
139
def get_merge_type(typestring):
 
140
    """Attempt to find the merge class/factory associated with a string."""
 
141
    from merge import merge_types
 
142
    try:
 
143
        return merge_types[typestring][0]
 
144
    except KeyError:
 
145
        templ = '%s%%7s: %%s' % (' '*12)
 
146
        lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
 
147
        type_list = '\n'.join(lines)
 
148
        msg = "No known merge type %s. Supported types are:\n%s" %\
 
149
            (typestring, type_list)
 
150
        raise BzrCommandError(msg)
 
151
    
 
152
 
 
153
def get_merge_type(typestring):
 
154
    """Attempt to find the merge class/factory associated with a string."""
 
155
    from merge import merge_types
 
156
    try:
 
157
        return merge_types[typestring][0]
 
158
    except KeyError:
 
159
        templ = '%s%%7s: %%s' % (' '*12)
 
160
        lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
 
161
        type_list = '\n'.join(lines)
 
162
        msg = "No known merge type %s. Supported types are:\n%s" %\
 
163
            (typestring, type_list)
 
164
        raise BzrCommandError(msg)
 
165
 
 
166
 
149
167
def _builtin_commands():
150
168
    import bzrlib.builtins
151
169
    r = {}
338
356
    return parsed
339
357
 
340
358
 
 
359
 
 
360
 
341
361
# list of all available options; the rhs can be either None for an
342
362
# option that takes no argument, or a constructor function that checks
343
363
# the type.
344
364
OPTIONS = {
345
365
    'all':                    None,
346
 
    'basis':                  str,
347
366
    'diff-options':           str,
348
367
    'help':                   None,
349
368
    'file':                   unicode,
350
369
    'force':                  None,
351
370
    'format':                 unicode,
352
371
    'forward':                None,
353
 
    'quiet':                  None,
354
372
    'message':                unicode,
355
373
    'no-recurse':             None,
356
374
    'profile':                None,
366
384
    'long':                   None,
367
385
    'root':                   str,
368
386
    'no-backup':              None,
 
387
    'merge-type':             get_merge_type,
369
388
    'pattern':                str,
370
 
    'remember':               None,
371
389
    }
372
390
 
373
391
SHORT_OPTIONS = {
377
395
    'r':                      'revision',
378
396
    'v':                      'verbose',
379
397
    'l':                      'long',
380
 
    'q':                      'quiet',
381
398
}
382
399
 
383
400
 
400
417
    >>> parse_args('commit --message=biter'.split())
401
418
    (['commit'], {'message': u'biter'})
402
419
    >>> parse_args('log -r 500'.split())
403
 
    (['log'], {'revision': [<RevisionSpec_int 500>]})
 
420
    (['log'], {'revision': [500]})
404
421
    >>> parse_args('log -r500..600'.split())
405
 
    (['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
 
422
    (['log'], {'revision': [500, 600]})
406
423
    >>> parse_args('log -vr500..600'.split())
407
 
    (['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
408
 
    >>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
409
 
    (['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
 
424
    (['log'], {'verbose': True, 'revision': [500, 600]})
 
425
    >>> parse_args('log -rv500..600'.split()) #the r takes an argument
 
426
    (['log'], {'revision': ['v500', 600]})
410
427
    """
411
428
    args = []
412
429
    opts = {}
533
550
def apply_profiled(the_callable, *args, **kwargs):
534
551
    import hotshot
535
552
    import tempfile
536
 
    import hotshot.stats
537
553
    pffileno, pfname = tempfile.mkstemp()
538
554
    try:
539
555
        prof = hotshot.Profile(pfname)
541
557
            ret = prof.runcall(the_callable, *args, **kwargs) or 0
542
558
        finally:
543
559
            prof.close()
 
560
 
 
561
        import hotshot.stats
544
562
        stats = hotshot.stats.load(pfname)
545
 
        stats.strip_dirs()
546
 
        stats.sort_stats('cum')   # 'time'
 
563
        #stats.strip_dirs()
 
564
        stats.sort_stats('time')
547
565
        ## XXX: Might like to write to stderr or the trace file instead but
548
566
        ## print_stats seems hardcoded to stdout
549
567
        stats.print_stats(20)
 
568
 
550
569
        return ret
551
570
    finally:
552
571
        os.close(pffileno)
577
596
    --profile
578
597
        Run under the Python profiler.
579
598
    """
580
 
    # Load all of the transport methods
581
 
    import bzrlib.transport.local, bzrlib.transport.http
582
599
    
583
600
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
584
601
 
632
649
    bzrlib.trace.log_startup(argv)
633
650
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
634
651
 
635
 
    return run_bzr_catch_errors(argv[1:])
636
 
 
637
 
 
638
 
def run_bzr_catch_errors(argv):
639
652
    try:
640
653
        try:
641
 
            return run_bzr(argv)
 
654
            return run_bzr(argv[1:])
642
655
        finally:
643
656
            # do this here inside the exception wrappers to catch EPIPE
644
657
            sys.stdout.flush()
653
666
        bzrlib.trace.log_exception('assertion failed: ' + str(e))
654
667
        return 3
655
668
    except KeyboardInterrupt, e:
656
 
        bzrlib.trace.log_exception('interrupted')
 
669
        bzrlib.trace.note('interrupted')
657
670
        return 2
658
671
    except Exception, e:
659
672
        import errno
663
676
            bzrlib.trace.note('broken pipe')
664
677
            return 2
665
678
        else:
666
 
            ## import pdb
667
 
            ## pdb.pm()
668
679
            bzrlib.trace.log_exception()
669
680
            return 2
670
681
 
 
682
 
671
683
if __name__ == '__main__':
672
684
    sys.exit(main(sys.argv))