~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

[merge] bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
from bzrlib.commands import Command, display_command
28
28
from bzrlib.branch import Branch
29
29
from bzrlib.revision import common_ancestor
 
30
import bzrlib.errors as errors
30
31
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
31
32
                           NotBranchError, DivergedBranches, NotConflicted,
32
 
                           NoSuchFile, NoWorkingTree, FileInWrongBranch)
 
33
                           NoSuchFile, NoWorkingTree, FileInWrongBranch)
33
34
from bzrlib.option import Option
34
35
from bzrlib.revisionspec import RevisionSpec
35
36
import bzrlib.trace
36
 
from bzrlib.trace import mutter, note, log_error, warning
 
37
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
37
38
from bzrlib.workingtree import WorkingTree
38
39
 
39
40
 
40
 
def branch_files(file_list, default_branch='.'):
 
41
def tree_files(file_list, default_branch=u'.'):
41
42
    try:
42
 
        return inner_branch_files(file_list, default_branch)
 
43
        return internal_tree_files(file_list, default_branch)
43
44
    except FileInWrongBranch, e:
44
 
        print file_list
45
45
        raise BzrCommandError("%s is not in the same branch as %s" %
46
46
                             (e.path, file_list[0]))
47
47
 
48
 
def inner_branch_files(file_list, default_branch='.'):
 
48
def internal_tree_files(file_list, default_branch=u'.'):
49
49
    """\
50
50
    Return a branch and list of branch-relative paths.
51
51
    If supplied file_list is empty or None, the branch default will be used,
52
52
    and returned file_list will match the original.
53
53
    """
54
54
    if file_list is None or len(file_list) == 0:
55
 
        return Branch.open_containing(default_branch)[0], file_list
56
 
    b = Branch.open_containing(file_list[0])[0]
57
 
    
58
 
    # note that if this is a remote branch, we would want
59
 
    # relpath against the transport. RBC 20051018
60
 
    # Most branch ops can't meaningfully operate on files in remote branches;
61
 
    # the above comment was in cmd_status.  ADHB 20051026
62
 
    tree = WorkingTree(b.base, b)
 
55
        return WorkingTree.open_containing(default_branch)[0], file_list
 
56
    tree = WorkingTree.open_containing(file_list[0])[0]
63
57
    new_list = []
64
58
    for filename in file_list:
65
59
        try:
66
60
            new_list.append(tree.relpath(filename))
67
61
        except NotBranchError:
68
 
            raise FileInWrongBranch(b, filename)
69
 
    return b, new_list
 
62
            raise FileInWrongBranch(tree.branch, filename)
 
63
    return tree, new_list
70
64
 
71
65
 
72
66
# TODO: Make sure no commands unconditionally use the working directory as a
123
117
    
124
118
    @display_command
125
119
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
126
 
        b, file_list = branch_files(file_list)
 
120
        tree, file_list = tree_files(file_list)
127
121
            
128
122
        from bzrlib.status import show_status
129
 
        show_status(b, show_unchanged=all, show_ids=show_ids,
 
123
        show_status(tree.branch, show_unchanged=all, show_ids=show_ids,
130
124
                    specific_files=file_list, revision=revision)
131
125
 
132
126
 
148
142
            raise BzrCommandError('You can only supply one of revision_id or --revision')
149
143
        if revision_id is None and revision is None:
150
144
            raise BzrCommandError('You must supply either --revision or a revision_id')
151
 
        b = Branch.open_containing('.')[0]
 
145
        b = WorkingTree.open_containing(u'.')[0].branch
152
146
        if revision_id is not None:
153
 
            sys.stdout.write(b.get_revision_xml_file(revision_id).read())
 
147
            sys.stdout.write(b.get_revision_xml(revision_id))
154
148
        elif revision is not None:
155
149
            for rev in revision:
156
150
                if rev is None:
157
151
                    raise BzrCommandError('You cannot specify a NULL revision.')
158
152
                revno, rev_id = rev.in_history(b)
159
 
                sys.stdout.write(b.get_revision_xml_file(rev_id).read())
 
153
                sys.stdout.write(b.get_revision_xml(rev_id))
160
154
    
161
155
 
162
156
class cmd_revno(Command):
165
159
    This is equal to the number of revisions on this branch."""
166
160
    @display_command
167
161
    def run(self):
168
 
        print Branch.open_containing('.')[0].revno()
 
162
        print Branch.open_containing(u'.')[0].revno()
169
163
 
170
164
 
171
165
class cmd_revision_info(Command):
186
180
        if len(revs) == 0:
187
181
            raise BzrCommandError('You must supply a revision identifier')
188
182
 
189
 
        b = Branch.open_containing('.')[0]
 
183
        b = WorkingTree.open_containing(u'.')[0].branch
190
184
 
191
185
        for rev in revs:
192
186
            revinfo = rev.in_history(b)
220
214
    get added when you add a file in the directory.
221
215
    """
222
216
    takes_args = ['file*']
223
 
    takes_options = ['no-recurse', 'quiet']
 
217
    takes_options = ['no-recurse']
224
218
    
225
 
    def run(self, file_list, no_recurse=False, quiet=False):
 
219
    def run(self, file_list, no_recurse=False):
226
220
        from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
227
 
        if quiet:
 
221
        if is_quiet():
228
222
            reporter = add_reporter_null
229
223
        else:
230
224
            reporter = add_reporter_print
239
233
    takes_args = ['dir+']
240
234
 
241
235
    def run(self, dir_list):
242
 
        b = None
243
 
        
244
236
        for d in dir_list:
245
237
            os.mkdir(d)
246
 
            b, dd = Branch.open_containing(d)
247
 
            b.add([dd])
 
238
            wt, dd = WorkingTree.open_containing(d)
 
239
            wt.add([dd])
248
240
            print 'added', d
249
241
 
250
242
 
255
247
    
256
248
    @display_command
257
249
    def run(self, filename):
258
 
        branch, relpath = Branch.open_containing(filename)
 
250
        tree, relpath = WorkingTree.open_containing(filename)
259
251
        print relpath
260
252
 
261
253
 
262
254
class cmd_inventory(Command):
263
 
    """Show inventory of the current working copy or a revision."""
264
 
    takes_options = ['revision', 'show-ids']
 
255
    """Show inventory of the current working copy or a revision.
 
256
 
 
257
    It is possible to limit the output to a particular entry
 
258
    type using the --kind option.  For example; --kind file.
 
259
    """
 
260
    takes_options = ['revision', 'show-ids', 'kind']
265
261
    
266
262
    @display_command
267
 
    def run(self, revision=None, show_ids=False):
268
 
        b = Branch.open_containing('.')[0]
 
263
    def run(self, revision=None, show_ids=False, kind=None):
 
264
        if kind and kind not in ['file', 'directory', 'symlink']:
 
265
            raise BzrCommandError('invalid kind specified')
 
266
        tree = WorkingTree.open_containing(u'.')[0]
269
267
        if revision is None:
270
 
            inv = b.working_tree().read_working_inventory()
 
268
            inv = tree.read_working_inventory()
271
269
        else:
272
270
            if len(revision) > 1:
273
271
                raise BzrCommandError('bzr inventory --revision takes'
274
272
                    ' exactly one revision identifier')
275
 
            inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
 
273
            inv = tree.branch.get_revision_inventory(
 
274
                revision[0].in_history(tree.branch).rev_id)
276
275
 
277
276
        for path, entry in inv.entries():
 
277
            if kind and kind != entry.kind:
 
278
                continue
278
279
            if show_ids:
279
280
                print '%-50s %s' % (path, entry.file_id)
280
281
            else:
291
292
    """
292
293
    takes_args = ['source$', 'dest']
293
294
    def run(self, source_list, dest):
294
 
        b, source_list = branch_files(source_list)
295
 
 
 
295
        tree, source_list = tree_files(source_list)
296
296
        # TODO: glob expansion on windows?
297
 
        tree = WorkingTree(b.base, b)
298
 
        b.move(source_list, tree.relpath(dest))
 
297
        tree.move(source_list, tree.relpath(dest))
299
298
 
300
299
 
301
300
class cmd_rename(Command):
315
314
    takes_args = ['from_name', 'to_name']
316
315
    
317
316
    def run(self, from_name, to_name):
318
 
        b, (from_name, to_name) = branch_files((from_name, to_name))
319
 
        b.rename_one(from_name, to_name)
 
317
        tree, (from_name, to_name) = tree_files((from_name, to_name))
 
318
        tree.rename_one(from_name, to_name)
320
319
 
321
320
 
322
321
class cmd_mv(Command):
336
335
    def run(self, names_list):
337
336
        if len(names_list) < 2:
338
337
            raise BzrCommandError("missing file argument")
339
 
        b, rel_names = branch_files(names_list)
 
338
        tree, rel_names = tree_files(names_list)
340
339
        
341
340
        if os.path.isdir(names_list[-1]):
342
341
            # move into existing directory
343
 
            for pair in b.move(rel_names[:-1], rel_names[-1]):
 
342
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
344
343
                print "%s => %s" % pair
345
344
        else:
346
345
            if len(names_list) != 2:
347
346
                raise BzrCommandError('to mv multiple files the destination '
348
347
                                      'must be a versioned directory')
349
 
            b.rename_one(rel_names[0], rel_names[1])
 
348
            tree.rename_one(rel_names[0], rel_names[1])
350
349
            print "%s => %s" % (rel_names[0], rel_names[1])
351
350
            
352
351
    
375
374
        from bzrlib.merge import merge
376
375
        from shutil import rmtree
377
376
        import errno
378
 
        
379
 
        br_to = Branch.open_containing('.')[0]
380
 
        stored_loc = br_to.get_parent()
 
377
        # FIXME: too much stuff is in the command class        
 
378
        tree_to = WorkingTree.open_containing(u'.')[0]
 
379
        stored_loc = tree_to.branch.get_parent()
381
380
        if location is None:
382
381
            if stored_loc is None:
383
382
                raise BzrCommandError("No pull location known or specified.")
385
384
                print "Using saved location: %s" % stored_loc
386
385
                location = stored_loc
387
386
        br_from = Branch.open(location)
 
387
        br_to = tree_to.branch
388
388
        try:
389
389
            old_rh = br_to.revision_history()
390
 
            count = br_to.working_tree().pull(br_from, overwrite)
 
390
            count = tree_to.pull(br_from, overwrite)
391
391
        except DivergedBranches:
 
392
            # FIXME: Just make DivergedBranches display the right message
 
393
            # itself.
392
394
            raise BzrCommandError("These branches have diverged."
393
395
                                  "  Try merge.")
394
396
        if br_to.get_parent() is None or remember:
395
397
            br_to.set_parent(location)
396
 
        if count:
397
 
            note('%d revision(s) pushed.' % (count,))
398
 
        else:
399
 
            note('No revisions pushed.')
 
398
        note('%d revision(s) pulled.', count)
400
399
 
401
400
        if verbose:
402
 
            new_rh = br_to.revision_history()
 
401
            new_rh = tree_to.branch.revision_history()
403
402
            if old_rh != new_rh:
404
403
                # Something changed
405
404
                from bzrlib.log import show_changed_revisions
406
 
                show_changed_revisions(br_to, old_rh, new_rh)
 
405
                show_changed_revisions(tree_to.branch, old_rh, new_rh)
407
406
 
408
407
 
409
408
class cmd_push(Command):
437
436
 
438
437
    def run(self, location=None, remember=False, overwrite=False,
439
438
            create_prefix=False, verbose=False):
 
439
        # FIXME: Way too big!  Put this into a function called from the
 
440
        # command.
440
441
        import errno
441
442
        from shutil import rmtree
442
443
        from bzrlib.transport import get_transport
443
444
        
444
 
        br_from = Branch.open_containing('.')[0]
445
 
        stored_loc = br_from.get_push_location()
 
445
        tree_from = WorkingTree.open_containing(u'.')[0]
 
446
        br_from = tree_from.branch
 
447
        stored_loc = tree_from.branch.get_push_location()
446
448
        if location is None:
447
449
            if stored_loc is None:
448
450
                raise BzrCommandError("No push location known or specified.")
475
477
                        if new_transport.base == transport.base:
476
478
                            raise BzrCommandError("Could not creeate "
477
479
                                                  "path prefix.")
478
 
                        
479
 
            NoSuchFile
480
480
            br_to = Branch.initialize(location)
481
481
        try:
482
482
            old_rh = br_to.revision_history()
486
486
                                  "  Try a merge then push with overwrite.")
487
487
        if br_from.get_push_location() is None or remember:
488
488
            br_from.set_push_location(location)
489
 
        if count:
490
 
            note('%d revision(s) pushed.' % (count,))
491
 
        else:
492
 
            note('No revisions pushed.')
 
489
        note('%d revision(s) pushed.' % (count,))
493
490
 
494
491
        if verbose:
495
492
            new_rh = br_to.revision_history()
498
495
                from bzrlib.log import show_changed_revisions
499
496
                show_changed_revisions(br_to, old_rh, new_rh)
500
497
 
 
498
 
501
499
class cmd_branch(Command):
502
500
    """Create a new copy of a branch.
503
501
 
535
533
        br_from.lock_read()
536
534
        try:
537
535
            if basis is not None:
538
 
                basis_branch = Branch.open_containing(basis)[0]
 
536
                basis_branch = WorkingTree.open_containing(basis)[0].branch
539
537
            else:
540
538
                basis_branch = None
541
539
            if len(revision) == 1 and revision[0] is not None:
586
584
    takes_args = ['dir?']
587
585
 
588
586
    @display_command
589
 
    def run(self, dir='.'):
590
 
        b = Branch.open_containing(dir)[0]
591
 
        old_inv = b.basis_tree().inventory
592
 
        new_inv = b.working_tree().read_working_inventory()
 
587
    def run(self, dir=u'.'):
 
588
        tree = WorkingTree.open_containing(dir)[0]
 
589
        old_inv = tree.branch.basis_tree().inventory
 
590
        new_inv = tree.read_working_inventory()
593
591
 
594
592
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
595
593
        renames.sort()
604
602
    @display_command
605
603
    def run(self, branch=None):
606
604
        import info
607
 
        b = Branch.open_containing(branch)[0]
 
605
        b = WorkingTree.open_containing(branch)[0].branch
608
606
        info.show_info(b)
609
607
 
610
608
 
619
617
    aliases = ['rm']
620
618
    
621
619
    def run(self, file_list, verbose=False):
622
 
        b, file_list = branch_files(file_list)
623
 
        tree = b.working_tree()
 
620
        tree, file_list = tree_files(file_list)
624
621
        tree.remove(file_list, verbose=verbose)
625
622
 
626
623
 
635
632
    takes_args = ['filename']
636
633
    @display_command
637
634
    def run(self, filename):
638
 
        b, relpath = Branch.open_containing(filename)
639
 
        i = b.working_tree().inventory.path2id(relpath)
 
635
        tree, relpath = WorkingTree.open_containing(filename)
 
636
        i = tree.inventory.path2id(relpath)
640
637
        if i == None:
641
638
            raise BzrError("%r is not a versioned file" % filename)
642
639
        else:
652
649
    takes_args = ['filename']
653
650
    @display_command
654
651
    def run(self, filename):
655
 
        b, relpath = Branch.open_containing(filename)
656
 
        inv = b.inventory
 
652
        tree, relpath = WorkingTree.open_containing(filename)
 
653
        inv = tree.inventory
657
654
        fid = inv.path2id(relpath)
658
655
        if fid == None:
659
656
            raise BzrError("%r is not a versioned file" % filename)
666
663
    hidden = True
667
664
    @display_command
668
665
    def run(self):
669
 
        for patchid in Branch.open_containing('.')[0].revision_history():
 
666
        branch = WorkingTree.open_containing(u'.')[0].branch
 
667
        for patchid in branch.revision_history():
670
668
            print patchid
671
669
 
672
670
 
675
673
    hidden = True
676
674
    @display_command
677
675
    def run(self):
678
 
        b = Branch.open_containing('.')[0]
 
676
        tree = WorkingTree.open_containing(u'.')[0]
 
677
        b = tree.branch
 
678
        # FIXME. should be tree.last_revision
679
679
        for revision_id in b.get_ancestry(b.last_revision()):
680
680
            print revision_id
681
681
 
682
682
 
683
 
class cmd_directories(Command):
684
 
    """Display list of versioned directories in this branch."""
685
 
    @display_command
686
 
    def run(self):
687
 
        for name, ie in (Branch.open_containing('.')[0].working_tree().
688
 
                         read_working_inventory().directories()):
689
 
            if name == '':
690
 
                print '.'
691
 
            else:
692
 
                print name
693
 
 
694
 
 
695
683
class cmd_init(Command):
696
684
    """Make a directory into a versioned branch.
697
685
 
709
697
    def run(self, location=None):
710
698
        from bzrlib.branch import Branch
711
699
        if location is None:
712
 
            location = '.'
 
700
            location = u'.'
713
701
        else:
714
702
            # The path has to exist to initialize a
715
703
            # branch inside of it.
754
742
    def run(self, revision=None, file_list=None, diff_options=None):
755
743
        from bzrlib.diff import show_diff
756
744
        try:
757
 
            b, file_list = inner_branch_files(file_list)
 
745
            tree, file_list = internal_tree_files(file_list)
 
746
            b = None
758
747
            b2 = None
759
748
        except FileInWrongBranch:
760
749
            if len(file_list) != 2:
763
752
            b, file1 = Branch.open_containing(file_list[0])
764
753
            b2, file2 = Branch.open_containing(file_list[1])
765
754
            if file1 != "" or file2 != "":
 
755
                # FIXME diff those two files. rbc 20051123
766
756
                raise BzrCommandError("Files are in different branches")
767
757
            file_list = None
768
758
        if revision is not None:
769
759
            if b2 is not None:
770
760
                raise BzrCommandError("Can't specify -r with two branches")
771
761
            if len(revision) == 1:
772
 
                return show_diff(b, revision[0], specific_files=file_list,
 
762
                return show_diff(tree.branch, revision[0], specific_files=file_list,
773
763
                                 external_diff_options=diff_options)
774
764
            elif len(revision) == 2:
775
 
                return show_diff(b, revision[0], specific_files=file_list,
 
765
                return show_diff(tree.branch, revision[0], specific_files=file_list,
776
766
                                 external_diff_options=diff_options,
777
767
                                 revision2=revision[1])
778
768
            else:
779
769
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
780
770
        else:
781
 
            return show_diff(b, None, specific_files=file_list,
782
 
                             external_diff_options=diff_options, b2=b2)
 
771
            if b is not None:
 
772
                return show_diff(b, None, specific_files=file_list,
 
773
                                 external_diff_options=diff_options, b2=b2)
 
774
            else:
 
775
                return show_diff(tree.branch, None, specific_files=file_list,
 
776
                                 external_diff_options=diff_options)
783
777
 
784
778
 
785
779
class cmd_deleted(Command):
793
787
    # if the directories are very large...)
794
788
    @display_command
795
789
    def run(self, show_ids=False):
796
 
        b = Branch.open_containing('.')[0]
797
 
        old = b.basis_tree()
798
 
        new = b.working_tree()
 
790
        tree = WorkingTree.open_containing(u'.')[0]
 
791
        old = tree.branch.basis_tree()
799
792
        for path, ie in old.inventory.iter_entries():
800
 
            if not new.has_id(ie.file_id):
 
793
            if not tree.has_id(ie.file_id):
801
794
                if show_ids:
802
795
                    print '%-50s %s' % (path, ie.file_id)
803
796
                else:
811
804
    def run(self):
812
805
        from bzrlib.delta import compare_trees
813
806
 
814
 
        b = Branch.open_containing('.')[0]
815
 
        td = compare_trees(b.basis_tree(), b.working_tree())
 
807
        tree = WorkingTree.open_containing(u'.')[0]
 
808
        td = compare_trees(tree.branch.basis_tree(), tree)
816
809
 
817
810
        for path, id, kind, text_modified, meta_modified in td.modified:
818
811
            print path
824
817
    hidden = True
825
818
    @display_command
826
819
    def run(self):
827
 
        b = Branch.open_containing('.')[0]
828
 
        wt = b.working_tree()
829
 
        basis_inv = b.basis_tree().inventory
 
820
        wt = WorkingTree.open_containing(u'.')[0]
 
821
        basis_inv = wt.branch.basis_tree().inventory
830
822
        inv = wt.inventory
831
823
        for file_id in inv:
832
824
            if file_id in basis_inv:
847
839
    @display_command
848
840
    def run(self, filename=None):
849
841
        """Print the branch root."""
850
 
        b = Branch.open_containing(filename)[0]
851
 
        print b.base
 
842
        tree = WorkingTree.open_containing(filename)[0]
 
843
        print tree.basedir
852
844
 
853
845
 
854
846
class cmd_log(Command):
890
882
        direction = (forward and 'forward') or 'reverse'
891
883
        
892
884
        if filename:
893
 
            b, fp = Branch.open_containing(filename)
 
885
            # might be a tree:
 
886
            tree = None
 
887
            try:
 
888
                tree, fp = WorkingTree.open_containing(filename)
 
889
                b = tree.branch
 
890
                if fp != '':
 
891
                    inv = tree.read_working_inventory()
 
892
            except NotBranchError:
 
893
                pass
 
894
            if tree is None:
 
895
                b, fp = Branch.open_containing(filename)
 
896
                if fp != '':
 
897
                    inv = b.get_inventory(b.last_revision())
894
898
            if fp != '':
895
 
                try:
896
 
                    inv = b.working_tree().read_working_inventory()
897
 
                except NoWorkingTree:
898
 
                    inv = b.get_inventory(b.last_revision())
899
899
                file_id = inv.path2id(fp)
900
900
            else:
901
901
                file_id = None  # points to branch root
902
902
        else:
903
 
            b, relpath = Branch.open_containing('.')
 
903
            tree, relpath = WorkingTree.open_containing(u'.')
 
904
            b = tree.branch
904
905
            file_id = None
905
906
 
906
907
        if revision is None:
955
956
    takes_args = ["filename"]
956
957
    @display_command
957
958
    def run(self, filename):
958
 
        b, relpath = Branch.open_containing(filename)[0]
959
 
        inv = b.working_tree().read_working_inventory()
 
959
        tree, relpath = WorkingTree.open_containing(filename)
 
960
        b = tree.branch
 
961
        inv = tree.read_working_inventory()
960
962
        file_id = inv.path2id(relpath)
961
963
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
962
964
            print "%6d %s" % (revno, what)
990
992
 
991
993
        selection = {'I':ignored, '?':unknown, 'V':versioned}
992
994
 
993
 
        b, relpath = Branch.open_containing('.')
 
995
        tree, relpath = WorkingTree.open_containing(u'.')
994
996
        if from_root:
995
 
            relpath = ''
 
997
            relpath = u''
996
998
        elif relpath:
997
999
            relpath += '/'
998
 
        if revision == None:
999
 
            tree = b.working_tree()
1000
 
        else:
1001
 
            tree = b.revision_tree(revision[0].in_history(b).rev_id)
 
1000
        if revision is not None:
 
1001
            tree = tree.branch.revision_tree(
 
1002
                revision[0].in_history(tree.branch).rev_id)
1002
1003
        for fp, fc, kind, fid, entry in tree.list_files():
1003
1004
            if fp.startswith(relpath):
1004
1005
                fp = fp[len(relpath):]
1017
1018
                    print fp
1018
1019
 
1019
1020
 
1020
 
 
1021
1021
class cmd_unknowns(Command):
1022
1022
    """List unknown files."""
1023
1023
    @display_command
1024
1024
    def run(self):
1025
1025
        from bzrlib.osutils import quotefn
1026
 
        for f in Branch.open_containing('.')[0].unknowns():
 
1026
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1027
1027
            print quotefn(f)
1028
1028
 
1029
1029
 
1030
 
 
1031
1030
class cmd_ignore(Command):
1032
1031
    """Ignore a command or pattern.
1033
1032
 
1053
1052
        from bzrlib.atomicfile import AtomicFile
1054
1053
        import os.path
1055
1054
 
1056
 
        b, relpath = Branch.open_containing('.')
1057
 
        ifn = b.abspath('.bzrignore')
 
1055
        tree, relpath = WorkingTree.open_containing(u'.')
 
1056
        ifn = tree.abspath('.bzrignore')
1058
1057
 
1059
1058
        if os.path.exists(ifn):
1060
1059
            f = open(ifn, 'rt')
1079
1078
        finally:
1080
1079
            f.close()
1081
1080
 
1082
 
        inv = b.working_tree().inventory
 
1081
        inv = tree.inventory
1083
1082
        if inv.path2id('.bzrignore'):
1084
1083
            mutter('.bzrignore is already versioned')
1085
1084
        else:
1086
1085
            mutter('need to make new .bzrignore file versioned')
1087
 
            b.add(['.bzrignore'])
1088
 
 
 
1086
            tree.add(['.bzrignore'])
1089
1087
 
1090
1088
 
1091
1089
class cmd_ignored(Command):
1094
1092
    See also: bzr ignore"""
1095
1093
    @display_command
1096
1094
    def run(self):
1097
 
        tree = Branch.open_containing('.')[0].working_tree()
 
1095
        tree = WorkingTree.open_containing(u'.')[0]
1098
1096
        for path, file_class, kind, file_id, entry in tree.list_files():
1099
1097
            if file_class != 'I':
1100
1098
                continue
1119
1117
        except ValueError:
1120
1118
            raise BzrCommandError("not a valid revision-number: %r" % revno)
1121
1119
 
1122
 
        print Branch.open_containing('.')[0].get_rev_id(revno)
 
1120
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1123
1121
 
1124
1122
 
1125
1123
class cmd_export(Command):
1132
1130
    is found exports to a directory (equivalent to --format=dir).
1133
1131
 
1134
1132
    Root may be the top directory for tar, tgz and tbz2 formats. If none
1135
 
    is given, the top directory will be the root name of the file."""
1136
 
    # TODO: list known exporters
 
1133
    is given, the top directory will be the root name of the file.
 
1134
 
 
1135
    Note: export of tree with non-ascii filenames to zip is not supported.
 
1136
 
 
1137
    Supported formats       Autodetected by extension
 
1138
    -----------------       -------------------------
 
1139
         dir                            -
 
1140
         tar                          .tar
 
1141
         tbz2                    .tar.bz2, .tbz2
 
1142
         tgz                      .tar.gz, .tgz
 
1143
         zip                          .zip
 
1144
    """
1137
1145
    takes_args = ['dest']
1138
1146
    takes_options = ['revision', 'format', 'root']
1139
1147
    def run(self, dest, revision=None, format=None, root=None):
1140
1148
        import os.path
1141
 
        b = Branch.open_containing('.')[0]
 
1149
        from bzrlib.export import export
 
1150
        tree = WorkingTree.open_containing(u'.')[0]
 
1151
        b = tree.branch
1142
1152
        if revision is None:
 
1153
            # should be tree.last_revision  FIXME
1143
1154
            rev_id = b.last_revision()
1144
1155
        else:
1145
1156
            if len(revision) != 1:
1146
1157
                raise BzrError('bzr export --revision takes exactly 1 argument')
1147
1158
            rev_id = revision[0].in_history(b).rev_id
1148
1159
        t = b.revision_tree(rev_id)
1149
 
        arg_root, ext = os.path.splitext(os.path.basename(dest))
1150
 
        if ext in ('.gz', '.bz2'):
1151
 
            new_root, new_ext = os.path.splitext(arg_root)
1152
 
            if new_ext == '.tar':
1153
 
                arg_root = new_root
1154
 
                ext = new_ext + ext
1155
 
        if root is None:
1156
 
            root = arg_root
1157
 
        if not format:
1158
 
            if ext in (".tar",):
1159
 
                format = "tar"
1160
 
            elif ext in (".tar.gz", ".tgz"):
1161
 
                format = "tgz"
1162
 
            elif ext in (".tar.bz2", ".tbz2"):
1163
 
                format = "tbz2"
1164
 
            else:
1165
 
                format = "dir"
1166
 
        t.export(dest, format, root)
 
1160
        try:
 
1161
            export(t, dest, format, root)
 
1162
        except errors.NoSuchExportFormat, e:
 
1163
            raise BzrCommandError('Unsupported export format: %s' % e.format)
1167
1164
 
1168
1165
 
1169
1166
class cmd_cat(Command):
1178
1175
            raise BzrCommandError("bzr cat requires a revision number")
1179
1176
        elif len(revision) != 1:
1180
1177
            raise BzrCommandError("bzr cat --revision takes exactly one number")
1181
 
        b, relpath = Branch.open_containing(filename)
 
1178
        tree = None
 
1179
        try:
 
1180
            tree, relpath = WorkingTree.open_containing(filename)
 
1181
            b = tree.branch
 
1182
        except NotBranchError:
 
1183
            pass
 
1184
        if tree is None:
 
1185
            b, relpath = Branch.open_containing(filename)
1182
1186
        b.print_file(relpath, revision[0].in_history(b).revno)
1183
1187
 
1184
1188
 
1234
1238
        from bzrlib.status import show_status
1235
1239
        from cStringIO import StringIO
1236
1240
 
1237
 
        b, selected_list = branch_files(selected_list)
 
1241
        tree, selected_list = tree_files(selected_list)
1238
1242
        if message is None and not file:
1239
1243
            catcher = StringIO()
1240
 
            show_status(b, specific_files=selected_list,
 
1244
            show_status(tree.branch, specific_files=selected_list,
1241
1245
                        to_file=catcher)
1242
1246
            message = edit_commit_message(catcher.getvalue())
1243
1247
 
1255
1259
                raise BzrCommandError("empty commit message specified")
1256
1260
            
1257
1261
        try:
1258
 
            b.working_tree().commit(message, specific_files=selected_list,
1259
 
                     allow_pointless=unchanged, strict=strict)
 
1262
            tree.commit(message, specific_files=selected_list,
 
1263
                        allow_pointless=unchanged, strict=strict)
1260
1264
        except PointlessCommit:
1261
1265
            # FIXME: This should really happen before the file is read in;
1262
1266
            # perhaps prepare the commit; get the message; then actually commit
1268
1272
        except StrictCommitFailed:
1269
1273
            raise BzrCommandError("Commit refused because there are unknown "
1270
1274
                                  "files in the working tree.")
1271
 
        note('Committed revision %d.' % (b.revno(),))
 
1275
        note('Committed revision %d.' % (tree.branch.revno(),))
1272
1276
        
1273
1277
 
1274
1278
class cmd_check(Command):
1277
1281
    This command checks various invariants about the branch storage to
1278
1282
    detect data corruption or bzr bugs.
1279
1283
    """
1280
 
    takes_args = ['dir?']
 
1284
    takes_args = ['branch?']
1281
1285
    takes_options = ['verbose']
1282
1286
 
1283
 
    def run(self, dir='.', verbose=False):
 
1287
    def run(self, branch=None, verbose=False):
1284
1288
        from bzrlib.check import check
1285
 
        check(Branch.open_containing(dir)[0], verbose)
 
1289
        if branch is None:
 
1290
            tree = WorkingTree.open_containing()[0]
 
1291
            branch = tree.branch
 
1292
        else:
 
1293
            branch = Branch.open(branch)
 
1294
        check(branch, verbose)
1286
1295
 
1287
1296
 
1288
1297
class cmd_scan_cache(Command):
1290
1299
    def run(self):
1291
1300
        from bzrlib.hashcache import HashCache
1292
1301
 
1293
 
        c = HashCache('.')
 
1302
        c = HashCache(u'.')
1294
1303
        c.read()
1295
1304
        c.scan()
1296
1305
            
1316
1325
    """
1317
1326
    takes_args = ['dir?']
1318
1327
 
1319
 
    def run(self, dir='.'):
 
1328
    def run(self, dir=u'.'):
1320
1329
        from bzrlib.upgrade import upgrade
1321
1330
        upgrade(dir)
1322
1331
 
1328
1337
    @display_command
1329
1338
    def run(self, email=False):
1330
1339
        try:
1331
 
            b = bzrlib.branch.Branch.open_containing('.')[0]
 
1340
            b = WorkingTree.open_containing(u'.')[0].branch
1332
1341
            config = bzrlib.config.BranchConfig(b)
1333
1342
        except NotBranchError:
1334
1343
            config = bzrlib.config.GlobalConfig()
1346
1355
    """
1347
1356
    takes_args = ['nickname?']
1348
1357
    def run(self, nickname=None):
1349
 
        branch = Branch.open_containing('.')[0]
 
1358
        branch = Branch.open_containing(u'.')[0]
1350
1359
        if nickname is None:
1351
1360
            self.printme(branch)
1352
1361
        else:
1379
1388
    def run(self, testspecs_list=None, verbose=False, one=False,
1380
1389
            keep_output=False):
1381
1390
        import bzrlib.ui
1382
 
        from bzrlib.selftest import selftest
 
1391
        from bzrlib.tests import selftest
1383
1392
        # we don't want progress meters from the tests to go to the
1384
1393
        # real output; and we don't want log messages cluttering up
1385
1394
        # the real logs.
1511
1520
        if merge_type is None:
1512
1521
            merge_type = ApplyMerge3
1513
1522
        if branch is None:
1514
 
            branch = Branch.open_containing('.')[0].get_parent()
 
1523
            branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1515
1524
            if branch is None:
1516
1525
                raise BzrCommandError("No merge location known or specified.")
1517
1526
            else:
1567
1576
        from bzrlib.merge_core import ApplyMerge3
1568
1577
        if merge_type is None:
1569
1578
            merge_type = ApplyMerge3
1570
 
        b, file_list = branch_files(file_list)
1571
 
        b.lock_write()
 
1579
        tree, file_list = tree_files(file_list)
 
1580
        tree.lock_write()
1572
1581
        try:
1573
 
            pending_merges = b.working_tree().pending_merges() 
 
1582
            pending_merges = tree.pending_merges() 
1574
1583
            if len(pending_merges) != 1:
1575
1584
                raise BzrCommandError("Sorry, remerge only works after normal"
1576
1585
                                      + " merges.  Not cherrypicking or"
1577
1586
                                      + "multi-merges.")
1578
 
            this_tree = b.working_tree()
1579
 
            base_revision = common_ancestor(b.last_revision(), 
1580
 
                                            pending_merges[0], b)
1581
 
            base_tree = b.revision_tree(base_revision)
1582
 
            other_tree = b.revision_tree(pending_merges[0])
 
1587
            base_revision = common_ancestor(tree.branch.last_revision(), 
 
1588
                                            pending_merges[0], tree.branch)
 
1589
            base_tree = tree.branch.revision_tree(base_revision)
 
1590
            other_tree = tree.branch.revision_tree(pending_merges[0])
1583
1591
            interesting_ids = None
1584
1592
            if file_list is not None:
1585
1593
                interesting_ids = set()
1586
1594
                for filename in file_list:
1587
 
                    file_id = this_tree.path2id(filename)
 
1595
                    file_id = tree.path2id(filename)
1588
1596
                    interesting_ids.add(file_id)
1589
 
                    if this_tree.kind(file_id) != "directory":
 
1597
                    if tree.kind(file_id) != "directory":
1590
1598
                        continue
1591
1599
                    
1592
 
                    for name, ie in this_tree.inventory.iter_entries(file_id):
 
1600
                    for name, ie in tree.inventory.iter_entries(file_id):
1593
1601
                        interesting_ids.add(ie.file_id)
1594
 
            transform_tree(this_tree, b.basis_tree(), interesting_ids)
 
1602
            transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1595
1603
            if file_list is None:
1596
 
                restore_files = list(this_tree.iter_conflicts())
 
1604
                restore_files = list(tree.iter_conflicts())
1597
1605
            else:
1598
1606
                restore_files = file_list
1599
1607
            for filename in restore_files:
1600
1608
                try:
1601
 
                    restore(this_tree.abspath(filename))
 
1609
                    restore(tree.abspath(filename))
1602
1610
                except NotConflicted:
1603
1611
                    pass
1604
 
            conflicts =  merge_inner(b, other_tree, base_tree, 
 
1612
            conflicts =  merge_inner(tree.branch, other_tree, base_tree, 
1605
1613
                                     interesting_ids = interesting_ids, 
1606
1614
                                     other_rev_id=pending_merges[0], 
1607
1615
                                     merge_type=merge_type, 
1608
1616
                                     show_base=show_base,
1609
1617
                                     reprocess=reprocess)
1610
1618
        finally:
1611
 
            b.unlock()
 
1619
            tree.unlock()
1612
1620
        if conflicts > 0:
1613
1621
            return 1
1614
1622
        else:
1635
1643
            file_list = []
1636
1644
        if revision is None:
1637
1645
            revno = -1
1638
 
            b = Branch.open_containing('.')[0]
1639
 
            rev_id = b.last_revision()
 
1646
            tree = WorkingTree.open_containing(u'.')[0]
 
1647
            # FIXME should be tree.last_revision
 
1648
            rev_id = tree.branch.last_revision()
1640
1649
        elif len(revision) != 1:
1641
1650
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1642
1651
        else:
1643
 
            b, file_list = branch_files(file_list)
1644
 
            rev_id = revision[0].in_history(b).rev_id
1645
 
        b.working_tree().revert(file_list, b.revision_tree(rev_id),
 
1652
            tree, file_list = tree_files(file_list)
 
1653
            rev_id = revision[0].in_history(tree.branch).rev_id
 
1654
        tree.revert(file_list, tree.branch.revision_tree(rev_id),
1646
1655
                                not no_backup)
1647
1656
 
1648
1657
 
1713
1722
    
1714
1723
    takes_args = ['remote?']
1715
1724
    aliases = ['mis', 'miss']
1716
 
    # We don't have to add quiet to the list, because 
1717
 
    # unknown options are parsed as booleans
1718
 
    takes_options = ['verbose', 'quiet']
 
1725
    takes_options = ['verbose']
1719
1726
 
1720
1727
    @display_command
1721
 
    def run(self, remote=None, verbose=False, quiet=False):
 
1728
    def run(self, remote=None, verbose=False):
1722
1729
        from bzrlib.errors import BzrCommandError
1723
1730
        from bzrlib.missing import show_missing
1724
1731
 
1725
 
        if verbose and quiet:
 
1732
        if verbose and is_quiet():
1726
1733
            raise BzrCommandError('Cannot pass both quiet and verbose')
1727
1734
 
1728
 
        b = Branch.open_containing('.')[0]
1729
 
        parent = b.get_parent()
 
1735
        tree = WorkingTree.open_containing(u'.')[0]
 
1736
        parent = tree.branch.get_parent()
1730
1737
        if remote is None:
1731
1738
            if parent is None:
1732
1739
                raise BzrCommandError("No missing location known or specified.")
1733
1740
            else:
1734
 
                if not quiet:
 
1741
                if not is_quiet():
1735
1742
                    print "Using last location: %s" % parent
1736
1743
                remote = parent
1737
1744
        elif parent is None:
1738
1745
            # We only update parent if it did not exist, missing
1739
1746
            # should not change the parent
1740
 
            b.set_parent(remote)
 
1747
            tree.branch.set_parent(remote)
1741
1748
        br_remote = Branch.open_containing(remote)[0]
1742
 
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
 
1749
        return show_missing(tree.branch, br_remote, verbose=verbose, 
 
1750
                            quiet=is_quiet())
1743
1751
 
1744
1752
 
1745
1753
class cmd_plugins(Command):
1767
1775
    takes_options = ['revision', 'long']
1768
1776
    takes_args = ['branch?']
1769
1777
    @display_command
1770
 
    def run(self, branch='.', revision=None, long=False):
 
1778
    def run(self, branch=u'.', revision=None, long=False):
1771
1779
        from bzrlib.testament import Testament
1772
 
        b = Branch.open_containing(branch)[0]
 
1780
        b = WorkingTree.open_containing(branch)[0].branch
1773
1781
        b.lock_read()
1774
1782
        try:
1775
1783
            if revision is None:
1807
1815
    @display_command
1808
1816
    def run(self, filename, all=False, long=False):
1809
1817
        from bzrlib.annotate import annotate_file
1810
 
        b, relpath = Branch.open_containing(filename)
1811
 
        b.lock_read()
 
1818
        tree, relpath = WorkingTree.open_containing(filename)
 
1819
        branch = tree.branch
 
1820
        branch.lock_read()
1812
1821
        try:
1813
 
            tree = WorkingTree(b.base, b)
1814
 
            tree = b.revision_tree(b.last_revision())
1815
1822
            file_id = tree.inventory.path2id(relpath)
 
1823
            tree = branch.revision_tree(branch.last_revision())
1816
1824
            file_version = tree.inventory[file_id].revision
1817
 
            annotate_file(b, file_version, file_id, long, all, sys.stdout)
 
1825
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
1818
1826
        finally:
1819
 
            b.unlock()
 
1827
            branch.unlock()
1820
1828
 
1821
1829
 
1822
1830
class cmd_re_sign(Command):
1834
1842
            raise BzrCommandError('You can only supply one of revision_id or --revision')
1835
1843
        if revision_id is None and revision is None:
1836
1844
            raise BzrCommandError('You must supply either --revision or a revision_id')
1837
 
        b = Branch.open_containing('.')[0]
 
1845
        b = WorkingTree.open_containing(u'.')[0].branch
1838
1846
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1839
1847
        if revision_id is not None:
1840
1848
            b.sign_revision(revision_id, gpg_strategy)
1858
1866
                raise BzrCommandError('Please supply either one revision, or a range.')
1859
1867
 
1860
1868
 
 
1869
class cmd_uncommit(bzrlib.commands.Command):
 
1870
    """Remove the last committed revision.
 
1871
 
 
1872
    By supplying the --all flag, it will not only remove the entry 
 
1873
    from revision_history, but also remove all of the entries in the
 
1874
    stores.
 
1875
 
 
1876
    --verbose will print out what is being removed.
 
1877
    --dry-run will go through all the motions, but not actually
 
1878
    remove anything.
 
1879
    
 
1880
    In the future, uncommit will create a changeset, which can then
 
1881
    be re-applied.
 
1882
    """
 
1883
    takes_options = ['all', 'verbose', 'revision',
 
1884
                    Option('dry-run', help='Don\'t actually make changes'),
 
1885
                    Option('force', help='Say yes to all questions.')]
 
1886
    takes_args = ['location?']
 
1887
    aliases = []
 
1888
 
 
1889
    def run(self, location=None, all=False,
 
1890
            dry_run=False, verbose=False,
 
1891
            revision=None, force=False):
 
1892
        from bzrlib.branch import Branch
 
1893
        from bzrlib.log import log_formatter
 
1894
        import sys
 
1895
        from bzrlib.uncommit import uncommit
 
1896
 
 
1897
        if location is None:
 
1898
            location = u'.'
 
1899
        b, relpath = Branch.open_containing(location)
 
1900
 
 
1901
        if revision is None:
 
1902
            revno = b.revno()
 
1903
            rev_id = b.last_revision()
 
1904
        else:
 
1905
            revno, rev_id = revision[0].in_history(b)
 
1906
        if rev_id is None:
 
1907
            print 'No revisions to uncommit.'
 
1908
 
 
1909
        for r in range(revno, b.revno()+1):
 
1910
            rev_id = b.get_rev_id(r)
 
1911
            lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
 
1912
            lf.show(r, b.get_revision(rev_id), None)
 
1913
 
 
1914
        if dry_run:
 
1915
            print 'Dry-run, pretending to remove the above revisions.'
 
1916
            if not force:
 
1917
                val = raw_input('Press <enter> to continue')
 
1918
        else:
 
1919
            print 'The above revision(s) will be removed.'
 
1920
            if not force:
 
1921
                val = raw_input('Are you sure [y/N]? ')
 
1922
                if val.lower() not in ('y', 'yes'):
 
1923
                    print 'Canceled'
 
1924
                    return 0
 
1925
 
 
1926
        uncommit(b, remove_files=all,
 
1927
                dry_run=dry_run, verbose=verbose,
 
1928
                revno=revno)
 
1929
 
 
1930
 
1861
1931
# these get imported and then picked up by the scan for cmd_*
1862
1932
# TODO: Some more consistent way to split command definitions across files;
1863
1933
# we do need to load at least some information about them to know of