~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Martin Pool
  • Date: 2005-08-30 06:10:39 UTC
  • Revision ID: mbp@sourcefrog.net-20050830061039-1d0347fb236c39ad
- clean up some code in revision.py

- move all exceptions to bzrlib.errors

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, NotBranchError
25
 
from bzrlib.branch import Branch
 
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
 
25
from bzrlib.branch import find_branch
26
26
from bzrlib import BZRDIR
27
27
from bzrlib.commands import Command
28
28
 
63
63
    files or directories is reported.  If a directory is given, status
64
64
    is reported for everything inside that directory.
65
65
 
66
 
    If a revision argument is given, the status is calculated against
67
 
    that revision, or between two revisions if two are provided.
 
66
    If a revision is specified, the changes since that revision are shown.
68
67
    """
69
 
    # XXX: FIXME: bzr status should accept a -r option to show changes
70
 
    # relative to a revision, or between revisions
71
 
 
72
68
    takes_args = ['file*']
73
69
    takes_options = ['all', 'show-ids', 'revision']
74
70
    aliases = ['st', 'stat']
75
71
    
76
 
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
 
72
    def run(self, all=False, show_ids=False, file_list=None):
77
73
        if file_list:
78
 
            b = Branch.open_containing(file_list[0])
 
74
            b = find_branch(file_list[0])
79
75
            file_list = [b.relpath(x) for x in file_list]
80
76
            # special case: only one path was given and it's the root
81
77
            # of the branch
82
78
            if file_list == ['']:
83
79
                file_list = None
84
80
        else:
85
 
            b = Branch.open_containing('.')
 
81
            b = find_branch('.')
86
82
            
87
83
        from bzrlib.status import show_status
88
84
        show_status(b, show_unchanged=all, show_ids=show_ids,
89
 
                    specific_files=file_list, revision=revision)
 
85
                    specific_files=file_list)
90
86
 
91
87
 
92
88
class cmd_cat_revision(Command):
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
 
    """
 
89
    """Write out metadata for a revision."""
98
90
 
99
91
    hidden = True
100
 
    takes_args = ['revision_id?']
101
 
    takes_options = ['revision']
 
92
    takes_args = ['revision_id']
102
93
    
103
 
    def run(self, revision_id=None, revision=None):
104
 
        from bzrlib.revisionspec import RevisionSpec
 
94
    def run(self, revision_id):
 
95
        from bzrlib.xml import pack_xml
 
96
        pack_xml(find_branch('.').get_revision(revision_id), sys.stdout)
105
97
 
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
 
    
120
98
 
121
99
class cmd_revno(Command):
122
100
    """Show current revision number.
123
101
 
124
102
    This is equal to the number of revisions on this branch."""
125
103
    def run(self):
126
 
        print Branch.open_containing('.').revno()
127
 
 
 
104
        print find_branch('.').revno()
128
105
 
129
106
class cmd_revision_info(Command):
130
107
    """Show revision number and revision id for a given revision identifier.
132
109
    hidden = True
133
110
    takes_args = ['revision_info*']
134
111
    takes_options = ['revision']
135
 
    def run(self, revision=None, revision_info_list=[]):
136
 
        from bzrlib.revisionspec import RevisionSpec
 
112
    def run(self, revision=None, revision_info_list=None):
 
113
        from bzrlib.branch import find_branch
137
114
 
138
115
        revs = []
139
116
        if revision is not None:
140
117
            revs.extend(revision)
141
118
        if revision_info_list is not None:
142
 
            for rev in revision_info_list:
143
 
                revs.append(RevisionSpec(rev))
 
119
            revs.extend(revision_info_list)
144
120
        if len(revs) == 0:
145
121
            raise BzrCommandError('You must supply a revision identifier')
146
122
 
147
 
        b = Branch.open_containing('.')
 
123
        b = find_branch('.')
148
124
 
149
125
        for rev in revs:
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)
 
126
            print '%4d %s' % b.get_revision_info(rev)
155
127
 
156
128
    
157
129
class cmd_add(Command):
172
144
    Therefore simply saying 'bzr add' will version all files that
173
145
    are currently unknown.
174
146
 
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.
 
147
    TODO: Perhaps adding a file whose directly is not versioned should
 
148
    recursively add that parent, rather than giving an error?
179
149
    """
180
150
    takes_args = ['file*']
181
151
    takes_options = ['verbose', 'no-recurse']
182
152
    
183
153
    def run(self, file_list, verbose=False, no_recurse=False):
184
 
        # verbose currently has no effect
185
 
        from bzrlib.add import smart_add, add_reporter_print
186
 
        smart_add(file_list, not no_recurse, add_reporter_print)
 
154
        from bzrlib.add import smart_add, _PrintAddCallback
 
155
        smart_add(file_list, verbose, not no_recurse,
 
156
                  callback=_PrintAddCallback)
187
157
 
188
158
 
189
159
 
200
170
        for d in dir_list:
201
171
            os.mkdir(d)
202
172
            if not b:
203
 
                b = Branch.open_containing(d)
 
173
                b = find_branch(d)
204
174
            b.add([d])
205
175
            print 'added', d
206
176
 
211
181
    hidden = True
212
182
    
213
183
    def run(self, filename):
214
 
        print Branch.open_containing(filename).relpath(filename)
 
184
        print find_branch(filename).relpath(filename)
215
185
 
216
186
 
217
187
 
220
190
    takes_options = ['revision', 'show-ids']
221
191
    
222
192
    def run(self, revision=None, show_ids=False):
223
 
        b = Branch.open_containing('.')
224
 
        if revision is None:
 
193
        b = find_branch('.')
 
194
        if revision == None:
225
195
            inv = b.read_working_inventory()
226
196
        else:
227
197
            if len(revision) > 1:
228
198
                raise BzrCommandError('bzr inventory --revision takes'
229
199
                    ' exactly one revision identifier')
230
 
            inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
 
200
            inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
231
201
 
232
202
        for path, entry in inv.entries():
233
203
            if show_ids:
246
216
    """
247
217
    takes_args = ['source$', 'dest']
248
218
    def run(self, source_list, dest):
249
 
        b = Branch.open_containing('.')
 
219
        b = find_branch('.')
250
220
 
251
221
        # TODO: glob expansion on windows?
252
222
        b.move([b.relpath(s) for s in source_list], b.relpath(dest))
269
239
    takes_args = ['from_name', 'to_name']
270
240
    
271
241
    def run(self, from_name, to_name):
272
 
        b = Branch.open_containing('.')
 
242
        b = find_branch('.')
273
243
        b.rename_one(b.relpath(from_name), b.relpath(to_name))
274
244
 
275
245
 
291
261
    def run(self, names_list):
292
262
        if len(names_list) < 2:
293
263
            raise BzrCommandError("missing file argument")
294
 
        b = Branch.open_containing(names_list[0])
 
264
        b = find_branch(names_list[0])
295
265
 
296
266
        rel_names = [b.relpath(x) for x in names_list]
297
267
        
303
273
            if len(names_list) != 2:
304
274
                raise BzrCommandError('to mv multiple files the destination '
305
275
                                      'must be a versioned directory')
306
 
            b.rename_one(rel_names[0], rel_names[1])
307
 
            print "%s => %s" % (rel_names[0], rel_names[1])
 
276
            for pair in b.move(rel_names[0], rel_names[1]):
 
277
                print "%s => %s" % pair
308
278
            
309
279
    
310
280
 
330
300
        import tempfile
331
301
        from shutil import rmtree
332
302
        import errno
 
303
        from bzrlib.branch import pull_loc
333
304
        
334
 
        br_to = Branch.open_containing('.')
335
 
        stored_loc = br_to.get_parent()
 
305
        br_to = find_branch('.')
 
306
        stored_loc = None
 
307
        try:
 
308
            stored_loc = br_to.controlfile("x-pull", "rb").read().rstrip('\n')
 
309
        except IOError, e:
 
310
            if e.errno != errno.ENOENT:
 
311
                raise
336
312
        if location is None:
337
313
            if stored_loc is None:
338
314
                raise BzrCommandError("No pull location known or specified.")
340
316
                print "Using last location: %s" % stored_loc
341
317
                location = stored_loc
342
318
        cache_root = tempfile.mkdtemp()
343
 
        from bzrlib.errors import DivergedBranches
344
 
        br_from = Branch.open_containing(location)
345
 
        location = br_from.base
 
319
        from bzrlib.branch import DivergedBranches
 
320
        br_from = find_branch(location)
 
321
        location = pull_loc(br_from)
346
322
        old_revno = br_to.revno()
347
323
        try:
348
 
            from bzrlib.errors import DivergedBranches
349
 
            br_from = Branch.open(location)
350
 
            br_from.setup_caching(cache_root)
351
 
            location = br_from.base
 
324
            from branch import find_cached_branch, DivergedBranches
 
325
            br_from = find_cached_branch(location, cache_root)
 
326
            location = pull_loc(br_from)
352
327
            old_revno = br_to.revno()
353
328
            try:
354
329
                br_to.update_revisions(br_from)
358
333
                
359
334
            merge(('.', -1), ('.', old_revno), check_clean=False)
360
335
            if location != stored_loc:
361
 
                br_to.set_parent(location)
 
336
                br_to.controlfile("x-pull", "wb").write(location + "\n")
362
337
        finally:
363
338
            rmtree(cache_root)
364
339
 
372
347
 
373
348
    To retrieve the branch as of a particular revision, supply the --revision
374
349
    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.
379
350
    """
380
351
    takes_args = ['from_location', 'to_location?']
381
 
    takes_options = ['revision', 'basis']
 
352
    takes_options = ['revision']
382
353
    aliases = ['get', 'clone']
383
354
 
384
 
    def run(self, from_location, to_location=None, revision=None, basis=None):
385
 
        from bzrlib.clone import copy_branch
 
355
    def run(self, from_location, to_location=None, revision=None):
 
356
        from bzrlib.branch import copy_branch, find_cached_branch
386
357
        import tempfile
387
358
        import errno
388
359
        from shutil import rmtree
394
365
                raise BzrCommandError(
395
366
                    'bzr branch --revision takes exactly 1 revision value')
396
367
            try:
397
 
                br_from = Branch.open(from_location)
 
368
                br_from = find_cached_branch(from_location, cache_root)
398
369
            except OSError, e:
399
370
                if e.errno == errno.ENOENT:
400
371
                    raise BzrCommandError('Source location "%s" does not'
401
372
                                          ' exist.' % to_location)
402
373
                else:
403
374
                    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
413
375
            if to_location is None:
414
376
                to_location = os.path.basename(from_location.rstrip("/\\"))
415
377
            try:
424
386
                else:
425
387
                    raise
426
388
            try:
427
 
                copy_branch(br_from, to_location, revision_id, basis_branch)
 
389
                copy_branch(br_from, to_location, revision[0])
428
390
            except bzrlib.errors.NoSuchRevision:
429
391
                rmtree(to_location)
430
392
                msg = "The branch %s has no revision %d." % (from_location, revision[0])
431
393
                raise BzrCommandError(msg)
432
 
            except bzrlib.errors.UnlistableBranch:
433
 
                msg = "The branch %s cannot be used as a --basis"
434
394
        finally:
435
395
            rmtree(cache_root)
436
396
 
445
405
    takes_args = ['dir?']
446
406
 
447
407
    def run(self, dir='.'):
448
 
        b = Branch.open_containing(dir)
 
408
        b = find_branch(dir)
449
409
        old_inv = b.basis_tree().inventory
450
410
        new_inv = b.read_working_inventory()
451
411
 
462
422
    def run(self, branch=None):
463
423
        import info
464
424
 
465
 
        b = Branch.open_containing(branch)
 
425
        b = find_branch(branch)
466
426
        info.show_info(b)
467
427
 
468
428
 
476
436
    takes_options = ['verbose']
477
437
    
478
438
    def run(self, file_list, verbose=False):
479
 
        b = Branch.open_containing(file_list[0])
 
439
        b = find_branch(file_list[0])
480
440
        b.remove([b.relpath(f) for f in file_list], verbose=verbose)
481
441
 
482
442
 
490
450
    hidden = True
491
451
    takes_args = ['filename']
492
452
    def run(self, filename):
493
 
        b = Branch.open_containing(filename)
 
453
        b = find_branch(filename)
494
454
        i = b.inventory.path2id(b.relpath(filename))
495
455
        if i == None:
496
456
            raise BzrError("%r is not a versioned file" % filename)
506
466
    hidden = True
507
467
    takes_args = ['filename']
508
468
    def run(self, filename):
509
 
        b = Branch.open_containing(filename)
 
469
        b = find_branch(filename)
510
470
        inv = b.inventory
511
471
        fid = inv.path2id(b.relpath(filename))
512
472
        if fid == None:
519
479
    """Display list of revision ids on this branch."""
520
480
    hidden = True
521
481
    def run(self):
522
 
        for patchid in Branch.open_containing('.').revision_history():
 
482
        for patchid in find_branch('.').revision_history():
523
483
            print patchid
524
484
 
525
485
 
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
 
 
535
486
class cmd_directories(Command):
536
487
    """Display list of versioned directories in this branch."""
537
488
    def run(self):
538
 
        for name, ie in Branch.open_containing('.').read_working_inventory().directories():
 
489
        for name, ie in find_branch('.').read_working_inventory().directories():
539
490
            if name == '':
540
491
                print '.'
541
492
            else:
557
508
    """
558
509
    def run(self):
559
510
        from bzrlib.branch import Branch
560
 
        Branch.initialize('.')
 
511
        Branch('.', init=True)
561
512
 
562
513
 
563
514
class cmd_diff(Command):
584
535
    examples:
585
536
        bzr diff
586
537
        bzr diff -r1
587
 
        bzr diff -r1..2
 
538
        bzr diff -r1:2
588
539
    """
589
540
    
590
541
    takes_args = ['file*']
595
546
        from bzrlib.diff import show_diff
596
547
 
597
548
        if file_list:
598
 
            b = Branch.open_containing(file_list[0])
 
549
            b = find_branch(file_list[0])
599
550
            file_list = [b.relpath(f) for f in file_list]
600
551
            if file_list == ['']:
601
552
                # just pointing to top-of-tree
602
553
                file_list = None
603
554
        else:
604
 
            b = Branch.open_containing('.')
 
555
            b = find_branch('.')
605
556
 
606
557
        if revision is not None:
607
558
            if len(revision) == 1:
626
577
    TODO: Show files deleted since a previous revision, or between two revisions.
627
578
    """
628
579
    def run(self, show_ids=False):
629
 
        b = Branch.open_containing('.')
 
580
        b = find_branch('.')
630
581
        old = b.basis_tree()
631
582
        new = b.working_tree()
632
583
 
649
600
    def run(self):
650
601
        from bzrlib.delta import compare_trees
651
602
 
652
 
        b = Branch.open_containing('.')
 
603
        b = find_branch('.')
653
604
        td = compare_trees(b.basis_tree(), b.working_tree())
654
605
 
655
606
        for path, id, kind in td.modified:
661
612
    """List files added in working tree."""
662
613
    hidden = True
663
614
    def run(self):
664
 
        b = Branch.open_containing('.')
 
615
        b = find_branch('.')
665
616
        wt = b.working_tree()
666
617
        basis_inv = b.basis_tree().inventory
667
618
        inv = wt.inventory
683
634
    takes_args = ['filename?']
684
635
    def run(self, filename=None):
685
636
        """Print the branch root."""
686
 
        b = Branch.open_containing(filename)
687
 
        print b.base
 
637
        b = find_branch(filename)
 
638
        print getattr(b, 'base', None) or getattr(b, 'baseurl')
688
639
 
689
640
 
690
641
class cmd_log(Command):
719
670
        direction = (forward and 'forward') or 'reverse'
720
671
        
721
672
        if filename:
722
 
            b = Branch.open_containing(filename)
 
673
            b = find_branch(filename)
723
674
            fp = b.relpath(filename)
724
675
            if fp:
725
676
                file_id = b.read_working_inventory().path2id(fp)
726
677
            else:
727
678
                file_id = None  # points to branch root
728
679
        else:
729
 
            b = Branch.open_containing('.')
 
680
            b = find_branch('.')
730
681
            file_id = None
731
682
 
732
683
        if revision is None:
733
684
            rev1 = None
734
685
            rev2 = None
735
686
        elif len(revision) == 1:
736
 
            rev1 = rev2 = revision[0].in_history(b).revno
 
687
            rev1 = rev2 = b.get_revision_info(revision[0])[0]
737
688
        elif len(revision) == 2:
738
 
            rev1 = revision[0].in_history(b).revno
739
 
            rev2 = revision[1].in_history(b).revno
 
689
            rev1 = b.get_revision_info(revision[0])[0]
 
690
            rev2 = b.get_revision_info(revision[1])[0]
740
691
        else:
741
692
            raise BzrCommandError('bzr log --revision takes one or two values.')
742
693
 
778
729
    hidden = True
779
730
    takes_args = ["filename"]
780
731
    def run(self, filename):
781
 
        b = Branch.open_containing(filename)
 
732
        b = find_branch(filename)
782
733
        inv = b.read_working_inventory()
783
734
        file_id = inv.path2id(b.relpath(filename))
784
735
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
792
743
    """
793
744
    hidden = True
794
745
    def run(self, revision=None, verbose=False):
795
 
        b = Branch.open_containing('.')
 
746
        b = find_branch('.')
796
747
        if revision == None:
797
748
            tree = b.working_tree()
798
749
        else:
799
 
            tree = b.revision_tree(revision.in_history(b).rev_id)
 
750
            tree = b.revision_tree(b.lookup_revision(revision))
800
751
 
801
752
        for fp, fc, kind, fid in tree.list_files():
802
753
            if verbose:
817
768
    """List unknown files."""
818
769
    def run(self):
819
770
        from bzrlib.osutils import quotefn
820
 
        for f in Branch.open_containing('.').unknowns():
 
771
        for f in find_branch('.').unknowns():
821
772
            print quotefn(f)
822
773
 
823
774
 
845
796
        from bzrlib.atomicfile import AtomicFile
846
797
        import os.path
847
798
 
848
 
        b = Branch.open_containing('.')
 
799
        b = find_branch('.')
849
800
        ifn = b.abspath('.bzrignore')
850
801
 
851
802
        if os.path.exists(ifn):
885
836
 
886
837
    See also: bzr ignore"""
887
838
    def run(self):
888
 
        tree = Branch.open_containing('.').working_tree()
 
839
        tree = find_branch('.').working_tree()
889
840
        for path, file_class, kind, file_id in tree.list_files():
890
841
            if file_class != 'I':
891
842
                continue
909
860
        except ValueError:
910
861
            raise BzrCommandError("not a valid revision-number: %r" % revno)
911
862
 
912
 
        print Branch.open_containing('.').get_rev_id(revno)
 
863
        print find_branch('.').lookup_revision(revno)
913
864
 
914
865
 
915
866
class cmd_export(Command):
928
879
    takes_options = ['revision', 'format', 'root']
929
880
    def run(self, dest, revision=None, format=None, root=None):
930
881
        import os.path
931
 
        b = Branch.open_containing('.')
 
882
        b = find_branch('.')
932
883
        if revision is None:
933
 
            rev_id = b.last_revision()
 
884
            rev_id = b.last_patch()
934
885
        else:
935
886
            if len(revision) != 1:
936
887
                raise BzrError('bzr export --revision takes exactly 1 argument')
937
 
            rev_id = revision[0].in_history(b).rev_id
 
888
            revno, rev_id = b.get_revision_info(revision[0])
938
889
        t = b.revision_tree(rev_id)
939
890
        root, ext = os.path.splitext(dest)
940
891
        if not format:
956
907
    takes_args = ['filename']
957
908
 
958
909
    def run(self, filename, revision=None):
959
 
        if revision is None:
 
910
        if revision == None:
960
911
            raise BzrCommandError("bzr cat requires a revision number")
961
912
        elif len(revision) != 1:
962
913
            raise BzrCommandError("bzr cat --revision takes exactly one number")
963
 
        b = Branch.open_containing('.')
964
 
        b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
 
914
        b = find_branch('.')
 
915
        b.print_file(b.relpath(filename), revision[0])
965
916
 
966
917
 
967
918
class cmd_local_time_offset(Command):
994
945
    aliases = ['ci', 'checkin']
995
946
 
996
947
    # TODO: Give better message for -s, --summary, used by tla people
997
 
 
998
 
    # XXX: verbose currently does nothing
999
948
    
1000
949
    def run(self, message=None, file=None, verbose=True, selected_list=None,
1001
950
            unchanged=False):
1002
951
        from bzrlib.errors import PointlessCommit
1003
 
        from bzrlib.msgeditor import edit_commit_message
1004
 
        from bzrlib.status import show_status
1005
 
        from cStringIO import StringIO
 
952
        from bzrlib.osutils import get_text_message
1006
953
 
1007
 
        b = Branch.open_containing('.')
1008
 
        if selected_list:
1009
 
            selected_list = [b.relpath(s) for s in selected_list]
1010
 
            
 
954
        ## Warning: shadows builtin file()
1011
955
        if not message and not file:
1012
 
            catcher = StringIO()
1013
 
            show_status(b, specific_files=selected_list,
1014
 
                        to_file=catcher)
1015
 
            message = edit_commit_message(catcher.getvalue())
 
956
            # FIXME: Ugly; change status code to send to a provided function?
 
957
            
 
958
            import cStringIO
 
959
            stdout = sys.stdout
 
960
            catcher = cStringIO.StringIO()
 
961
            sys.stdout = catcher
 
962
            cmd_status({"file_list":selected_list}, {})
 
963
            info = catcher.getvalue()
 
964
            sys.stdout = stdout
 
965
            message = get_text_message(info)
1016
966
            
1017
967
            if message is None:
1018
 
                raise BzrCommandError("please specify a commit message"
1019
 
                                      " with either --message or --file")
 
968
                raise BzrCommandError("please specify a commit message",
 
969
                                      ["use either --message or --file"])
1020
970
        elif message and file:
1021
971
            raise BzrCommandError("please specify either --message or --file")
1022
972
        
1024
974
            import codecs
1025
975
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1026
976
 
 
977
        b = find_branch('.')
 
978
        if selected_list:
 
979
            selected_list = [b.relpath(s) for s in selected_list]
 
980
            
1027
981
        try:
1028
 
            b.commit(message,
 
982
            b.commit(message, verbose=verbose,
1029
983
                     specific_files=selected_list,
1030
984
                     allow_pointless=unchanged)
1031
985
        except PointlessCommit:
1040
994
 
1041
995
    This command checks various invariants about the branch storage to
1042
996
    detect data corruption or bzr bugs.
 
997
 
 
998
    If given the --update flag, it will update some optional fields
 
999
    to help ensure data consistency.
1043
1000
    """
1044
1001
    takes_args = ['dir?']
1045
1002
 
1046
1003
    def run(self, dir='.'):
1047
1004
        from bzrlib.check import check
1048
1005
 
1049
 
        check(Branch.open_containing(dir))
 
1006
        check(find_branch(dir))
1050
1007
 
1051
1008
 
1052
1009
class cmd_scan_cache(Command):
1074
1031
 
1075
1032
    The check command or bzr developers may sometimes advise you to run
1076
1033
    this command.
1077
 
 
1078
 
    This version of this command upgrades from the full-text storage
1079
 
    used by bzr 0.0.8 and earlier to the weave format (v5).
1080
1034
    """
1081
1035
    takes_args = ['dir?']
1082
1036
 
1083
1037
    def run(self, dir='.'):
1084
1038
        from bzrlib.upgrade import upgrade
1085
 
        upgrade(dir)
 
1039
        upgrade(find_branch(dir))
 
1040
 
1086
1041
 
1087
1042
 
1088
1043
class cmd_whoami(Command):
1091
1046
    
1092
1047
    def run(self, email=False):
1093
1048
        try:
1094
 
            b = bzrlib.branch.Branch.open_containing('.')
1095
 
        except NotBranchError:
 
1049
            b = bzrlib.branch.find_branch('.')
 
1050
        except:
1096
1051
            b = None
1097
1052
        
1098
1053
        if email:
1161
1116
    hidden = True
1162
1117
    
1163
1118
    def run(self, branch, other):
1164
 
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
1165
 
        
1166
 
        branch1 = Branch.open_containing(branch)
1167
 
        branch2 = Branch.open_containing(other)
1168
 
 
1169
 
        history_1 = branch1.revision_history()
1170
 
        history_2 = branch2.revision_history()
1171
 
 
1172
 
        last1 = branch1.last_revision()
1173
 
        last2 = branch2.last_revision()
1174
 
 
1175
 
        source = MultipleRevisionSources(branch1, branch2)
1176
 
        
1177
 
        base_rev_id = common_ancestor(last1, last2, source)
1178
 
 
1179
 
        print 'merge base is revision %s' % base_rev_id
1180
 
        
1181
 
        return
 
1119
        branch1 = find_branch(branch)
 
1120
        branch2 = find_branch(other)
 
1121
 
 
1122
        base_revno, base_revid = branch1.common_ancestor(branch2)
1182
1123
 
1183
1124
        if base_revno is None:
1184
1125
            raise bzrlib.errors.UnrelatedBranches()
1185
1126
 
 
1127
        print 'merge base is revision %s' % base_revid
1186
1128
        print ' r%-6d in %s' % (base_revno, branch)
1187
1129
 
1188
1130
        other_revno = branch2.revision_id_to_revno(base_revid)
1194
1136
class cmd_merge(Command):
1195
1137
    """Perform a three-way merge.
1196
1138
    
1197
 
    The branch is the branch you will merge from.  By default, it will
1198
 
    merge the latest revision.  If you specify a revision, that
1199
 
    revision will be merged.  If you specify two revisions, the first
1200
 
    will be used as a BASE, and the second one as OTHER.  Revision
1201
 
    numbers are always relative to the specified branch.
1202
 
 
1203
 
    By default bzr will try to merge in all new work from the other
1204
 
    branch, automatically determining an appropriate base.  If this
1205
 
    fails, you may need to give an explicit base.
 
1139
    The branch is the branch you will merge from.  By default, it will merge
 
1140
    the latest revision.  If you specify a revision, that revision will be
 
1141
    merged.  If you specify two revisions, the first will be used as a BASE, 
 
1142
    and the second one as OTHER.  Revision numbers are always relative to the
 
1143
    specified branch.
1206
1144
    
1207
1145
    Examples:
1208
1146
 
1230
1168
 
1231
1169
        if revision is None or len(revision) < 1:
1232
1170
            base = [None, None]
1233
 
            other = [branch, -1]
 
1171
            other = (branch, -1)
1234
1172
        else:
1235
1173
            if len(revision) == 1:
1236
 
                base = [None, None]
1237
 
                other = [branch, revision[0].in_history(branch).revno]
 
1174
                other = (branch, revision[0])
 
1175
                base = (None, None)
1238
1176
            else:
1239
1177
                assert len(revision) == 2
1240
1178
                if None in revision:
1241
1179
                    raise BzrCommandError(
1242
1180
                        "Merge doesn't permit that revision specifier.")
1243
 
                from bzrlib.branch import Branch
1244
 
                b = Branch.open(branch)
1245
 
 
1246
 
                base = [branch, revision[0].in_history(b).revno]
1247
 
                other = [branch, revision[1].in_history(b).revno]
1248
 
 
1249
 
        try:
1250
 
            merge(other, base, check_clean=(not force), merge_type=merge_type)
1251
 
        except bzrlib.errors.AmbiguousBase, e:
1252
 
            m = ("sorry, bzr can't determine the right merge base yet\n"
1253
 
                 "candidates are:\n  "
1254
 
                 + "\n  ".join(e.bases)
1255
 
                 + "\n"
1256
 
                 "please specify an explicit base with -r,\n"
1257
 
                 "and (if you want) report this to the bzr developers\n")
1258
 
            log_error(m)
 
1181
                base = (branch, revision[0])
 
1182
                other = (branch, revision[1])
 
1183
            
 
1184
        merge(other, base, check_clean=(not force), merge_type=merge_type)
1259
1185
 
1260
1186
 
1261
1187
class cmd_revert(Command):
1278
1204
            if len(file_list) == 0:
1279
1205
                raise BzrCommandError("No files specified")
1280
1206
        if revision is None:
1281
 
            revno = -1
 
1207
            revision = [-1]
1282
1208
        elif len(revision) != 1:
1283
1209
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1284
 
        else:
1285
 
            b = Branch.open_containing('.')
1286
 
            revno = revision[0].in_history(b).revno
1287
 
        merge(('.', revno), parse_spec('.'),
 
1210
        merge(('.', revision[0]), parse_spec('.'),
1288
1211
              check_clean=False,
1289
1212
              ignore_zero=True,
1290
1213
              backup_files=not no_backup,
1291
1214
              file_list=file_list)
1292
1215
        if not file_list:
1293
 
            Branch.open_containing('.').set_pending_merges([])
 
1216
            Branch('.').set_pending_merges([])
1294
1217
 
1295
1218
 
1296
1219
class cmd_assert_fail(Command):
1328
1251
        shellcomplete.shellcomplete(context)
1329
1252
 
1330
1253
 
1331
 
class cmd_fetch(Command):
1332
 
    """Copy in history from another branch but don't merge it.
1333
 
 
1334
 
    This is an internal method used for pull and merge."""
1335
 
    hidden = True
1336
 
    takes_args = ['from_branch', 'to_branch']
1337
 
    def run(self, from_branch, to_branch):
1338
 
        from bzrlib.fetch import Fetcher
1339
 
        from bzrlib.branch import Branch
1340
 
        from_b = Branch(from_branch)
1341
 
        to_b = Branch(to_branch)
1342
 
        Fetcher(to_b, from_b)
1343
 
        
1344
 
 
1345
 
 
1346
1254
class cmd_missing(Command):
1347
1255
    """What is missing in this branch relative to other branch.
1348
1256
    """
1349
 
    # TODO: rewrite this in terms of ancestry so that it shows only
1350
 
    # unmerged things
1351
 
    
1352
1257
    takes_args = ['remote?']
1353
1258
    aliases = ['mis', 'miss']
1354
1259
    # We don't have to add quiet to the list, because 
1362
1267
        if verbose and quiet:
1363
1268
            raise BzrCommandError('Cannot pass both quiet and verbose')
1364
1269
 
1365
 
        b = Branch.open_containing('.')
 
1270
        b = find_branch('.')
1366
1271
        parent = b.get_parent()
1367
1272
        if remote is None:
1368
1273
            if parent is None:
1372
1277
                    print "Using last location: %s" % parent
1373
1278
                remote = parent
1374
1279
        elif parent is None:
1375
 
            # We only update parent if it did not exist, missing
1376
 
            # should not change the parent
1377
 
            b.set_parent(remote)
1378
 
        br_remote = Branch.open_containing(remote)
 
1280
            # We only update x-pull if it did not exist, missing should not change the parent
 
1281
            b.controlfile('x-pull', 'wb').write(remote + '\n')
 
1282
        br_remote = find_branch(remote)
1379
1283
 
1380
1284
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1381
1285