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