~bzr-pqm/bzr/bzr.dev

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
572 by Martin Pool
- trim imports
19
import sys, os
1 by mbp at sourcefrog
import from baz patch-364
20
21
import bzrlib
22
from bzrlib.trace import mutter, note, log_error
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
23
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
592 by Martin Pool
- trim imports more
24
from bzrlib.osutils import quotefn
25
from bzrlib import Branch, Inventory, InventoryEntry, BZRDIR, \
1 by mbp at sourcefrog
import from baz patch-364
26
     format_date
27
28
350 by Martin Pool
- refactor command aliases into command classes
29
def _squish_command_name(cmd):
30
    return 'cmd_' + cmd.replace('-', '_')
31
32
33
def _unsquish_command_name(cmd):
34
    assert cmd.startswith("cmd_")
35
    return cmd[4:].replace('_','-')
36
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
37
def _parse_revision_str(revstr):
38
    """This handles a revision string -> revno. 
39
40
    There are several possibilities:
41
42
        '234'       -> 234
43
        '234:345'   -> [234, 345]
44
        ':234'      -> [None, 234]
45
        '234:'      -> [234, None]
46
47
    In the future we will also support:
48
        'uuid:blah-blah-blah'   -> ?
49
        'hash:blahblahblah'     -> ?
50
        potentially:
51
        'tag:mytag'             -> ?
52
    """
53
    if revstr.find(':') != -1:
54
        revs = revstr.split(':')
55
        if len(revs) > 2:
56
            raise ValueError('More than 2 pieces not supported for --revision: %r' % revstr)
57
58
        if not revs[0]:
59
            revs[0] = None
60
        else:
61
            revs[0] = int(revs[0])
62
63
        if not revs[1]:
64
            revs[1] = None
65
        else:
66
            revs[1] = int(revs[1])
67
    else:
68
        revs = int(revstr)
69
    return revs
70
641 by Martin Pool
- improved external-command patch from john
71
def _find_plugins():
72
    """Find all python files which are plugins, and load their commands
73
    to add to the list of "all commands"
74
75
    The environment variable BZRPATH is considered a delimited set of
76
    paths to look through. Each entry is searched for *.py files.
77
    If a directory is found, it is also searched, but they are 
78
    not searched recursively. This allows you to revctl the plugins.
79
    
80
    Inside the plugin should be a series of cmd_* function, which inherit from
81
    the bzrlib.commands.Command class.
82
    """
83
    bzrpath = os.environ.get('BZRPLUGINPATH', '')
84
85
    plugin_cmds = {} 
86
    if not bzrpath:
87
        return plugin_cmds
88
    _platform_extensions = {
89
        'win32':'.pyd',
90
        'cygwin':'.dll',
91
        'darwin':'.dylib',
92
        'linux2':'.so'
93
        }
94
    if _platform_extensions.has_key(sys.platform):
95
        platform_extension = _platform_extensions[sys.platform]
96
    else:
97
        platform_extension = None
98
    for d in bzrpath.split(os.pathsep):
99
        plugin_names = {} # This should really be a set rather than a dict
100
        for f in os.listdir(d):
101
            if f.endswith('.py'):
102
                f = f[:-3]
103
            elif f.endswith('.pyc') or f.endswith('.pyo'):
104
                f = f[:-4]
105
            elif platform_extension and f.endswith(platform_extension):
106
                f = f[:-len(platform_extension)]
107
                if f.endswidth('module'):
108
                    f = f[:-len('module')]
109
            else:
110
                continue
111
            if not plugin_names.has_key(f):
112
                plugin_names[f] = True
113
114
        plugin_names = plugin_names.keys()
115
        plugin_names.sort()
116
        try:
117
            sys.path.insert(0, d)
118
            for name in plugin_names:
119
                try:
120
                    old_module = None
121
                    try:
122
                        if sys.modules.has_key(name):
123
                            old_module = sys.modules[name]
124
                            del sys.modules[name]
125
                        plugin = __import__(name, locals())
126
                        for k in dir(plugin):
127
                            if k.startswith('cmd_'):
128
                                k_unsquished = _unsquish_command_name(k)
129
                                if not plugin_cmds.has_key(k_unsquished):
130
                                    plugin_cmds[k_unsquished] = getattr(plugin, k)
131
                                else:
132
                                    log_error('Two plugins defined the same command: %r' % k)
133
                                    log_error('Not loading the one in %r in dir %r' % (name, d))
134
                    finally:
135
                        if old_module:
136
                            sys.modules[name] = old_module
137
                except ImportError, e:
138
                    log_error('Unable to load plugin: %r from %r\n%s' % (name, d, e))
139
        finally:
140
            sys.path.pop(0)
141
    return plugin_cmds
142
143
def _get_cmd_dict(include_plugins=True):
144
    d = {}
350 by Martin Pool
- refactor command aliases into command classes
145
    for k, v in globals().iteritems():
146
        if k.startswith("cmd_"):
641 by Martin Pool
- improved external-command patch from john
147
            d[_unsquish_command_name(k)] = v
148
    if include_plugins:
149
        d.update(_find_plugins())
150
    return d
151
    
152
def get_all_cmds(include_plugins=True):
153
    """Return canonical name and class for all registered commands."""
154
    for k, v in _get_cmd_dict(include_plugins=include_plugins).iteritems():
155
        yield k,v
156
157
158
def get_cmd_class(cmd,include_plugins=True):
350 by Martin Pool
- refactor command aliases into command classes
159
    """Return the canonical name and command class for a command.
160
    """
161
    cmd = str(cmd)                      # not unicode
162
163
    # first look up this command under the specified name
641 by Martin Pool
- improved external-command patch from john
164
    cmds = _get_cmd_dict(include_plugins=include_plugins)
272 by Martin Pool
- Add command aliases
165
    try:
641 by Martin Pool
- improved external-command patch from john
166
        return cmd, cmds[cmd]
272 by Martin Pool
- Add command aliases
167
    except KeyError:
350 by Martin Pool
- refactor command aliases into command classes
168
        pass
169
170
    # look for any command which claims this as an alias
641 by Martin Pool
- improved external-command patch from john
171
    for cmdname, cmdclass in cmds.iteritems():
350 by Martin Pool
- refactor command aliases into command classes
172
        if cmd in cmdclass.aliases:
173
            return cmdname, cmdclass
422 by Martin Pool
- External-command patch from mpe
174
175
    cmdclass = ExternalCommand.find_command(cmd)
176
    if cmdclass:
177
        return cmd, cmdclass
178
179
    raise BzrCommandError("unknown command %r" % cmd)
272 by Martin Pool
- Add command aliases
180
329 by Martin Pool
- refactor command functions into command classes
181
558 by Martin Pool
- All top-level classes inherit from object
182
class Command(object):
329 by Martin Pool
- refactor command functions into command classes
183
    """Base class for commands.
184
185
    The docstring for an actual command should give a single-line
186
    summary, then a complete description of the command.  A grammar
187
    description will be inserted.
188
189
    takes_args
190
        List of argument forms, marked with whether they are optional,
191
        repeated, etc.
192
193
    takes_options
194
        List of options that may be given for this command.
195
196
    hidden
197
        If true, this command isn't advertised.
198
    """
199
    aliases = []
200
    
201
    takes_args = []
202
    takes_options = []
203
204
    hidden = False
205
    
206
    def __init__(self, options, arguments):
207
        """Construct and run the command.
208
209
        Sets self.status to the return value of run()."""
210
        assert isinstance(options, dict)
211
        assert isinstance(arguments, dict)
212
        cmdargs = options.copy()
213
        cmdargs.update(arguments)
214
        assert self.__doc__ != Command.__doc__, \
215
               ("No help message set for %r" % self)
216
        self.status = self.run(**cmdargs)
217
218
    
219
    def run(self):
220
        """Override this in sub-classes.
221
222
        This is invoked with the options and arguments bound to
223
        keyword parameters.
224
337 by Martin Pool
- Clarify return codes from command objects
225
        Return 0 or None if the command was successful, or a shell
226
        error code if not.
329 by Martin Pool
- refactor command functions into command classes
227
        """
337 by Martin Pool
- Clarify return codes from command objects
228
        return 0
329 by Martin Pool
- refactor command functions into command classes
229
230
422 by Martin Pool
- External-command patch from mpe
231
class ExternalCommand(Command):
232
    """Class to wrap external commands.
233
234
    We cheat a little here, when get_cmd_class() calls us we actually give it back
235
    an object we construct that has the appropriate path, help, options etc for the
236
    specified command.
237
238
    When run_bzr() tries to instantiate that 'class' it gets caught by the __call__
239
    method, which we override to call the Command.__init__ method. That then calls
240
    our run method which is pretty straight forward.
241
242
    The only wrinkle is that we have to map bzr's dictionary of options and arguments
243
    back into command line options and arguments for the script.
244
    """
245
246
    def find_command(cls, cmd):
572 by Martin Pool
- trim imports
247
        import os.path
422 by Martin Pool
- External-command patch from mpe
248
        bzrpath = os.environ.get('BZRPATH', '')
249
641 by Martin Pool
- improved external-command patch from john
250
        for dir in bzrpath.split(os.pathsep):
422 by Martin Pool
- External-command patch from mpe
251
            path = os.path.join(dir, cmd)
252
            if os.path.isfile(path):
253
                return ExternalCommand(path)
254
255
        return None
256
257
    find_command = classmethod(find_command)
258
259
    def __init__(self, path):
260
        self.path = path
261
262
        pipe = os.popen('%s --bzr-usage' % path, 'r')
263
        self.takes_options = pipe.readline().split()
687 by Martin Pool
- trap more errors from external commands
264
265
        for opt in self.takes_options:
266
            if not opt in OPTIONS:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
267
                raise BzrError("Unknown option '%s' returned by external command %s"
268
                               % (opt, path))
687 by Martin Pool
- trap more errors from external commands
269
270
        # TODO: Is there any way to check takes_args is valid here?
422 by Martin Pool
- External-command patch from mpe
271
        self.takes_args = pipe.readline().split()
687 by Martin Pool
- trap more errors from external commands
272
273
        if pipe.close() is not None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
274
            raise BzrError("Failed funning '%s --bzr-usage'" % path)
422 by Martin Pool
- External-command patch from mpe
275
276
        pipe = os.popen('%s --bzr-help' % path, 'r')
277
        self.__doc__ = pipe.read()
687 by Martin Pool
- trap more errors from external commands
278
        if pipe.close() is not None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
279
            raise BzrError("Failed funning '%s --bzr-help'" % path)
422 by Martin Pool
- External-command patch from mpe
280
281
    def __call__(self, options, arguments):
282
        Command.__init__(self, options, arguments)
283
        return self
284
285
    def run(self, **kargs):
286
        opts = []
287
        args = []
288
289
        keys = kargs.keys()
290
        keys.sort()
291
        for name in keys:
689 by Martin Pool
- make options with - work with external commands
292
            optname = name.replace('_','-')
422 by Martin Pool
- External-command patch from mpe
293
            value = kargs[name]
689 by Martin Pool
- make options with - work with external commands
294
            if OPTIONS.has_key(optname):
422 by Martin Pool
- External-command patch from mpe
295
                # it's an option
689 by Martin Pool
- make options with - work with external commands
296
                opts.append('--%s' % optname)
422 by Martin Pool
- External-command patch from mpe
297
                if value is not None and value is not True:
298
                    opts.append(str(value))
299
            else:
300
                # it's an arg, or arg list
301
                if type(value) is not list:
302
                    value = [value]
303
                for v in value:
304
                    if v is not None:
305
                        args.append(str(v))
306
307
        self.status = os.spawnv(os.P_WAIT, self.path, [self.path] + opts + args)
308
        return self.status
309
329 by Martin Pool
- refactor command functions into command classes
310
311
class cmd_status(Command):
1 by mbp at sourcefrog
import from baz patch-364
312
    """Display status summary.
313
466 by Martin Pool
- doc for status command
314
    This reports on versioned and unknown files, reporting them
315
    grouped by state.  Possible states are:
316
317
    added
318
        Versioned in the working copy but not in the previous revision.
319
320
    removed
467 by Martin Pool
- doc for status command
321
        Versioned in the previous revision but removed or deleted
466 by Martin Pool
- doc for status command
322
        in the working copy.
323
324
    renamed
325
        Path of this file changed from the previous revision;
326
        the text may also have changed.  This includes files whose
467 by Martin Pool
- doc for status command
327
        parent directory was renamed.
466 by Martin Pool
- doc for status command
328
329
    modified
330
        Text has changed since the previous revision.
331
332
    unchanged
467 by Martin Pool
- doc for status command
333
        Nothing about this file has changed since the previous revision.
334
        Only shown with --all.
466 by Martin Pool
- doc for status command
335
336
    unknown
337
        Not versioned and not matching an ignore pattern.
338
339
    To see ignored files use 'bzr ignored'.  For details in the
340
    changes to file texts, use 'bzr diff'.
468 by Martin Pool
- Interpret arguments to bzr status
341
342
    If no arguments are specified, the status of the entire working
343
    directory is shown.  Otherwise, only the status of the specified
344
    files or directories is reported.  If a directory is given, status
345
    is reported for everything inside that directory.
1 by mbp at sourcefrog
import from baz patch-364
346
    """
404 by Martin Pool
- bzr status now optionally takes filenames to check
347
    takes_args = ['file*']
465 by Martin Pool
- Move show_status() out of Branch into a new function in
348
    takes_options = ['all', 'show-ids']
350 by Martin Pool
- refactor command aliases into command classes
349
    aliases = ['st', 'stat']
329 by Martin Pool
- refactor command functions into command classes
350
    
465 by Martin Pool
- Move show_status() out of Branch into a new function in
351
    def run(self, all=False, show_ids=False, file_list=None):
468 by Martin Pool
- Interpret arguments to bzr status
352
        if file_list:
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
353
            b = Branch(file_list[0])
468 by Martin Pool
- Interpret arguments to bzr status
354
            file_list = [b.relpath(x) for x in file_list]
355
            # special case: only one path was given and it's the root
356
            # of the branch
357
            if file_list == ['']:
358
                file_list = None
359
        else:
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
360
            b = Branch('.')
465 by Martin Pool
- Move show_status() out of Branch into a new function in
361
        import status
362
        status.show_status(b, show_unchanged=all, show_ids=show_ids,
483 by Martin Pool
- change 'file_list' to more explanatory 'specific_files'
363
                           specific_files=file_list)
329 by Martin Pool
- refactor command functions into command classes
364
365
366
class cmd_cat_revision(Command):
367
    """Write out metadata for a revision."""
368
369
    hidden = True
370
    takes_args = ['revision_id']
371
    
372
    def run(self, revision_id):
373
        Branch('.').get_revision(revision_id).write_xml(sys.stdout)
374
375
376
class cmd_revno(Command):
377
    """Show current revision number.
378
379
    This is equal to the number of revisions on this branch."""
380
    def run(self):
381
        print Branch('.').revno()
382
383
    
384
class cmd_add(Command):
70 by mbp at sourcefrog
Prepare for smart recursive add.
385
    """Add specified files or directories.
386
387
    In non-recursive mode, all the named items are added, regardless
388
    of whether they were previously ignored.  A warning is given if
389
    any of the named files are already versioned.
390
391
    In recursive mode (the default), files are treated the same way
392
    but the behaviour for directories is different.  Directories that
393
    are already versioned do not give a warning.  All directories,
394
    whether already versioned or not, are searched for files or
395
    subdirectories that are neither versioned or ignored, and these
396
    are added.  This search proceeds recursively into versioned
397
    directories.
398
399
    Therefore simply saying 'bzr add .' will version all files that
400
    are currently unknown.
279 by Martin Pool
todo
401
402
    TODO: Perhaps adding a file whose directly is not versioned should
403
    recursively add that parent, rather than giving an error?
70 by mbp at sourcefrog
Prepare for smart recursive add.
404
    """
329 by Martin Pool
- refactor command functions into command classes
405
    takes_args = ['file+']
594 by Martin Pool
- add --no-recurse option for add command
406
    takes_options = ['verbose', 'no-recurse']
329 by Martin Pool
- refactor command functions into command classes
407
    
594 by Martin Pool
- add --no-recurse option for add command
408
    def run(self, file_list, verbose=False, no_recurse=False):
409
        bzrlib.add.smart_add(file_list, verbose, not no_recurse)
329 by Martin Pool
- refactor command functions into command classes
410
411
386 by Martin Pool
- Typo (reported by uws)
412
class cmd_relpath(Command):
329 by Martin Pool
- refactor command functions into command classes
413
    """Show path of a file relative to root"""
392 by Martin Pool
- fix relpath and add tests
414
    takes_args = ['filename']
584 by Martin Pool
- make relpath and revision-history hidden commands
415
    hidden = True
329 by Martin Pool
- refactor command functions into command classes
416
    
392 by Martin Pool
- fix relpath and add tests
417
    def run(self, filename):
418
        print Branch(filename).relpath(filename)
329 by Martin Pool
- refactor command functions into command classes
419
420
421
422
class cmd_inventory(Command):
423
    """Show inventory of the current working copy or a revision."""
588 by Martin Pool
- change inventory command to not show ids by default
424
    takes_options = ['revision', 'show-ids']
329 by Martin Pool
- refactor command functions into command classes
425
    
588 by Martin Pool
- change inventory command to not show ids by default
426
    def run(self, revision=None, show_ids=False):
329 by Martin Pool
- refactor command functions into command classes
427
        b = Branch('.')
428
        if revision == None:
429
            inv = b.read_working_inventory()
430
        else:
431
            inv = b.get_revision_inventory(b.lookup_revision(revision))
432
556 by Martin Pool
- fix up Inventory.entries()
433
        for path, entry in inv.entries():
588 by Martin Pool
- change inventory command to not show ids by default
434
            if show_ids:
435
                print '%-50s %s' % (path, entry.file_id)
436
            else:
437
                print path
329 by Martin Pool
- refactor command functions into command classes
438
439
440
class cmd_move(Command):
441
    """Move files to a different directory.
442
443
    examples:
444
        bzr move *.txt doc
445
446
    The destination must be a versioned directory in the same branch.
447
    """
448
    takes_args = ['source$', 'dest']
449
    def run(self, source_list, dest):
450
        b = Branch('.')
451
452
        b.move([b.relpath(s) for s in source_list], b.relpath(dest))
453
454
455
class cmd_rename(Command):
168 by mbp at sourcefrog
new "rename" command
456
    """Change the name of an entry.
457
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
458
    examples:
459
      bzr rename frob.c frobber.c
460
      bzr rename src/frob.c lib/frob.c
461
462
    It is an error if the destination name exists.
463
464
    See also the 'move' command, which moves files into a different
465
    directory without changing their name.
466
467
    TODO: Some way to rename multiple files without invoking bzr for each
468
    one?"""
329 by Martin Pool
- refactor command functions into command classes
469
    takes_args = ['from_name', 'to_name']
168 by mbp at sourcefrog
new "rename" command
470
    
329 by Martin Pool
- refactor command functions into command classes
471
    def run(self, from_name, to_name):
472
        b = Branch('.')
473
        b.rename_one(b.relpath(from_name), b.relpath(to_name))
474
475
476
628 by Martin Pool
- merge aaron's updated merge/pull code
477
478
479
class cmd_pull(Command):
480
    """Pull any changes from another branch into the current one.
481
482
    If the location is omitted, the last-used location will be used.
483
    Both the revision history and the working directory will be
484
    updated.
485
486
    This command only works on branches that have not diverged.  Branches are
487
    considered diverged if both branches have had commits without first
488
    pulling from the other.
489
490
    If branches have diverged, you can use 'bzr merge' to pull the text changes
491
    from one into the other.
492
    """
493
    takes_args = ['location?']
494
495
    def run(self, location=None):
496
        from bzrlib.merge import merge
497
        import errno
498
        
499
        br_to = Branch('.')
500
        stored_loc = None
501
        try:
502
            stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
503
        except IOError, e:
504
            if errno == errno.ENOENT:
505
                raise
506
        if location is None:
507
            location = stored_loc
508
        if location is None:
509
            raise BzrCommandError("No pull location known or specified.")
510
        from branch import find_branch, DivergedBranches
511
        br_from = find_branch(location)
512
        location = pull_loc(br_from)
513
        old_revno = br_to.revno()
514
        try:
515
            br_to.update_revisions(br_from)
516
        except DivergedBranches:
517
            raise BzrCommandError("These branches have diverged.  Try merge.")
518
            
640 by Martin Pool
- bzr pull should not check that the tree is clean
519
        merge(('.', -1), ('.', old_revno), check_clean=False)
628 by Martin Pool
- merge aaron's updated merge/pull code
520
        if location != stored_loc:
521
            br_to.controlfile("x-pull", "wb").write(location + "\n")
522
523
524
525
class cmd_branch(Command):
526
    """Create a new copy of a branch.
527
685 by Martin Pool
- add -r option to the branch command
528
    If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
529
    be used.  In other words, "branch ../foo/bar" will attempt to create ./bar.
530
531
    To retrieve the branch as of a particular revision, supply the --revision
532
    parameter, as in "branch foo/bar -r 5".
628 by Martin Pool
- merge aaron's updated merge/pull code
533
    """
534
    takes_args = ['from_location', 'to_location?']
685 by Martin Pool
- add -r option to the branch command
535
    takes_options = ['revision']
628 by Martin Pool
- merge aaron's updated merge/pull code
536
685 by Martin Pool
- add -r option to the branch command
537
    def run(self, from_location, to_location=None, revision=None):
628 by Martin Pool
- merge aaron's updated merge/pull code
538
        import errno
539
        from bzrlib.merge import merge
685 by Martin Pool
- add -r option to the branch command
540
        from branch import find_branch, DivergedBranches, NoSuchRevision
541
        from shutil import rmtree
671 by Martin Pool
- Don't create an empty destination directory when
542
        try:
543
            br_from = find_branch(from_location)
544
        except OSError, e:
545
            if e.errno == errno.ENOENT:
546
                raise BzrCommandError('Source location "%s" does not exist.' %
547
                                      to_location)
548
            else:
549
                raise
550
628 by Martin Pool
- merge aaron's updated merge/pull code
551
        if to_location is None:
684 by Martin Pool
- Strip any number of trailing slashes and backslashes from the path name
552
            to_location = os.path.basename(from_location.rstrip("/\\"))
628 by Martin Pool
- merge aaron's updated merge/pull code
553
554
        try:
555
            os.mkdir(to_location)
556
        except OSError, e:
557
            if e.errno == errno.EEXIST:
558
                raise BzrCommandError('Target directory "%s" already exists.' %
559
                                      to_location)
560
            if e.errno == errno.ENOENT:
561
                raise BzrCommandError('Parent of "%s" does not exist.' %
562
                                      to_location)
563
            else:
564
                raise
565
        br_to = Branch(to_location, init=True)
566
685 by Martin Pool
- add -r option to the branch command
567
        try:
568
            br_to.update_revisions(br_from, stop_revision=revision)
569
        except NoSuchRevision:
570
            rmtree(to_location)
571
            msg = "The branch %s has no revision %d." % (from_location,
572
                                                         revision)
573
            raise BzrCommandError(msg)
628 by Martin Pool
- merge aaron's updated merge/pull code
574
        merge((to_location, -1), (to_location, 0), this_dir=to_location,
698 by Martin Pool
- bzr branch shouldn't say "0 conflicts"
575
              check_clean=False, ignore_zero=True)
685 by Martin Pool
- add -r option to the branch command
576
        from_location = pull_loc(br_from)
628 by Martin Pool
- merge aaron's updated merge/pull code
577
        br_to.controlfile("x-pull", "wb").write(from_location + "\n")
578
579
580
def pull_loc(branch):
581
    # TODO: Should perhaps just make attribute be 'base' in
582
    # RemoteBranch and Branch?
583
    if hasattr(branch, "baseurl"):
584
        return branch.baseurl
585
    else:
586
        return branch.base
587
588
589
329 by Martin Pool
- refactor command functions into command classes
590
class cmd_renames(Command):
164 by mbp at sourcefrog
new 'renames' command
591
    """Show list of renamed files.
592
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
593
    TODO: Option to show renames between two historical versions.
594
595
    TODO: Only show renames under dir, rather than in the whole branch.
596
    """
329 by Martin Pool
- refactor command functions into command classes
597
    takes_args = ['dir?']
598
599
    def run(self, dir='.'):
600
        b = Branch(dir)
601
        old_inv = b.basis_tree().inventory
602
        new_inv = b.read_working_inventory()
603
604
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
605
        renames.sort()
606
        for old_name, new_name in renames:
607
            print "%s => %s" % (old_name, new_name)        
608
609
610
class cmd_info(Command):
472 by Martin Pool
- Optional branch parameter to info command
611
    """Show statistical information about a branch."""
612
    takes_args = ['branch?']
613
    
614
    def run(self, branch=None):
329 by Martin Pool
- refactor command functions into command classes
615
        import info
472 by Martin Pool
- Optional branch parameter to info command
616
617
        from branch import find_branch
618
        b = find_branch(branch)
619
        info.show_info(b)
329 by Martin Pool
- refactor command functions into command classes
620
621
622
class cmd_remove(Command):
623
    """Make a file unversioned.
624
625
    This makes bzr stop tracking changes to a versioned file.  It does
626
    not delete the working copy.
627
    """
628
    takes_args = ['file+']
629
    takes_options = ['verbose']
630
    
631
    def run(self, file_list, verbose=False):
632
        b = Branch(file_list[0])
633
        b.remove([b.relpath(f) for f in file_list], verbose=verbose)
634
635
636
class cmd_file_id(Command):
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
637
    """Print file_id of a particular file or directory.
638
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
639
    The file_id is assigned when the file is first added and remains the
640
    same through all revisions where the file exists, even when it is
641
    moved or renamed.
642
    """
329 by Martin Pool
- refactor command functions into command classes
643
    hidden = True
644
    takes_args = ['filename']
645
    def run(self, filename):
646
        b = Branch(filename)
647
        i = b.inventory.path2id(b.relpath(filename))
648
        if i == None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
649
            raise BzrError("%r is not a versioned file" % filename)
329 by Martin Pool
- refactor command functions into command classes
650
        else:
651
            print i
652
653
654
class cmd_file_path(Command):
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
655
    """Print path of file_ids to a file or directory.
656
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
657
    This prints one line for each directory down to the target,
658
    starting at the branch root."""
329 by Martin Pool
- refactor command functions into command classes
659
    hidden = True
660
    takes_args = ['filename']
661
    def run(self, filename):
662
        b = Branch(filename)
663
        inv = b.inventory
664
        fid = inv.path2id(b.relpath(filename))
665
        if fid == None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
666
            raise BzrError("%r is not a versioned file" % filename)
329 by Martin Pool
- refactor command functions into command classes
667
        for fip in inv.get_idpath(fid):
668
            print fip
669
670
671
class cmd_revision_history(Command):
672
    """Display list of revision ids on this branch."""
584 by Martin Pool
- make relpath and revision-history hidden commands
673
    hidden = True
329 by Martin Pool
- refactor command functions into command classes
674
    def run(self):
675
        for patchid in Branch('.').revision_history():
676
            print patchid
677
678
679
class cmd_directories(Command):
680
    """Display list of versioned directories in this branch."""
681
    def run(self):
682
        for name, ie in Branch('.').read_working_inventory().directories():
683
            if name == '':
684
                print '.'
685
            else:
686
                print name
687
688
689
class cmd_init(Command):
690
    """Make a directory into a versioned branch.
691
692
    Use this to create an empty branch, or before importing an
693
    existing project.
694
695
    Recipe for importing a tree of files:
696
        cd ~/project
697
        bzr init
698
        bzr add -v .
699
        bzr status
700
        bzr commit -m 'imported project'
701
    """
702
    def run(self):
703
        Branch('.', init=True)
704
705
706
class cmd_diff(Command):
707
    """Show differences in working tree.
708
    
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
709
    If files are listed, only the changes in those files are listed.
710
    Otherwise, all changes for the tree are listed.
711
712
    TODO: Given two revision arguments, show the difference between them.
713
714
    TODO: Allow diff across branches.
715
716
    TODO: Option to use external diff command; could be GNU diff, wdiff,
717
          or a graphical diff.
718
276 by Martin Pool
Doc
719
    TODO: Python difflib is not exactly the same as unidiff; should
720
          either fix it up or prefer to use an external diff.
721
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
722
    TODO: If a directory is given, diff everything under that.
723
276 by Martin Pool
Doc
724
    TODO: Selected-file diff is inefficient and doesn't show you
725
          deleted files.
278 by Martin Pool
- Better workaround for trailing newlines in diffs
726
727
    TODO: This probably handles non-Unix newlines poorly.
329 by Martin Pool
- refactor command functions into command classes
728
    """
729
    
730
    takes_args = ['file*']
571 by Martin Pool
- new --diff-options to pass options through to external
731
    takes_options = ['revision', 'diff-options']
638 by Martin Pool
- add 'dif' as alias for 'diff' command
732
    aliases = ['di', 'dif']
329 by Martin Pool
- refactor command functions into command classes
733
571 by Martin Pool
- new --diff-options to pass options through to external
734
    def run(self, revision=None, file_list=None, diff_options=None):
329 by Martin Pool
- refactor command functions into command classes
735
        from bzrlib.diff import show_diff
547 by Martin Pool
- bzr diff finds a branch from the first parameter,
736
        from bzrlib import find_branch
737
738
        if file_list:
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
739
            b = find_branch(file_list[0])
547 by Martin Pool
- bzr diff finds a branch from the first parameter,
740
            file_list = [b.relpath(f) for f in file_list]
741
            if file_list == ['']:
742
                # just pointing to top-of-tree
743
                file_list = None
744
        else:
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
745
            b = Branch('.')
329 by Martin Pool
- refactor command functions into command classes
746
    
571 by Martin Pool
- new --diff-options to pass options through to external
747
        show_diff(b, revision, specific_files=file_list,
748
                  external_diff_options=diff_options)
329 by Martin Pool
- refactor command functions into command classes
749
750
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
751
        
752
753
329 by Martin Pool
- refactor command functions into command classes
754
class cmd_deleted(Command):
135 by mbp at sourcefrog
Simple new 'deleted' command
755
    """List files deleted in the working tree.
756
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
757
    TODO: Show files deleted since a previous revision, or between two revisions.
135 by mbp at sourcefrog
Simple new 'deleted' command
758
    """
329 by Martin Pool
- refactor command functions into command classes
759
    def run(self, show_ids=False):
760
        b = Branch('.')
761
        old = b.basis_tree()
762
        new = b.working_tree()
763
764
        ## TODO: Much more efficient way to do this: read in new
765
        ## directories with readdir, rather than stating each one.  Same
766
        ## level of effort but possibly much less IO.  (Or possibly not,
767
        ## if the directories are very large...)
768
769
        for path, ie in old.inventory.iter_entries():
770
            if not new.has_id(ie.file_id):
771
                if show_ids:
772
                    print '%-50s %s' % (path, ie.file_id)
773
                else:
774
                    print path
775
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
776
777
class cmd_modified(Command):
778
    """List files modified in working tree."""
779
    hidden = True
780
    def run(self):
781
        import statcache
782
        b = Branch('.')
438 by Martin Pool
- Avoid calling Inventory.iter_entries() when finding modified
783
        inv = b.read_working_inventory()
784
        sc = statcache.update_cache(b, inv)
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
785
        basis = b.basis_tree()
786
        basis_inv = basis.inventory
438 by Martin Pool
- Avoid calling Inventory.iter_entries() when finding modified
787
        
788
        # We used to do this through iter_entries(), but that's slow
789
        # when most of the files are unmodified, as is usually the
790
        # case.  So instead we iterate by inventory entry, and only
791
        # calculate paths as necessary.
792
793
        for file_id in basis_inv:
794
            cacheentry = sc.get(file_id)
795
            if not cacheentry:                 # deleted
796
                continue
797
            ie = basis_inv[file_id]
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
798
            if cacheentry[statcache.SC_SHA1] != ie.text_sha1:
438 by Martin Pool
- Avoid calling Inventory.iter_entries() when finding modified
799
                path = inv.id2path(file_id)
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
800
                print path
439 by Martin Pool
- new command 'bzr added'
801
802
803
804
class cmd_added(Command):
805
    """List files added in working tree."""
806
    hidden = True
807
    def run(self):
808
        b = Branch('.')
809
        wt = b.working_tree()
810
        basis_inv = b.basis_tree().inventory
811
        inv = wt.inventory
812
        for file_id in inv:
813
            if file_id in basis_inv:
814
                continue
815
            path = inv.id2path(file_id)
816
            if not os.access(b.abspath(path), os.F_OK):
817
                continue
818
            print path
437 by Martin Pool
- new command 'bzr modified' to exercise the statcache
819
                
820
        
821
329 by Martin Pool
- refactor command functions into command classes
822
class cmd_root(Command):
823
    """Show the tree root directory.
824
825
    The root is the nearest enclosing directory with a .bzr control
826
    directory."""
827
    takes_args = ['filename?']
828
    def run(self, filename=None):
829
        """Print the branch root."""
416 by Martin Pool
- bzr log and bzr root now accept an http URL
830
        from branch import find_branch
831
        b = find_branch(filename)
832
        print getattr(b, 'base', None) or getattr(b, 'baseurl')
329 by Martin Pool
- refactor command functions into command classes
833
834
835
class cmd_log(Command):
1 by mbp at sourcefrog
import from baz patch-364
836
    """Show log of this branch.
837
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
838
    To request a range of logs, you can use the command -r begin:end
839
    -r revision requests a specific revision, -r :end or -r begin: are
840
    also valid.
841
842
    TODO: Make --revision support uuid: and hash: [future tag:] notation.
843
  
545 by Martin Pool
- --forward option for log
844
    """
367 by Martin Pool
- New --show-ids option for bzr log
845
378 by Martin Pool
- New usage bzr log FILENAME
846
    takes_args = ['filename?']
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
847
    takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision']
545 by Martin Pool
- --forward option for log
848
    
849
    def run(self, filename=None, timezone='original',
850
            verbose=False,
851
            show_ids=False,
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
852
            forward=False,
853
            revision=None):
527 by Martin Pool
- refactor log command
854
        from bzrlib import show_log, find_branch
562 by Martin Pool
- bug fix for printing logs containing unicode
855
        import codecs
545 by Martin Pool
- --forward option for log
856
857
        direction = (forward and 'forward') or 'reverse'
527 by Martin Pool
- refactor log command
858
        
378 by Martin Pool
- New usage bzr log FILENAME
859
        if filename:
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
860
            b = find_branch(filename)
527 by Martin Pool
- refactor log command
861
            fp = b.relpath(filename)
533 by Martin Pool
- fix up asking for the log for the root of a remote branch
862
            if fp:
863
                file_id = b.read_working_inventory().path2id(fp)
864
            else:
865
                file_id = None  # points to branch root
527 by Martin Pool
- refactor log command
866
        else:
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
867
            b = find_branch('.')
527 by Martin Pool
- refactor log command
868
            file_id = None
869
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
870
        if revision == None:
871
            revision = [None, None]
872
        elif isinstance(revision, int):
873
            revision = [revision, revision]
874
        else:
875
            # pair of revisions?
876
            pass
877
            
878
        assert len(revision) == 2
879
562 by Martin Pool
- bug fix for printing logs containing unicode
880
        mutter('encoding log as %r' % bzrlib.user_encoding)
610 by Martin Pool
- replace Branch.lock(mode) with separate lock_read and lock_write
881
882
        # use 'replace' so that we don't abort if trying to write out
883
        # in e.g. the default C locale.
884
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
562 by Martin Pool
- bug fix for printing logs containing unicode
885
527 by Martin Pool
- refactor log command
886
        show_log(b, file_id,
887
                 show_timezone=timezone,
888
                 verbose=verbose,
889
                 show_ids=show_ids,
562 by Martin Pool
- bug fix for printing logs containing unicode
890
                 to_file=outf,
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
891
                 direction=direction,
892
                 start_revision=revision[0],
893
                 end_revision=revision[1])
329 by Martin Pool
- refactor command functions into command classes
894
895
375 by Martin Pool
- New command touching-revisions and function to trace
896
897
class cmd_touching_revisions(Command):
523 by Martin Pool
doc
898
    """Return revision-ids which affected a particular file.
899
900
    A more user-friendly interface is "bzr log FILE"."""
375 by Martin Pool
- New command touching-revisions and function to trace
901
    hidden = True
902
    takes_args = ["filename"]
903
    def run(self, filename):
580 by Martin Pool
- Use explicit lock methods on a branch, rather than doing it
904
        b = Branch(filename)
375 by Martin Pool
- New command touching-revisions and function to trace
905
        inv = b.read_working_inventory()
906
        file_id = inv.path2id(b.relpath(filename))
907
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
908
            print "%6d %s" % (revno, what)
909
910
329 by Martin Pool
- refactor command functions into command classes
911
class cmd_ls(Command):
1 by mbp at sourcefrog
import from baz patch-364
912
    """List files in a tree.
913
254 by Martin Pool
- Doc cleanups from Magnus Therning
914
    TODO: Take a revision or remote path and list that tree instead.
1 by mbp at sourcefrog
import from baz patch-364
915
    """
329 by Martin Pool
- refactor command functions into command classes
916
    hidden = True
917
    def run(self, revision=None, verbose=False):
918
        b = Branch('.')
919
        if revision == None:
920
            tree = b.working_tree()
921
        else:
922
            tree = b.revision_tree(b.lookup_revision(revision))
923
924
        for fp, fc, kind, fid in tree.list_files():
925
            if verbose:
926
                if kind == 'directory':
927
                    kindch = '/'
928
                elif kind == 'file':
929
                    kindch = ''
930
                else:
931
                    kindch = '???'
932
933
                print '%-8s %s%s' % (fc, fp, kindch)
1 by mbp at sourcefrog
import from baz patch-364
934
            else:
329 by Martin Pool
- refactor command functions into command classes
935
                print fp
936
937
938
939
class cmd_unknowns(Command):
634 by Martin Pool
- Tidy help messages
940
    """List unknown files."""
329 by Martin Pool
- refactor command functions into command classes
941
    def run(self):
942
        for f in Branch('.').unknowns():
943
            print quotefn(f)
944
945
946
947
class cmd_ignore(Command):
634 by Martin Pool
- Tidy help messages
948
    """Ignore a command or pattern.
420 by Martin Pool
Doc
949
950
    To remove patterns from the ignore list, edit the .bzrignore file.
951
952
    If the pattern contains a slash, it is compared to the whole path
953
    from the branch root.  Otherwise, it is comapred to only the last
954
    component of the path.
955
956
    Ignore patterns are case-insensitive on case-insensitive systems.
957
958
    Note: wildcards must be quoted from the shell on Unix.
959
960
    examples:
961
        bzr ignore ./Makefile
962
        bzr ignore '*.class'
963
    """
329 by Martin Pool
- refactor command functions into command classes
964
    takes_args = ['name_pattern']
310 by Martin Pool
- new 'bzr ignored' command!
965
    
329 by Martin Pool
- refactor command functions into command classes
966
    def run(self, name_pattern):
409 by Martin Pool
- New AtomicFile class
967
        from bzrlib.atomicfile import AtomicFile
575 by Martin Pool
- cleanup imports
968
        import os.path
409 by Martin Pool
- New AtomicFile class
969
329 by Martin Pool
- refactor command functions into command classes
970
        b = Branch('.')
410 by Martin Pool
- Fix ignore command and add tests
971
        ifn = b.abspath('.bzrignore')
329 by Martin Pool
- refactor command functions into command classes
972
410 by Martin Pool
- Fix ignore command and add tests
973
        if os.path.exists(ifn):
498 by Martin Pool
bugfix for bzr ignore reported by ddaa:
974
            f = open(ifn, 'rt')
975
            try:
976
                igns = f.read().decode('utf-8')
977
            finally:
978
                f.close()
409 by Martin Pool
- New AtomicFile class
979
        else:
980
            igns = ''
981
575 by Martin Pool
- cleanup imports
982
        # TODO: If the file already uses crlf-style termination, maybe
983
        # we should use that for the newly added lines?
984
409 by Martin Pool
- New AtomicFile class
985
        if igns and igns[-1] != '\n':
986
            igns += '\n'
987
        igns += name_pattern + '\n'
988
498 by Martin Pool
bugfix for bzr ignore reported by ddaa:
989
        try:
990
            f = AtomicFile(ifn, 'wt')
991
            f.write(igns.encode('utf-8'))
992
            f.commit()
993
        finally:
994
            f.close()
329 by Martin Pool
- refactor command functions into command classes
995
996
        inv = b.working_tree().inventory
997
        if inv.path2id('.bzrignore'):
998
            mutter('.bzrignore is already versioned')
999
        else:
1000
            mutter('need to make new .bzrignore file versioned')
1001
            b.add(['.bzrignore'])
1002
1003
1004
1005
class cmd_ignored(Command):
421 by Martin Pool
doc
1006
    """List ignored files and the patterns that matched them.
1007
1008
    See also: bzr ignore"""
329 by Martin Pool
- refactor command functions into command classes
1009
    def run(self):
1010
        tree = Branch('.').working_tree()
1011
        for path, file_class, kind, file_id in tree.list_files():
1012
            if file_class != 'I':
1013
                continue
1014
            ## XXX: Slightly inefficient since this was already calculated
1015
            pat = tree.is_ignored(path)
1016
            print '%-50s %s' % (path, pat)
1017
1018
1019
class cmd_lookup_revision(Command):
1020
    """Lookup the revision-id from a revision-number
1021
1022
    example:
1023
        bzr lookup-revision 33
421 by Martin Pool
doc
1024
    """
329 by Martin Pool
- refactor command functions into command classes
1025
    hidden = True
338 by Martin Pool
- cleanup of some imports
1026
    takes_args = ['revno']
1027
    
329 by Martin Pool
- refactor command functions into command classes
1028
    def run(self, revno):
1029
        try:
1030
            revno = int(revno)
1031
        except ValueError:
338 by Martin Pool
- cleanup of some imports
1032
            raise BzrCommandError("not a valid revision-number: %r" % revno)
1033
1034
        print Branch('.').lookup_revision(revno)
329 by Martin Pool
- refactor command functions into command classes
1035
1036
1037
class cmd_export(Command):
1038
    """Export past revision to destination directory.
1039
678 by Martin Pool
- export to tarballs
1040
    If no revision is specified this exports the last committed revision.
1041
1042
    Format may be an "exporter" name, such as tar, tgz, tbz2.  If none is
1043
    given, exports to a directory (equivalent to --format=dir)."""
1044
    # TODO: list known exporters
329 by Martin Pool
- refactor command functions into command classes
1045
    takes_args = ['dest']
678 by Martin Pool
- export to tarballs
1046
    takes_options = ['revision', 'format']
1047
    def run(self, dest, revision=None, format='dir'):
329 by Martin Pool
- refactor command functions into command classes
1048
        b = Branch('.')
394 by Martin Pool
- Fix argument handling in export command
1049
        if revision == None:
1050
            rh = b.revision_history()[-1]
329 by Martin Pool
- refactor command functions into command classes
1051
        else:
394 by Martin Pool
- Fix argument handling in export command
1052
            rh = b.lookup_revision(int(revision))
329 by Martin Pool
- refactor command functions into command classes
1053
        t = b.revision_tree(rh)
678 by Martin Pool
- export to tarballs
1054
        t.export(dest, format)
329 by Martin Pool
- refactor command functions into command classes
1055
1056
1057
class cmd_cat(Command):
1058
    """Write a file's text from a previous revision."""
1059
1060
    takes_options = ['revision']
1061
    takes_args = ['filename']
1062
1063
    def run(self, filename, revision=None):
1064
        if revision == None:
1065
            raise BzrCommandError("bzr cat requires a revision number")
1066
        b = Branch('.')
1067
        b.print_file(b.relpath(filename), int(revision))
1068
1069
1070
class cmd_local_time_offset(Command):
1071
    """Show the offset in seconds from GMT to local time."""
1072
    hidden = True    
1073
    def run(self):
1074
        print bzrlib.osutils.local_time_offset()
1075
1076
1077
1078
class cmd_commit(Command):
1079
    """Commit changes into a new revision.
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
1080
491 by Martin Pool
- Selective commit!
1081
    If selected files are specified, only changes to those files are
1082
    committed.  If a directory is specified then its contents are also
1083
    committed.
1084
1085
    A selected-file commit may fail in some cases where the committed
1086
    tree would be invalid, such as trying to commit a file in a
1087
    newly-added directory that is not itself committed.
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
1088
1089
    TODO: Run hooks on tree to-be-committed, and after commit.
1090
1091
    TODO: Strict commit that fails if there are unknown or deleted files.
1092
    """
491 by Martin Pool
- Selective commit!
1093
    takes_args = ['selected*']
389 by Martin Pool
- new commit --file option!
1094
    takes_options = ['message', 'file', 'verbose']
350 by Martin Pool
- refactor command aliases into command classes
1095
    aliases = ['ci', 'checkin']
1096
505 by Martin Pool
- commit is verbose by default
1097
    def run(self, message=None, file=None, verbose=True, selected_list=None):
485 by Martin Pool
- move commit code into its own module
1098
        from bzrlib.commit import commit
1099
389 by Martin Pool
- new commit --file option!
1100
        ## Warning: shadows builtin file()
1101
        if not message and not file:
1102
            raise BzrCommandError("please specify a commit message",
1103
                                  ["use either --message or --file"])
1104
        elif message and file:
1105
            raise BzrCommandError("please specify either --message or --file")
1106
        
1107
        if file:
1108
            import codecs
1109
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1110
485 by Martin Pool
- move commit code into its own module
1111
        b = Branch('.')
491 by Martin Pool
- Selective commit!
1112
        commit(b, message, verbose=verbose, specific_files=selected_list)
329 by Martin Pool
- refactor command functions into command classes
1113
1114
1115
class cmd_check(Command):
1116
    """Validate consistency of branch history.
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
1117
1118
    This command checks various invariants about the branch storage to
1119
    detect data corruption or bzr bugs.
674 by Martin Pool
- check command now also checks new inventory_sha1 and
1120
1121
    If given the --update flag, it will update some optional fields
1122
    to help ensure data consistency.
232 by mbp at sourcefrog
Allow docstrings for help to be in PEP0257 format.
1123
    """
329 by Martin Pool
- refactor command functions into command classes
1124
    takes_args = ['dir?']
674 by Martin Pool
- check command now also checks new inventory_sha1 and
1125
703 by Martin Pool
- split out a new 'bzr upgrade' command separate from
1126
    def run(self, dir='.'):
329 by Martin Pool
- refactor command functions into command classes
1127
        import bzrlib.check
703 by Martin Pool
- split out a new 'bzr upgrade' command separate from
1128
        bzrlib.check.check(Branch(dir))
1129
1130
1131
1132
class cmd_upgrade(Command):
1133
    """Upgrade branch storage to current format.
1134
1135
    This should normally be used only after the check command tells
1136
    you to run it.
1137
    """
1138
    takes_args = ['dir?']
1139
1140
    def run(self, dir='.'):
1141
        from bzrlib.upgrade import upgrade
1142
        upgrade(Branch(dir))
329 by Martin Pool
- refactor command functions into command classes
1143
1144
1145
1146
class cmd_whoami(Command):
1147
    """Show bzr user id."""
1148
    takes_options = ['email']
286 by Martin Pool
- New bzr whoami --email option
1149
    
329 by Martin Pool
- refactor command functions into command classes
1150
    def run(self, email=False):
1151
        if email:
1152
            print bzrlib.osutils.user_email()
1153
        else:
1154
            print bzrlib.osutils.username()
1155
1156
1157
class cmd_selftest(Command):
55 by mbp at sourcefrog
bzr selftest shows some counts of tests
1158
    """Run internal test suite"""
329 by Martin Pool
- refactor command functions into command classes
1159
    hidden = True
1160
    def run(self):
608 by Martin Pool
- Split selftests out into a new module and start changing them
1161
        from bzrlib.selftest import selftest
723 by Martin Pool
- move whitebox/blackbox modules into bzrlib.selftest subdirectory
1162
        return int(not selftest())
329 by Martin Pool
- refactor command functions into command classes
1163
1164
1165
class cmd_version(Command):
634 by Martin Pool
- Tidy help messages
1166
    """Show version of bzr."""
329 by Martin Pool
- refactor command functions into command classes
1167
    def run(self):
1168
        show_version()
1169
1170
def show_version():
1171
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
605 by Martin Pool
- patch from Lalo Martins to show version of bzr itself
1172
    # is bzrlib itself in a branch?
606 by Martin Pool
- new bzrlib.get_bzr_revision() tells about the history of
1173
    bzrrev = bzrlib.get_bzr_revision()
1174
    if bzrrev:
1175
        print "  (bzr checkout, revision %d {%s})" % bzrrev
329 by Martin Pool
- refactor command functions into command classes
1176
    print bzrlib.__copyright__
1177
    print "http://bazaar-ng.org/"
1178
    print
1179
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
1180
    print "you may use, modify and redistribute it under the terms of the GNU"
1181
    print "General Public License version 2 or later."
1182
1183
1184
class cmd_rocks(Command):
1185
    """Statement of optimism."""
1186
    hidden = True
1187
    def run(self):
1188
        print "it sure does!"
1189
493 by Martin Pool
- Merge aaron's merge command
1190
def parse_spec(spec):
622 by Martin Pool
Updated merge patch from Aaron
1191
    """
1192
    >>> parse_spec(None)
1193
    [None, None]
1194
    >>> parse_spec("./")
1195
    ['./', None]
1196
    >>> parse_spec("../@")
1197
    ['..', -1]
1198
    >>> parse_spec("../f/@35")
1199
    ['../f', 35]
1200
    """
1201
    if spec is None:
1202
        return [None, None]
493 by Martin Pool
- Merge aaron's merge command
1203
    if '/@' in spec:
1204
        parsed = spec.split('/@')
1205
        assert len(parsed) == 2
1206
        if parsed[1] == "":
1207
            parsed[1] = -1
1208
        else:
1209
            parsed[1] = int(parsed[1])
1210
            assert parsed[1] >=0
1211
    else:
1212
        parsed = [spec, None]
1213
    return parsed
1214
628 by Martin Pool
- merge aaron's updated merge/pull code
1215
1216
493 by Martin Pool
- Merge aaron's merge command
1217
class cmd_merge(Command):
622 by Martin Pool
Updated merge patch from Aaron
1218
    """Perform a three-way merge of trees.
1219
    
1220
    The SPEC parameters are working tree or revision specifiers.  Working trees
1221
    are specified using standard paths or urls.  No component of a directory
1222
    path may begin with '@'.
1223
    
1224
    Working tree examples: '.', '..', 'foo@', but NOT 'foo/@bar'
1225
1226
    Revisions are specified using a dirname/@revno pair, where dirname is the
1227
    branch directory and revno is the revision within that branch.  If no revno
1228
    is specified, the latest revision is used.
1229
1230
    Revision examples: './@127', 'foo/@', '../@1'
1231
1232
    The OTHER_SPEC parameter is required.  If the BASE_SPEC parameter is
1233
    not supplied, the common ancestor of OTHER_SPEC the current branch is used
1234
    as the BASE.
628 by Martin Pool
- merge aaron's updated merge/pull code
1235
1236
    merge refuses to run if there are any uncommitted changes, unless
1237
    --force is given.
622 by Martin Pool
Updated merge patch from Aaron
1238
    """
1239
    takes_args = ['other_spec', 'base_spec?']
628 by Martin Pool
- merge aaron's updated merge/pull code
1240
    takes_options = ['force']
622 by Martin Pool
Updated merge patch from Aaron
1241
628 by Martin Pool
- merge aaron's updated merge/pull code
1242
    def run(self, other_spec, base_spec=None, force=False):
591 by Martin Pool
- trim imports
1243
        from bzrlib.merge import merge
628 by Martin Pool
- merge aaron's updated merge/pull code
1244
        merge(parse_spec(other_spec), parse_spec(base_spec),
1245
              check_clean=(not force))
329 by Martin Pool
- refactor command functions into command classes
1246
622 by Martin Pool
Updated merge patch from Aaron
1247
1248
class cmd_revert(Command):
628 by Martin Pool
- merge aaron's updated merge/pull code
1249
    """Reverse all changes since the last commit.
1250
1251
    Only versioned files are affected.
1252
1253
    TODO: Store backups of any files that will be reverted, so
1254
          that the revert can be undone.          
622 by Martin Pool
Updated merge patch from Aaron
1255
    """
1256
    takes_options = ['revision']
1257
1258
    def run(self, revision=-1):
636 by Martin Pool
- fix missing import in revert
1259
        from bzrlib.merge import merge
628 by Martin Pool
- merge aaron's updated merge/pull code
1260
        merge(('.', revision), parse_spec('.'),
1261
              check_clean=False,
1262
              ignore_zero=True)
622 by Martin Pool
Updated merge patch from Aaron
1263
1264
329 by Martin Pool
- refactor command functions into command classes
1265
class cmd_assert_fail(Command):
1266
    """Test reporting of assertion failures"""
1267
    hidden = True
1268
    def run(self):
1269
        assert False, "always fails"
1270
1271
1272
class cmd_help(Command):
1273
    """Show help on a command or other topic.
1274
1275
    For a list of all available commands, say 'bzr help commands'."""
1276
    takes_args = ['topic?']
350 by Martin Pool
- refactor command aliases into command classes
1277
    aliases = ['?']
329 by Martin Pool
- refactor command functions into command classes
1278
    
1279
    def run(self, topic=None):
351 by Martin Pool
- Split out help functions into bzrlib.help
1280
        import help
1281
        help.help(topic)
1282
1 by mbp at sourcefrog
import from baz patch-364
1283
429 by Martin Pool
- New command update-stat-cache for testing
1284
class cmd_update_stat_cache(Command):
1285
    """Update stat-cache mapping inodes to SHA-1 hashes.
1286
1287
    For testing only."""
1288
    hidden = True
1289
    def run(self):
1290
        import statcache
1291
        b = Branch('.')
454 by Martin Pool
- fix update-stat-cache command
1292
        statcache.update_cache(b.base, b.read_working_inventory())
429 by Martin Pool
- New command update-stat-cache for testing
1293
1294
1 by mbp at sourcefrog
import from baz patch-364
1295
1296
# list of all available options; the rhs can be either None for an
1297
# option that takes no argument, or a constructor function that checks
1298
# the type.
1299
OPTIONS = {
1300
    'all':                    None,
571 by Martin Pool
- new --diff-options to pass options through to external
1301
    'diff-options':           str,
1 by mbp at sourcefrog
import from baz patch-364
1302
    'help':                   None,
389 by Martin Pool
- new commit --file option!
1303
    'file':                   unicode,
628 by Martin Pool
- merge aaron's updated merge/pull code
1304
    'force':                  None,
678 by Martin Pool
- export to tarballs
1305
    'format':                 unicode,
545 by Martin Pool
- --forward option for log
1306
    'forward':                None,
1 by mbp at sourcefrog
import from baz patch-364
1307
    'message':                unicode,
594 by Martin Pool
- add --no-recurse option for add command
1308
    'no-recurse':             None,
137 by mbp at sourcefrog
new --profile option
1309
    'profile':                None,
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
1310
    'revision':               _parse_revision_str,
1 by mbp at sourcefrog
import from baz patch-364
1311
    'show-ids':               None,
12 by mbp at sourcefrog
new --timezone option for bzr log
1312
    'timezone':               str,
1 by mbp at sourcefrog
import from baz patch-364
1313
    'verbose':                None,
1314
    'version':                None,
286 by Martin Pool
- New bzr whoami --email option
1315
    'email':                  None,
674 by Martin Pool
- check command now also checks new inventory_sha1 and
1316
    'update':                 None,
1 by mbp at sourcefrog
import from baz patch-364
1317
    }
1318
1319
SHORT_OPTIONS = {
583 by Martin Pool
- add -h as short name for --help
1320
    'F':                      'file', 
1321
    'h':                      'help',
1 by mbp at sourcefrog
import from baz patch-364
1322
    'm':                      'message',
1323
    'r':                      'revision',
1324
    'v':                      'verbose',
1325
}
1326
1327
1328
def parse_args(argv):
1329
    """Parse command line.
1330
    
1331
    Arguments and options are parsed at this level before being passed
1332
    down to specific command handlers.  This routine knows, from a
1333
    lookup table, something about the available options, what optargs
1334
    they take, and which commands will accept them.
1335
31 by Martin Pool
fix up parse_args doctest
1336
    >>> parse_args('--help'.split())
1 by mbp at sourcefrog
import from baz patch-364
1337
    ([], {'help': True})
31 by Martin Pool
fix up parse_args doctest
1338
    >>> parse_args('--version'.split())
1 by mbp at sourcefrog
import from baz patch-364
1339
    ([], {'version': True})
31 by Martin Pool
fix up parse_args doctest
1340
    >>> parse_args('status --all'.split())
1 by mbp at sourcefrog
import from baz patch-364
1341
    (['status'], {'all': True})
31 by Martin Pool
fix up parse_args doctest
1342
    >>> parse_args('commit --message=biter'.split())
17 by mbp at sourcefrog
allow --option=ARG syntax
1343
    (['commit'], {'message': u'biter'})
683 by Martin Pool
- short option stacking patch from John A Meinel
1344
    >>> parse_args('log -r 500'.split())
1345
    (['log'], {'revision': 500})
1346
    >>> parse_args('log -r500:600'.split())
1347
    (['log'], {'revision': [500, 600]})
1348
    >>> parse_args('log -vr500:600'.split())
1349
    (['log'], {'verbose': True, 'revision': [500, 600]})
1350
    >>> parse_args('log -rv500:600'.split()) #the r takes an argument
1351
    Traceback (most recent call last):
1352
    ...
1353
    ValueError: invalid literal for int(): v500
1 by mbp at sourcefrog
import from baz patch-364
1354
    """
1355
    args = []
1356
    opts = {}
1357
1358
    # TODO: Maybe handle '--' to end options?
1359
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1360
    while argv:
1361
        a = argv.pop(0)
1 by mbp at sourcefrog
import from baz patch-364
1362
        if a[0] == '-':
264 by Martin Pool
parse_args: option names must be ascii
1363
            # option names must not be unicode
1364
            a = str(a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1365
            optarg = None
1 by mbp at sourcefrog
import from baz patch-364
1366
            if a[1] == '-':
1367
                mutter("  got option %r" % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1368
                if '=' in a:
1369
                    optname, optarg = a[2:].split('=', 1)
1370
                else:
1371
                    optname = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
1372
                if optname not in OPTIONS:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1373
                    raise BzrError('unknown long option %r' % a)
1 by mbp at sourcefrog
import from baz patch-364
1374
            else:
1375
                shortopt = a[1:]
683 by Martin Pool
- short option stacking patch from John A Meinel
1376
                if shortopt in SHORT_OPTIONS:
1377
                    # Multi-character options must have a space to delimit
1378
                    # their value
1379
                    optname = SHORT_OPTIONS[shortopt]
1380
                else:
1381
                    # Single character short options, can be chained,
1382
                    # and have their value appended to their name
1383
                    shortopt = a[1:2]
1384
                    if shortopt not in SHORT_OPTIONS:
1385
                        # We didn't find the multi-character name, and we
1386
                        # didn't find the single char name
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1387
                        raise BzrError('unknown short option %r' % a)
683 by Martin Pool
- short option stacking patch from John A Meinel
1388
                    optname = SHORT_OPTIONS[shortopt]
1389
1390
                    if a[2:]:
1391
                        # There are extra things on this option
1392
                        # see if it is the value, or if it is another
1393
                        # short option
1394
                        optargfn = OPTIONS[optname]
1395
                        if optargfn is None:
1396
                            # This option does not take an argument, so the
1397
                            # next entry is another short option, pack it back
1398
                            # into the list
1399
                            argv.insert(0, '-' + a[2:])
1400
                        else:
1401
                            # This option takes an argument, so pack it
1402
                            # into the array
1403
                            optarg = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
1404
            
1405
            if optname in opts:
1406
                # XXX: Do we ever want to support this, e.g. for -r?
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1407
                raise BzrError('repeated option %r' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1408
                
1 by mbp at sourcefrog
import from baz patch-364
1409
            optargfn = OPTIONS[optname]
1410
            if optargfn:
17 by mbp at sourcefrog
allow --option=ARG syntax
1411
                if optarg == None:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1412
                    if not argv:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1413
                        raise BzrError('option %r needs an argument' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1414
                    else:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1415
                        optarg = argv.pop(0)
17 by mbp at sourcefrog
allow --option=ARG syntax
1416
                opts[optname] = optargfn(optarg)
1 by mbp at sourcefrog
import from baz patch-364
1417
            else:
17 by mbp at sourcefrog
allow --option=ARG syntax
1418
                if optarg != None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1419
                    raise BzrError('option %r takes no argument' % optname)
1 by mbp at sourcefrog
import from baz patch-364
1420
                opts[optname] = True
1421
        else:
1422
            args.append(a)
1423
1424
    return args, opts
1425
1426
1427
1428
329 by Martin Pool
- refactor command functions into command classes
1429
def _match_argform(cmd, takes_args, args):
1 by mbp at sourcefrog
import from baz patch-364
1430
    argdict = {}
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1431
329 by Martin Pool
- refactor command functions into command classes
1432
    # step through args and takes_args, allowing appropriate 0-many matches
1433
    for ap in takes_args:
1 by mbp at sourcefrog
import from baz patch-364
1434
        argname = ap[:-1]
1435
        if ap[-1] == '?':
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
1436
            if args:
1437
                argdict[argname] = args.pop(0)
196 by mbp at sourcefrog
selected-file diff
1438
        elif ap[-1] == '*': # all remaining arguments
1439
            if args:
1440
                argdict[argname + '_list'] = args[:]
1441
                args = []
1442
            else:
1443
                argdict[argname + '_list'] = None
1 by mbp at sourcefrog
import from baz patch-364
1444
        elif ap[-1] == '+':
1445
            if not args:
329 by Martin Pool
- refactor command functions into command classes
1446
                raise BzrCommandError("command %r needs one or more %s"
1 by mbp at sourcefrog
import from baz patch-364
1447
                        % (cmd, argname.upper()))
1448
            else:
1449
                argdict[argname + '_list'] = args[:]
1450
                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
1451
        elif ap[-1] == '$': # all but one
1452
            if len(args) < 2:
329 by Martin Pool
- refactor command functions into command classes
1453
                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
1454
                        % (cmd, argname.upper()))
1455
            argdict[argname + '_list'] = args[:-1]
1456
            args[:-1] = []                
1 by mbp at sourcefrog
import from baz patch-364
1457
        else:
1458
            # just a plain arg
1459
            argname = ap
1460
            if not args:
329 by Martin Pool
- refactor command functions into command classes
1461
                raise BzrCommandError("command %r requires argument %s"
1 by mbp at sourcefrog
import from baz patch-364
1462
                        % (cmd, argname.upper()))
1463
            else:
1464
                argdict[argname] = args.pop(0)
1465
            
1466
    if args:
329 by Martin Pool
- refactor command functions into command classes
1467
        raise BzrCommandError("extra argument to command %s: %s"
1468
                              % (cmd, args[0]))
1 by mbp at sourcefrog
import from baz patch-364
1469
1470
    return argdict
1471
1472
1473
1474
def run_bzr(argv):
1475
    """Execute a command.
1476
1477
    This is similar to main(), but without all the trappings for
245 by mbp at sourcefrog
- control files always in utf-8-unix format
1478
    logging and error handling.  
1 by mbp at sourcefrog
import from baz patch-364
1479
    """
251 by mbp at sourcefrog
- factor out locale.getpreferredencoding()
1480
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
245 by mbp at sourcefrog
- control files always in utf-8-unix format
1481
    
641 by Martin Pool
- improved external-command patch from john
1482
    include_plugins=True
1 by mbp at sourcefrog
import from baz patch-364
1483
    try:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1484
        args, opts = parse_args(argv[1:])
1 by mbp at sourcefrog
import from baz patch-364
1485
        if 'help' in opts:
351 by Martin Pool
- Split out help functions into bzrlib.help
1486
            import help
159 by mbp at sourcefrog
bzr commit --help now works
1487
            if args:
351 by Martin Pool
- Split out help functions into bzrlib.help
1488
                help.help(args[0])
159 by mbp at sourcefrog
bzr commit --help now works
1489
            else:
351 by Martin Pool
- Split out help functions into bzrlib.help
1490
                help.help()
1 by mbp at sourcefrog
import from baz patch-364
1491
            return 0
1492
        elif 'version' in opts:
336 by Martin Pool
- fix up 'bzr --version'
1493
            show_version()
1 by mbp at sourcefrog
import from baz patch-364
1494
            return 0
641 by Martin Pool
- improved external-command patch from john
1495
        elif args and args[0] == 'builtin':
1496
            include_plugins=False
1497
            args = args[1:]
265 by Martin Pool
parse_args: command names must also be ascii
1498
        cmd = str(args.pop(0))
1 by mbp at sourcefrog
import from baz patch-364
1499
    except IndexError:
448 by Martin Pool
- bzr with no command now shows help, not just an error
1500
        import help
1501
        help.help()
1 by mbp at sourcefrog
import from baz patch-364
1502
        return 1
448 by Martin Pool
- bzr with no command now shows help, not just an error
1503
          
115 by mbp at sourcefrog
todo
1504
641 by Martin Pool
- improved external-command patch from john
1505
    canonical_cmd, cmd_class = get_cmd_class(cmd,include_plugins=include_plugins)
1 by mbp at sourcefrog
import from baz patch-364
1506
137 by mbp at sourcefrog
new --profile option
1507
    # global option
1508
    if 'profile' in opts:
1509
        profile = True
1510
        del opts['profile']
1511
    else:
1512
        profile = False
1 by mbp at sourcefrog
import from baz patch-364
1513
1514
    # check options are reasonable
329 by Martin Pool
- refactor command functions into command classes
1515
    allowed = cmd_class.takes_options
1 by mbp at sourcefrog
import from baz patch-364
1516
    for oname in opts:
1517
        if oname not in allowed:
381 by Martin Pool
- Better message when a wrong argument is given
1518
            raise BzrCommandError("option '--%s' is not allowed for command %r"
329 by Martin Pool
- refactor command functions into command classes
1519
                                  % (oname, cmd))
176 by mbp at sourcefrog
New cat command contributed by janmar.
1520
137 by mbp at sourcefrog
new --profile option
1521
    # mix arguments and options into one dictionary
329 by Martin Pool
- refactor command functions into command classes
1522
    cmdargs = _match_argform(cmd, cmd_class.takes_args, args)
1523
    cmdopts = {}
136 by mbp at sourcefrog
new --show-ids option for 'deleted' command
1524
    for k, v in opts.items():
329 by Martin Pool
- refactor command functions into command classes
1525
        cmdopts[k.replace('-', '_')] = v
1 by mbp at sourcefrog
import from baz patch-364
1526
137 by mbp at sourcefrog
new --profile option
1527
    if profile:
338 by Martin Pool
- cleanup of some imports
1528
        import hotshot, tempfile
239 by mbp at sourcefrog
- remove profiler temporary file when done
1529
        pffileno, pfname = tempfile.mkstemp()
1530
        try:
1531
            prof = hotshot.Profile(pfname)
329 by Martin Pool
- refactor command functions into command classes
1532
            ret = prof.runcall(cmd_class, cmdopts, cmdargs) or 0
239 by mbp at sourcefrog
- remove profiler temporary file when done
1533
            prof.close()
1534
1535
            import hotshot.stats
1536
            stats = hotshot.stats.load(pfname)
1537
            #stats.strip_dirs()
1538
            stats.sort_stats('time')
1539
            ## XXX: Might like to write to stderr or the trace file instead but
1540
            ## print_stats seems hardcoded to stdout
1541
            stats.print_stats(20)
1542
            
337 by Martin Pool
- Clarify return codes from command objects
1543
            return ret.status
239 by mbp at sourcefrog
- remove profiler temporary file when done
1544
1545
        finally:
1546
            os.close(pffileno)
1547
            os.remove(pfname)
137 by mbp at sourcefrog
new --profile option
1548
    else:
500 by Martin Pool
- fix return value from run_bzr
1549
        return cmd_class(cmdopts, cmdargs).status 
1 by mbp at sourcefrog
import from baz patch-364
1550
1551
359 by Martin Pool
- pychecker fixups
1552
def _report_exception(summary, quiet=False):
267 by Martin Pool
- better reporting of errors
1553
    import traceback
1554
    log_error('bzr: ' + summary)
359 by Martin Pool
- pychecker fixups
1555
    bzrlib.trace.log_exception()
317 by Martin Pool
- better error message for broken pipe
1556
1557
    if not quiet:
1558
        tb = sys.exc_info()[2]
1559
        exinfo = traceback.extract_tb(tb)
1560
        if exinfo:
1561
            sys.stderr.write('  at %s:%d in %s()\n' % exinfo[-1][:3])
1562
        sys.stderr.write('  see ~/.bzr.log for debug information\n')
267 by Martin Pool
- better reporting of errors
1563
1564
1565
1 by mbp at sourcefrog
import from baz patch-364
1566
def main(argv):
317 by Martin Pool
- better error message for broken pipe
1567
    import errno
1568
    
344 by Martin Pool
- It's not an error to use the library without
1569
    bzrlib.open_tracefile(argv)
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1570
1 by mbp at sourcefrog
import from baz patch-364
1571
    try:
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1572
        try:
337 by Martin Pool
- Clarify return codes from command objects
1573
            try:
1574
                return run_bzr(argv)
1575
            finally:
1576
                # do this here inside the exception wrappers to catch EPIPE
1577
                sys.stdout.flush()
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1578
        except BzrError, e:
329 by Martin Pool
- refactor command functions into command classes
1579
            quiet = isinstance(e, (BzrCommandError))
359 by Martin Pool
- pychecker fixups
1580
            _report_exception('error: ' + e.args[0], quiet=quiet)
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1581
            if len(e.args) > 1:
1582
                for h in e.args[1]:
267 by Martin Pool
- better reporting of errors
1583
                    # some explanation or hints
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1584
                    log_error('  ' + h)
1585
            return 1
267 by Martin Pool
- better reporting of errors
1586
        except AssertionError, e:
1587
            msg = 'assertion failed'
1588
            if str(e):
1589
                msg += ': ' + str(e)
359 by Martin Pool
- pychecker fixups
1590
            _report_exception(msg)
318 by Martin Pool
- better error message for Ctrl-c
1591
            return 2
1592
        except KeyboardInterrupt, e:
359 by Martin Pool
- pychecker fixups
1593
            _report_exception('interrupted', quiet=True)
318 by Martin Pool
- better error message for Ctrl-c
1594
            return 2
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1595
        except Exception, e:
317 by Martin Pool
- better error message for broken pipe
1596
            quiet = False
419 by Martin Pool
- RemoteBranch.__str__ and repr
1597
            if (isinstance(e, IOError) 
1598
                and hasattr(e, 'errno')
1599
                and e.errno == errno.EPIPE):
317 by Martin Pool
- better error message for broken pipe
1600
                quiet = True
1601
                msg = 'broken pipe'
1602
            else:
1603
                msg = str(e).rstrip('\n')
359 by Martin Pool
- pychecker fixups
1604
            _report_exception(msg, quiet)
318 by Martin Pool
- better error message for Ctrl-c
1605
            return 2
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1606
    finally:
1607
        bzrlib.trace.close_trace()
1 by mbp at sourcefrog
import from baz patch-364
1608
1609
1610
if __name__ == '__main__':
1611
    sys.exit(main(sys.argv))