~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
1162
        if selftest():
1163
            return 0
1164
        else:
515 by Martin Pool
- bzr selftest: return shell false (1) if any tests fail
1165
            return 1
55 by mbp at sourcefrog
bzr selftest shows some counts of tests
1166
329 by Martin Pool
- refactor command functions into command classes
1167
1168
1169
class cmd_version(Command):
634 by Martin Pool
- Tidy help messages
1170
    """Show version of bzr."""
329 by Martin Pool
- refactor command functions into command classes
1171
    def run(self):
1172
        show_version()
1173
1174
def show_version():
1175
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
605 by Martin Pool
- patch from Lalo Martins to show version of bzr itself
1176
    # is bzrlib itself in a branch?
606 by Martin Pool
- new bzrlib.get_bzr_revision() tells about the history of
1177
    bzrrev = bzrlib.get_bzr_revision()
1178
    if bzrrev:
1179
        print "  (bzr checkout, revision %d {%s})" % bzrrev
329 by Martin Pool
- refactor command functions into command classes
1180
    print bzrlib.__copyright__
1181
    print "http://bazaar-ng.org/"
1182
    print
1183
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
1184
    print "you may use, modify and redistribute it under the terms of the GNU"
1185
    print "General Public License version 2 or later."
1186
1187
1188
class cmd_rocks(Command):
1189
    """Statement of optimism."""
1190
    hidden = True
1191
    def run(self):
1192
        print "it sure does!"
1193
493 by Martin Pool
- Merge aaron's merge command
1194
def parse_spec(spec):
622 by Martin Pool
Updated merge patch from Aaron
1195
    """
1196
    >>> parse_spec(None)
1197
    [None, None]
1198
    >>> parse_spec("./")
1199
    ['./', None]
1200
    >>> parse_spec("../@")
1201
    ['..', -1]
1202
    >>> parse_spec("../f/@35")
1203
    ['../f', 35]
1204
    """
1205
    if spec is None:
1206
        return [None, None]
493 by Martin Pool
- Merge aaron's merge command
1207
    if '/@' in spec:
1208
        parsed = spec.split('/@')
1209
        assert len(parsed) == 2
1210
        if parsed[1] == "":
1211
            parsed[1] = -1
1212
        else:
1213
            parsed[1] = int(parsed[1])
1214
            assert parsed[1] >=0
1215
    else:
1216
        parsed = [spec, None]
1217
    return parsed
1218
628 by Martin Pool
- merge aaron's updated merge/pull code
1219
1220
493 by Martin Pool
- Merge aaron's merge command
1221
class cmd_merge(Command):
622 by Martin Pool
Updated merge patch from Aaron
1222
    """Perform a three-way merge of trees.
1223
    
1224
    The SPEC parameters are working tree or revision specifiers.  Working trees
1225
    are specified using standard paths or urls.  No component of a directory
1226
    path may begin with '@'.
1227
    
1228
    Working tree examples: '.', '..', 'foo@', but NOT 'foo/@bar'
1229
1230
    Revisions are specified using a dirname/@revno pair, where dirname is the
1231
    branch directory and revno is the revision within that branch.  If no revno
1232
    is specified, the latest revision is used.
1233
1234
    Revision examples: './@127', 'foo/@', '../@1'
1235
1236
    The OTHER_SPEC parameter is required.  If the BASE_SPEC parameter is
1237
    not supplied, the common ancestor of OTHER_SPEC the current branch is used
1238
    as the BASE.
628 by Martin Pool
- merge aaron's updated merge/pull code
1239
1240
    merge refuses to run if there are any uncommitted changes, unless
1241
    --force is given.
622 by Martin Pool
Updated merge patch from Aaron
1242
    """
1243
    takes_args = ['other_spec', 'base_spec?']
628 by Martin Pool
- merge aaron's updated merge/pull code
1244
    takes_options = ['force']
622 by Martin Pool
Updated merge patch from Aaron
1245
628 by Martin Pool
- merge aaron's updated merge/pull code
1246
    def run(self, other_spec, base_spec=None, force=False):
591 by Martin Pool
- trim imports
1247
        from bzrlib.merge import merge
628 by Martin Pool
- merge aaron's updated merge/pull code
1248
        merge(parse_spec(other_spec), parse_spec(base_spec),
1249
              check_clean=(not force))
329 by Martin Pool
- refactor command functions into command classes
1250
622 by Martin Pool
Updated merge patch from Aaron
1251
1252
class cmd_revert(Command):
628 by Martin Pool
- merge aaron's updated merge/pull code
1253
    """Reverse all changes since the last commit.
1254
1255
    Only versioned files are affected.
1256
1257
    TODO: Store backups of any files that will be reverted, so
1258
          that the revert can be undone.          
622 by Martin Pool
Updated merge patch from Aaron
1259
    """
1260
    takes_options = ['revision']
1261
1262
    def run(self, revision=-1):
636 by Martin Pool
- fix missing import in revert
1263
        from bzrlib.merge import merge
628 by Martin Pool
- merge aaron's updated merge/pull code
1264
        merge(('.', revision), parse_spec('.'),
1265
              check_clean=False,
1266
              ignore_zero=True)
622 by Martin Pool
Updated merge patch from Aaron
1267
1268
329 by Martin Pool
- refactor command functions into command classes
1269
class cmd_assert_fail(Command):
1270
    """Test reporting of assertion failures"""
1271
    hidden = True
1272
    def run(self):
1273
        assert False, "always fails"
1274
1275
1276
class cmd_help(Command):
1277
    """Show help on a command or other topic.
1278
1279
    For a list of all available commands, say 'bzr help commands'."""
1280
    takes_args = ['topic?']
350 by Martin Pool
- refactor command aliases into command classes
1281
    aliases = ['?']
329 by Martin Pool
- refactor command functions into command classes
1282
    
1283
    def run(self, topic=None):
351 by Martin Pool
- Split out help functions into bzrlib.help
1284
        import help
1285
        help.help(topic)
1286
1 by mbp at sourcefrog
import from baz patch-364
1287
429 by Martin Pool
- New command update-stat-cache for testing
1288
class cmd_update_stat_cache(Command):
1289
    """Update stat-cache mapping inodes to SHA-1 hashes.
1290
1291
    For testing only."""
1292
    hidden = True
1293
    def run(self):
1294
        import statcache
1295
        b = Branch('.')
454 by Martin Pool
- fix update-stat-cache command
1296
        statcache.update_cache(b.base, b.read_working_inventory())
429 by Martin Pool
- New command update-stat-cache for testing
1297
1298
1 by mbp at sourcefrog
import from baz patch-364
1299
1300
# list of all available options; the rhs can be either None for an
1301
# option that takes no argument, or a constructor function that checks
1302
# the type.
1303
OPTIONS = {
1304
    'all':                    None,
571 by Martin Pool
- new --diff-options to pass options through to external
1305
    'diff-options':           str,
1 by mbp at sourcefrog
import from baz patch-364
1306
    'help':                   None,
389 by Martin Pool
- new commit --file option!
1307
    'file':                   unicode,
628 by Martin Pool
- merge aaron's updated merge/pull code
1308
    'force':                  None,
678 by Martin Pool
- export to tarballs
1309
    'format':                 unicode,
545 by Martin Pool
- --forward option for log
1310
    'forward':                None,
1 by mbp at sourcefrog
import from baz patch-364
1311
    'message':                unicode,
594 by Martin Pool
- add --no-recurse option for add command
1312
    'no-recurse':             None,
137 by mbp at sourcefrog
new --profile option
1313
    'profile':                None,
567 by Martin Pool
- New form 'bzr log -r FROM:TO'
1314
    'revision':               _parse_revision_str,
1 by mbp at sourcefrog
import from baz patch-364
1315
    'show-ids':               None,
12 by mbp at sourcefrog
new --timezone option for bzr log
1316
    'timezone':               str,
1 by mbp at sourcefrog
import from baz patch-364
1317
    'verbose':                None,
1318
    'version':                None,
286 by Martin Pool
- New bzr whoami --email option
1319
    'email':                  None,
674 by Martin Pool
- check command now also checks new inventory_sha1 and
1320
    'update':                 None,
1 by mbp at sourcefrog
import from baz patch-364
1321
    }
1322
1323
SHORT_OPTIONS = {
583 by Martin Pool
- add -h as short name for --help
1324
    'F':                      'file', 
1325
    'h':                      'help',
1 by mbp at sourcefrog
import from baz patch-364
1326
    'm':                      'message',
1327
    'r':                      'revision',
1328
    'v':                      'verbose',
1329
}
1330
1331
1332
def parse_args(argv):
1333
    """Parse command line.
1334
    
1335
    Arguments and options are parsed at this level before being passed
1336
    down to specific command handlers.  This routine knows, from a
1337
    lookup table, something about the available options, what optargs
1338
    they take, and which commands will accept them.
1339
31 by Martin Pool
fix up parse_args doctest
1340
    >>> parse_args('--help'.split())
1 by mbp at sourcefrog
import from baz patch-364
1341
    ([], {'help': True})
31 by Martin Pool
fix up parse_args doctest
1342
    >>> parse_args('--version'.split())
1 by mbp at sourcefrog
import from baz patch-364
1343
    ([], {'version': True})
31 by Martin Pool
fix up parse_args doctest
1344
    >>> parse_args('status --all'.split())
1 by mbp at sourcefrog
import from baz patch-364
1345
    (['status'], {'all': True})
31 by Martin Pool
fix up parse_args doctest
1346
    >>> parse_args('commit --message=biter'.split())
17 by mbp at sourcefrog
allow --option=ARG syntax
1347
    (['commit'], {'message': u'biter'})
683 by Martin Pool
- short option stacking patch from John A Meinel
1348
    >>> parse_args('log -r 500'.split())
1349
    (['log'], {'revision': 500})
1350
    >>> parse_args('log -r500:600'.split())
1351
    (['log'], {'revision': [500, 600]})
1352
    >>> parse_args('log -vr500:600'.split())
1353
    (['log'], {'verbose': True, 'revision': [500, 600]})
1354
    >>> parse_args('log -rv500:600'.split()) #the r takes an argument
1355
    Traceback (most recent call last):
1356
    ...
1357
    ValueError: invalid literal for int(): v500
1 by mbp at sourcefrog
import from baz patch-364
1358
    """
1359
    args = []
1360
    opts = {}
1361
1362
    # TODO: Maybe handle '--' to end options?
1363
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1364
    while argv:
1365
        a = argv.pop(0)
1 by mbp at sourcefrog
import from baz patch-364
1366
        if a[0] == '-':
264 by Martin Pool
parse_args: option names must be ascii
1367
            # option names must not be unicode
1368
            a = str(a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1369
            optarg = None
1 by mbp at sourcefrog
import from baz patch-364
1370
            if a[1] == '-':
1371
                mutter("  got option %r" % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1372
                if '=' in a:
1373
                    optname, optarg = a[2:].split('=', 1)
1374
                else:
1375
                    optname = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
1376
                if optname not in OPTIONS:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1377
                    raise BzrError('unknown long option %r' % a)
1 by mbp at sourcefrog
import from baz patch-364
1378
            else:
1379
                shortopt = a[1:]
683 by Martin Pool
- short option stacking patch from John A Meinel
1380
                if shortopt in SHORT_OPTIONS:
1381
                    # Multi-character options must have a space to delimit
1382
                    # their value
1383
                    optname = SHORT_OPTIONS[shortopt]
1384
                else:
1385
                    # Single character short options, can be chained,
1386
                    # and have their value appended to their name
1387
                    shortopt = a[1:2]
1388
                    if shortopt not in SHORT_OPTIONS:
1389
                        # We didn't find the multi-character name, and we
1390
                        # didn't find the single char name
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1391
                        raise BzrError('unknown short option %r' % a)
683 by Martin Pool
- short option stacking patch from John A Meinel
1392
                    optname = SHORT_OPTIONS[shortopt]
1393
1394
                    if a[2:]:
1395
                        # There are extra things on this option
1396
                        # see if it is the value, or if it is another
1397
                        # short option
1398
                        optargfn = OPTIONS[optname]
1399
                        if optargfn is None:
1400
                            # This option does not take an argument, so the
1401
                            # next entry is another short option, pack it back
1402
                            # into the list
1403
                            argv.insert(0, '-' + a[2:])
1404
                        else:
1405
                            # This option takes an argument, so pack it
1406
                            # into the array
1407
                            optarg = a[2:]
1 by mbp at sourcefrog
import from baz patch-364
1408
            
1409
            if optname in opts:
1410
                # 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
1411
                raise BzrError('repeated option %r' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1412
                
1 by mbp at sourcefrog
import from baz patch-364
1413
            optargfn = OPTIONS[optname]
1414
            if optargfn:
17 by mbp at sourcefrog
allow --option=ARG syntax
1415
                if optarg == None:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1416
                    if not argv:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1417
                        raise BzrError('option %r needs an argument' % a)
17 by mbp at sourcefrog
allow --option=ARG syntax
1418
                    else:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1419
                        optarg = argv.pop(0)
17 by mbp at sourcefrog
allow --option=ARG syntax
1420
                opts[optname] = optargfn(optarg)
1 by mbp at sourcefrog
import from baz patch-364
1421
            else:
17 by mbp at sourcefrog
allow --option=ARG syntax
1422
                if optarg != None:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
1423
                    raise BzrError('option %r takes no argument' % optname)
1 by mbp at sourcefrog
import from baz patch-364
1424
                opts[optname] = True
1425
        else:
1426
            args.append(a)
1427
1428
    return args, opts
1429
1430
1431
1432
329 by Martin Pool
- refactor command functions into command classes
1433
def _match_argform(cmd, takes_args, args):
1 by mbp at sourcefrog
import from baz patch-364
1434
    argdict = {}
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1435
329 by Martin Pool
- refactor command functions into command classes
1436
    # step through args and takes_args, allowing appropriate 0-many matches
1437
    for ap in takes_args:
1 by mbp at sourcefrog
import from baz patch-364
1438
        argname = ap[:-1]
1439
        if ap[-1] == '?':
62 by mbp at sourcefrog
- new find_branch_root function; based on suggestion from aaron
1440
            if args:
1441
                argdict[argname] = args.pop(0)
196 by mbp at sourcefrog
selected-file diff
1442
        elif ap[-1] == '*': # all remaining arguments
1443
            if args:
1444
                argdict[argname + '_list'] = args[:]
1445
                args = []
1446
            else:
1447
                argdict[argname + '_list'] = None
1 by mbp at sourcefrog
import from baz patch-364
1448
        elif ap[-1] == '+':
1449
            if not args:
329 by Martin Pool
- refactor command functions into command classes
1450
                raise BzrCommandError("command %r needs one or more %s"
1 by mbp at sourcefrog
import from baz patch-364
1451
                        % (cmd, argname.upper()))
1452
            else:
1453
                argdict[argname + '_list'] = args[:]
1454
                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
1455
        elif ap[-1] == '$': # all but one
1456
            if len(args) < 2:
329 by Martin Pool
- refactor command functions into command classes
1457
                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
1458
                        % (cmd, argname.upper()))
1459
            argdict[argname + '_list'] = args[:-1]
1460
            args[:-1] = []                
1 by mbp at sourcefrog
import from baz patch-364
1461
        else:
1462
            # just a plain arg
1463
            argname = ap
1464
            if not args:
329 by Martin Pool
- refactor command functions into command classes
1465
                raise BzrCommandError("command %r requires argument %s"
1 by mbp at sourcefrog
import from baz patch-364
1466
                        % (cmd, argname.upper()))
1467
            else:
1468
                argdict[argname] = args.pop(0)
1469
            
1470
    if args:
329 by Martin Pool
- refactor command functions into command classes
1471
        raise BzrCommandError("extra argument to command %s: %s"
1472
                              % (cmd, args[0]))
1 by mbp at sourcefrog
import from baz patch-364
1473
1474
    return argdict
1475
1476
1477
1478
def run_bzr(argv):
1479
    """Execute a command.
1480
1481
    This is similar to main(), but without all the trappings for
245 by mbp at sourcefrog
- control files always in utf-8-unix format
1482
    logging and error handling.  
1 by mbp at sourcefrog
import from baz patch-364
1483
    """
251 by mbp at sourcefrog
- factor out locale.getpreferredencoding()
1484
    argv = [a.decode(bzrlib.user_encoding) for a in argv]
245 by mbp at sourcefrog
- control files always in utf-8-unix format
1485
    
641 by Martin Pool
- improved external-command patch from john
1486
    include_plugins=True
1 by mbp at sourcefrog
import from baz patch-364
1487
    try:
26 by mbp at sourcefrog
fix StopIteration error on python2.3(?)
1488
        args, opts = parse_args(argv[1:])
1 by mbp at sourcefrog
import from baz patch-364
1489
        if 'help' in opts:
351 by Martin Pool
- Split out help functions into bzrlib.help
1490
            import help
159 by mbp at sourcefrog
bzr commit --help now works
1491
            if args:
351 by Martin Pool
- Split out help functions into bzrlib.help
1492
                help.help(args[0])
159 by mbp at sourcefrog
bzr commit --help now works
1493
            else:
351 by Martin Pool
- Split out help functions into bzrlib.help
1494
                help.help()
1 by mbp at sourcefrog
import from baz patch-364
1495
            return 0
1496
        elif 'version' in opts:
336 by Martin Pool
- fix up 'bzr --version'
1497
            show_version()
1 by mbp at sourcefrog
import from baz patch-364
1498
            return 0
641 by Martin Pool
- improved external-command patch from john
1499
        elif args and args[0] == 'builtin':
1500
            include_plugins=False
1501
            args = args[1:]
265 by Martin Pool
parse_args: command names must also be ascii
1502
        cmd = str(args.pop(0))
1 by mbp at sourcefrog
import from baz patch-364
1503
    except IndexError:
448 by Martin Pool
- bzr with no command now shows help, not just an error
1504
        import help
1505
        help.help()
1 by mbp at sourcefrog
import from baz patch-364
1506
        return 1
448 by Martin Pool
- bzr with no command now shows help, not just an error
1507
          
115 by mbp at sourcefrog
todo
1508
641 by Martin Pool
- improved external-command patch from john
1509
    canonical_cmd, cmd_class = get_cmd_class(cmd,include_plugins=include_plugins)
1 by mbp at sourcefrog
import from baz patch-364
1510
137 by mbp at sourcefrog
new --profile option
1511
    # global option
1512
    if 'profile' in opts:
1513
        profile = True
1514
        del opts['profile']
1515
    else:
1516
        profile = False
1 by mbp at sourcefrog
import from baz patch-364
1517
1518
    # check options are reasonable
329 by Martin Pool
- refactor command functions into command classes
1519
    allowed = cmd_class.takes_options
1 by mbp at sourcefrog
import from baz patch-364
1520
    for oname in opts:
1521
        if oname not in allowed:
381 by Martin Pool
- Better message when a wrong argument is given
1522
            raise BzrCommandError("option '--%s' is not allowed for command %r"
329 by Martin Pool
- refactor command functions into command classes
1523
                                  % (oname, cmd))
176 by mbp at sourcefrog
New cat command contributed by janmar.
1524
137 by mbp at sourcefrog
new --profile option
1525
    # mix arguments and options into one dictionary
329 by Martin Pool
- refactor command functions into command classes
1526
    cmdargs = _match_argform(cmd, cmd_class.takes_args, args)
1527
    cmdopts = {}
136 by mbp at sourcefrog
new --show-ids option for 'deleted' command
1528
    for k, v in opts.items():
329 by Martin Pool
- refactor command functions into command classes
1529
        cmdopts[k.replace('-', '_')] = v
1 by mbp at sourcefrog
import from baz patch-364
1530
137 by mbp at sourcefrog
new --profile option
1531
    if profile:
338 by Martin Pool
- cleanup of some imports
1532
        import hotshot, tempfile
239 by mbp at sourcefrog
- remove profiler temporary file when done
1533
        pffileno, pfname = tempfile.mkstemp()
1534
        try:
1535
            prof = hotshot.Profile(pfname)
329 by Martin Pool
- refactor command functions into command classes
1536
            ret = prof.runcall(cmd_class, cmdopts, cmdargs) or 0
239 by mbp at sourcefrog
- remove profiler temporary file when done
1537
            prof.close()
1538
1539
            import hotshot.stats
1540
            stats = hotshot.stats.load(pfname)
1541
            #stats.strip_dirs()
1542
            stats.sort_stats('time')
1543
            ## XXX: Might like to write to stderr or the trace file instead but
1544
            ## print_stats seems hardcoded to stdout
1545
            stats.print_stats(20)
1546
            
337 by Martin Pool
- Clarify return codes from command objects
1547
            return ret.status
239 by mbp at sourcefrog
- remove profiler temporary file when done
1548
1549
        finally:
1550
            os.close(pffileno)
1551
            os.remove(pfname)
137 by mbp at sourcefrog
new --profile option
1552
    else:
500 by Martin Pool
- fix return value from run_bzr
1553
        return cmd_class(cmdopts, cmdargs).status 
1 by mbp at sourcefrog
import from baz patch-364
1554
1555
359 by Martin Pool
- pychecker fixups
1556
def _report_exception(summary, quiet=False):
267 by Martin Pool
- better reporting of errors
1557
    import traceback
1558
    log_error('bzr: ' + summary)
359 by Martin Pool
- pychecker fixups
1559
    bzrlib.trace.log_exception()
317 by Martin Pool
- better error message for broken pipe
1560
1561
    if not quiet:
1562
        tb = sys.exc_info()[2]
1563
        exinfo = traceback.extract_tb(tb)
1564
        if exinfo:
1565
            sys.stderr.write('  at %s:%d in %s()\n' % exinfo[-1][:3])
1566
        sys.stderr.write('  see ~/.bzr.log for debug information\n')
267 by Martin Pool
- better reporting of errors
1567
1568
1569
1 by mbp at sourcefrog
import from baz patch-364
1570
def main(argv):
317 by Martin Pool
- better error message for broken pipe
1571
    import errno
1572
    
344 by Martin Pool
- It's not an error to use the library without
1573
    bzrlib.open_tracefile(argv)
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1574
1 by mbp at sourcefrog
import from baz patch-364
1575
    try:
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1576
        try:
337 by Martin Pool
- Clarify return codes from command objects
1577
            try:
1578
                return run_bzr(argv)
1579
            finally:
1580
                # do this here inside the exception wrappers to catch EPIPE
1581
                sys.stdout.flush()
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1582
        except BzrError, e:
329 by Martin Pool
- refactor command functions into command classes
1583
            quiet = isinstance(e, (BzrCommandError))
359 by Martin Pool
- pychecker fixups
1584
            _report_exception('error: ' + e.args[0], quiet=quiet)
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1585
            if len(e.args) > 1:
1586
                for h in e.args[1]:
267 by Martin Pool
- better reporting of errors
1587
                    # some explanation or hints
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1588
                    log_error('  ' + h)
1589
            return 1
267 by Martin Pool
- better reporting of errors
1590
        except AssertionError, e:
1591
            msg = 'assertion failed'
1592
            if str(e):
1593
                msg += ': ' + str(e)
359 by Martin Pool
- pychecker fixups
1594
            _report_exception(msg)
318 by Martin Pool
- better error message for Ctrl-c
1595
            return 2
1596
        except KeyboardInterrupt, e:
359 by Martin Pool
- pychecker fixups
1597
            _report_exception('interrupted', quiet=True)
318 by Martin Pool
- better error message for Ctrl-c
1598
            return 2
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1599
        except Exception, e:
317 by Martin Pool
- better error message for broken pipe
1600
            quiet = False
419 by Martin Pool
- RemoteBranch.__str__ and repr
1601
            if (isinstance(e, IOError) 
1602
                and hasattr(e, 'errno')
1603
                and e.errno == errno.EPIPE):
317 by Martin Pool
- better error message for broken pipe
1604
                quiet = True
1605
                msg = 'broken pipe'
1606
            else:
1607
                msg = str(e).rstrip('\n')
359 by Martin Pool
- pychecker fixups
1608
            _report_exception(msg, quiet)
318 by Martin Pool
- better error message for Ctrl-c
1609
            return 2
260 by Martin Pool
- remove atexit() dependency for writing out execution times
1610
    finally:
1611
        bzrlib.trace.close_trace()
1 by mbp at sourcefrog
import from baz patch-364
1612
1613
1614
if __name__ == '__main__':
1615
    sys.exit(main(sys.argv))