~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

- merge various windows and other fixes from Ollie Rutherfurd
  
1179: changed diff help example to -r1..2 from deprecated -r1:2
1178: fixed \r\n -> \n conversion in branch._check_format
1177: disable urlgrabber on win32, since it converts / -> \
1176: changed assert path.startswith('./') -> '.'+os.sep in merge.py
1175: replaced os.spawnvp with subprocess.call in msgeditor.py
1174: os.name == 'windows' -> 'nt', check for %EDITOR% on win32
1173: fixed bzr mv filename newfilename, re-enabled test_mv_modes

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.
 
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
    [234, 456, 789]
88
89
    >>> _parse_revision_str('234....789') # Error?
89
 
    [<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
 
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'
 
112
    ['abc']
116
113
    """
117
114
    import re
118
115
    old_format_re = re.compile('\d*:\d*')
119
116
    m = old_format_re.match(revstr)
120
 
    revs = []
121
117
    if m:
122
118
        warning('Colon separator for revision numbers is deprecated.'
123
119
                ' Use .. instead')
 
120
        revs = []
124
121
        for rev in revstr.split(':'):
125
122
            if rev:
126
 
                revs.append(RevisionSpec(int(rev)))
127
 
            else:
128
 
                revs.append(RevisionSpec(None))
129
 
    else:
130
 
        for x in revstr.split('..'):
131
 
            if not x:
132
 
                revs.append(RevisionSpec(None))
133
 
            else:
134
 
                revs.append(RevisionSpec(x))
 
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)
135
136
    return revs
136
137
 
137
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
 
138
167
def _builtin_commands():
139
168
    import bzrlib.builtins
140
169
    r = {}
327
356
    return parsed
328
357
 
329
358
 
 
359
 
 
360
 
330
361
# list of all available options; the rhs can be either None for an
331
362
# option that takes no argument, or a constructor function that checks
332
363
# the type.
333
364
OPTIONS = {
334
365
    'all':                    None,
335
 
    'basis':                  str,
336
366
    'diff-options':           str,
337
367
    'help':                   None,
338
368
    'file':                   unicode,
354
384
    'long':                   None,
355
385
    'root':                   str,
356
386
    'no-backup':              None,
 
387
    'merge-type':             get_merge_type,
357
388
    'pattern':                str,
358
389
    }
359
390
 
386
417
    >>> parse_args('commit --message=biter'.split())
387
418
    (['commit'], {'message': u'biter'})
388
419
    >>> parse_args('log -r 500'.split())
389
 
    (['log'], {'revision': [<RevisionSpec_int 500>]})
 
420
    (['log'], {'revision': [500]})
390
421
    >>> parse_args('log -r500..600'.split())
391
 
    (['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
 
422
    (['log'], {'revision': [500, 600]})
392
423
    >>> parse_args('log -vr500..600'.split())
393
 
    (['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
394
 
    >>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
395
 
    (['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]})
396
427
    """
397
428
    args = []
398
429
    opts = {}
519
550
def apply_profiled(the_callable, *args, **kwargs):
520
551
    import hotshot
521
552
    import tempfile
522
 
    import hotshot.stats
523
553
    pffileno, pfname = tempfile.mkstemp()
524
554
    try:
525
555
        prof = hotshot.Profile(pfname)
527
557
            ret = prof.runcall(the_callable, *args, **kwargs) or 0
528
558
        finally:
529
559
            prof.close()
 
560
 
 
561
        import hotshot.stats
530
562
        stats = hotshot.stats.load(pfname)
531
 
        stats.strip_dirs()
532
 
        stats.sort_stats('cum')   # 'time'
 
563
        #stats.strip_dirs()
 
564
        stats.sort_stats('time')
533
565
        ## XXX: Might like to write to stderr or the trace file instead but
534
566
        ## print_stats seems hardcoded to stdout
535
567
        stats.print_stats(20)
 
568
 
536
569
        return ret
537
570
    finally:
538
571
        os.close(pffileno)
563
596
    --profile
564
597
        Run under the Python profiler.
565
598
    """
566
 
    # Load all of the transport methods
567
 
    import bzrlib.transport.local, bzrlib.transport.http
568
599
    
569
600
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
570
601
 
618
649
    bzrlib.trace.log_startup(argv)
619
650
    bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
620
651
 
621
 
    return run_bzr_catch_errors(argv[1:])
622
 
 
623
 
 
624
 
def run_bzr_catch_errors(argv):
625
652
    try:
626
653
        try:
627
 
            try:
628
 
                return run_bzr(argv)
629
 
            finally:
630
 
                # do this here inside the exception wrappers to catch EPIPE
631
 
                sys.stdout.flush()
632
 
        #wrap common errors as CommandErrors.
633
 
        except (NotBranchError,), e:
634
 
            raise BzrCommandError(str(e))
 
654
            return run_bzr(argv[1:])
 
655
        finally:
 
656
            # do this here inside the exception wrappers to catch EPIPE
 
657
            sys.stdout.flush()
635
658
    except BzrCommandError, e:
636
659
        # command line syntax error, etc
637
660
        log_error(str(e))
643
666
        bzrlib.trace.log_exception('assertion failed: ' + str(e))
644
667
        return 3
645
668
    except KeyboardInterrupt, e:
646
 
        bzrlib.trace.log_exception('interrupted')
 
669
        bzrlib.trace.note('interrupted')
647
670
        return 2
648
671
    except Exception, e:
649
672
        import errno
656
679
            bzrlib.trace.log_exception()
657
680
            return 2
658
681
 
 
682
 
659
683
if __name__ == '__main__':
660
684
    sys.exit(main(sys.argv))