~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Martin Pool
  • Date: 2006-06-20 07:55:43 UTC
  • mfrom: (1798 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1799.
  • Revision ID: mbp@sourcefrog.net-20060620075543-b10f6575d4a4fa32
[merge] bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""builtin bzr commands"""
18
18
 
19
19
 
 
20
import codecs
20
21
import errno
21
22
import os
22
23
import sys
23
24
 
24
25
import bzrlib
25
 
import bzrlib.branch
26
 
from bzrlib.branch import Branch
27
 
import bzrlib.bzrdir as bzrdir
 
26
from bzrlib.branch import Branch, BranchReferenceFormat
 
27
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
 
28
    repository, log)
28
29
from bzrlib.bundle.read_bundle import BundleReader
29
 
from bzrlib.bundle.apply_bundle import merge_bundle
 
30
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
30
31
from bzrlib.commands import Command, display_command
31
 
import bzrlib.errors as errors
32
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
33
33
                           NotBranchError, DivergedBranches, NotConflicted,
34
34
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
35
 
                           NotVersionedError, BadBundle)
36
 
from bzrlib.log import show_one_log
 
35
                           NotVersionedError, NotABundle)
37
36
from bzrlib.merge import Merge3Merger
38
37
from bzrlib.option import Option
39
38
from bzrlib.progress import DummyProgress, ProgressPhase
40
39
from bzrlib.revision import common_ancestor
41
40
from bzrlib.revisionspec import RevisionSpec
42
 
import bzrlib.trace
43
 
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
 
41
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
44
42
from bzrlib.transport.local import LocalTransport
45
 
import bzrlib.ui
 
43
import bzrlib.urlutils as urlutils
46
44
from bzrlib.workingtree import WorkingTree
47
45
 
48
46
 
90
88
        return bzrdir.BzrDirMetaFormat1()
91
89
    if typestring == "metaweave":
92
90
        format = bzrdir.BzrDirMetaFormat1()
93
 
        format.repository_format = bzrlib.repository.RepositoryFormat7()
 
91
        format.repository_format = repository.RepositoryFormat7()
94
92
        return format
95
93
    if typestring == "knit":
96
94
        format = bzrdir.BzrDirMetaFormat1()
97
 
        format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
 
95
        format.repository_format = repository.RepositoryFormatKnit1()
98
96
        return format
99
97
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
100
98
          "metaweave and weave" % typestring
128
126
    modified
129
127
        Text has changed since the previous revision.
130
128
 
131
 
    unchanged
132
 
        Nothing about this file has changed since the previous revision.
133
 
        Only shown with --all.
134
 
 
135
129
    unknown
136
130
        Not versioned and not matching an ignore pattern.
137
131
 
150
144
    # TODO: --no-recurse, --recurse options
151
145
    
152
146
    takes_args = ['file*']
153
 
    takes_options = ['all', 'show-ids', 'revision']
 
147
    takes_options = ['show-ids', 'revision']
154
148
    aliases = ['st', 'stat']
 
149
 
 
150
    encoding_type = 'replace'
155
151
    
156
152
    @display_command
157
 
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
158
 
        tree, file_list = tree_files(file_list)
159
 
            
 
153
    def run(self, show_ids=False, file_list=None, revision=None):
160
154
        from bzrlib.status import show_tree_status
161
 
        show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
162
 
                         specific_files=file_list, revision=revision)
 
155
 
 
156
        tree, file_list = tree_files(file_list)
 
157
            
 
158
        show_tree_status(tree, show_ids=show_ids,
 
159
                         specific_files=file_list, revision=revision,
 
160
                         to_file=self.outf)
163
161
 
164
162
 
165
163
class cmd_cat_revision(Command):
172
170
    hidden = True
173
171
    takes_args = ['revision_id?']
174
172
    takes_options = ['revision']
 
173
    # cat-revision is more for frontends so should be exact
 
174
    encoding = 'strict'
175
175
    
176
176
    @display_command
177
177
    def run(self, revision_id=None, revision=None):
181
181
        if revision_id is None and revision is None:
182
182
            raise BzrCommandError('You must supply either --revision or a revision_id')
183
183
        b = WorkingTree.open_containing(u'.')[0].branch
 
184
 
 
185
        # TODO: jam 20060112 should cat-revision always output utf-8?
184
186
        if revision_id is not None:
185
 
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
 
187
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
186
188
        elif revision is not None:
187
189
            for rev in revision:
188
190
                if rev is None:
189
191
                    raise BzrCommandError('You cannot specify a NULL revision.')
190
192
                revno, rev_id = rev.in_history(b)
191
 
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
 
193
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
192
194
    
193
195
 
194
196
class cmd_revno(Command):
195
197
    """Show current revision number.
196
198
 
197
 
    This is equal to the number of revisions on this branch."""
 
199
    This is equal to the number of revisions on this branch.
 
200
    """
 
201
 
198
202
    takes_args = ['location?']
 
203
 
199
204
    @display_command
200
205
    def run(self, location=u'.'):
201
 
        print Branch.open_containing(location)[0].revno()
 
206
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
 
207
        self.outf.write('\n')
202
208
 
203
209
 
204
210
class cmd_revision_info(Command):
207
213
    hidden = True
208
214
    takes_args = ['revision_info*']
209
215
    takes_options = ['revision']
 
216
 
210
217
    @display_command
211
218
    def run(self, revision=None, revision_info_list=[]):
212
219
 
249
256
 
250
257
    Adding a file whose parent directory is not versioned will
251
258
    implicitly add the parent, and so on up to the root. This means
252
 
    you should never need to explictly add a directory, they'll just
 
259
    you should never need to explicitly add a directory, they'll just
253
260
    get added when you add a file in the directory.
254
261
 
255
262
    --dry-run will show which files would be added, but not actually 
257
264
    """
258
265
    takes_args = ['file*']
259
266
    takes_options = ['no-recurse', 'dry-run', 'verbose']
 
267
    encoding_type = 'replace'
260
268
 
261
269
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
262
270
        import bzrlib.add
263
271
 
264
 
        if dry_run:
265
 
            if is_quiet():
266
 
                # This is pointless, but I'd rather not raise an error
267
 
                action = bzrlib.add.add_action_null
268
 
            else:
269
 
                action = bzrlib.add.add_action_print
270
 
        elif is_quiet():
271
 
            action = bzrlib.add.add_action_add
272
 
        else:
273
 
            action = bzrlib.add.add_action_add_and_print
 
272
        action = bzrlib.add.AddAction(to_file=self.outf,
 
273
            should_print=(not is_quiet()))
274
274
 
275
275
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
276
 
                                              action)
 
276
                                              action=action, save=not dry_run)
277
277
        if len(ignored) > 0:
278
278
            if verbose:
279
279
                for glob in sorted(ignored.keys()):
280
280
                    for path in ignored[glob]:
281
 
                        print "ignored %s matching \"%s\"" % (path, glob)
 
281
                        self.outf.write("ignored %s matching \"%s\"\n" 
 
282
                                        % (path, glob))
282
283
            else:
283
284
                match_len = 0
284
285
                for glob, paths in ignored.items():
285
286
                    match_len += len(paths)
286
 
                print "ignored %d file(s)." % match_len
287
 
            print "If you wish to add some of these files, please add them"\
288
 
                " by name."
 
287
                self.outf.write("ignored %d file(s).\n" % match_len)
 
288
            self.outf.write("If you wish to add some of these files,"
 
289
                            " please add them by name.\n")
289
290
 
290
291
 
291
292
class cmd_mkdir(Command):
293
294
 
294
295
    This is equivalent to creating the directory and then adding it.
295
296
    """
 
297
 
296
298
    takes_args = ['dir+']
 
299
    encoding_type = 'replace'
297
300
 
298
301
    def run(self, dir_list):
299
302
        for d in dir_list:
300
303
            os.mkdir(d)
301
304
            wt, dd = WorkingTree.open_containing(d)
302
305
            wt.add([dd])
303
 
            print 'added', d
 
306
            self.outf.write('added %s\n' % d)
304
307
 
305
308
 
306
309
class cmd_relpath(Command):
307
310
    """Show path of a file relative to root"""
 
311
 
308
312
    takes_args = ['filename']
309
313
    hidden = True
310
314
    
311
315
    @display_command
312
316
    def run(self, filename):
 
317
        # TODO: jam 20050106 Can relpath return a munged path if
 
318
        #       sys.stdout encoding cannot represent it?
313
319
        tree, relpath = WorkingTree.open_containing(filename)
314
 
        print relpath
 
320
        self.outf.write(relpath)
 
321
        self.outf.write('\n')
315
322
 
316
323
 
317
324
class cmd_inventory(Command):
320
327
    It is possible to limit the output to a particular entry
321
328
    type using the --kind option.  For example; --kind file.
322
329
    """
 
330
 
323
331
    takes_options = ['revision', 'show-ids', 'kind']
324
332
    
325
333
    @display_command
340
348
            if kind and kind != entry.kind:
341
349
                continue
342
350
            if show_ids:
343
 
                print '%-50s %s' % (path, entry.file_id)
 
351
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
344
352
            else:
345
 
                print path
 
353
                self.outf.write(path)
 
354
                self.outf.write('\n')
346
355
 
347
356
 
348
357
class cmd_mv(Command):
358
367
 
359
368
    Files cannot be moved between branches.
360
369
    """
 
370
 
361
371
    takes_args = ['names*']
362
372
    aliases = ['move', 'rename']
 
373
    encoding_type = 'replace'
363
374
 
364
375
    def run(self, names_list):
365
376
        if len(names_list) < 2:
369
380
        if os.path.isdir(names_list[-1]):
370
381
            # move into existing directory
371
382
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
372
 
                print "%s => %s" % pair
 
383
                self.outf.write("%s => %s\n" % pair)
373
384
        else:
374
385
            if len(names_list) != 2:
375
386
                raise BzrCommandError('to mv multiple files the destination '
376
387
                                      'must be a versioned directory')
377
388
            tree.rename_one(rel_names[0], rel_names[1])
378
 
            print "%s => %s" % (rel_names[0], rel_names[1])
 
389
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
379
390
            
380
391
    
381
392
class cmd_pull(Command):
398
409
 
399
410
    If there is no default location set, the first pull will set it.  After
400
411
    that, you can omit the location to use the default.  To change the
401
 
    default, use --remember.
 
412
    default, use --remember. The value will only be saved if the remote
 
413
    location can be accessed.
402
414
    """
 
415
 
403
416
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
404
417
    takes_args = ['location?']
 
418
    encoding_type = 'replace'
405
419
 
406
420
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
407
421
        # FIXME: too much stuff is in the command class
410
424
            branch_to = tree_to.branch
411
425
        except NoWorkingTree:
412
426
            tree_to = None
413
 
            branch_to = Branch.open_containing(u'.')[0] 
 
427
            branch_to = Branch.open_containing(u'.')[0]
 
428
 
 
429
        reader = None
 
430
        if location is not None:
 
431
            try:
 
432
                reader = bundle.read_bundle_from_url(location)
 
433
            except NotABundle:
 
434
                pass # Continue on considering this url a Branch
 
435
 
414
436
        stored_loc = branch_to.get_parent()
415
437
        if location is None:
416
438
            if stored_loc is None:
417
439
                raise BzrCommandError("No pull location known or specified.")
418
440
            else:
419
 
                print "Using saved location: %s" % stored_loc
 
441
                display_url = urlutils.unescape_for_display(stored_loc,
 
442
                        self.outf.encoding)
 
443
                self.outf.write("Using saved location: %s\n" % display_url)
420
444
                location = stored_loc
421
445
 
422
 
        if branch_to.get_parent() is None or remember:
423
 
            branch_to.set_parent(location)
424
 
 
425
 
        branch_from = Branch.open(location)
426
 
 
 
446
 
 
447
        if reader is not None:
 
448
            install_bundle(branch_to.repository, reader)
 
449
            branch_from = branch_to
 
450
        else:
 
451
            branch_from = Branch.open(location)
 
452
 
 
453
            if branch_to.get_parent() is None or remember:
 
454
                branch_to.set_parent(branch_from.base)
 
455
 
 
456
        rev_id = None
427
457
        if revision is None:
428
 
            rev_id = None
 
458
            if reader is not None:
 
459
                rev_id = reader.info.target
429
460
        elif len(revision) == 1:
430
461
            rev_id = revision[0].in_history(branch_from).rev_id
431
462
        else:
443
474
            if old_rh != new_rh:
444
475
                # Something changed
445
476
                from bzrlib.log import show_changed_revisions
446
 
                show_changed_revisions(branch_to, old_rh, new_rh)
 
477
                show_changed_revisions(branch_to, old_rh, new_rh,
 
478
                                       to_file=self.outf)
447
479
 
448
480
 
449
481
class cmd_push(Command):
468
500
 
469
501
    If there is no default push location set, the first push will set it.
470
502
    After that, you can omit the location to use the default.  To change the
471
 
    default, use --remember.
 
503
    default, use --remember. The value will only be saved if the remote
 
504
    location can be accessed.
472
505
    """
473
 
    takes_options = ['remember', 'overwrite', 
 
506
 
 
507
    takes_options = ['remember', 'overwrite', 'verbose',
474
508
                     Option('create-prefix', 
475
509
                            help='Create the path leading up to the branch '
476
510
                                 'if it does not already exist')]
477
511
    takes_args = ['location?']
 
512
    encoding_type = 'replace'
478
513
 
479
514
    def run(self, location=None, remember=False, overwrite=False,
480
515
            create_prefix=False, verbose=False):
488
523
            if stored_loc is None:
489
524
                raise BzrCommandError("No push location known or specified.")
490
525
            else:
491
 
                print "Using saved location: %s" % stored_loc
 
526
                display_url = urlutils.unescape_for_display(stored_loc,
 
527
                        self.outf.encoding)
 
528
                self.outf.write("Using saved location: %s\n" % display_url)
492
529
                location = stored_loc
493
 
        if br_from.get_push_location() is None or remember:
494
 
            br_from.set_push_location(location)
 
530
 
 
531
        transport = get_transport(location)
 
532
        location_url = transport.base
 
533
 
 
534
        old_rh = []
495
535
        try:
496
 
            dir_to = bzrlib.bzrdir.BzrDir.open(location)
 
536
            dir_to = bzrdir.BzrDir.open(location_url)
497
537
            br_to = dir_to.open_branch()
498
538
        except NotBranchError:
499
539
            # create a branch.
500
 
            transport = get_transport(location).clone('..')
 
540
            transport = transport.clone('..')
501
541
            if not create_prefix:
502
542
                try:
503
 
                    transport.mkdir(transport.relpath(location))
 
543
                    relurl = transport.relpath(location_url)
 
544
                    mutter('creating directory %s => %s', location_url, relurl)
 
545
                    transport.mkdir(relurl)
504
546
                except NoSuchFile:
505
547
                    raise BzrCommandError("Parent directory of %s "
506
548
                                          "does not exist." % location)
507
549
            else:
508
550
                current = transport.base
509
 
                needed = [(transport, transport.relpath(location))]
 
551
                needed = [(transport, transport.relpath(location_url))]
510
552
                while needed:
511
553
                    try:
512
554
                        transport, relpath = needed[-1]
519
561
                        if new_transport.base == transport.base:
520
562
                            raise BzrCommandError("Could not create "
521
563
                                                  "path prefix.")
522
 
            dir_to = br_from.bzrdir.clone(location,
 
564
            dir_to = br_from.bzrdir.clone(location_url,
523
565
                revision_id=br_from.last_revision())
524
566
            br_to = dir_to.open_branch()
525
567
            count = len(br_to.revision_history())
 
568
            # We successfully created the target, remember it
 
569
            if br_from.get_push_location() is None or remember:
 
570
                br_from.set_push_location(br_to.base)
526
571
        else:
 
572
            # We were able to connect to the remote location, so remember it
 
573
            # we don't need to successfully push because of possible divergence.
 
574
            if br_from.get_push_location() is None or remember:
 
575
                br_from.set_push_location(br_to.base)
527
576
            old_rh = br_to.revision_history()
528
577
            try:
529
578
                try:
546
595
            if old_rh != new_rh:
547
596
                # Something changed
548
597
                from bzrlib.log import show_changed_revisions
549
 
                show_changed_revisions(br_to, old_rh, new_rh)
 
598
                show_changed_revisions(br_to, old_rh, new_rh,
 
599
                                       to_file=self.outf)
550
600
 
551
601
 
552
602
class cmd_branch(Command):
567
617
    aliases = ['get', 'clone']
568
618
 
569
619
    def run(self, from_location, to_location=None, revision=None, basis=None):
570
 
        from bzrlib.osutils import rmtree
 
620
        from bzrlib.transport import get_transport
571
621
        if revision is None:
572
622
            revision = [None]
573
623
        elif len(revision) > 1:
599
649
                name = None
600
650
            else:
601
651
                name = os.path.basename(to_location) + '\n'
 
652
 
 
653
            to_transport = get_transport(to_location)
602
654
            try:
603
 
                os.mkdir(to_location)
604
 
            except OSError, e:
605
 
                if e.errno == errno.EEXIST:
606
 
                    raise BzrCommandError('Target directory "%s" already'
607
 
                                          ' exists.' % to_location)
608
 
                if e.errno == errno.ENOENT:
609
 
                    raise BzrCommandError('Parent of "%s" does not exist.' %
610
 
                                          to_location)
611
 
                else:
612
 
                    raise
 
655
                to_transport.mkdir('.')
 
656
            except errors.FileExists:
 
657
                raise BzrCommandError('Target directory "%s" already'
 
658
                                      ' exists.' % to_location)
 
659
            except errors.NoSuchFile:
 
660
                raise BzrCommandError('Parent of "%s" does not exist.' %
 
661
                                      to_location)
613
662
            try:
614
663
                # preserve whatever source format we have.
615
 
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
 
664
                dir = br_from.bzrdir.sprout(to_transport.base,
 
665
                        revision_id, basis_dir)
616
666
                branch = dir.open_branch()
617
 
            except bzrlib.errors.NoSuchRevision:
618
 
                rmtree(to_location)
 
667
            except errors.NoSuchRevision:
 
668
                to_transport.delete_tree('.')
619
669
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
620
670
                raise BzrCommandError(msg)
621
 
            except bzrlib.errors.UnlistableBranch:
622
 
                rmtree(to_location)
 
671
            except errors.UnlistableBranch:
 
672
                osutils.rmtree(to_location)
623
673
                msg = "The branch %s cannot be used as a --basis" % (basis,)
624
674
                raise BzrCommandError(msg)
625
675
            if name:
626
676
                branch.control_files.put_utf8('branch-name', name)
627
 
 
628
677
            note('Branched %d revision(s).' % branch.revno())
629
678
        finally:
630
679
            br_from.unlock()
669
718
            raise BzrCommandError(
670
719
                'bzr checkout --revision takes exactly 1 revision value')
671
720
        if branch_location is None:
672
 
            branch_location = bzrlib.osutils.getcwd()
 
721
            branch_location = osutils.getcwd()
673
722
            to_location = branch_location
674
723
        source = Branch.open(branch_location)
675
724
        if len(revision) == 1 and revision[0] is not None:
681
730
        # if the source and to_location are the same, 
682
731
        # and there is no working tree,
683
732
        # then reconstitute a branch
684
 
        if (bzrlib.osutils.abspath(to_location) == 
685
 
            bzrlib.osutils.abspath(branch_location)):
 
733
        if (osutils.abspath(to_location) == 
 
734
            osutils.abspath(branch_location)):
686
735
            try:
687
736
                source.bzrdir.open_workingtree()
688
737
            except errors.NoWorkingTree:
699
748
                                      to_location)
700
749
            else:
701
750
                raise
702
 
        old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
703
 
        bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
 
751
        old_format = bzrdir.BzrDirFormat.get_default_format()
 
752
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
704
753
        try:
705
754
            if lightweight:
706
755
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
707
 
                bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
 
756
                branch.BranchReferenceFormat().initialize(checkout, source)
708
757
            else:
709
 
                checkout_branch =  bzrlib.bzrdir.BzrDir.create_branch_convenience(
 
758
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
710
759
                    to_location, force_new_tree=False)
711
760
                checkout = checkout_branch.bzrdir
712
761
                checkout_branch.bind(source)
715
764
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
716
765
            checkout.create_workingtree(revision_id)
717
766
        finally:
718
 
            bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
 
767
            bzrdir.BzrDirFormat.set_default_format(old_format)
719
768
 
720
769
 
721
770
class cmd_renames(Command):
728
777
 
729
778
    @display_command
730
779
    def run(self, dir=u'.'):
 
780
        from bzrlib.tree import find_renames
731
781
        tree = WorkingTree.open_containing(dir)[0]
732
782
        old_inv = tree.basis_tree().inventory
733
783
        new_inv = tree.read_working_inventory()
734
 
 
735
 
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
 
784
        renames = list(find_renames(old_inv, new_inv))
736
785
        renames.sort()
737
786
        for old_name, new_name in renames:
738
 
            print "%s => %s" % (old_name, new_name)        
 
787
            self.outf.write("%s => %s\n" % (old_name, new_name))
739
788
 
740
789
 
741
790
class cmd_update(Command):
804
853
    takes_args = ['file*']
805
854
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
806
855
    aliases = ['rm']
 
856
    encoding_type = 'replace'
807
857
    
808
858
    def run(self, file_list, verbose=False, new=False):
809
859
        tree, file_list = tree_files(file_list)
818
868
            file_list = sorted([f[0] for f in added[0]], reverse=True)
819
869
            if len(file_list) == 0:
820
870
                raise BzrCommandError('No matching files.')
821
 
        tree.remove(file_list, verbose=verbose)
 
871
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
822
872
 
823
873
 
824
874
class cmd_file_id(Command):
828
878
    same through all revisions where the file exists, even when it is
829
879
    moved or renamed.
830
880
    """
 
881
 
831
882
    hidden = True
832
883
    takes_args = ['filename']
 
884
 
833
885
    @display_command
834
886
    def run(self, filename):
835
887
        tree, relpath = WorkingTree.open_containing(filename)
837
889
        if i == None:
838
890
            raise BzrError("%r is not a versioned file" % filename)
839
891
        else:
840
 
            print i
 
892
            self.outf.write(i + '\n')
841
893
 
842
894
 
843
895
class cmd_file_path(Command):
844
896
    """Print path of file_ids to a file or directory.
845
897
 
846
898
    This prints one line for each directory down to the target,
847
 
    starting at the branch root."""
 
899
    starting at the branch root.
 
900
    """
 
901
 
848
902
    hidden = True
849
903
    takes_args = ['filename']
 
904
 
850
905
    @display_command
851
906
    def run(self, filename):
852
907
        tree, relpath = WorkingTree.open_containing(filename)
855
910
        if fid == None:
856
911
            raise BzrError("%r is not a versioned file" % filename)
857
912
        for fip in inv.get_idpath(fid):
858
 
            print fip
 
913
            self.outf.write(fip + '\n')
859
914
 
860
915
 
861
916
class cmd_reconcile(Command):
880
935
 
881
936
    def run(self, branch="."):
882
937
        from bzrlib.reconcile import reconcile
883
 
        dir = bzrlib.bzrdir.BzrDir.open(branch)
 
938
        dir = bzrdir.BzrDir.open(branch)
884
939
        reconcile(dir)
885
940
 
886
941
 
887
942
class cmd_revision_history(Command):
888
 
    """Display list of revision ids on this branch."""
 
943
    """Display the list of revision ids on a branch."""
 
944
    takes_args = ['location?']
 
945
 
889
946
    hidden = True
 
947
 
890
948
    @display_command
891
 
    def run(self):
892
 
        branch = WorkingTree.open_containing(u'.')[0].branch
893
 
        for patchid in branch.revision_history():
894
 
            print patchid
 
949
    def run(self, location="."):
 
950
        branch = Branch.open_containing(location)[0]
 
951
        for revid in branch.revision_history():
 
952
            self.outf.write(revid)
 
953
            self.outf.write('\n')
895
954
 
896
955
 
897
956
class cmd_ancestry(Command):
898
957
    """List all revisions merged into this branch."""
 
958
    takes_args = ['location?']
 
959
 
899
960
    hidden = True
 
961
 
900
962
    @display_command
901
 
    def run(self):
902
 
        tree = WorkingTree.open_containing(u'.')[0]
903
 
        b = tree.branch
904
 
        # FIXME. should be tree.last_revision
905
 
        revision_ids = b.repository.get_ancestry(b.last_revision())
 
963
    def run(self, location="."):
 
964
        try:
 
965
            wt = WorkingTree.open_containing(location)[0]
 
966
        except errors.NoWorkingTree:
 
967
            b = Branch.open(location)
 
968
            last_revision = b.last_revision()
 
969
        else:
 
970
            b = wt.branch
 
971
            last_revision = wt.last_revision()
 
972
 
 
973
        revision_ids = b.repository.get_ancestry(last_revision)
906
974
        assert revision_ids[0] == None
907
975
        revision_ids.pop(0)
908
976
        for revision_id in revision_ids:
909
 
            print revision_id
 
977
            self.outf.write(revision_id + '\n')
910
978
 
911
979
 
912
980
class cmd_init(Command):
940
1008
                            type=get_format_type),
941
1009
                     ]
942
1010
    def run(self, location=None, format=None):
943
 
        from bzrlib.branch import Branch
944
1011
        if format is None:
945
1012
            format = get_format_type('default')
946
1013
        if location is None:
1037
1104
    takes_args = ['file*']
1038
1105
    takes_options = ['revision', 'diff-options', 'prefix']
1039
1106
    aliases = ['di', 'dif']
 
1107
    encoding_type = 'exact'
1040
1108
 
1041
1109
    @display_command
1042
1110
    def run(self, revision=None, file_list=None, diff_options=None,
1103
1171
    # directories with readdir, rather than stating each one.  Same
1104
1172
    # level of effort but possibly much less IO.  (Or possibly not,
1105
1173
    # if the directories are very large...)
 
1174
    takes_options = ['show-ids']
 
1175
 
1106
1176
    @display_command
1107
1177
    def run(self, show_ids=False):
1108
1178
        tree = WorkingTree.open_containing(u'.')[0]
1109
1179
        old = tree.basis_tree()
1110
1180
        for path, ie in old.inventory.iter_entries():
1111
1181
            if not tree.has_id(ie.file_id):
 
1182
                self.outf.write(path)
1112
1183
                if show_ids:
1113
 
                    print '%-50s %s' % (path, ie.file_id)
1114
 
                else:
1115
 
                    print path
 
1184
                    self.outf.write(' ')
 
1185
                    self.outf.write(ie.file_id)
 
1186
                self.outf.write('\n')
1116
1187
 
1117
1188
 
1118
1189
class cmd_modified(Command):
1126
1197
        td = compare_trees(tree.basis_tree(), tree)
1127
1198
 
1128
1199
        for path, id, kind, text_modified, meta_modified in td.modified:
1129
 
            print path
1130
 
 
 
1200
            self.outf.write(path + '\n')
1131
1201
 
1132
1202
 
1133
1203
class cmd_added(Command):
1142
1212
            if file_id in basis_inv:
1143
1213
                continue
1144
1214
            path = inv.id2path(file_id)
1145
 
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
 
1215
            if not os.access(osutils.abspath(path), os.F_OK):
1146
1216
                continue
1147
 
            print path
1148
 
                
1149
 
        
 
1217
            self.outf.write(path + '\n')
 
1218
 
1150
1219
 
1151
1220
class cmd_root(Command):
1152
1221
    """Show the tree root directory.
1158
1227
    def run(self, filename=None):
1159
1228
        """Print the branch root."""
1160
1229
        tree = WorkingTree.open_containing(filename)[0]
1161
 
        print tree.basedir
 
1230
        self.outf.write(tree.basedir + '\n')
1162
1231
 
1163
1232
 
1164
1233
class cmd_log(Command):
1192
1261
                            type=str),
1193
1262
                     'short',
1194
1263
                     ]
 
1264
    encoding_type = 'replace'
 
1265
 
1195
1266
    @display_command
1196
1267
    def run(self, location=None, timezone='original',
1197
1268
            verbose=False,
1204
1275
            short=False,
1205
1276
            line=False):
1206
1277
        from bzrlib.log import log_formatter, show_log
1207
 
        import codecs
1208
1278
        assert message is None or isinstance(message, basestring), \
1209
1279
            "invalid message argument %r" % message
1210
1280
        direction = (forward and 'forward') or 'reverse'
1256
1326
        if rev1 > rev2:
1257
1327
            (rev2, rev1) = (rev1, rev2)
1258
1328
 
1259
 
        mutter('encoding log as %r', bzrlib.user_encoding)
1260
 
 
1261
 
        # use 'replace' so that we don't abort if trying to write out
1262
 
        # in e.g. the default C locale.
1263
 
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1264
 
 
1265
1329
        if (log_format == None):
1266
 
            default = bzrlib.config.BranchConfig(b).log_format()
 
1330
            default = config.BranchConfig(b).log_format()
1267
1331
            log_format = get_log_format(long=long, short=short, line=line, default=default)
1268
 
 
1269
1332
        lf = log_formatter(log_format,
1270
1333
                           show_ids=show_ids,
1271
 
                           to_file=outf,
 
1334
                           to_file=self.outf,
1272
1335
                           show_timezone=timezone)
1273
1336
 
1274
1337
        show_log(b,
1295
1358
class cmd_touching_revisions(Command):
1296
1359
    """Return revision-ids which affected a particular file.
1297
1360
 
1298
 
    A more user-friendly interface is "bzr log FILE"."""
 
1361
    A more user-friendly interface is "bzr log FILE".
 
1362
    """
 
1363
 
1299
1364
    hidden = True
1300
1365
    takes_args = ["filename"]
 
1366
 
1301
1367
    @display_command
1302
1368
    def run(self, filename):
1303
1369
        tree, relpath = WorkingTree.open_containing(filename)
1304
1370
        b = tree.branch
1305
1371
        inv = tree.read_working_inventory()
1306
1372
        file_id = inv.path2id(relpath)
1307
 
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1308
 
            print "%6d %s" % (revno, what)
 
1373
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
 
1374
            self.outf.write("%6d %s\n" % (revno, what))
1309
1375
 
1310
1376
 
1311
1377
class cmd_ls(Command):
1344
1410
        if revision is not None:
1345
1411
            tree = tree.branch.repository.revision_tree(
1346
1412
                revision[0].in_history(tree.branch).rev_id)
 
1413
 
1347
1414
        for fp, fc, kind, fid, entry in tree.list_files():
1348
1415
            if fp.startswith(relpath):
1349
1416
                fp = fp[len(relpath):]
1353
1420
                    continue
1354
1421
                if verbose:
1355
1422
                    kindch = entry.kind_character()
1356
 
                    print '%-8s %s%s' % (fc, fp, kindch)
 
1423
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
1357
1424
                elif null:
1358
 
                    sys.stdout.write(fp)
1359
 
                    sys.stdout.write('\0')
1360
 
                    sys.stdout.flush()
 
1425
                    self.outf.write(fp + '\0')
 
1426
                    self.outf.flush()
1361
1427
                else:
1362
 
                    print fp
 
1428
                    self.outf.write(fp + '\n')
1363
1429
 
1364
1430
 
1365
1431
class cmd_unknowns(Command):
1366
1432
    """List unknown files."""
1367
1433
    @display_command
1368
1434
    def run(self):
1369
 
        from bzrlib.osutils import quotefn
1370
1435
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1371
 
            print quotefn(f)
 
1436
            self.outf.write(osutils.quotefn(f) + '\n')
1372
1437
 
1373
1438
 
1374
1439
class cmd_ignore(Command):
1538
1603
    hidden = True    
1539
1604
    @display_command
1540
1605
    def run(self):
1541
 
        print bzrlib.osutils.local_time_offset()
 
1606
        print osutils.local_time_offset()
1542
1607
 
1543
1608
 
1544
1609
 
1591
1656
        from bzrlib.msgeditor import edit_commit_message, \
1592
1657
                make_commit_message_template
1593
1658
        from tempfile import TemporaryFile
1594
 
        import codecs
1595
1659
 
1596
1660
        # TODO: Need a blackbox test for invoking the external editor; may be
1597
1661
        # slightly problematic to run this cross-platform.
1620
1684
            raise BzrCommandError("please specify either --message or --file")
1621
1685
        
1622
1686
        if file:
1623
 
            import codecs
1624
1687
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1625
1688
 
1626
1689
        if message == "":
1627
 
                raise BzrCommandError("empty commit message specified")
 
1690
            raise BzrCommandError("empty commit message specified")
1628
1691
        
1629
1692
        if verbose:
1630
1693
            reporter = ReportCommitToLog()
1723
1786
    def run(self, email=False):
1724
1787
        try:
1725
1788
            b = WorkingTree.open_containing(u'.')[0].branch
1726
 
            config = bzrlib.config.BranchConfig(b)
 
1789
            c = config.BranchConfig(b)
1727
1790
        except NotBranchError:
1728
 
            config = bzrlib.config.GlobalConfig()
1729
 
        
 
1791
            c = config.GlobalConfig()
1730
1792
        if email:
1731
 
            print config.user_email()
 
1793
            print c.user_email()
1732
1794
        else:
1733
 
            print config.username()
 
1795
            print c.username()
1734
1796
 
1735
1797
 
1736
1798
class cmd_nick(Command):
1816
1878
        # we don't want progress meters from the tests to go to the
1817
1879
        # real output; and we don't want log messages cluttering up
1818
1880
        # the real logs.
1819
 
        save_ui = bzrlib.ui.ui_factory
1820
 
        print '%10s: %s' % ('bzr', bzrlib.osutils.realpath(sys.argv[0]))
 
1881
        save_ui = ui.ui_factory
 
1882
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1821
1883
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1822
1884
        print
1823
 
        bzrlib.trace.info('running tests...')
 
1885
        info('running tests...')
1824
1886
        try:
1825
 
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
1887
            ui.ui_factory = ui.SilentUIFactory()
1826
1888
            if testspecs_list is not None:
1827
1889
                pattern = '|'.join(testspecs_list)
1828
1890
            else:
1843
1905
                              test_suite_factory=test_suite_factory,
1844
1906
                              lsprof_timed=lsprof_timed)
1845
1907
            if result:
1846
 
                bzrlib.trace.info('tests passed')
 
1908
                info('tests passed')
1847
1909
            else:
1848
 
                bzrlib.trace.info('tests failed')
 
1910
                info('tests failed')
1849
1911
            return int(not result)
1850
1912
        finally:
1851
 
            bzrlib.ui.ui_factory = save_ui
 
1913
            ui.ui_factory = save_ui
1852
1914
 
1853
1915
 
1854
1916
def _get_bzr_branch():
1855
1917
    """If bzr is run from a branch, return Branch or None"""
1856
 
    import bzrlib.errors
1857
 
    from bzrlib.branch import Branch
1858
 
    from bzrlib.osutils import abspath
1859
1918
    from os.path import dirname
1860
1919
    
1861
1920
    try:
1862
 
        branch = Branch.open(dirname(abspath(dirname(__file__))))
 
1921
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1863
1922
        return branch
1864
 
    except bzrlib.errors.BzrError:
 
1923
    except errors.BzrError:
1865
1924
        return None
1866
1925
    
1867
1926
 
1868
1927
def show_version():
 
1928
    import bzrlib
1869
1929
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
1870
1930
    # is bzrlib itself in a branch?
1871
1931
    branch = _get_bzr_branch()
1937
1997
        base_rev_id = common_ancestor(last1, last2, source)
1938
1998
 
1939
1999
        print 'merge base is revision %s' % base_rev_id
1940
 
        
1941
 
        return
1942
 
 
1943
 
        if base_revno is None:
1944
 
            raise bzrlib.errors.UnrelatedBranches()
1945
 
 
1946
 
        print ' r%-6d in %s' % (base_revno, branch)
1947
 
 
1948
 
        other_revno = branch2.revision_id_to_revno(base_revid)
1949
 
        
1950
 
        print ' r%-6d in %s' % (other_revno, other)
1951
 
 
1952
2000
 
1953
2001
 
1954
2002
class cmd_merge(Command):
1955
2003
    """Perform a three-way merge.
1956
2004
    
1957
 
    The branch is the branch you will merge from.  By default, it will
1958
 
    merge the latest revision.  If you specify a revision, that
1959
 
    revision will be merged.  If you specify two revisions, the first
1960
 
    will be used as a BASE, and the second one as OTHER.  Revision
1961
 
    numbers are always relative to the specified branch.
 
2005
    The branch is the branch you will merge from.  By default, it will merge
 
2006
    the latest revision.  If you specify a revision, that revision will be
 
2007
    merged.  If you specify two revisions, the first will be used as a BASE,
 
2008
    and the second one as OTHER.  Revision numbers are always relative to the
 
2009
    specified branch.
1962
2010
 
1963
2011
    By default, bzr will try to merge in all new work from the other
1964
2012
    branch, automatically determining an appropriate base.  If this
1973
2021
 
1974
2022
    If there is no default branch set, the first merge will set it. After
1975
2023
    that, you can omit the branch to use the default.  To change the
1976
 
    default, use --remember.
 
2024
    default, use --remember. The value will only be saved if the remote
 
2025
    location can be accessed.
1977
2026
 
1978
2027
    Examples:
1979
2028
 
2006
2055
        if merge_type is None:
2007
2056
            merge_type = Merge3Merger
2008
2057
 
2009
 
 
2010
2058
        tree = WorkingTree.open_containing(u'.')[0]
2011
 
        try:
2012
 
            if branch is not None:
2013
 
                reader = BundleReader(file(branch, 'rb'))
2014
 
            else:
2015
 
                reader = None
2016
 
        except IOError, e:
2017
 
            if e.errno not in (errno.ENOENT, errno.EISDIR):
2018
 
                raise
2019
 
            reader = None
2020
 
        except BadBundle:
2021
 
            reader = None
2022
 
        if reader is not None:
2023
 
            conflicts = merge_bundle(reader, tree, not force, merge_type,
2024
 
                                        reprocess, show_base)
2025
 
            if conflicts == 0:
2026
 
                return 0
2027
 
            else:
2028
 
                return 1
2029
 
 
2030
 
        stored_loc = tree.branch.get_parent()
2031
 
        if branch is None:
2032
 
            if stored_loc is None:
2033
 
                raise BzrCommandError("No merge branch known or specified.")
2034
 
            else:
2035
 
                print "Using saved branch: %s" % stored_loc
2036
 
                branch = stored_loc
2037
 
 
2038
 
        if tree.branch.get_parent() is None or remember:
2039
 
            tree.branch.set_parent(branch)
 
2059
 
 
2060
        if branch is not None:
 
2061
            try:
 
2062
                reader = bundle.read_bundle_from_url(branch)
 
2063
            except NotABundle:
 
2064
                pass # Continue on considering this url a Branch
 
2065
            else:
 
2066
                conflicts = merge_bundle(reader, tree, not force, merge_type,
 
2067
                                            reprocess, show_base)
 
2068
                if conflicts == 0:
 
2069
                    return 0
 
2070
                else:
 
2071
                    return 1
 
2072
 
 
2073
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
2040
2074
 
2041
2075
        if revision is None or len(revision) < 1:
2042
2076
            base = [None, None]
2053
2087
                if None in revision:
2054
2088
                    raise BzrCommandError(
2055
2089
                        "Merge doesn't permit that revision specifier.")
2056
 
                b, path = Branch.open_containing(branch)
2057
 
 
2058
 
                base = [branch, revision[0].in_history(b).revno]
2059
 
                other = [branch, revision[1].in_history(b).revno]
 
2090
                other_branch, path = Branch.open_containing(branch)
 
2091
 
 
2092
                base = [branch, revision[0].in_history(other_branch).revno]
 
2093
                other = [branch, revision[1].in_history(other_branch).revno]
 
2094
 
 
2095
        if tree.branch.get_parent() is None or remember:
 
2096
            tree.branch.set_parent(other_branch.base)
 
2097
 
2060
2098
        if path != "":
2061
2099
            interesting_files = [path]
2062
2100
        else:
2063
2101
            interesting_files = None
2064
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
2102
        pb = ui.ui_factory.nested_progress_bar()
2065
2103
        try:
2066
2104
            try:
2067
2105
                conflict_count = merge(other, base, check_clean=(not force),
2068
 
                                       merge_type=merge_type, 
 
2106
                                       merge_type=merge_type,
2069
2107
                                       reprocess=reprocess,
2070
 
                                       show_base=show_base, 
 
2108
                                       show_base=show_base,
2071
2109
                                       pb=pb, file_list=interesting_files)
2072
2110
            finally:
2073
2111
                pb.finished()
2075
2113
                return 1
2076
2114
            else:
2077
2115
                return 0
2078
 
        except bzrlib.errors.AmbiguousBase, e:
 
2116
        except errors.AmbiguousBase, e:
2079
2117
            m = ("sorry, bzr can't determine the right merge base yet\n"
2080
2118
                 "candidates are:\n  "
2081
2119
                 + "\n  ".join(e.bases)
2084
2122
                 "and (if you want) report this to the bzr developers\n")
2085
2123
            log_error(m)
2086
2124
 
 
2125
    # TODO: move up to common parent; this isn't merge-specific anymore. 
 
2126
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
 
2127
        """Use tree.branch's parent if none was supplied.
 
2128
 
 
2129
        Report if the remembered location was used.
 
2130
        """
 
2131
        if supplied_location is not None:
 
2132
            return supplied_location
 
2133
        stored_location = tree.branch.get_parent()
 
2134
        mutter("%s", stored_location)
 
2135
        if stored_location is None:
 
2136
            raise BzrCommandError("No location specified or remembered")
 
2137
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
 
2138
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
 
2139
        return stored_location
 
2140
 
2087
2141
 
2088
2142
class cmd_remerge(Command):
2089
2143
    """Redo a merge.
2198
2252
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2199
2253
        else:
2200
2254
            rev_id = revision[0].in_history(tree.branch).rev_id
2201
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
2255
        pb = ui.ui_factory.nested_progress_bar()
2202
2256
        try:
2203
2257
            tree.revert(file_list, 
2204
2258
                        tree.branch.repository.revision_tree(rev_id),
2252
2306
    takes_args = ['from_branch', 'to_branch']
2253
2307
    def run(self, from_branch, to_branch):
2254
2308
        from bzrlib.fetch import Fetcher
2255
 
        from bzrlib.branch import Branch
2256
2309
        from_b = Branch.open(from_branch)
2257
2310
        to_b = Branch.open(to_branch)
2258
2311
        Fetcher(to_b, from_b)
2281
2334
            show_ids=False, verbose=False):
2282
2335
        from bzrlib.missing import find_unmerged, iter_log_data
2283
2336
        from bzrlib.log import log_formatter
2284
 
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
 
2337
        local_branch = Branch.open_containing(u".")[0]
2285
2338
        parent = local_branch.get_parent()
2286
2339
        if other_branch is None:
2287
2340
            other_branch = parent
2288
2341
            if other_branch is None:
2289
2342
                raise BzrCommandError("No missing location known or specified.")
2290
2343
            print "Using last location: " + local_branch.get_parent()
2291
 
        remote_branch = bzrlib.branch.Branch.open(other_branch)
 
2344
        remote_branch = Branch.open(other_branch)
2292
2345
        if remote_branch.base == local_branch.base:
2293
2346
            remote_branch = local_branch
2294
2347
        local_branch.lock_read()
2297
2350
            try:
2298
2351
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2299
2352
                if (log_format == None):
2300
 
                    default = bzrlib.config.BranchConfig(local_branch).log_format()
 
2353
                    default = config.BranchConfig(local_branch).log_format()
2301
2354
                    log_format = get_log_format(long=long, short=short, line=line, default=default)
2302
2355
                lf = log_formatter(log_format, sys.stdout,
2303
2356
                                   show_ids=show_ids,
2334
2387
            try:
2335
2388
                # handle race conditions - a parent might be set while we run.
2336
2389
                if local_branch.get_parent() is None:
2337
 
                    local_branch.set_parent(other_branch)
 
2390
                    local_branch.set_parent(remote_branch.base)
2338
2391
            finally:
2339
2392
                local_branch.unlock()
2340
2393
        return status_code
2362
2415
 
2363
2416
class cmd_testament(Command):
2364
2417
    """Show testament (signing-form) of a revision."""
2365
 
    takes_options = ['revision', 'long']
 
2418
    takes_options = ['revision', 'long', 
 
2419
                     Option('strict', help='Produce a strict testament')]
2366
2420
    takes_args = ['branch?']
2367
2421
    @display_command
2368
 
    def run(self, branch=u'.', revision=None, long=False):
2369
 
        from bzrlib.testament import Testament
 
2422
    def run(self, branch=u'.', revision=None, long=False, strict=False):
 
2423
        from bzrlib.testament import Testament, StrictTestament
 
2424
        if strict is True:
 
2425
            testament_class = StrictTestament
 
2426
        else:
 
2427
            testament_class = Testament
2370
2428
        b = WorkingTree.open_containing(branch)[0].branch
2371
2429
        b.lock_read()
2372
2430
        try:
2374
2432
                rev_id = b.last_revision()
2375
2433
            else:
2376
2434
                rev_id = revision[0].in_history(b).rev_id
2377
 
            t = Testament.from_revision(b.repository, rev_id)
 
2435
            t = testament_class.from_revision(b.repository, rev_id)
2378
2436
            if long:
2379
2437
                sys.stdout.writelines(t.as_text_lines())
2380
2438
            else:
2432
2490
    takes_options = ['revision']
2433
2491
    
2434
2492
    def run(self, revision_id_list=None, revision=None):
2435
 
        import bzrlib.config as config
2436
2493
        import bzrlib.gpg as gpg
2437
2494
        if revision_id_list is not None and revision is not None:
2438
2495
            raise BzrCommandError('You can only supply one of revision_id or --revision')
2500
2557
            raise BzrCommandError('Local branch is not bound')
2501
2558
 
2502
2559
 
2503
 
class cmd_uncommit(bzrlib.commands.Command):
 
2560
class cmd_uncommit(Command):
2504
2561
    """Remove the last committed revision.
2505
2562
 
2506
2563
    --verbose will print out what is being removed.
2512
2569
    """
2513
2570
 
2514
2571
    # TODO: jam 20060108 Add an option to allow uncommit to remove
2515
 
    # unreferenced information in 'branch-as-repostory' branches.
 
2572
    # unreferenced information in 'branch-as-repository' branches.
2516
2573
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2517
2574
    # information in shared branches as well.
2518
2575
    takes_options = ['verbose', 'revision',
2524
2581
    def run(self, location=None, 
2525
2582
            dry_run=False, verbose=False,
2526
2583
            revision=None, force=False):
2527
 
        from bzrlib.branch import Branch
2528
2584
        from bzrlib.log import log_formatter
2529
2585
        import sys
2530
2586
        from bzrlib.uncommit import uncommit