~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Merge in format-5 work - release bzr 0.1rc1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
import bzrlib
22
22
import bzrlib.trace
23
23
from bzrlib.trace import mutter, note, log_error, warning
24
 
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
25
 
from bzrlib.branch import find_branch
26
 
from bzrlib.revisionspec import RevisionSpec
 
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
 
25
from bzrlib.branch import Branch
27
26
from bzrlib import BZRDIR
28
27
from bzrlib.commands import Command
29
28
 
64
63
    files or directories is reported.  If a directory is given, status
65
64
    is reported for everything inside that directory.
66
65
 
67
 
    If a revision is specified, the changes since that revision are shown.
 
66
    If a revision argument is given, the status is calculated against
 
67
    that revision, or between two revisions if two are provided.
68
68
    """
 
69
    # XXX: FIXME: bzr status should accept a -r option to show changes
 
70
    # relative to a revision, or between revisions
 
71
 
69
72
    takes_args = ['file*']
70
 
    takes_options = ['all', 'show-ids', 'revision']
 
73
    takes_options = ['all', 'show-ids']
71
74
    aliases = ['st', 'stat']
72
75
    
73
 
    def run(self, all=False, show_ids=False, file_list=None):
 
76
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
74
77
        if file_list:
75
 
            b = find_branch(file_list[0])
 
78
            b = Branch.open_containing(file_list[0])
76
79
            file_list = [b.relpath(x) for x in file_list]
77
80
            # special case: only one path was given and it's the root
78
81
            # of the branch
79
82
            if file_list == ['']:
80
83
                file_list = None
81
84
        else:
82
 
            b = find_branch('.')
 
85
            b = Branch.open_containing('.')
83
86
            
84
87
        from bzrlib.status import show_status
85
88
        show_status(b, show_unchanged=all, show_ids=show_ids,
86
 
                    specific_files=file_list)
 
89
                    specific_files=file_list, revision=revision)
87
90
 
88
91
 
89
92
class cmd_cat_revision(Command):
90
 
    """Write out metadata for a revision."""
 
93
    """Write out metadata for a revision.
 
94
    
 
95
    The revision to print can either be specified by a specific
 
96
    revision identifier, or you can use --revision.
 
97
    """
91
98
 
92
99
    hidden = True
93
 
    takes_args = ['revision_id']
 
100
    takes_args = ['revision_id?']
 
101
    takes_options = ['revision']
94
102
    
95
 
    def run(self, revision_id):
96
 
        b = find_branch('.')
97
 
        sys.stdout.write(b.get_revision_xml_file(revision_id).read())
 
103
    def run(self, revision_id=None, revision=None):
 
104
        from bzrlib.revisionspec import RevisionSpec
98
105
 
 
106
        if revision_id is not None and revision is not None:
 
107
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
108
        if revision_id is None and revision is None:
 
109
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
110
        b = Branch.open_containing('.')
 
111
        if revision_id is not None:
 
112
            sys.stdout.write(b.get_revision_xml_file(revision_id).read())
 
113
        elif revision is not None:
 
114
            for rev in revision:
 
115
                if rev is None:
 
116
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
117
                revno, rev_id = rev.in_history(b)
 
118
                sys.stdout.write(b.get_revision_xml_file(rev_id).read())
 
119
    
99
120
 
100
121
class cmd_revno(Command):
101
122
    """Show current revision number.
102
123
 
103
124
    This is equal to the number of revisions on this branch."""
104
125
    def run(self):
105
 
        print find_branch('.').revno()
 
126
        print Branch.open_containing('.').revno()
106
127
 
107
128
 
108
129
class cmd_revision_info(Command):
111
132
    hidden = True
112
133
    takes_args = ['revision_info*']
113
134
    takes_options = ['revision']
114
 
    def run(self, revision=None, revision_info_list=None):
115
 
        from bzrlib.branch import find_branch
 
135
    def run(self, revision=None, revision_info_list=[]):
 
136
        from bzrlib.revisionspec import RevisionSpec
116
137
 
117
138
        revs = []
118
139
        if revision is not None:
119
140
            revs.extend(revision)
120
141
        if revision_info_list is not None:
121
 
            revs.extend(revision_info_list)
 
142
            for rev in revision_info_list:
 
143
                revs.append(RevisionSpec(rev))
122
144
        if len(revs) == 0:
123
145
            raise BzrCommandError('You must supply a revision identifier')
124
146
 
125
 
        b = find_branch('.')
 
147
        b = Branch.open_containing('.')
126
148
 
127
149
        for rev in revs:
128
 
            print '%4d %s' % RevisionSpec(b, rev)
 
150
            revinfo = rev.in_history(b)
 
151
            if revinfo.revno is None:
 
152
                print '     %s' % revinfo.rev_id
 
153
            else:
 
154
                print '%4d %s' % (revinfo.revno, revinfo.rev_id)
129
155
 
130
156
    
131
157
class cmd_add(Command):
146
172
    Therefore simply saying 'bzr add' will version all files that
147
173
    are currently unknown.
148
174
 
149
 
    TODO: Perhaps adding a file whose directly is not versioned should
150
 
    recursively add that parent, rather than giving an error?
 
175
    Adding a file whose parent directory is not versioned will
 
176
    implicitly add the parent, and so on up to the root. This means
 
177
    you should never need to explictly add a directory, they'll just
 
178
    get added when you add a file in the directory.
151
179
    """
152
180
    takes_args = ['file*']
153
181
    takes_options = ['verbose', 'no-recurse']
172
200
        for d in dir_list:
173
201
            os.mkdir(d)
174
202
            if not b:
175
 
                b = find_branch(d)
 
203
                b = Branch.open_containing(d)
176
204
            b.add([d])
177
205
            print 'added', d
178
206
 
183
211
    hidden = True
184
212
    
185
213
    def run(self, filename):
186
 
        print find_branch(filename).relpath(filename)
 
214
        print Branch.open_containing(filename).relpath(filename)
187
215
 
188
216
 
189
217
 
192
220
    takes_options = ['revision', 'show-ids']
193
221
    
194
222
    def run(self, revision=None, show_ids=False):
195
 
        b = find_branch('.')
196
 
        if revision == None:
 
223
        b = Branch.open_containing('.')
 
224
        if revision is None:
197
225
            inv = b.read_working_inventory()
198
226
        else:
199
227
            if len(revision) > 1:
200
228
                raise BzrCommandError('bzr inventory --revision takes'
201
229
                    ' exactly one revision identifier')
202
 
            inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
 
230
            inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
203
231
 
204
232
        for path, entry in inv.entries():
205
233
            if show_ids:
218
246
    """
219
247
    takes_args = ['source$', 'dest']
220
248
    def run(self, source_list, dest):
221
 
        b = find_branch('.')
 
249
        b = Branch.open_containing('.')
222
250
 
223
251
        # TODO: glob expansion on windows?
224
252
        b.move([b.relpath(s) for s in source_list], b.relpath(dest))
241
269
    takes_args = ['from_name', 'to_name']
242
270
    
243
271
    def run(self, from_name, to_name):
244
 
        b = find_branch('.')
 
272
        b = Branch.open_containing('.')
245
273
        b.rename_one(b.relpath(from_name), b.relpath(to_name))
246
274
 
247
275
 
263
291
    def run(self, names_list):
264
292
        if len(names_list) < 2:
265
293
            raise BzrCommandError("missing file argument")
266
 
        b = find_branch(names_list[0])
 
294
        b = Branch.open_containing(names_list[0])
267
295
 
268
296
        rel_names = [b.relpath(x) for x in names_list]
269
297
        
275
303
            if len(names_list) != 2:
276
304
                raise BzrCommandError('to mv multiple files the destination '
277
305
                                      'must be a versioned directory')
278
 
            for pair in b.move(rel_names[0], rel_names[1]):
279
 
                print "%s => %s" % pair
 
306
            b.rename_one(rel_names[0], rel_names[1])
 
307
            print "%s => %s" % (rel_names[0], rel_names[1])
280
308
            
281
309
    
282
310
 
303
331
        from shutil import rmtree
304
332
        import errno
305
333
        
306
 
        br_to = find_branch('.')
307
 
        stored_loc = None
308
 
        try:
309
 
            stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
310
 
        except IOError, e:
311
 
            if e.errno != errno.ENOENT:
312
 
                raise
 
334
        br_to = Branch.open_containing('.')
 
335
        stored_loc = br_to.get_parent()
313
336
        if location is None:
314
337
            if stored_loc is None:
315
338
                raise BzrCommandError("No pull location known or specified.")
317
340
                print "Using last location: %s" % stored_loc
318
341
                location = stored_loc
319
342
        cache_root = tempfile.mkdtemp()
320
 
        from bzrlib.branch import DivergedBranches
321
 
        br_from = find_branch(location)
 
343
        from bzrlib.errors import DivergedBranches
 
344
        br_from = Branch.open_containing(location)
322
345
        location = br_from.base
323
346
        old_revno = br_to.revno()
324
347
        try:
325
 
            from branch import find_cached_branch, DivergedBranches
326
 
            br_from = find_cached_branch(location, cache_root)
 
348
            from bzrlib.errors import DivergedBranches
 
349
            br_from = Branch.open(location)
 
350
            br_from.setup_caching(cache_root)
327
351
            location = br_from.base
328
352
            old_revno = br_to.revno()
329
353
            try:
334
358
                
335
359
            merge(('.', -1), ('.', old_revno), check_clean=False)
336
360
            if location != stored_loc:
337
 
                br_to.controlfile("x-pull", "wb").write(location + "\n")
 
361
                br_to.set_parent(location)
338
362
        finally:
339
363
            rmtree(cache_root)
340
364
 
348
372
 
349
373
    To retrieve the branch as of a particular revision, supply the --revision
350
374
    parameter, as in "branch foo/bar -r 5".
 
375
 
 
376
    --basis is to speed up branching from remote branches.  When specified, it
 
377
    copies all the file-contents, inventory and revision data from the basis
 
378
    branch before copying anything from the remote branch.
351
379
    """
352
380
    takes_args = ['from_location', 'to_location?']
353
 
    takes_options = ['revision']
 
381
    takes_options = ['revision', 'basis']
354
382
    aliases = ['get', 'clone']
355
383
 
356
 
    def run(self, from_location, to_location=None, revision=None):
357
 
        from bzrlib.branch import copy_branch, find_cached_branch
 
384
    def run(self, from_location, to_location=None, revision=None, basis=None):
 
385
        from bzrlib.clone import copy_branch
358
386
        import tempfile
359
387
        import errno
360
388
        from shutil import rmtree
366
394
                raise BzrCommandError(
367
395
                    'bzr branch --revision takes exactly 1 revision value')
368
396
            try:
369
 
                br_from = find_cached_branch(from_location, cache_root)
 
397
                br_from = Branch.open(from_location)
370
398
            except OSError, e:
371
399
                if e.errno == errno.ENOENT:
372
400
                    raise BzrCommandError('Source location "%s" does not'
373
401
                                          ' exist.' % to_location)
374
402
                else:
375
403
                    raise
 
404
            br_from.setup_caching(cache_root)
 
405
            if basis is not None:
 
406
                basis_branch = Branch.open_containing(basis)
 
407
            else:
 
408
                basis_branch = None
 
409
            if len(revision) == 1 and revision[0] is not None:
 
410
                revision_id = revision[0].in_history(br_from)[1]
 
411
            else:
 
412
                revision_id = None
376
413
            if to_location is None:
377
414
                to_location = os.path.basename(from_location.rstrip("/\\"))
378
415
            try:
387
424
                else:
388
425
                    raise
389
426
            try:
390
 
                copy_branch(br_from, to_location, revision[0])
 
427
                copy_branch(br_from, to_location, revision_id, basis_branch)
391
428
            except bzrlib.errors.NoSuchRevision:
392
429
                rmtree(to_location)
393
430
                msg = "The branch %s has no revision %d." % (from_location, revision[0])
394
431
                raise BzrCommandError(msg)
 
432
            except bzrlib.errors.UnlistableBranch:
 
433
                msg = "The branch %s cannot be used as a --basis"
395
434
        finally:
396
435
            rmtree(cache_root)
397
436
 
406
445
    takes_args = ['dir?']
407
446
 
408
447
    def run(self, dir='.'):
409
 
        b = find_branch(dir)
 
448
        b = Branch.open_containing(dir)
410
449
        old_inv = b.basis_tree().inventory
411
450
        new_inv = b.read_working_inventory()
412
451
 
423
462
    def run(self, branch=None):
424
463
        import info
425
464
 
426
 
        b = find_branch(branch)
 
465
        b = Branch.open_containing(branch)
427
466
        info.show_info(b)
428
467
 
429
468
 
437
476
    takes_options = ['verbose']
438
477
    
439
478
    def run(self, file_list, verbose=False):
440
 
        b = find_branch(file_list[0])
 
479
        b = Branch.open_containing(file_list[0])
441
480
        b.remove([b.relpath(f) for f in file_list], verbose=verbose)
442
481
 
443
482
 
451
490
    hidden = True
452
491
    takes_args = ['filename']
453
492
    def run(self, filename):
454
 
        b = find_branch(filename)
 
493
        b = Branch.open_containing(filename)
455
494
        i = b.inventory.path2id(b.relpath(filename))
456
495
        if i == None:
457
496
            raise BzrError("%r is not a versioned file" % filename)
467
506
    hidden = True
468
507
    takes_args = ['filename']
469
508
    def run(self, filename):
470
 
        b = find_branch(filename)
 
509
        b = Branch.open_containing(filename)
471
510
        inv = b.inventory
472
511
        fid = inv.path2id(b.relpath(filename))
473
512
        if fid == None:
480
519
    """Display list of revision ids on this branch."""
481
520
    hidden = True
482
521
    def run(self):
483
 
        for patchid in find_branch('.').revision_history():
 
522
        for patchid in Branch.open_containing('.').revision_history():
484
523
            print patchid
485
524
 
486
525
 
 
526
class cmd_ancestry(Command):
 
527
    """List all revisions merged into this branch."""
 
528
    hidden = True
 
529
    def run(self):
 
530
        b = find_branch('.')
 
531
        for revision_id in b.get_ancestry(b.last_revision()):
 
532
            print revision_id
 
533
 
 
534
 
487
535
class cmd_directories(Command):
488
536
    """Display list of versioned directories in this branch."""
489
537
    def run(self):
490
 
        for name, ie in find_branch('.').read_working_inventory().directories():
 
538
        for name, ie in Branch.open_containing('.').read_working_inventory().directories():
491
539
            if name == '':
492
540
                print '.'
493
541
            else:
508
556
        bzr commit -m 'imported project'
509
557
    """
510
558
    def run(self):
511
 
        from bzrlib.branch import Branch
512
 
        Branch('.', init=True)
 
559
        Branch.initialize('.')
513
560
 
514
561
 
515
562
class cmd_diff(Command):
547
594
        from bzrlib.diff import show_diff
548
595
 
549
596
        if file_list:
550
 
            b = find_branch(file_list[0])
 
597
            b = Branch.open_containing(file_list[0])
551
598
            file_list = [b.relpath(f) for f in file_list]
552
599
            if file_list == ['']:
553
600
                # just pointing to top-of-tree
554
601
                file_list = None
555
602
        else:
556
 
            b = find_branch('.')
 
603
            b = Branch.open_containing('.')
557
604
 
558
605
        if revision is not None:
559
606
            if len(revision) == 1:
578
625
    TODO: Show files deleted since a previous revision, or between two revisions.
579
626
    """
580
627
    def run(self, show_ids=False):
581
 
        b = find_branch('.')
 
628
        b = Branch.open_containing('.')
582
629
        old = b.basis_tree()
583
630
        new = b.working_tree()
584
631
 
601
648
    def run(self):
602
649
        from bzrlib.delta import compare_trees
603
650
 
604
 
        b = find_branch('.')
 
651
        b = Branch.open_containing('.')
605
652
        td = compare_trees(b.basis_tree(), b.working_tree())
606
653
 
607
 
        for path, id, kind in td.modified:
 
654
        for path, id, kind, text_modified, meta_modified in td.modified:
608
655
            print path
609
656
 
610
657
 
613
660
    """List files added in working tree."""
614
661
    hidden = True
615
662
    def run(self):
616
 
        b = find_branch('.')
 
663
        b = Branch.open_containing('.')
617
664
        wt = b.working_tree()
618
665
        basis_inv = b.basis_tree().inventory
619
666
        inv = wt.inventory
635
682
    takes_args = ['filename?']
636
683
    def run(self, filename=None):
637
684
        """Print the branch root."""
638
 
        b = find_branch(filename)
 
685
        b = Branch.open_containing(filename)
639
686
        print b.base
640
687
 
641
688
 
648
695
 
649
696
    --message allows you to give a regular expression, which will be evaluated
650
697
    so that only matching entries will be displayed.
651
 
 
652
 
    TODO: Make --revision support uuid: and hash: [future tag:] notation.
653
 
  
654
698
    """
655
699
 
 
700
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
 
701
 
656
702
    takes_args = ['filename?']
657
703
    takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
658
704
                     'long', 'message', 'short',]
671
717
        direction = (forward and 'forward') or 'reverse'
672
718
        
673
719
        if filename:
674
 
            b = find_branch(filename)
 
720
            b = Branch.open_containing(filename)
675
721
            fp = b.relpath(filename)
676
722
            if fp:
677
723
                file_id = b.read_working_inventory().path2id(fp)
678
724
            else:
679
725
                file_id = None  # points to branch root
680
726
        else:
681
 
            b = find_branch('.')
 
727
            b = Branch.open_containing('.')
682
728
            file_id = None
683
729
 
684
730
        if revision is None:
685
731
            rev1 = None
686
732
            rev2 = None
687
733
        elif len(revision) == 1:
688
 
            rev1 = rev2 = RevisionSpec(b, revision[0]).revno
 
734
            rev1 = rev2 = revision[0].in_history(b).revno
689
735
        elif len(revision) == 2:
690
 
            rev1 = RevisionSpec(b, revision[0]).revno
691
 
            rev2 = RevisionSpec(b, revision[1]).revno
 
736
            rev1 = revision[0].in_history(b).revno
 
737
            rev2 = revision[1].in_history(b).revno
692
738
        else:
693
739
            raise BzrCommandError('bzr log --revision takes one or two values.')
694
740
 
730
776
    hidden = True
731
777
    takes_args = ["filename"]
732
778
    def run(self, filename):
733
 
        b = find_branch(filename)
 
779
        b = Branch.open_containing(filename)
734
780
        inv = b.read_working_inventory()
735
781
        file_id = inv.path2id(b.relpath(filename))
736
782
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
744
790
    """
745
791
    hidden = True
746
792
    def run(self, revision=None, verbose=False):
747
 
        b = find_branch('.')
 
793
        b = Branch.open_containing('.')
748
794
        if revision == None:
749
795
            tree = b.working_tree()
750
796
        else:
751
 
            tree = b.revision_tree(b.lookup_revision(revision))
752
 
 
753
 
        for fp, fc, kind, fid in tree.list_files():
 
797
            tree = b.revision_tree(revision.in_history(b).rev_id)
 
798
        for fp, fc, kind, fid, entry in tree.list_files():
754
799
            if verbose:
755
 
                if kind == 'directory':
756
 
                    kindch = '/'
757
 
                elif kind == 'file':
758
 
                    kindch = ''
759
 
                else:
760
 
                    kindch = '???'
761
 
 
 
800
                kindch = entry.kind_character()
762
801
                print '%-8s %s%s' % (fc, fp, kindch)
763
802
            else:
764
803
                print fp
769
808
    """List unknown files."""
770
809
    def run(self):
771
810
        from bzrlib.osutils import quotefn
772
 
        for f in find_branch('.').unknowns():
 
811
        for f in Branch.open_containing('.').unknowns():
773
812
            print quotefn(f)
774
813
 
775
814
 
797
836
        from bzrlib.atomicfile import AtomicFile
798
837
        import os.path
799
838
 
800
 
        b = find_branch('.')
 
839
        b = Branch.open_containing('.')
801
840
        ifn = b.abspath('.bzrignore')
802
841
 
803
842
        if os.path.exists(ifn):
837
876
 
838
877
    See also: bzr ignore"""
839
878
    def run(self):
840
 
        tree = find_branch('.').working_tree()
841
 
        for path, file_class, kind, file_id in tree.list_files():
 
879
        tree = Branch.open_containing('.').working_tree()
 
880
        for path, file_class, kind, file_id, entry in tree.list_files():
842
881
            if file_class != 'I':
843
882
                continue
844
883
            ## XXX: Slightly inefficient since this was already calculated
861
900
        except ValueError:
862
901
            raise BzrCommandError("not a valid revision-number: %r" % revno)
863
902
 
864
 
        print find_branch('.').get_rev_id(revno)
 
903
        print Branch.open_containing('.').get_rev_id(revno)
865
904
 
866
905
 
867
906
class cmd_export(Command):
880
919
    takes_options = ['revision', 'format', 'root']
881
920
    def run(self, dest, revision=None, format=None, root=None):
882
921
        import os.path
883
 
        b = find_branch('.')
 
922
        b = Branch.open_containing('.')
884
923
        if revision is None:
885
 
            rev_id = b.last_patch()
 
924
            rev_id = b.last_revision()
886
925
        else:
887
926
            if len(revision) != 1:
888
927
                raise BzrError('bzr export --revision takes exactly 1 argument')
889
 
            rev_id = RevisionSpec(b, revision[0]).rev_id
 
928
            rev_id = revision[0].in_history(b).rev_id
890
929
        t = b.revision_tree(rev_id)
891
 
        root, ext = os.path.splitext(dest)
 
930
        arg_root, ext = os.path.splitext(os.path.basename(dest))
 
931
        if ext in ('.gz', '.bz2'):
 
932
            new_root, new_ext = os.path.splitext(arg_root)
 
933
            if new_ext == '.tar':
 
934
                arg_root = new_root
 
935
                ext = new_ext + ext
 
936
        if root is None:
 
937
            root = arg_root
892
938
        if not format:
893
939
            if ext in (".tar",):
894
940
                format = "tar"
895
 
            elif ext in (".gz", ".tgz"):
 
941
            elif ext in (".tar.gz", ".tgz"):
896
942
                format = "tgz"
897
 
            elif ext in (".bz2", ".tbz2"):
 
943
            elif ext in (".tar.bz2", ".tbz2"):
898
944
                format = "tbz2"
899
945
            else:
900
946
                format = "dir"
908
954
    takes_args = ['filename']
909
955
 
910
956
    def run(self, filename, revision=None):
911
 
        if revision == None:
 
957
        if revision is None:
912
958
            raise BzrCommandError("bzr cat requires a revision number")
913
959
        elif len(revision) != 1:
914
960
            raise BzrCommandError("bzr cat --revision takes exactly one number")
915
 
        b = find_branch('.')
916
 
        b.print_file(b.relpath(filename), revision[0])
 
961
        b = Branch.open_containing('.')
 
962
        b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
917
963
 
918
964
 
919
965
class cmd_local_time_offset(Command):
946
992
    aliases = ['ci', 'checkin']
947
993
 
948
994
    # TODO: Give better message for -s, --summary, used by tla people
 
995
 
 
996
    # XXX: verbose currently does nothing
949
997
    
950
998
    def run(self, message=None, file=None, verbose=True, selected_list=None,
951
999
            unchanged=False):
954
1002
        from bzrlib.status import show_status
955
1003
        from cStringIO import StringIO
956
1004
 
957
 
        b = find_branch('.')
 
1005
        b = Branch.open_containing('.')
958
1006
        if selected_list:
959
1007
            selected_list = [b.relpath(s) for s in selected_list]
960
1008
            
961
 
        if not message and not file:
 
1009
        if message is None and not file:
962
1010
            catcher = StringIO()
963
1011
            show_status(b, specific_files=selected_list,
964
1012
                        to_file=catcher)
965
1013
            message = edit_commit_message(catcher.getvalue())
966
 
            
 
1014
 
967
1015
            if message is None:
968
1016
                raise BzrCommandError("please specify a commit message"
969
1017
                                      " with either --message or --file")
974
1022
            import codecs
975
1023
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
976
1024
 
 
1025
        if message == "":
 
1026
                raise BzrCommandError("empty commit message specified")
 
1027
            
977
1028
        try:
978
 
            b.commit(message, verbose=verbose,
 
1029
            b.commit(message,
979
1030
                     specific_files=selected_list,
980
1031
                     allow_pointless=unchanged)
981
1032
        except PointlessCommit:
990
1041
 
991
1042
    This command checks various invariants about the branch storage to
992
1043
    detect data corruption or bzr bugs.
993
 
 
994
 
    If given the --update flag, it will update some optional fields
995
 
    to help ensure data consistency.
996
1044
    """
997
1045
    takes_args = ['dir?']
998
1046
 
999
1047
    def run(self, dir='.'):
1000
1048
        from bzrlib.check import check
1001
1049
 
1002
 
        check(find_branch(dir))
 
1050
        check(Branch.open_containing(dir))
1003
1051
 
1004
1052
 
1005
1053
class cmd_scan_cache(Command):
1027
1075
 
1028
1076
    The check command or bzr developers may sometimes advise you to run
1029
1077
    this command.
 
1078
 
 
1079
    This version of this command upgrades from the full-text storage
 
1080
    used by bzr 0.0.8 and earlier to the weave format (v5).
1030
1081
    """
1031
1082
    takes_args = ['dir?']
1032
1083
 
1033
1084
    def run(self, dir='.'):
1034
1085
        from bzrlib.upgrade import upgrade
1035
 
        upgrade(find_branch(dir))
1036
 
 
 
1086
        upgrade(dir)
1037
1087
 
1038
1088
 
1039
1089
class cmd_whoami(Command):
1042
1092
    
1043
1093
    def run(self, email=False):
1044
1094
        try:
1045
 
            b = bzrlib.branch.find_branch('.')
1046
 
        except:
 
1095
            b = bzrlib.branch.Branch.open_containing('.')
 
1096
        except NotBranchError:
1047
1097
            b = None
1048
1098
        
1049
1099
        if email:
1053
1103
 
1054
1104
 
1055
1105
class cmd_selftest(Command):
1056
 
    """Run internal test suite"""
 
1106
    """Run internal test suite.
 
1107
    
 
1108
    This creates temporary test directories in the working directory,
 
1109
    but not existing data is affected.  These directories are deleted
 
1110
    if the tests pass, or left behind to help in debugging if they
 
1111
    fail.
 
1112
    
 
1113
    If arguments are given, they are regular expressions that say
 
1114
    which tests should run."""
 
1115
    # TODO: --list should give a list of all available tests
1057
1116
    hidden = True
 
1117
    takes_args = ['testnames*']
1058
1118
    takes_options = ['verbose', 'pattern']
1059
 
    def run(self, verbose=False, pattern=".*"):
 
1119
    def run(self, testnames_list=None, verbose=False, pattern=".*"):
1060
1120
        import bzrlib.ui
1061
1121
        from bzrlib.selftest import selftest
1062
1122
        # we don't want progress meters from the tests to go to the
1066
1126
        bzrlib.trace.info('running tests...')
1067
1127
        try:
1068
1128
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1069
 
            result = selftest(verbose=verbose, pattern=pattern)
 
1129
            result = selftest(verbose=verbose, 
 
1130
                              pattern=pattern,
 
1131
                              testnames=testnames_list)
1070
1132
            if result:
1071
1133
                bzrlib.trace.info('tests passed')
1072
1134
            else:
1114
1176
    def run(self, branch, other):
1115
1177
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
1116
1178
        
1117
 
        branch1 = find_branch(branch)
1118
 
        branch2 = find_branch(other)
 
1179
        branch1 = Branch.open_containing(branch)
 
1180
        branch2 = Branch.open_containing(other)
1119
1181
 
1120
1182
        history_1 = branch1.revision_history()
1121
1183
        history_2 = branch2.revision_history()
1122
1184
 
1123
 
        last1 = branch1.last_patch()
1124
 
        last2 = branch2.last_patch()
 
1185
        last1 = branch1.last_revision()
 
1186
        last2 = branch2.last_revision()
1125
1187
 
1126
1188
        source = MultipleRevisionSources(branch1, branch2)
1127
1189
        
1184
1246
            other = [branch, -1]
1185
1247
        else:
1186
1248
            if len(revision) == 1:
1187
 
                other = [branch, revision[0]]
1188
1249
                base = [None, None]
 
1250
                other = [branch, revision[0].in_history(branch).revno]
1189
1251
            else:
1190
1252
                assert len(revision) == 2
1191
1253
                if None in revision:
1192
1254
                    raise BzrCommandError(
1193
1255
                        "Merge doesn't permit that revision specifier.")
1194
 
                base = [branch, revision[0]]
1195
 
                other = [branch, revision[1]]
 
1256
                b = Branch.open(branch)
 
1257
 
 
1258
                base = [branch, revision[0].in_history(b).revno]
 
1259
                other = [branch, revision[1].in_history(b).revno]
1196
1260
 
1197
1261
        try:
1198
1262
            merge(other, base, check_clean=(not force), merge_type=merge_type)
1219
1283
 
1220
1284
    def run(self, revision=None, no_backup=False, file_list=None):
1221
1285
        from bzrlib.merge import merge
1222
 
        from bzrlib.branch import Branch
1223
1286
        from bzrlib.commands import parse_spec
1224
1287
 
1225
1288
        if file_list is not None:
1226
1289
            if len(file_list) == 0:
1227
1290
                raise BzrCommandError("No files specified")
1228
1291
        if revision is None:
1229
 
            revision = [-1]
 
1292
            revno = -1
1230
1293
        elif len(revision) != 1:
1231
1294
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1232
 
        merge(('.', revision[0]), parse_spec('.'),
 
1295
        else:
 
1296
            b = Branch.open_containing('.')
 
1297
            revno = revision[0].in_history(b).revno
 
1298
        merge(('.', revno), parse_spec('.'),
1233
1299
              check_clean=False,
1234
1300
              ignore_zero=True,
1235
1301
              backup_files=not no_backup,
1236
1302
              file_list=file_list)
1237
1303
        if not file_list:
1238
 
            Branch('.').set_pending_merges([])
 
1304
            Branch.open_containing('.').set_pending_merges([])
1239
1305
 
1240
1306
 
1241
1307
class cmd_assert_fail(Command):
1273
1339
        shellcomplete.shellcomplete(context)
1274
1340
 
1275
1341
 
 
1342
class cmd_fetch(Command):
 
1343
    """Copy in history from another branch but don't merge it.
 
1344
 
 
1345
    This is an internal method used for pull and merge."""
 
1346
    hidden = True
 
1347
    takes_args = ['from_branch', 'to_branch']
 
1348
    def run(self, from_branch, to_branch):
 
1349
        from bzrlib.fetch import Fetcher
 
1350
        from bzrlib.branch import Branch
 
1351
        from_b = Branch(from_branch)
 
1352
        to_b = Branch(to_branch)
 
1353
        Fetcher(to_b, from_b)
 
1354
        
 
1355
 
 
1356
 
1276
1357
class cmd_missing(Command):
1277
1358
    """What is missing in this branch relative to other branch.
1278
1359
    """
 
1360
    # TODO: rewrite this in terms of ancestry so that it shows only
 
1361
    # unmerged things
 
1362
    
1279
1363
    takes_args = ['remote?']
1280
1364
    aliases = ['mis', 'miss']
1281
1365
    # We don't have to add quiet to the list, because 
1289
1373
        if verbose and quiet:
1290
1374
            raise BzrCommandError('Cannot pass both quiet and verbose')
1291
1375
 
1292
 
        b = find_branch('.')
 
1376
        b = Branch.open_containing('.')
1293
1377
        parent = b.get_parent()
1294
1378
        if remote is None:
1295
1379
            if parent is None:
1299
1383
                    print "Using last location: %s" % parent
1300
1384
                remote = parent
1301
1385
        elif parent is None:
1302
 
            # We only update x-pull if it did not exist, missing should not change the parent
1303
 
            b.controlfile('x-pull', 'wb').write(remote + '\n')
1304
 
        br_remote = find_branch(remote)
1305
 
 
 
1386
            # We only update parent if it did not exist, missing
 
1387
            # should not change the parent
 
1388
            b.set_parent(remote)
 
1389
        br_remote = Branch.open_containing(remote)
1306
1390
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1307
1391
 
1308
1392
 
1309
 
 
1310
1393
class cmd_plugins(Command):
1311
1394
    """List plugins"""
1312
1395
    hidden = True