~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Jelmer Vernooij
  • Date: 2005-10-19 09:34:39 UTC
  • mfrom: (1185.16.78)
  • mto: (1185.16.102)
  • mto: This revision was merged to the branch mainline in revision 1488.
  • Revision ID: jelmer@samba.org-20051019093439-e1d8e3508d1ba46b
MergeĀ fromĀ Martin

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import os
20
20
 
21
21
import bzrlib
22
 
import bzrlib.trace
23
 
from bzrlib.trace import mutter, note, log_error, warning
 
22
from bzrlib import BZRDIR
 
23
from bzrlib.commands import Command
 
24
from bzrlib.branch import Branch
24
25
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
25
26
from bzrlib.errors import DivergedBranches
26
 
from bzrlib.branch import Branch
27
 
from bzrlib import BZRDIR
28
 
from bzrlib.commands import Command
29
27
from bzrlib.option import Option
 
28
from bzrlib.revisionspec import RevisionSpec
 
29
import bzrlib.trace
 
30
from bzrlib.trace import mutter, note, log_error, warning
30
31
from bzrlib.workingtree import WorkingTree
31
32
 
32
33
 
69
70
    If a revision argument is given, the status is calculated against
70
71
    that revision, or between two revisions if two are provided.
71
72
    """
 
73
    
72
74
    # XXX: FIXME: bzr status should accept a -r option to show changes
73
75
    # relative to a revision, or between revisions
74
76
 
 
77
    # TODO: --no-recurse, --recurse options
 
78
    
75
79
    takes_args = ['file*']
76
80
    takes_options = ['all', 'show-ids']
77
81
    aliases = ['st', 'stat']
78
82
    
79
83
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
80
84
        if file_list:
81
 
            b = Branch.open_containing(file_list[0])
82
 
            tree = WorkingTree(b.base, b)
83
 
            file_list = [tree.relpath(x) for x in file_list]
84
 
            # special case: only one path was given and it's the root
85
 
            # of the branch
86
 
            if file_list == ['']:
 
85
            b, relpath = Branch.open_containing(file_list[0])
 
86
            if relpath == '' and len(file_list) == 1:
87
87
                file_list = None
 
88
            else:
 
89
                # generate relative paths.
 
90
                # note that if this is a remote branch, we would want
 
91
                # relpath against the transport. RBC 20051018
 
92
                tree = WorkingTree(b.base, b)
 
93
                file_list = [tree.relpath(x) for x in file_list]
88
94
        else:
89
 
            b = Branch.open_containing('.')
 
95
            b = Branch.open_containing('.')[0]
90
96
            
91
97
        from bzrlib.status import show_status
92
98
        show_status(b, show_unchanged=all, show_ids=show_ids,
105
111
    takes_options = ['revision']
106
112
    
107
113
    def run(self, revision_id=None, revision=None):
108
 
        from bzrlib.revisionspec import RevisionSpec
109
114
 
110
115
        if revision_id is not None and revision is not None:
111
116
            raise BzrCommandError('You can only supply one of revision_id or --revision')
112
117
        if revision_id is None and revision is None:
113
118
            raise BzrCommandError('You must supply either --revision or a revision_id')
114
 
        b = Branch.open_containing('.')
 
119
        b = Branch.open_containing('.')[0]
115
120
        if revision_id is not None:
116
121
            sys.stdout.write(b.get_revision_xml_file(revision_id).read())
117
122
        elif revision is not None:
127
132
 
128
133
    This is equal to the number of revisions on this branch."""
129
134
    def run(self):
130
 
        print Branch.open_containing('.').revno()
 
135
        print Branch.open_containing('.')[0].revno()
131
136
 
132
137
 
133
138
class cmd_revision_info(Command):
137
142
    takes_args = ['revision_info*']
138
143
    takes_options = ['revision']
139
144
    def run(self, revision=None, revision_info_list=[]):
140
 
        from bzrlib.revisionspec import RevisionSpec
141
145
 
142
146
        revs = []
143
147
        if revision is not None:
148
152
        if len(revs) == 0:
149
153
            raise BzrCommandError('You must supply a revision identifier')
150
154
 
151
 
        b = Branch.open_containing('.')
 
155
        b = Branch.open_containing('.')[0]
152
156
 
153
157
        for rev in revs:
154
158
            revinfo = rev.in_history(b)
206
210
        for d in dir_list:
207
211
            os.mkdir(d)
208
212
            if not b:
209
 
                b = Branch.open_containing(d)
 
213
                b = Branch.open_containing(d)[0]
210
214
            b.add([d])
211
215
            print 'added', d
212
216
 
217
221
    hidden = True
218
222
    
219
223
    def run(self, filename):
220
 
        branch = Branch.open_containing(filename)
221
 
        print WorkingTree(branch.base, branch).relpath(filename)
 
224
        branch, relpath = Branch.open_containing(filename)
 
225
        print relpath
222
226
 
223
227
 
224
228
class cmd_inventory(Command):
226
230
    takes_options = ['revision', 'show-ids']
227
231
    
228
232
    def run(self, revision=None, show_ids=False):
229
 
        b = Branch.open_containing('.')
 
233
        b = Branch.open_containing('.')[0]
230
234
        if revision is None:
231
235
            inv = b.read_working_inventory()
232
236
        else:
252
256
    """
253
257
    takes_args = ['source$', 'dest']
254
258
    def run(self, source_list, dest):
255
 
        b = Branch.open_containing('.')
 
259
        b = Branch.open_containing('.')[0]
256
260
 
257
261
        # TODO: glob expansion on windows?
258
262
        tree = WorkingTree(b.base, b)
276
280
    takes_args = ['from_name', 'to_name']
277
281
    
278
282
    def run(self, from_name, to_name):
279
 
        b = Branch.open_containing('.')
 
283
        b = Branch.open_containing('.')[0]
280
284
        tree = WorkingTree(b.base, b)
281
285
        b.rename_one(tree.relpath(from_name), tree.relpath(to_name))
282
286
 
298
302
    def run(self, names_list):
299
303
        if len(names_list) < 2:
300
304
            raise BzrCommandError("missing file argument")
301
 
        b = Branch.open_containing(names_list[0])
 
305
        b = Branch.open_containing(names_list[0])[0]
302
306
        tree = WorkingTree(b.base, b)
303
307
        rel_names = [tree.relpath(x) for x in names_list]
304
308
        
339
343
        from shutil import rmtree
340
344
        import errno
341
345
        
342
 
        br_to = Branch.open_containing('.')
 
346
        br_to = Branch.open_containing('.')[0]
343
347
        stored_loc = br_to.get_parent()
344
348
        if location is None:
345
349
            if stored_loc is None:
411
415
        try:
412
416
            br_from.setup_caching(cache_root)
413
417
            if basis is not None:
414
 
                basis_branch = Branch.open_containing(basis)
 
418
                basis_branch = Branch.open_containing(basis)[0]
415
419
            else:
416
420
                basis_branch = None
417
421
            if len(revision) == 1 and revision[0] is not None:
453
457
    takes_args = ['dir?']
454
458
 
455
459
    def run(self, dir='.'):
456
 
        b = Branch.open_containing(dir)
 
460
        b = Branch.open_containing(dir)[0]
457
461
        old_inv = b.basis_tree().inventory
458
462
        new_inv = b.read_working_inventory()
459
463
 
469
473
    
470
474
    def run(self, branch=None):
471
475
        import info
472
 
        b = Branch.open_containing(branch)
 
476
        b = Branch.open_containing(branch)[0]
473
477
        info.show_info(b)
474
478
 
475
479
 
484
488
    aliases = ['rm']
485
489
    
486
490
    def run(self, file_list, verbose=False):
487
 
        b = Branch.open_containing(file_list[0])
 
491
        b = Branch.open_containing(file_list[0])[0]
488
492
        tree = WorkingTree(b.base, b)
489
 
        b.remove([tree.relpath(f) for f in file_list], verbose=verbose)
 
493
        tree.remove([tree.relpath(f) for f in file_list], verbose=verbose)
490
494
 
491
495
 
492
496
class cmd_file_id(Command):
499
503
    hidden = True
500
504
    takes_args = ['filename']
501
505
    def run(self, filename):
502
 
        b = Branch.open_containing(filename)
503
 
        tree = WorkingTree(b.base, b)
504
 
        i = b.inventory.path2id(tree.relpath(filename))
 
506
        b, relpath = Branch.open_containing(filename)
 
507
        i = b.inventory.path2id(relpath)
505
508
        if i == None:
506
509
            raise BzrError("%r is not a versioned file" % filename)
507
510
        else:
516
519
    hidden = True
517
520
    takes_args = ['filename']
518
521
    def run(self, filename):
519
 
        b = Branch.open_containing(filename)
 
522
        b, relpath = Branch.open_containing(filename)
520
523
        inv = b.inventory
521
 
        tree = WorkingTree(b.base, b)
522
 
        fid = inv.path2id(tree.relpath(filename))
 
524
        fid = inv.path2id(relpath)
523
525
        if fid == None:
524
526
            raise BzrError("%r is not a versioned file" % filename)
525
527
        for fip in inv.get_idpath(fid):
530
532
    """Display list of revision ids on this branch."""
531
533
    hidden = True
532
534
    def run(self):
533
 
        for patchid in Branch.open_containing('.').revision_history():
 
535
        for patchid in Branch.open_containing('.')[0].revision_history():
534
536
            print patchid
535
537
 
536
538
 
546
548
class cmd_directories(Command):
547
549
    """Display list of versioned directories in this branch."""
548
550
    def run(self):
549
 
        for name, ie in Branch.open_containing('.').read_working_inventory().directories():
 
551
        for name, ie in Branch.open_containing('.')[0].read_working_inventory().directories():
550
552
            if name == '':
551
553
                print '.'
552
554
            else:
603
605
        from bzrlib.diff import show_diff
604
606
 
605
607
        if file_list:
606
 
            b = Branch.open_containing(file_list[0])
 
608
            b = Branch.open_containing(file_list[0])[0]
607
609
            tree = WorkingTree(b.base, b)
608
610
            file_list = [tree.relpath(f) for f in file_list]
609
611
            if file_list == ['']:
610
612
                # just pointing to top-of-tree
611
613
                file_list = None
612
614
        else:
613
 
            b = Branch.open_containing('.')
 
615
            b = Branch.open_containing('.')[0]
614
616
 
615
617
        if revision is not None:
616
618
            if len(revision) == 1:
639
641
    # level of effort but possibly much less IO.  (Or possibly not,
640
642
    # if the directories are very large...)
641
643
    def run(self, show_ids=False):
642
 
        b = Branch.open_containing('.')
 
644
        b = Branch.open_containing('.')[0]
643
645
        old = b.basis_tree()
644
646
        new = b.working_tree()
645
647
        for path, ie in old.inventory.iter_entries():
656
658
    def run(self):
657
659
        from bzrlib.delta import compare_trees
658
660
 
659
 
        b = Branch.open_containing('.')
 
661
        b = Branch.open_containing('.')[0]
660
662
        td = compare_trees(b.basis_tree(), b.working_tree())
661
663
 
662
664
        for path, id, kind, text_modified, meta_modified in td.modified:
668
670
    """List files added in working tree."""
669
671
    hidden = True
670
672
    def run(self):
671
 
        b = Branch.open_containing('.')
 
673
        b = Branch.open_containing('.')[0]
672
674
        wt = b.working_tree()
673
675
        basis_inv = b.basis_tree().inventory
674
676
        inv = wt.inventory
690
692
    takes_args = ['filename?']
691
693
    def run(self, filename=None):
692
694
        """Print the branch root."""
693
 
        b = Branch.open_containing(filename)
 
695
        b = Branch.open_containing(filename)[0]
694
696
        print b.base
695
697
 
696
698
 
733
735
        direction = (forward and 'forward') or 'reverse'
734
736
        
735
737
        if filename:
736
 
            b = Branch.open_containing(filename)
737
 
            tree = WorkingTree(b.base, b)
738
 
            fp = tree.relpath(filename)
739
 
            if fp:
 
738
            b, fp = Branch.open_containing(filename)
 
739
            if fp != '':
740
740
                file_id = b.read_working_inventory().path2id(fp)
741
741
            else:
742
742
                file_id = None  # points to branch root
743
743
        else:
744
 
            b = Branch.open_containing('.')
 
744
            b, relpath = Branch.open_containing('.')
745
745
            file_id = None
746
746
 
747
747
        if revision is None:
794
794
    hidden = True
795
795
    takes_args = ["filename"]
796
796
    def run(self, filename):
797
 
        b = Branch.open_containing(filename)
 
797
        b, relpath = Branch.open_containing(filename)[0]
798
798
        inv = b.read_working_inventory()
799
 
        tree = WorkingTree(b.base, b)
800
 
        file_id = inv.path2id(tree.relpath(filename))
 
799
        file_id = inv.path2id(relpath)
801
800
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
802
801
            print "%6d %s" % (revno, what)
803
802
 
808
807
    # TODO: Take a revision or remote path and list that tree instead.
809
808
    hidden = True
810
809
    def run(self, revision=None, verbose=False):
811
 
        b = Branch.open_containing('.')
 
810
        b, relpath = Branch.open_containing('.')[0]
812
811
        if revision == None:
813
812
            tree = b.working_tree()
814
813
        else:
826
825
    """List unknown files."""
827
826
    def run(self):
828
827
        from bzrlib.osutils import quotefn
829
 
        for f in Branch.open_containing('.').unknowns():
 
828
        for f in Branch.open_containing('.')[0].unknowns():
830
829
            print quotefn(f)
831
830
 
832
831
 
856
855
        from bzrlib.atomicfile import AtomicFile
857
856
        import os.path
858
857
 
859
 
        b = Branch.open_containing('.')
 
858
        b, relpath = Branch.open_containing('.')
860
859
        ifn = b.abspath('.bzrignore')
861
860
 
862
861
        if os.path.exists(ifn):
896
895
 
897
896
    See also: bzr ignore"""
898
897
    def run(self):
899
 
        tree = Branch.open_containing('.').working_tree()
 
898
        tree = Branch.open_containing('.')[0].working_tree()
900
899
        for path, file_class, kind, file_id, entry in tree.list_files():
901
900
            if file_class != 'I':
902
901
                continue
920
919
        except ValueError:
921
920
            raise BzrCommandError("not a valid revision-number: %r" % revno)
922
921
 
923
 
        print Branch.open_containing('.').get_rev_id(revno)
 
922
        print Branch.open_containing('.')[0].get_rev_id(revno)
924
923
 
925
924
 
926
925
class cmd_export(Command):
939
938
    takes_options = ['revision', 'format', 'root']
940
939
    def run(self, dest, revision=None, format=None, root=None):
941
940
        import os.path
942
 
        b = Branch.open_containing('.')
 
941
        b = Branch.open_containing('.')[0]
943
942
        if revision is None:
944
943
            rev_id = b.last_revision()
945
944
        else:
978
977
            raise BzrCommandError("bzr cat requires a revision number")
979
978
        elif len(revision) != 1:
980
979
            raise BzrCommandError("bzr cat --revision takes exactly one number")
981
 
        b = Branch.open_containing('.')
982
 
        tree = WorkingTree(b.base, b)
983
 
        b.print_file(tree.relpath(filename), revision[0].in_history(b).revno)
 
980
        b, relpath = Branch.open_containing(filename)
 
981
        b.print_file(relpath, revision[0].in_history(b).revno)
984
982
 
985
983
 
986
984
class cmd_local_time_offset(Command):
1006
1004
    """
1007
1005
    # TODO: Run hooks on tree to-be-committed, and after commit.
1008
1006
 
1009
 
    # TODO: Strict commit that fails if there are unknown or deleted files.
 
1007
    # TODO: Strict commit that fails if there are deleted files.
 
1008
    #       (what does "deleted files" mean ??)
 
1009
 
1010
1010
    # TODO: Give better message for -s, --summary, used by tla people
1011
1011
 
1012
1012
    # XXX: verbose currently does nothing
1018
1018
                     Option('file', type=str, 
1019
1019
                            argname='msgfile',
1020
1020
                            help='file containing commit message'),
 
1021
                     Option('strict',
 
1022
                            help="refuse to commit if there are unknown "
 
1023
                            "files in the working tree."),
1021
1024
                     ]
1022
1025
    aliases = ['ci', 'checkin']
1023
1026
 
1024
1027
    def run(self, message=None, file=None, verbose=True, selected_list=None,
1025
 
            unchanged=False):
1026
 
        from bzrlib.errors import PointlessCommit, ConflictsInTree
 
1028
            unchanged=False, strict=False):
 
1029
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
 
1030
                StrictCommitFailed)
1027
1031
        from bzrlib.msgeditor import edit_commit_message
1028
1032
        from bzrlib.status import show_status
1029
1033
        from cStringIO import StringIO
1030
1034
 
1031
 
        b = Branch.open_containing('.')
 
1035
        b = Branch.open_containing('.')[0]
1032
1036
        tree = WorkingTree(b.base, b)
1033
1037
        if selected_list:
1034
1038
            selected_list = [tree.relpath(s) for s in selected_list]
1052
1056
                raise BzrCommandError("empty commit message specified")
1053
1057
            
1054
1058
        try:
1055
 
            b.commit(message,
1056
 
                     specific_files=selected_list,
1057
 
                     allow_pointless=unchanged)
 
1059
            b.commit(message, specific_files=selected_list,
 
1060
                     allow_pointless=unchanged, strict=strict)
1058
1061
        except PointlessCommit:
1059
1062
            # FIXME: This should really happen before the file is read in;
1060
1063
            # perhaps prepare the commit; get the message; then actually commit
1063
1066
        except ConflictsInTree:
1064
1067
            raise BzrCommandError("Conflicts detected in working tree.  "
1065
1068
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
 
1069
        except StrictCommitFailed:
 
1070
            raise BzrCommandError("Commit refused because there are unknown "
 
1071
                                  "files in the working tree.")
1066
1072
 
1067
1073
 
1068
1074
class cmd_check(Command):
1076
1082
 
1077
1083
    def run(self, dir='.', verbose=False):
1078
1084
        from bzrlib.check import check
1079
 
        check(Branch.open_containing(dir), verbose)
 
1085
        check(Branch.open_containing(dir)[0], verbose)
1080
1086
 
1081
1087
 
1082
1088
class cmd_scan_cache(Command):
1121
1127
    
1122
1128
    def run(self, email=False):
1123
1129
        try:
1124
 
            b = bzrlib.branch.Branch.open_containing('.')
 
1130
            b = bzrlib.branch.Branch.open_containing('.')[0]
1125
1131
            config = bzrlib.config.BranchConfig(b)
1126
1132
        except NotBranchError:
1127
1133
            config = bzrlib.config.GlobalConfig()
1213
1219
    def run(self, branch, other):
1214
1220
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
1215
1221
        
1216
 
        branch1 = Branch.open_containing(branch)
1217
 
        branch2 = Branch.open_containing(other)
 
1222
        branch1 = Branch.open_containing(branch)[0]
 
1223
        branch2 = Branch.open_containing(other)[0]
1218
1224
 
1219
1225
        history_1 = branch1.revision_history()
1220
1226
        history_2 = branch2.revision_history()
1278
1284
        if merge_type is None:
1279
1285
            merge_type = ApplyMerge3
1280
1286
        if branch is None:
1281
 
            branch = Branch.open_containing('.').get_parent()
 
1287
            branch = Branch.open_containing('.')[0].get_parent()
1282
1288
            if branch is None:
1283
1289
                raise BzrCommandError("No merge location known or specified.")
1284
1290
            else:
1335
1341
        elif len(revision) != 1:
1336
1342
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1337
1343
        else:
1338
 
            b = Branch.open_containing('.')
 
1344
            b = Branch.open_containing('.')[0]
1339
1345
            revno = revision[0].in_history(b).revno
1340
1346
        merge(('.', revno), parse_spec('.'),
1341
1347
              check_clean=False,
1343
1349
              backup_files=not no_backup,
1344
1350
              file_list=file_list)
1345
1351
        if not file_list:
1346
 
            Branch.open_containing('.').set_pending_merges([])
 
1352
            Branch.open_containing('.')[0].set_pending_merges([])
1347
1353
 
1348
1354
 
1349
1355
class cmd_assert_fail(Command):
1415
1421
        if verbose and quiet:
1416
1422
            raise BzrCommandError('Cannot pass both quiet and verbose')
1417
1423
 
1418
 
        b = Branch.open_containing('.')
 
1424
        b = Branch.open_containing('.')[0]
1419
1425
        parent = b.get_parent()
1420
1426
        if remote is None:
1421
1427
            if parent is None:
1428
1434
            # We only update parent if it did not exist, missing
1429
1435
            # should not change the parent
1430
1436
            b.set_parent(remote)
1431
 
        br_remote = Branch.open_containing(remote)
 
1437
        br_remote = Branch.open_containing(remote)[0]
1432
1438
        return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1433
1439
 
1434
1440
 
1457
1463
    takes_args = ['branch?']
1458
1464
    def run(self, branch='.', revision=None, long=False):
1459
1465
        from bzrlib.testament import Testament
1460
 
        b = Branch.open_containing(branch)
 
1466
        b = Branch.open_containing(branch)[0]
1461
1467
        b.lock_read()
1462
1468
        try:
1463
1469
            if revision is None:
1494
1500
 
1495
1501
    def run(self, filename, all=False, long=False):
1496
1502
        from bzrlib.annotate import annotate_file
1497
 
        b = Branch.open_containing(filename)
 
1503
        b, relpath = Branch.open_containing(filename)
1498
1504
        b.lock_read()
1499
1505
        try:
1500
1506
            tree = WorkingTree(b.base, b)
1501
 
            rp = tree.relpath(filename)
1502
1507
            tree = b.revision_tree(b.last_revision())
1503
 
            file_id = tree.inventory.path2id(rp)
 
1508
            file_id = tree.inventory.path2id(relpath)
1504
1509
            file_version = tree.inventory[file_id].revision
1505
1510
            annotate_file(b, file_version, file_id, long, all, sys.stdout)
1506
1511
        finally:
1507
1512
            b.unlock()
1508
1513
 
 
1514
 
 
1515
class cmd_re_sign(Command):
 
1516
    """Create a digital signature for an existing revision."""
 
1517
    # TODO be able to replace existing ones.
 
1518
 
 
1519
    hidden = True # is this right ?
 
1520
    takes_args = ['revision_id?']
 
1521
    takes_options = ['revision']
 
1522
    
 
1523
    def run(self, revision_id=None, revision=None):
 
1524
        import bzrlib.config as config
 
1525
        import bzrlib.gpg as gpg
 
1526
        if revision_id is not None and revision is not None:
 
1527
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
1528
        if revision_id is None and revision is None:
 
1529
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
1530
        b = Branch.open_containing('.')[0]
 
1531
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
 
1532
        if revision_id is not None:
 
1533
            b.sign_revision(revision_id, gpg_strategy)
 
1534
        elif revision is not None:
 
1535
            for rev in revision:
 
1536
                if rev is None:
 
1537
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
1538
                revno, rev_id = rev.in_history(b)
 
1539
                b.sign_revision(rev_id, gpg_strategy)
 
1540
 
 
1541
 
1509
1542
# these get imported and then picked up by the scan for cmd_*
1510
1543
# TODO: Some more consistent way to split command definitions across files;
1511
1544
# we do need to load at least some information about them to know of