~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Aaron Bentley
  • Date: 2006-03-07 05:59:14 UTC
  • mfrom: (1558.1.20 Aaron's integration)
  • mto: This revision was merged to the branch mainline in revision 1595.
  • Revision ID: aaron.bentley@utoronto.ca-20060307055914-a88728997afceb90
MergeĀ fromĀ mainline

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005 by Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006 by Canonical Ltd
2
2
 
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
31
31
import bzrlib.errors as errors
32
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
33
33
                           NotBranchError, DivergedBranches, NotConflicted,
34
 
                           NoSuchFile, NoWorkingTree, FileInWrongBranch)
 
34
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
 
35
                           NotVersionedError)
35
36
from bzrlib.log import show_one_log
36
37
from bzrlib.merge import Merge3Merger
37
38
from bzrlib.option import Option
595
596
                else:
596
597
                    raise
597
598
            try:
 
599
                # preserve whatever source format we have.
598
600
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
599
601
                branch = dir.open_branch()
600
602
            except bzrlib.errors.NoSuchRevision:
603
605
                raise BzrCommandError(msg)
604
606
            except bzrlib.errors.UnlistableBranch:
605
607
                rmtree(to_location)
606
 
                msg = "The branch %s cannot be used as a --basis"
 
608
                msg = "The branch %s cannot be used as a --basis" % (basis,)
607
609
                raise BzrCommandError(msg)
608
610
            if name:
609
611
                branch.control_files.put_utf8('branch-name', name)
629
631
    branch being checked out. [Not implemented yet.]
630
632
    """
631
633
    takes_args = ['branch_location', 'to_location?']
632
 
    takes_options = ['revision'] # , 'basis']
 
634
    takes_options = ['revision', # , 'basis']
 
635
                     Option('lightweight',
 
636
                            help="perform a lightweight checkout. Lightweight "
 
637
                                 "checkouts depend on access to the branch for "
 
638
                                 "every operation. Normal checkouts can perform "
 
639
                                 "common operations like diff and status without "
 
640
                                 "such access, and also support local commits."
 
641
                            ),
 
642
                     ]
633
643
 
634
 
    def run(self, branch_location, to_location=None, revision=None, basis=None):
 
644
    def run(self, branch_location, to_location=None, revision=None, basis=None,
 
645
            lightweight=False):
635
646
        if revision is None:
636
647
            revision = [None]
637
648
        elif len(revision) > 1:
655
666
                                      to_location)
656
667
            else:
657
668
                raise
658
 
        checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
659
 
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
660
 
        checkout.create_workingtree(revision_id)
 
669
        old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
670
        bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
 
671
        try:
 
672
            if lightweight:
 
673
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
 
674
                bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
 
675
            else:
 
676
                checkout_branch =  bzrlib.bzrdir.BzrDir.create_branch_convenience(
 
677
                    to_location, force_new_tree=False)
 
678
                checkout = checkout_branch.bzrdir
 
679
                checkout_branch.bind(source)
 
680
                if revision_id is not None:
 
681
                    rh = checkout_branch.revision_history()
 
682
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
 
683
            checkout.create_workingtree(revision_id)
 
684
        finally:
 
685
            bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
661
686
 
662
687
 
663
688
class cmd_renames(Command):
684
709
    """Update a tree to have the latest code committed to its branch.
685
710
    
686
711
    This will perform a merge into the working tree, and may generate
687
 
    conflicts. If you have any uncommitted changes, you will still 
688
 
    need to commit them after the update.
 
712
    conflicts. If you have any local changes, you will still 
 
713
    need to commit them after the update for the update to be complete.
 
714
    
 
715
    If you want to discard your local changes, you can just do a 
 
716
    'bzr revert' instead of 'bzr commit' after the update.
689
717
    """
690
718
    takes_args = ['dir?']
691
719
 
694
722
        tree.lock_write()
695
723
        try:
696
724
            if tree.last_revision() == tree.branch.last_revision():
697
 
                note("Tree is up to date.")
698
 
                return
 
725
                # may be up to date, check master too.
 
726
                master = tree.branch.get_master_branch()
 
727
                if master is None or master.last_revision == tree.last_revision():
 
728
                    note("Tree is up to date.")
 
729
                    return
699
730
            conflicts = tree.update()
700
731
            note('Updated to revision %d.' %
701
732
                 (tree.branch.revision_id_to_revno(tree.last_revision()),))
769
800
            print fip
770
801
 
771
802
 
 
803
class cmd_reconcile(Command):
 
804
    """Reconcile bzr metadata in a branch.
 
805
 
 
806
    This can correct data mismatches that may have been caused by
 
807
    previous ghost operations or bzr upgrades. You should only
 
808
    need to run this command if 'bzr check' or a bzr developer 
 
809
    advises you to run it.
 
810
 
 
811
    If a second branch is provided, cross-branch reconciliation is
 
812
    also attempted, which will check that data like the tree root
 
813
    id which was not present in very early bzr versions is represented
 
814
    correctly in both branches.
 
815
 
 
816
    At the same time it is run it may recompress data resulting in 
 
817
    a potential saving in disk space or performance gain.
 
818
 
 
819
    The branch *MUST* be on a listable system such as local disk or sftp.
 
820
    """
 
821
    takes_args = ['branch?']
 
822
 
 
823
    def run(self, branch="."):
 
824
        from bzrlib.reconcile import reconcile
 
825
        dir = bzrlib.bzrdir.BzrDir.open(branch)
 
826
        reconcile(dir)
 
827
 
 
828
 
772
829
class cmd_revision_history(Command):
773
830
    """Display list of revision ids on this branch."""
774
831
    hidden = True
851
908
 
852
909
    @display_command
853
910
    def run(self, revision=None, file_list=None, diff_options=None):
854
 
        from bzrlib.diff import show_diff
 
911
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
855
912
        try:
856
 
            tree, file_list = internal_tree_files(file_list)
 
913
            tree1, file_list = internal_tree_files(file_list)
 
914
            tree2 = None
857
915
            b = None
858
916
            b2 = None
859
917
        except FileInWrongBranch:
860
918
            if len(file_list) != 2:
861
919
                raise BzrCommandError("Files are in different branches")
862
920
 
863
 
            b, file1 = Branch.open_containing(file_list[0])
864
 
            b2, file2 = Branch.open_containing(file_list[1])
 
921
            tree1, file1 = WorkingTree.open_containing(file_list[0])
 
922
            tree2, file2 = WorkingTree.open_containing(file_list[1])
865
923
            if file1 != "" or file2 != "":
866
924
                # FIXME diff those two files. rbc 20051123
867
925
                raise BzrCommandError("Files are in different branches")
868
926
            file_list = None
869
927
        if revision is not None:
870
 
            if b2 is not None:
 
928
            if tree2 is not None:
871
929
                raise BzrCommandError("Can't specify -r with two branches")
872
930
            if (len(revision) == 1) or (revision[1].spec is None):
873
 
                return show_diff(tree.branch, revision[0], specific_files=file_list,
874
 
                                 external_diff_options=diff_options)
 
931
                return diff_cmd_helper(tree1, file_list, diff_options,
 
932
                                       revision[0])
875
933
            elif len(revision) == 2:
876
 
                return show_diff(tree.branch, revision[0], specific_files=file_list,
877
 
                                 external_diff_options=diff_options,
878
 
                                 revision2=revision[1])
 
934
                return diff_cmd_helper(tree1, file_list, diff_options,
 
935
                                       revision[0], revision[1])
879
936
            else:
880
937
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
881
938
        else:
882
 
            if b is not None:
883
 
                return show_diff(b, None, specific_files=file_list,
884
 
                                 external_diff_options=diff_options, b2=b2)
 
939
            if tree2 is not None:
 
940
                return show_diff_trees(tree1, tree2, sys.stdout, 
 
941
                                       specific_files=file_list,
 
942
                                       external_diff_options=diff_options)
885
943
            else:
886
 
                return show_diff(tree.branch, None, specific_files=file_list,
887
 
                                 external_diff_options=diff_options)
 
944
                return diff_cmd_helper(tree1, file_list, diff_options)
888
945
 
889
946
 
890
947
class cmd_deleted(Command):
1358
1415
                     Option('strict',
1359
1416
                            help="refuse to commit if there are unknown "
1360
1417
                            "files in the working tree."),
 
1418
                     Option('local',
 
1419
                            help="perform a local only commit in a bound "
 
1420
                                 "branch. Such commits are not pushed to "
 
1421
                                 "the master branch until a normal commit "
 
1422
                                 "is performed."
 
1423
                            ),
1361
1424
                     ]
1362
1425
    aliases = ['ci', 'checkin']
1363
1426
 
1364
1427
    def run(self, message=None, file=None, verbose=True, selected_list=None,
1365
 
            unchanged=False, strict=False):
 
1428
            unchanged=False, strict=False, local=False):
1366
1429
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1367
1430
                StrictCommitFailed)
1368
1431
        from bzrlib.msgeditor import edit_commit_message, \
1379
1442
        # TODO: if the commit *does* happen to fail, then save the commit 
1380
1443
        # message to a temporary file where it can be recovered
1381
1444
        tree, selected_list = tree_files(selected_list)
 
1445
        if local and not tree.branch.get_bound_location():
 
1446
            raise errors.LocalRequiresBoundBranch()
1382
1447
        if message is None and not file:
1383
1448
            template = make_commit_message_template(tree, selected_list)
1384
1449
            message = edit_commit_message(template)
1397
1462
            
1398
1463
        try:
1399
1464
            tree.commit(message, specific_files=selected_list,
1400
 
                        allow_pointless=unchanged, strict=strict)
 
1465
                        allow_pointless=unchanged, strict=strict, local=local)
1401
1466
        except PointlessCommit:
1402
1467
            # FIXME: This should really happen before the file is read in;
1403
1468
            # perhaps prepare the commit; get the message; then actually commit
1409
1474
        except StrictCommitFailed:
1410
1475
            raise BzrCommandError("Commit refused because there are unknown "
1411
1476
                                  "files in the working tree.")
 
1477
        except errors.BoundBranchOutOfDate, e:
 
1478
            raise BzrCommandError(str(e)
 
1479
                                  + ' Either unbind, update, or'
 
1480
                                    ' pass --local to commit.')
 
1481
 
1412
1482
        note('Committed revision %d.' % (tree.branch.revno(),))
1413
1483
 
1414
1484
 
1798
1868
                interesting_ids = set()
1799
1869
                for filename in file_list:
1800
1870
                    file_id = tree.path2id(filename)
 
1871
                    if file_id is None:
 
1872
                        raise NotVersionedError(filename)
1801
1873
                    interesting_ids.add(file_id)
1802
1874
                    if tree.kind(file_id) != "directory":
1803
1875
                        continue
2093
2165
                raise BzrCommandError('Please supply either one revision, or a range.')
2094
2166
 
2095
2167
 
 
2168
class cmd_bind(Command):
 
2169
    """Bind the current branch to a master branch.
 
2170
 
 
2171
    After binding, commits must succeed on the master branch
 
2172
    before they are executed on the local one.
 
2173
    """
 
2174
 
 
2175
    takes_args = ['location']
 
2176
    takes_options = []
 
2177
 
 
2178
    def run(self, location=None):
 
2179
        b, relpath = Branch.open_containing(u'.')
 
2180
        b_other = Branch.open(location)
 
2181
        try:
 
2182
            b.bind(b_other)
 
2183
        except DivergedBranches:
 
2184
            raise BzrCommandError('These branches have diverged.'
 
2185
                                  ' Try merging, and then bind again.')
 
2186
 
 
2187
 
 
2188
class cmd_unbind(Command):
 
2189
    """Bind the current branch to its parent.
 
2190
 
 
2191
    After unbinding, the local branch is considered independent.
 
2192
    """
 
2193
 
 
2194
    takes_args = []
 
2195
    takes_options = []
 
2196
 
 
2197
    def run(self):
 
2198
        b, relpath = Branch.open_containing(u'.')
 
2199
        if not b.unbind():
 
2200
            raise BzrCommandError('Local branch is not bound')
 
2201
 
 
2202
 
2096
2203
class cmd_uncommit(bzrlib.commands.Command):
2097
2204
    """Remove the last committed revision.
2098
2205
 
2106
2213
    
2107
2214
    In the future, uncommit will create a changeset, which can then
2108
2215
    be re-applied.
 
2216
    """
2109
2217
 
2110
 
    TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
2111
 
              information in 'branch-as-repostory' branches.
2112
 
    TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2113
 
              information in shared branches as well.
2114
 
    """
 
2218
    # TODO: jam 20060108 Add an option to allow uncommit to remove
 
2219
    # unreferenced information in 'branch-as-repostory' branches.
 
2220
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
 
2221
    # information in shared branches as well.
2115
2222
    takes_options = ['verbose', 'revision',
2116
2223
                    Option('dry-run', help='Don\'t actually make changes'),
2117
2224
                    Option('force', help='Say yes to all questions.')]
2164
2271
                revno=revno)
2165
2272
 
2166
2273
 
 
2274
class cmd_break_lock(Command):
 
2275
    """Break a dead lock on a repository, branch or working directory.
 
2276
 
 
2277
    CAUTION: Locks should only be broken when you are sure that the process
 
2278
    holding the lock has been stopped.
 
2279
    
 
2280
    example:
 
2281
        bzr break-lock .
 
2282
    """
 
2283
    takes_args = ['location']
 
2284
    takes_options = [Option('show',
 
2285
                            help="just show information on the lock, " \
 
2286
                                 "don't break it"),
 
2287
                    ]
 
2288
    def run(self, location, show=False):
 
2289
        d = bzrdir.BzrDir.open(location)
 
2290
        repo = d.open_repository()
 
2291
        if not repo.is_locked():
 
2292
            raise errors.ObjectNotLocked(repo)
 
2293
 
 
2294
 
 
2295
# command-line interpretation helper for merge-related commands
2167
2296
def merge(other_revision, base_revision,
2168
2297
          check_clean=True, ignore_zero=False,
2169
2298
          this_dir=None, backup_files=False, merge_type=Merge3Merger,
2170
 
          file_list=None, show_base=False, reprocess=False, 
 
2299
          file_list=None, show_base=False, reprocess=False,
2171
2300
          pb=DummyProgress()):
2172
2301
    """Merge changes into a tree.
2173
2302