/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
329 by Martin Pool
- refactor command functions into command classes
1
# Copyright (C) 2004, 2005 by Canonical Ltd
1 by mbp at sourcefrog
import from baz patch-364
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
18
338 by Martin Pool
- cleanup of some imports
19
import sys, os, time, os.path
1 by mbp at sourcefrog
import from baz patch-364
20
from sets import Set
21
22
import bzrlib
23
from bzrlib.trace import mutter, note, log_error
329 by Martin Pool
- refactor command functions into command classes
24
from bzrlib.errors import bailout, BzrError, BzrCheckError, BzrCommandError
1 by mbp at sourcefrog
import from baz patch-364
25
from bzrlib.osutils import quotefn, pumpfile, isdir, isfile
453 by Martin Pool
- Split WorkingTree into its own file
26
from bzrlib.tree import RevisionTree, EmptyTree, Tree
1 by mbp at sourcefrog
import from baz patch-364
27
from bzrlib.revision import Revision
28
from bzrlib import Branch, Inventory, InventoryEntry, ScratchBranch, BZRDIR, \
29
     format_date
30
31
350 by Martin Pool
- refactor command aliases into command classes
32
def _squish_command_name(cmd):
33
    return 'cmd_' + cmd.replace('-', '_')
34
35
36
def _unsquish_command_name(cmd):
37
    assert cmd.startswith("cmd_")
38
    return cmd[4:].replace('_','-')
39
351 by Martin Pool
- Split out help functions into bzrlib.help
40
def get_all_cmds():
350 by Martin Pool
- refactor command aliases into command classes
41
    """Return canonical name and class for all registered commands."""
42
    for k, v in globals().iteritems():
43
        if k.startswith("cmd_"):
44
            yield _unsquish_command_name(k), v
45
351 by Martin Pool
- Split out help functions into bzrlib.help
46
def get_cmd_class(cmd):
350 by Martin Pool
- refactor command aliases into command classes
47
    """Return the canonical name and command class for a command.
48
    """
49
    cmd = str(cmd)                      # not unicode
50
51
    # first look up this command under the specified name
272 by Martin Pool
- Add command aliases
52
    try:
350 by Martin Pool
- refactor command aliases into command classes
53
        return cmd, globals()[_squish_command_name(cmd)]
272 by Martin Pool
- Add command aliases
54
    except KeyError:
350 by Martin Pool
- refactor command aliases into command classes
55
        pass
56
57
    # look for any command which claims this as an alias
351 by Martin Pool
- Split out help functions into bzrlib.help
58
    for cmdname, cmdclass in get_all_cmds():
350 by Martin Pool
- refactor command aliases into command classes
59
        if cmd in cmdclass.aliases:
60
            return cmdname, cmdclass
422 by Martin Pool
- External-command patch from mpe
61
62
    cmdclass = ExternalCommand.find_command(cmd)
63
    if cmdclass:
64
        return cmd, cmdclass
65
66
    raise BzrCommandError("unknown command %r" % cmd)
272 by Martin Pool
- Add command aliases
67
329 by Martin Pool
- refactor command functions into command classes
68
69
class Command:
70
    """Base class for commands.
71
72
    The docstring for an actual command should give a single-line
73
    summary, then a complete description of the command.  A grammar
74
    description will be inserted.
75
76
    takes_args
77
        List of argument forms, marked with whether they are optional,
78
        repeated, etc.
79
80
    takes_options
81
        List of options that may be given for this command.
82
83
    hidden
84
        If true, this command isn't advertised.
85
    """
86
    aliases = []
87
    
88
    takes_args = []
89
    takes_options = []
90
91
    hidden = False
92
    
93
    def __init__(self, options, arguments):
94
        """Construct and run the command.
95
96
        Sets self.status to the return value of run()."""
97
        assert isinstance(options, dict)
98
        assert isinstance(arguments, dict)
99
        cmdargs = options.copy()
100
        cmdargs.update(arguments)
101
        assert self.__doc__ != Command.__doc__, \
102
               ("No help message set for %r" % self)
103
        self.status = self.run(**cmdargs)
104
105
    
106
    def run(self):
107
        """Override this in sub-classes.
108
109
        This is invoked with the options and arguments bound to
110
        keyword parameters.
111
337 by Martin Pool
- Clarify return codes from command objects
112
        Return 0 or None if the command was successful, or a shell
113
        error code if not.
329 by Martin Pool
- refactor command functions into command classes
114
        """
337 by Martin Pool
- Clarify return codes from command objects
115
        return 0
329 by Martin Pool
- refactor command functions into command classes
116
117
422 by Martin Pool
- External-command patch from mpe
118
class ExternalCommand(Command):
119
    """Class to wrap external commands.
120
121
    We cheat a little here, when get_cmd_class() calls us we actually give it back
122
    an object we construct that has the appropriate path, help, options etc for the
123
    specified command.
124
125
    When run_bzr() tries to instantiate that 'class' it gets caught by the __call__
126
    method, which we override to call the Command.__init__ method. That then calls
127
    our run method which is pretty straight forward.
128
129
    The only wrinkle is that we have to map bzr's dictionary of options and arguments
130
    back into command line options and arguments for the script.
131
    """
132
133
    def find_command(cls, cmd):
134
        bzrpath = os.environ.get('BZRPATH', '')
135
136
        for dir in bzrpath.split(':'):
137
            path = os.path.join(dir, cmd)
138
            if os.path.isfile(path):
139
                return ExternalCommand(path)
140
141
        return None
142
143
    find_command = classmethod(find_command)
144
145
    def __init__(self, path):
146
        self.path = path
147
424 by Martin Pool
todo
148
        # TODO: If either of these fail, we should detect that and
149
        # assume that path is not really a bzr plugin after all.
150
422 by Martin Pool
- External-command patch from mpe
151
        pipe = os.popen('%s --bzr-usage' % path, 'r')
152
        self.takes_options = pipe.readline().split()
153
        self.takes_args = pipe.readline().split()
154
        pipe.close()
155
156
        pipe = os.popen('%s --bzr-help' % path, 'r')
157
        self.__doc__ = pipe.read()
158
        pipe.close()
159
160
    def __call__(self, options, arguments):
161
        Command.__init__(self, options, arguments)
162
        return self
163
164
    def run(self, **kargs):
165
        opts = []
166
        args = []
167
168
        keys = kargs.keys()
169
        keys.sort()
170
        for name in keys:
171
            value = kargs[name]
172
            if OPTIONS.has_key(name):
173
                # it's an option
174
                opts.append('--%s' % name)
175
                if value is not None and value is not True:
176
                    opts.append(str(value))
177
            else:
178
                # it's an arg, or arg list
179
                if type(value) is not list:
180
                    value = [value]
181
                for v in value:
182
                    if v is not None:
183
                        args.append(str(v))
184
185
        self.status = os.spawnv(os.P_WAIT, self.path, [self.path] + opts + args)
186
        return self.status
187
329 by Martin Pool
- refactor command functions into command classes
188
189
class cmd_status(Command):
1 by mbp at sourcefrog
import from baz patch-364
190
    """Display status summary.
191
466 by Martin Pool
- doc for status command
192
    This reports on versioned and unknown files, reporting them
193
    grouped by state.  Possible states are:
194
195
    added
196
        Versioned in the working copy but not in the previous revision.
197
198
    removed
199
        Versioned in the previous revision but not versioned or deleted
200
        in the working copy.
201
202
    renamed
203
        Path of this file changed from the previous revision;
204
        the text may also have changed.  This includes files whose
205
        parent directory was
206
207
    modified
208
        Text has changed since the previous revision.
209
210
    unchanged
211
        Nothing about this file has changed since the
212
        previous revision.  Only shown with --all.
213
214
    unknown
215
        Not versioned and not matching an ignore pattern.
216
217
    To see ignored files use 'bzr ignored'.  For details in the
218
    changes to file texts, use 'bzr diff'.
1 by mbp at sourcefrog
import from baz patch-364
219
    """
404 by Martin Pool
- bzr status now optionally takes filenames to check
220
    takes_args = ['file*']
465 by Martin Pool
- Move show_status() out of Branch into a new function in
221
    takes_options = ['all', 'show-ids']
350 by Martin Pool
- refactor command aliases into command classes
222
    aliases = ['st', 'stat']
329 by Martin Pool
- refactor command functions into command classes
223
    
465 by Martin Pool
- Move show_status() out of Branch into a new function in
224
    def run(self, all=False, show_ids=False, file_list=None):
406 by Martin Pool
- bzr status only needs a read-lock
225
        b = Branch('.', lock_mode='r')
465 by Martin Pool
- Move show_status() out of Branch into a new function in
226
        import status
227
        status.show_status(b, show_unchanged=all, show_ids=show_ids,
228
                           file_list=file_list)
329 by Martin Pool
- refactor command functions into command classes
229
230
231
class cmd_cat_revision(Command):
232
    """Write out metadata for a revision."""
233
234
    hidden = True
235
    takes_args = ['revision_id']
236
    
237
    def run(self, revision_id):
238
        Branch('.').get_revision(revision_id).write_xml(sys.stdout)
239
240
241
class cmd_revno(Command):
242
    """Show current revision number.
243
244
    This is equal to the number of revisions on this branch."""
245
    def run(self):
246
        print Branch('.').revno()
247
248
    
249
class cmd_add(Command):
70 by mbp at sourcefrog
Prepare for smart recursive add.
250
    """Add specified files or directories.
251
252
    In non-recursive mode, all the named items are added, regardless
253
    of whether they were previously ignored.  A warning is given if
254
    any of the named files are already versioned.
255
256
    In recursive mode (the default), files are treated the same way
257
    but the behaviour for directories is different.  Directories that
258
    are already versioned do not give a warning.  All directories,
259
    whether already versioned or not, are searched for files or
260
    subdirectories that are neither versioned or ignored, and these
261
    are added.  This search proceeds recursively into versioned
262
    directories.
263
264
    Therefore simply saying 'bzr add .' will version all files that
265
    are currently unknown.
279 by Martin Pool
todo
266
267
    TODO: Perhaps adding a file whose directly is not versioned should
268
    recursively add that parent, rather than giving an error?
70 by mbp at sourcefrog
Prepare for smart recursive add.
269
    """
329 by Martin Pool
- refactor command functions into command classes
270
    takes_args = ['file+']
271
    takes_options = ['verbose']
272
    
273
    def run(self, file_list, verbose=False):
274
        bzrlib.add.smart_add(file_list, verbose)
275
276
386 by Martin Pool
- Typo (reported by uws)
277
class cmd_relpath(Command):
329 by Martin Pool
- refactor command functions into command classes
278
    """Show path of a file relative to root"""
392 by Martin Pool
- fix relpath and add tests
279
    takes_args = ['filename']
329 by Martin Pool
- refactor command functions into command classes
280
    
392 by Martin Pool
- fix relpath and add tests
281
    def run(self, filename):
282
        print Branch(filename).relpath(filename)
329 by Martin Pool
- refactor command functions into command classes
283
284
285
286
class cmd_inventory(Command):
287
    """Show inventory of the current working copy or a revision."""
288
    takes_options = ['revision']
289
    
290
    def run(self, revision=None):
291
        b = Branch('.')
292
        if revision == None:
293
            inv = b.read_working_inventory()
294
        else:
295
            inv = b.get_revision_inventory(b.lookup_revision(revision))
296
297
        for path, entry in inv.iter_entries():
298
            print '%-50s %s' % (entry.file_id, path)
299
300
301
class cmd_move(Command):
302
    """Move files to a different directory.
303
304
    examples:
305
        bzr move *.txt doc
306
307
    The destination must be a versioned directory in the same branch.
308
    """
309
    takes_args = ['source$', 'dest']
310
    def run(self, source_list, dest):
311
        b = Branch('.')
312
313
        b.move([b.relpath(s) for s in source_list], b.relpath(dest))
314
315
316
class cmd_rename(Command):
168 by mbp at sourcefrog
new "rename" command
317
    """Change the name of an entry.
318
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
319
    examples:
320
      bzr rename frob.c frobber.c
321
      bzr rename src/frob.c lib/frob.c
322
323
    It is an error if the destination name exists.
324
325
    See also the 'move' command, which moves files into a different
326
    directory without changing their name.
327
328
    TODO: Some way to rename multiple files without invoking bzr for each
329
    one?"""
329 by Martin Pool
- refactor command functions into command classes
330
    takes_args = ['from_name', 'to_name']
168 by mbp at sourcefrog
new "rename" command
331
    
329 by Martin Pool
- refactor command functions into command classes
332
    def run(self, from_name, to_name):
333
        b = Branch('.')
334
        b.rename_one(b.relpath(from_name), b.relpath(to_name))
335
336
337
338
class cmd_renames(Command):
164 by mbp at sourcefrog
new 'renames' command
339
    """Show list of renamed files.
340
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
341
    TODO: Option to show renames between two historical versions.
342
343
    TODO: Only show renames under dir, rather than in the whole branch.
344
    """
329 by Martin Pool
- refactor command functions into command classes
345
    takes_args = ['dir?']
346
347
    def run(self, dir='.'):
348
        b = Branch(dir)
349
        old_inv = b.basis_tree().inventory
350
        new_inv = b.read_working_inventory()
351
352
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
353
        renames.sort()
354
        for old_name, new_name in renames:
355
            print "%s => %s" % (old_name, new_name)        
356
357
358
class cmd_info(Command):
359
    """Show statistical information for this branch"""
360
    def run(self):
361
        import info
362
        info.show_info(Branch('.'))        
363
364
365
class cmd_remove(Command):
366
    """Make a file unversioned.
367
368
    This makes bzr stop tracking changes to a versioned file.  It does
369
    not delete the working copy.
370
    """
371
    takes_args = ['file+']
372
    takes_options = ['verbose']
373
    
374
    def run(self, file_list, verbose=False):
375
        b = Branch(file_list[0])
376
        b.remove([b.relpath(f) for f in file_list], verbose=verbose)
377
378
379
class cmd_file_id(Command):
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
380
    """Print file_id of a particular file or directory.
381
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
382
    The file_id is assigned when the file is first added and remains the
383
    same through all revisions where the file exists, even when it is
384
    moved or renamed.
385
    """
329 by Martin Pool
- refactor command functions into command classes
386
    hidden = True
387
    takes_args = ['filename']
388
    def run(self, filename):
389
        b = Branch(filename)
390
        i = b.inventory.path2id(b.relpath(filename))
391
        if i == None:
392
            bailout("%r is not a versioned file" % filename)
393
        else:
394
            print i
395
396
397
class cmd_file_path(Command):
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
398
    """Print path of file_ids to a file or directory.
399
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
400
    This prints one line for each directory down to the target,
401
    starting at the branch root."""
329 by Martin Pool
- refactor command functions into command classes
402
    hidden = True
403
    takes_args = ['filename']
404
    def run(self, filename):
405
        b = Branch(filename)
406
        inv = b.inventory
407
        fid = inv.path2id(b.relpath(filename))
408
        if fid == None:
409
            bailout("%r is not a versioned file" % filename)
410
        for fip in inv.get_idpath(fid):
411
            print fip
412
413
414
class cmd_revision_history(Command):
415
    """Display list of revision ids on this branch."""
416
    def run(self):
417
        for patchid in Branch('.').revision_history():
418
            print patchid
419
420
421
class cmd_directories(Command):
422
    """Display list of versioned directories in this branch."""
423
    def run(self):
424
        for name, ie in Branch('.').read_working_inventory().directories():
425
            if name == '':
426
                print '.'
427
            else:
428
                print name
429
430
431
class cmd_init(Command):
432
    """Make a directory into a versioned branch.
433
434
    Use this to create an empty branch, or before importing an
435
    existing project.
436
437
    Recipe for importing a tree of files:
438
        cd ~/project
439
        bzr init
440
        bzr add -v .
441
        bzr status
442
        bzr commit -m 'imported project'
443
    """
444
    def run(self):
445
        Branch('.', init=True)
446
447
448
class cmd_diff(Command):
449
    """Show differences in working tree.
450
    
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
451
    If files are listed, only the changes in those files are listed.
452
    Otherwise, all changes for the tree are listed.
453
454
    TODO: Given two revision arguments, show the difference between them.
455
456
    TODO: Allow diff across branches.
457
458
    TODO: Option to use external diff command; could be GNU diff, wdiff,
459
          or a graphical diff.
460
276 by Martin Pool
Doc
461
    TODO: Python difflib is not exactly the same as unidiff; should
462
          either fix it up or prefer to use an external diff.
463
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
464
    TODO: If a directory is given, diff everything under that.
465
276 by Martin Pool
Doc
466
    TODO: Selected-file diff is inefficient and doesn't show you
467
          deleted files.
278 by Martin Pool
- Better workaround for trailing newlines in diffs
468
469
    TODO: This probably handles non-Unix newlines poorly.
329 by Martin Pool
- refactor command functions into command classes
470
    """
471
    
472
    takes_args = ['file*']
473
    takes_options = ['revision']
350 by Martin Pool
- refactor command aliases into command classes
474
    aliases = ['di']
329 by Martin Pool
- refactor command functions into command classes
475
476
    def run(self, revision=None, file_list=None):
477
        from bzrlib.diff import show_diff
478
    
479
        show_diff(Branch('.'), revision, file_list)
480
481
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
482
        
483
484
329 by Martin Pool
- refactor command functions into command classes
485
class cmd_deleted(Command):
135 by mbp at sourcefrog
Simple new 'deleted' command
486
    """List files deleted in the working tree.
487
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
488
    TODO: Show files deleted since a previous revision, or between two revisions.
135 by mbp at sourcefrog
Simple new 'deleted' command
489
    """
329 by Martin Pool
- refactor command functions into command classes
490
    def run(self, show_ids=False):
491
        b = Branch('.')
492
        old = b.basis_tree()
493
        new = b.working_tree()
494
495
        ## TODO: Much more efficient way to do this: read in new
496
        ## directories with readdir, rather than stating each one.  Same
497
        ## level of effort but possibly much less IO.  (Or possibly not,
498
        ## if the directories are very large...)
499
500
        for path, ie in old.inventory.iter_entries():
501
            if not new.has_id(ie.file_id):
502
                if show_ids:
503
                    print '%-50s %s' % (path, ie.file_id)
504
                else:
505
                    print path
506
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
507
508
class cmd_modified(Command):
509
    """List files modified in working tree."""
510
    hidden = True
511
    def run(self):
512
        import statcache
513
        b = Branch('.')
438 by Martin Pool
- Avoid calling Inventory.iter_entries() when finding modified
514
        inv = b.read_working_inventory()
515
        sc = statcache.update_cache(b, inv)
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
516
        basis = b.basis_tree()
517
        basis_inv = basis.inventory
438 by Martin Pool
- Avoid calling Inventory.iter_entries() when finding modified
518
        
519
        # We used to do this through iter_entries(), but that's slow
520
        # when most of the files are unmodified, as is usually the
521
        # case.  So instead we iterate by inventory entry, and only
522
        # calculate paths as necessary.
523
524
        for file_id in basis_inv:
525
            cacheentry = sc.get(file_id)
526
            if not cacheentry:                 # deleted
527
                continue
528
            ie = basis_inv[file_id]
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
529
            if cacheentry[statcache.SC_SHA1] != ie.text_sha1:
438 by Martin Pool
- Avoid calling Inventory.iter_entries() when finding modified
530
                path = inv.id2path(file_id)
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
531
                print path
439 by Martin Pool
- new command 'bzr added'
532
533
534
535
class cmd_added(Command):
536
    """List files added in working tree."""
537
    hidden = True
538
    def run(self):
539
        b = Branch('.')
540
        wt = b.working_tree()
541
        basis_inv = b.basis_tree().inventory
542
        inv = wt.inventory
543
        for file_id in inv:
544
            if file_id in basis_inv:
545
                continue
546
            path = inv.id2path(file_id)
547
            if not os.access(b.abspath(path), os.F_OK):
548
                continue
549
            print path
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
550
                
551
        
552
329 by Martin Pool
- refactor command functions into command classes
553
class cmd_root(Command):
554
    """Show the tree root directory.
555
556
    The root is the nearest enclosing directory with a .bzr control
557
    directory."""
558
    takes_args = ['filename?']
559
    def run(self, filename=None):
560
        """Print the branch root."""
416 by Martin Pool
- bzr log and bzr root now accept an http URL
561
        from branch import find_branch
562
        b = find_branch(filename)
563
        print getattr(b, 'base', None) or getattr(b, 'baseurl')
329 by Martin Pool
- refactor command functions into command classes
564
565
566
class cmd_log(Command):
1 by mbp at sourcefrog
import from baz patch-364
567
    """Show log of this branch.
568
367 by Martin Pool
- New --show-ids option for bzr log
569
    TODO: Option to limit range.
570
571
    TODO: Perhaps show most-recent first with an option for last.
1 by mbp at sourcefrog
import from baz patch-364
572
    """
378 by Martin Pool
- New usage bzr log FILENAME
573
    takes_args = ['filename?']
367 by Martin Pool
- New --show-ids option for bzr log
574
    takes_options = ['timezone', 'verbose', 'show-ids']
378 by Martin Pool
- New usage bzr log FILENAME
575
    def run(self, filename=None, timezone='original', verbose=False, show_ids=False):
416 by Martin Pool
- bzr log and bzr root now accept an http URL
576
        from branch import find_branch
577
        b = find_branch((filename or '.'), lock_mode='r')
378 by Martin Pool
- New usage bzr log FILENAME
578
        if filename:
579
            filename = b.relpath(filename)
580
        bzrlib.show_log(b, filename,
371 by Martin Pool
- Fix up bzr log command
581
                        show_timezone=timezone,
582
                        verbose=verbose,
583
                        show_ids=show_ids)
329 by Martin Pool
- refactor command functions into command classes
584
585
375 by Martin Pool
- New command touching-revisions and function to trace
586
587
class cmd_touching_revisions(Command):
588
    """Return revision-ids which affected a particular file."""
589
    hidden = True
590
    takes_args = ["filename"]
591
    def run(self, filename):
592
        b = Branch(filename, lock_mode='r')
593
        inv = b.read_working_inventory()
594
        file_id = inv.path2id(b.relpath(filename))
595
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
596
            print "%6d %s" % (revno, what)
597
598
329 by Martin Pool
- refactor command functions into command classes
599
class cmd_ls(Command):
1 by mbp at sourcefrog
import from baz patch-364
600
    """List files in a tree.
601
254 by Martin Pool
- Doc cleanups from Magnus Therning
602
    TODO: Take a revision or remote path and list that tree instead.
1 by mbp at sourcefrog
import from baz patch-364
603
    """
329 by Martin Pool
- refactor command functions into command classes
604
    hidden = True
605
    def run(self, revision=None, verbose=False):
606
        b = Branch('.')
607
        if revision == None:
608
            tree = b.working_tree()
609
        else:
610
            tree = b.revision_tree(b.lookup_revision(revision))
611
612
        for fp, fc, kind, fid in tree.list_files():
613
            if verbose:
614
                if kind == 'directory':
615
                    kindch = '/'
616
                elif kind == 'file':
617
                    kindch = ''
618
                else:
619
                    kindch = '???'
620
621
                print '%-8s %s%s' % (fc, fp, kindch)
1 by mbp at sourcefrog
import from baz patch-364
622
            else:
329 by Martin Pool
- refactor command functions into command classes
623
                print fp
624
625
626
627
class cmd_unknowns(Command):
1 by mbp at sourcefrog
import from baz patch-364
628
    """List unknown files"""
329 by Martin Pool
- refactor command functions into command classes
629
    def run(self):
630
        for f in Branch('.').unknowns():
631
            print quotefn(f)
632
633
634
635
class cmd_ignore(Command):
420 by Martin Pool
Doc
636
    """Ignore a command or pattern
637
638
    To remove patterns from the ignore list, edit the .bzrignore file.
639
640
    If the pattern contains a slash, it is compared to the whole path
641
    from the branch root.  Otherwise, it is comapred to only the last
642
    component of the path.
643
644
    Ignore patterns are case-insensitive on case-insensitive systems.
645
646
    Note: wildcards must be quoted from the shell on Unix.
647
648
    examples:
649
        bzr ignore ./Makefile
650
        bzr ignore '*.class'
651
    """
329 by Martin Pool
- refactor command functions into command classes
652
    takes_args = ['name_pattern']
310 by Martin Pool
- new 'bzr ignored' command!
653
    
329 by Martin Pool
- refactor command functions into command classes
654
    def run(self, name_pattern):
409 by Martin Pool
- New AtomicFile class
655
        from bzrlib.atomicfile import AtomicFile
656
        import codecs
657
329 by Martin Pool
- refactor command functions into command classes
658
        b = Branch('.')
410 by Martin Pool
- Fix ignore command and add tests
659
        ifn = b.abspath('.bzrignore')
329 by Martin Pool
- refactor command functions into command classes
660
409 by Martin Pool
- New AtomicFile class
661
        # FIXME: probably doesn't handle non-ascii patterns
662
410 by Martin Pool
- Fix ignore command and add tests
663
        if os.path.exists(ifn):
664
            f = b.controlfile(ifn, 'rt')
409 by Martin Pool
- New AtomicFile class
665
            igns = f.read()
666
            f.close()
667
        else:
668
            igns = ''
669
670
        if igns and igns[-1] != '\n':
671
            igns += '\n'
672
        igns += name_pattern + '\n'
673
410 by Martin Pool
- Fix ignore command and add tests
674
        f = AtomicFile(ifn, 'wt')
409 by Martin Pool
- New AtomicFile class
675
        f.write(igns)
676
        f.commit()
329 by Martin Pool
- refactor command functions into command classes
677
678
        inv = b.working_tree().inventory
679
        if inv.path2id('.bzrignore'):
680
            mutter('.bzrignore is already versioned')
681
        else:
682
            mutter('need to make new .bzrignore file versioned')
683
            b.add(['.bzrignore'])
684
685
686
687
class cmd_ignored(Command):
421 by Martin Pool
doc
688
    """List ignored files and the patterns that matched them.
689
690
    See also: bzr ignore"""
329 by Martin Pool
- refactor command functions into command classes
691
    def run(self):
692
        tree = Branch('.').working_tree()
693
        for path, file_class, kind, file_id in tree.list_files():
694
            if file_class != 'I':
695
                continue
696
            ## XXX: Slightly inefficient since this was already calculated
697
            pat = tree.is_ignored(path)
698
            print '%-50s %s' % (path, pat)
699
700
701
class cmd_lookup_revision(Command):
702
    """Lookup the revision-id from a revision-number
703
704
    example:
705
        bzr lookup-revision 33
421 by Martin Pool
doc
706
    """
329 by Martin Pool
- refactor command functions into command classes
707
    hidden = True
338 by Martin Pool
- cleanup of some imports
708
    takes_args = ['revno']
709
    
329 by Martin Pool
- refactor command functions into command classes
710
    def run(self, revno):
711
        try:
712
            revno = int(revno)
713
        except ValueError:
338 by Martin Pool
- cleanup of some imports
714
            raise BzrCommandError("not a valid revision-number: %r" % revno)
715
716
        print Branch('.').lookup_revision(revno)
329 by Martin Pool
- refactor command functions into command classes
717
718
719
class cmd_export(Command):
720
    """Export past revision to destination directory.
721
722
    If no revision is specified this exports the last committed revision."""
723
    takes_args = ['dest']
724
    takes_options = ['revision']
394 by Martin Pool
- Fix argument handling in export command
725
    def run(self, dest, revision=None):
329 by Martin Pool
- refactor command functions into command classes
726
        b = Branch('.')
394 by Martin Pool
- Fix argument handling in export command
727
        if revision == None:
728
            rh = b.revision_history()[-1]
329 by Martin Pool
- refactor command functions into command classes
729
        else:
394 by Martin Pool
- Fix argument handling in export command
730
            rh = b.lookup_revision(int(revision))
329 by Martin Pool
- refactor command functions into command classes
731
        t = b.revision_tree(rh)
732
        t.export(dest)
733
734
735
class cmd_cat(Command):
736
    """Write a file's text from a previous revision."""
737
738
    takes_options = ['revision']
739
    takes_args = ['filename']
740
741
    def run(self, filename, revision=None):
742
        if revision == None:
743
            raise BzrCommandError("bzr cat requires a revision number")
744
        b = Branch('.')
745
        b.print_file(b.relpath(filename), int(revision))
746
747
748
class cmd_local_time_offset(Command):
749
    """Show the offset in seconds from GMT to local time."""
750
    hidden = True    
751
    def run(self):
752
        print bzrlib.osutils.local_time_offset()
753
754
755
756
class cmd_commit(Command):
757
    """Commit changes into a new revision.
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
758
759
    TODO: Commit only selected files.
760
761
    TODO: Run hooks on tree to-be-committed, and after commit.
762
763
    TODO: Strict commit that fails if there are unknown or deleted files.
764
    """
389 by Martin Pool
- new commit --file option!
765
    takes_options = ['message', 'file', 'verbose']
350 by Martin Pool
- refactor command aliases into command classes
766
    aliases = ['ci', 'checkin']
767
389 by Martin Pool
- new commit --file option!
768
    def run(self, message=None, file=None, verbose=False):
769
        ## Warning: shadows builtin file()
770
        if not message and not file:
771
            raise BzrCommandError("please specify a commit message",
772
                                  ["use either --message or --file"])
773
        elif message and file:
774
            raise BzrCommandError("please specify either --message or --file")
775
        
776
        if file:
777
            import codecs
778
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
779
329 by Martin Pool
- refactor command functions into command classes
780
        Branch('.').commit(message, verbose=verbose)
781
782
783
class cmd_check(Command):
784
    """Validate consistency of branch history.
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
785
786
    This command checks various invariants about the branch storage to
787
    detect data corruption or bzr bugs.
788
    """
329 by Martin Pool
- refactor command functions into command classes
789
    takes_args = ['dir?']
790
    def run(self, dir='.'):
791
        import bzrlib.check
792
        bzrlib.check.check(Branch(dir, find_root=False))
793
794
795
796
class cmd_whoami(Command):
797
    """Show bzr user id."""
798
    takes_options = ['email']
286 by Martin Pool
- New bzr whoami --email option
799
    
329 by Martin Pool
- refactor command functions into command classes
800
    def run(self, email=False):
801
        if email:
802
            print bzrlib.osutils.user_email()
803
        else:
804
            print bzrlib.osutils.username()
805
806
807
class cmd_selftest(Command):
55 by mbp at sourcefrog
bzr selftest shows some counts of tests
808
    """Run internal test suite"""
329 by Martin Pool
- refactor command functions into command classes
809
    hidden = True
810
    def run(self):
811
        failures, tests = 0, 0
812
813
        import doctest, bzrlib.store, bzrlib.tests
814
        bzrlib.trace.verbose = False
815
816
        for m in bzrlib.store, bzrlib.inventory, bzrlib.branch, bzrlib.osutils, \
817
            bzrlib.tree, bzrlib.tests, bzrlib.commands, bzrlib.add:
818
            mf, mt = doctest.testmod(m)
819
            failures += mf
820
            tests += mt
821
            print '%-40s %3d tests' % (m.__name__, mt),
822
            if mf:
823
                print '%3d FAILED!' % mf
824
            else:
825
                print
826
827
        print '%-40s %3d tests' % ('total', tests),
828
        if failures:
829
            print '%3d FAILED!' % failures
55 by mbp at sourcefrog
bzr selftest shows some counts of tests
830
        else:
831
            print
832
329 by Martin Pool
- refactor command functions into command classes
833
834
835
class cmd_version(Command):
836
    """Show version of bzr"""
837
    def run(self):
838
        show_version()
839
840
def show_version():
841
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
842
    print bzrlib.__copyright__
843
    print "http://bazaar-ng.org/"
844
    print
845
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
846
    print "you may use, modify and redistribute it under the terms of the GNU"
847
    print "General Public License version 2 or later."
848
849
850
class cmd_rocks(Command):
851
    """Statement of optimism."""
852
    hidden = True
853
    def run(self):
854
        print "it sure does!"
855
856
857
class cmd_assert_fail(Command):
858
    """Test reporting of assertion failures"""
859
    hidden = True
860
    def run(self):
861
        assert False, "always fails"
862
863
864
class cmd_help(Command):
865
    """Show help on a command or other topic.
866
867
    For a list of all available commands, say 'bzr help commands'."""
868
    takes_args = ['topic?']
350 by Martin Pool
- refactor command aliases into command classes
869
    aliases = ['?']
329 by Martin Pool
- refactor command functions into command classes
870
    
871
    def run(self, topic=None):
351 by Martin Pool
- Split out help functions into bzrlib.help
872
        import help
873
        help.help(topic)
874
1 by mbp at sourcefrog
import from baz patch-364
875
429 by Martin Pool
- New command update-stat-cache for testing
876
class cmd_update_stat_cache(Command):
877
    """Update stat-cache mapping inodes to SHA-1 hashes.
878
879
    For testing only."""
880
    hidden = True
881
    def run(self):
882
        import statcache
883
        b = Branch('.')
454 by Martin Pool
- fix update-stat-cache command
884
        statcache.update_cache(b.base, b.read_working_inventory())
429 by Martin Pool
- New command update-stat-cache for testing
885
886
460 by Martin Pool
- new testing command compare-trees
887
class cmd_compare_trees(Command):
888
    """Show quick calculation of status."""
889
    hidden = True
890
    def run(self):
891
        import diff
892
        b = Branch('.')
893
        delta = diff.compare_trees(b.basis_tree(), b.working_tree())
894
        delta.show(sys.stdout, False)
895
896
1 by mbp at sourcefrog
import from baz patch-364
897
######################################################################
898
# main routine
899
900
901
# list of all available options; the rhs can be either None for an
902
# option that takes no argument, or a constructor function that checks
903
# the type.
904
OPTIONS = {
905
    'all':                    None,
906
    'help':                   None,
389 by Martin Pool
- new commit --file option!
907
    'file':                   unicode,
1 by mbp at sourcefrog
import from baz patch-364
908
    'message':                unicode,
137 by mbp at sourcefrog
new --profile option
909
    'profile':                None,
1 by mbp at sourcefrog
import from baz patch-364
910
    'revision':               int,
911
    'show-ids':               None,
12 by mbp at sourcefrog
new --timezone option for bzr log
912
    'timezone':               str,
1 by mbp at sourcefrog
import from baz patch-364
913
    'verbose':                None,
914
    'version':                None,
286 by Martin Pool
- New bzr whoami --email option
915
    'email':                  None,
1 by mbp at sourcefrog
import from baz patch-364
916
    }
917
918
SHORT_OPTIONS = {
919
    'm':                      'message',
389 by Martin Pool
- new commit --file option!
920
    'F':                      'file', 
1 by mbp at sourcefrog
import from baz patch-364
921
    'r':                      'revision',
922
    'v':                      'verbose',
923
}
924
925
926
def parse_args(argv):
927
    """Parse command line.
928
    
929
    Arguments and options are parsed at this level before being passed
930
    down to specific command handlers.  This routine knows, from a
931
    lookup table, something about the available options, what optargs
932
    they take, and which commands will accept them.
933
31 by Martin Pool
fix up parse_args doctest
934
    >>> parse_args('--help'.split())
1 by mbp at sourcefrog
import from baz patch-364
935
    ([], {'help': True})
31 by Martin Pool
fix up parse_args doctest
936
    >>> parse_args('--version'.split())
1 by mbp at sourcefrog
import from baz patch-364
937
    ([], {'version': True})
31 by Martin Pool
fix up parse_args doctest
938
    >>> parse_args('status --all'.split())
1 by mbp at sourcefrog
import from baz patch-364
939
    (['status'], {'all': True})
31 by Martin Pool
fix up parse_args doctest
940
    >>> parse_args('commit --message=biter'.split())
17 by mbp at sourcefrog
allow --option=ARG syntax
941
    (['commit'], {'message': u'biter'})
1 by mbp at sourcefrog
import from baz patch-364
942
    """
943
    args = []
944
    opts = {}
945
946
    # TODO: Maybe handle '--' to end options?
947
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
948
    while argv:
949
        a = argv.pop(0)
1 by mbp at sourcefrog
import from baz patch-364
950
        if a[0] == '-':
264 by Martin Pool
parse_args: option names must be ascii
951
            # option names must not be unicode
952
            a = str(a)
17 by mbp at sourcefrog
allow --option=ARG syntax
953
            optarg = None
1 by mbp at sourcefrog
import from baz patch-364
954
            if a[1] == '-':
955
                mutter("  got option %r" % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
956
                if '=' in a:
957
                    optname, optarg = a[2:].split('=', 1)
958
                else:
959
                    optname = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
960
                if optname not in OPTIONS:
961
                    bailout('unknown long option %r' % a)
962
            else:
963
                shortopt = a[1:]
964
                if shortopt not in SHORT_OPTIONS:
965
                    bailout('unknown short option %r' % a)
966
                optname = SHORT_OPTIONS[shortopt]
967
            
968
            if optname in opts:
969
                # XXX: Do we ever want to support this, e.g. for -r?
970
                bailout('repeated option %r' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
971
                
1 by mbp at sourcefrog
import from baz patch-364
972
            optargfn = OPTIONS[optname]
973
            if optargfn:
17 by mbp at sourcefrog
allow --option=ARG syntax
974
                if optarg == None:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
975
                    if not argv:
17 by mbp at sourcefrog
allow --option=ARG syntax
976
                        bailout('option %r needs an argument' % a)
977
                    else:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
978
                        optarg = argv.pop(0)
17 by mbp at sourcefrog
allow --option=ARG syntax
979
                opts[optname] = optargfn(optarg)
1 by mbp at sourcefrog
import from baz patch-364
980
            else:
17 by mbp at sourcefrog
allow --option=ARG syntax
981
                if optarg != None:
982
                    bailout('option %r takes no argument' % optname)
1 by mbp at sourcefrog
import from baz patch-364
983
                opts[optname] = True
984
        else:
985
            args.append(a)
986
987
    return args, opts
988
989
990
991
329 by Martin Pool
- refactor command functions into command classes
992
def _match_argform(cmd, takes_args, args):
1 by mbp at sourcefrog
import from baz patch-364
993
    argdict = {}
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
994
329 by Martin Pool
- refactor command functions into command classes
995
    # step through args and takes_args, allowing appropriate 0-many matches
996
    for ap in takes_args:
1 by mbp at sourcefrog
import from baz patch-364
997
        argname = ap[:-1]
998
        if ap[-1] == '?':
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
999
            if args:
1000
                argdict[argname] = args.pop(0)
196 by mbp at sourcefrog
selected-file diff
1001
        elif ap[-1] == '*': # all remaining arguments
1002
            if args:
1003
                argdict[argname + '_list'] = args[:]
1004
                args = []
1005
            else:
1006
                argdict[argname + '_list'] = None
1 by mbp at sourcefrog
import from baz patch-364
1007
        elif ap[-1] == '+':
1008
            if not args:
329 by Martin Pool
- refactor command functions into command classes
1009
                raise BzrCommandError("command %r needs one or more %s"
1 by mbp at sourcefrog
import from baz patch-364
1010
                        % (cmd, argname.upper()))
1011
            else:
1012
                argdict[argname + '_list'] = args[:]
1013
                args = []
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
1014
        elif ap[-1] == '$': # all but one
1015
            if len(args) < 2:
329 by Martin Pool
- refactor command functions into command classes
1016
                raise BzrCommandError("command %r needs one or more %s"
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
1017
                        % (cmd, argname.upper()))
1018
            argdict[argname + '_list'] = args[:-1]
1019
            args[:-1] = []                
1 by mbp at sourcefrog
import from baz patch-364
1020
        else:
1021
            # just a plain arg
1022
            argname = ap
1023
            if not args:
329 by Martin Pool
- refactor command functions into command classes
1024
                raise BzrCommandError("command %r requires argument %s"
1 by mbp at sourcefrog
import from baz patch-364
1025
                        % (cmd, argname.upper()))
1026
            else:
1027
                argdict[argname] = args.pop(0)
1028
            
1029
    if args:
329 by Martin Pool
- refactor command functions into command classes
1030
        raise BzrCommandError("extra argument to command %s: %s"
1031
                              % (cmd, args[0]))
1 by mbp at sourcefrog
import from baz patch-364
1032
1033
    return argdict
1034
1035
1036
1037
def run_bzr(argv):
1038
    """Execute a command.
1039
1040
    This is similar to main(), but without all the trappings for
245 by mbp at sourcefrog
- control files always in utf-8-unix format
1041
    logging and error handling.  
1 by mbp at sourcefrog
import from baz patch-364
1042
    """
251 by mbp at sourcefrog
- factor out locale.getpreferredencoding()
1043
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
245 by mbp at sourcefrog
- control files always in utf-8-unix format
1044
    
1 by mbp at sourcefrog
import from baz patch-364
1045
    try:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1046
        args, opts = parse_args(argv[1:])
1 by mbp at sourcefrog
import from baz patch-364
1047
        if 'help' in opts:
351 by Martin Pool
- Split out help functions into bzrlib.help
1048
            import help
159 by mbp at sourcefrog
bzr commit --help now works
1049
            if args:
351 by Martin Pool
- Split out help functions into bzrlib.help
1050
                help.help(args[0])
159 by mbp at sourcefrog
bzr commit --help now works
1051
            else:
351 by Martin Pool
- Split out help functions into bzrlib.help
1052
                help.help()
1 by mbp at sourcefrog
import from baz patch-364
1053
            return 0
1054
        elif 'version' in opts:
336 by Martin Pool
- fix up 'bzr --version'
1055
            show_version()
1 by mbp at sourcefrog
import from baz patch-364
1056
            return 0
265 by Martin Pool
parse_args: command names must also be ascii
1057
        cmd = str(args.pop(0))
1 by mbp at sourcefrog
import from baz patch-364
1058
    except IndexError:
448 by Martin Pool
- bzr with no command now shows help, not just an error
1059
        import help
1060
        help.help()
1 by mbp at sourcefrog
import from baz patch-364
1061
        return 1
448 by Martin Pool
- bzr with no command now shows help, not just an error
1062
          
115 by mbp at sourcefrog
todo
1063
351 by Martin Pool
- Split out help functions into bzrlib.help
1064
    canonical_cmd, cmd_class = get_cmd_class(cmd)
1 by mbp at sourcefrog
import from baz patch-364
1065
137 by mbp at sourcefrog
new --profile option
1066
    # global option
1067
    if 'profile' in opts:
1068
        profile = True
1069
        del opts['profile']
1070
    else:
1071
        profile = False
1 by mbp at sourcefrog
import from baz patch-364
1072
1073
    # check options are reasonable
329 by Martin Pool
- refactor command functions into command classes
1074
    allowed = cmd_class.takes_options
1 by mbp at sourcefrog
import from baz patch-364
1075
    for oname in opts:
1076
        if oname not in allowed:
381 by Martin Pool
- Better message when a wrong argument is given
1077
            raise BzrCommandError("option '--%s' is not allowed for command %r"
329 by Martin Pool
- refactor command functions into command classes
1078
                                  % (oname, cmd))
176 by mbp at sourcefrog
New cat command contributed by janmar.
1079
137 by mbp at sourcefrog
new --profile option
1080
    # mix arguments and options into one dictionary
329 by Martin Pool
- refactor command functions into command classes
1081
    cmdargs = _match_argform(cmd, cmd_class.takes_args, args)
1082
    cmdopts = {}
136 by mbp at sourcefrog
new --show-ids option for 'deleted' command
1083
    for k, v in opts.items():
329 by Martin Pool
- refactor command functions into command classes
1084
        cmdopts[k.replace('-', '_')] = v
1 by mbp at sourcefrog
import from baz patch-364
1085
137 by mbp at sourcefrog
new --profile option
1086
    if profile:
338 by Martin Pool
- cleanup of some imports
1087
        import hotshot, tempfile
239 by mbp at sourcefrog
- remove profiler temporary file when done
1088
        pffileno, pfname = tempfile.mkstemp()
1089
        try:
1090
            prof = hotshot.Profile(pfname)
329 by Martin Pool
- refactor command functions into command classes
1091
            ret = prof.runcall(cmd_class, cmdopts, cmdargs) or 0
239 by mbp at sourcefrog
- remove profiler temporary file when done
1092
            prof.close()
1093
1094
            import hotshot.stats
1095
            stats = hotshot.stats.load(pfname)
1096
            #stats.strip_dirs()
1097
            stats.sort_stats('time')
1098
            ## XXX: Might like to write to stderr or the trace file instead but
1099
            ## print_stats seems hardcoded to stdout
1100
            stats.print_stats(20)
1101
            
337 by Martin Pool
- Clarify return codes from command objects
1102
            return ret.status
239 by mbp at sourcefrog
- remove profiler temporary file when done
1103
1104
        finally:
1105
            os.close(pffileno)
1106
            os.remove(pfname)
137 by mbp at sourcefrog
new --profile option
1107
    else:
337 by Martin Pool
- Clarify return codes from command objects
1108
        cmdobj = cmd_class(cmdopts, cmdargs).status 
1 by mbp at sourcefrog
import from baz patch-364
1109
1110
359 by Martin Pool
- pychecker fixups
1111
def _report_exception(summary, quiet=False):
267 by Martin Pool
- better reporting of errors
1112
    import traceback
1113
    log_error('bzr: ' + summary)
359 by Martin Pool
- pychecker fixups
1114
    bzrlib.trace.log_exception()
317 by Martin Pool
- better error message for broken pipe
1115
1116
    if not quiet:
1117
        tb = sys.exc_info()[2]
1118
        exinfo = traceback.extract_tb(tb)
1119
        if exinfo:
1120
            sys.stderr.write('  at %s:%d in %s()\n' % exinfo[-1][:3])
1121
        sys.stderr.write('  see ~/.bzr.log for debug information\n')
267 by Martin Pool
- better reporting of errors
1122
1123
1124
1 by mbp at sourcefrog
import from baz patch-364
1125
def main(argv):
317 by Martin Pool
- better error message for broken pipe
1126
    import errno
1127
    
344 by Martin Pool
- It's not an error to use the library without
1128
    bzrlib.open_tracefile(argv)
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1129
1 by mbp at sourcefrog
import from baz patch-364
1130
    try:
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1131
        try:
337 by Martin Pool
- Clarify return codes from command objects
1132
            try:
1133
                return run_bzr(argv)
1134
            finally:
1135
                # do this here inside the exception wrappers to catch EPIPE
1136
                sys.stdout.flush()
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1137
        except BzrError, e:
329 by Martin Pool
- refactor command functions into command classes
1138
            quiet = isinstance(e, (BzrCommandError))
359 by Martin Pool
- pychecker fixups
1139
            _report_exception('error: ' + e.args[0], quiet=quiet)
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1140
            if len(e.args) > 1:
1141
                for h in e.args[1]:
267 by Martin Pool
- better reporting of errors
1142
                    # some explanation or hints
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1143
                    log_error('  ' + h)
1144
            return 1
267 by Martin Pool
- better reporting of errors
1145
        except AssertionError, e:
1146
            msg = 'assertion failed'
1147
            if str(e):
1148
                msg += ': ' + str(e)
359 by Martin Pool
- pychecker fixups
1149
            _report_exception(msg)
318 by Martin Pool
- better error message for Ctrl-c
1150
            return 2
1151
        except KeyboardInterrupt, e:
359 by Martin Pool
- pychecker fixups
1152
            _report_exception('interrupted', quiet=True)
318 by Martin Pool
- better error message for Ctrl-c
1153
            return 2
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1154
        except Exception, e:
317 by Martin Pool
- better error message for broken pipe
1155
            quiet = False
419 by Martin Pool
- RemoteBranch.__str__ and repr
1156
            if (isinstance(e, IOError) 
1157
                and hasattr(e, 'errno')
1158
                and e.errno == errno.EPIPE):
317 by Martin Pool
- better error message for broken pipe
1159
                quiet = True
1160
                msg = 'broken pipe'
1161
            else:
1162
                msg = str(e).rstrip('\n')
359 by Martin Pool
- pychecker fixups
1163
            _report_exception(msg, quiet)
318 by Martin Pool
- better error message for Ctrl-c
1164
            return 2
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1165
    finally:
1166
        bzrlib.trace.close_trace()
1 by mbp at sourcefrog
import from baz patch-364
1167
1168
1169
if __name__ == '__main__':
1170
    sys.exit(main(sys.argv))