~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: abentley
  • Date: 2006-04-20 23:47:53 UTC
  • mfrom: (1681 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1683.
  • Revision ID: abentley@lappy-20060420234753-6a6874b76f09f86d
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
        raise BzrCommandError("%s is not in the same branch as %s" %
53
53
                             (e.path, file_list[0]))
54
54
 
 
55
 
 
56
# XXX: Bad function name; should possibly also be a class method of
 
57
# WorkingTree rather than a function.
55
58
def internal_tree_files(file_list, default_branch=u'.'):
56
 
    """\
57
 
    Return a branch and list of branch-relative paths.
58
 
    If supplied file_list is empty or None, the branch default will be used,
59
 
    and returned file_list will match the original.
 
59
    """Convert command-line paths to a WorkingTree and relative paths.
 
60
 
 
61
    This is typically used for command-line processors that take one or
 
62
    more filenames, and infer the workingtree that contains them.
 
63
 
 
64
    The filenames given are not required to exist.
 
65
 
 
66
    :param file_list: Filenames to convert.  
 
67
 
 
68
    :param default_branch: Fallback tree path to use if file_list is empty or None.
 
69
 
 
70
    :return: workingtree, [relative_paths]
60
71
    """
61
72
    if file_list is None or len(file_list) == 0:
62
73
        return WorkingTree.open_containing(default_branch)[0], file_list
72
83
 
73
84
def get_format_type(typestring):
74
85
    """Parse and return a format specifier."""
 
86
    if typestring == "weave":
 
87
        return bzrdir.BzrDirFormat6()
75
88
    if typestring == "metadir":
76
89
        return bzrdir.BzrDirMetaFormat1()
77
90
    if typestring == "knit":
78
91
        format = bzrdir.BzrDirMetaFormat1()
79
92
        format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
80
93
        return format
81
 
    msg = "No known bzr-dir format %s. Supported types are: metadir\n" %\
 
94
    msg = "No known bzr-dir format %s. Supported types are: weave, metadir\n" %\
82
95
        (typestring)
83
96
    raise BzrCommandError(msg)
84
97
 
326
339
                print path
327
340
 
328
341
 
329
 
class cmd_move(Command):
330
 
    """Move files to a different directory.
331
 
 
332
 
    examples:
333
 
        bzr move *.txt doc
334
 
 
335
 
    The destination must be a versioned directory in the same branch.
336
 
    """
337
 
    takes_args = ['source$', 'dest']
338
 
    def run(self, source_list, dest):
339
 
        tree, source_list = tree_files(source_list)
340
 
        # TODO: glob expansion on windows?
341
 
        tree.move(source_list, tree.relpath(dest))
342
 
 
343
 
 
344
 
class cmd_rename(Command):
345
 
    """Change the name of an entry.
346
 
 
347
 
    examples:
348
 
      bzr rename frob.c frobber.c
349
 
      bzr rename src/frob.c lib/frob.c
350
 
 
351
 
    It is an error if the destination name exists.
352
 
 
353
 
    See also the 'move' command, which moves files into a different
354
 
    directory without changing their name.
355
 
    """
356
 
    # TODO: Some way to rename multiple files without invoking 
357
 
    # bzr for each one?"""
358
 
    takes_args = ['from_name', 'to_name']
359
 
    
360
 
    def run(self, from_name, to_name):
361
 
        tree, (from_name, to_name) = tree_files((from_name, to_name))
362
 
        tree.rename_one(from_name, to_name)
363
 
 
364
 
 
365
342
class cmd_mv(Command):
366
343
    """Move or rename a file.
367
344
 
376
353
    Files cannot be moved between branches.
377
354
    """
378
355
    takes_args = ['names*']
 
356
    aliases = ['move', 'rename']
 
357
 
379
358
    def run(self, names_list):
380
359
        if len(names_list) < 2:
381
360
            raise BzrCommandError("missing file argument")
394
373
            
395
374
    
396
375
class cmd_pull(Command):
397
 
    """Pull any changes from another branch into the current one.
 
376
    """Turn this branch into a mirror of another branch.
 
377
 
 
378
    This command only works on branches that have not diverged.  Branches are
 
379
    considered diverged if the destination branch's most recent commit is one
 
380
    that has not been merged (directly or indirectly) into the parent.
 
381
 
 
382
    If branches have diverged, you can use 'bzr merge' to integrate the changes
 
383
    from one into the other.  Once one branch has merged, the other should
 
384
    be able to pull it again.
 
385
 
 
386
    If branches have diverged, you can use 'bzr merge' to pull the text changes
 
387
    from one into the other.  Once one branch has merged, the other should
 
388
    be able to pull it again.
 
389
 
 
390
    If you want to forget your local changes and just update your branch to
 
391
    match the remote one, use pull --overwrite.
398
392
 
399
393
    If there is no default location set, the first pull will set it.  After
400
394
    that, you can omit the location to use the default.  To change the
401
395
    default, use --remember.
402
 
 
403
 
    This command only works on branches that have not diverged.  Branches are
404
 
    considered diverged if both branches have had commits without first
405
 
    pulling from the other.
406
 
 
407
 
    If branches have diverged, you can use 'bzr merge' to pull the text changes
408
 
    from one into the other.  Once one branch has merged, the other should
409
 
    be able to pull it again.
410
 
 
411
 
    If you want to forget your local changes and just update your branch to
412
 
    match the remote one, use --overwrite.
413
396
    """
414
397
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
415
398
    takes_args = ['location?']
416
399
 
417
400
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
418
 
        # FIXME: too much stuff is in the command class        
419
 
        tree_to = WorkingTree.open_containing(u'.')[0]
420
 
        stored_loc = tree_to.branch.get_parent()
 
401
        # FIXME: too much stuff is in the command class
 
402
        try:
 
403
            tree_to = WorkingTree.open_containing(u'.')[0]
 
404
            branch_to = tree_to.branch
 
405
        except NoWorkingTree:
 
406
            tree_to = None
 
407
            branch_to = Branch.open_containing(u'.')[0] 
 
408
        stored_loc = branch_to.get_parent()
421
409
        if location is None:
422
410
            if stored_loc is None:
423
411
                raise BzrCommandError("No pull location known or specified.")
425
413
                print "Using saved location: %s" % stored_loc
426
414
                location = stored_loc
427
415
 
428
 
        br_from = Branch.open(location)
429
 
        br_to = tree_to.branch
 
416
        if branch_to.get_parent() is None or remember:
 
417
            branch_to.set_parent(location)
 
418
 
 
419
        branch_from = Branch.open(location)
430
420
 
431
421
        if revision is None:
432
422
            rev_id = None
433
423
        elif len(revision) == 1:
434
 
            rev_id = revision[0].in_history(br_from).rev_id
 
424
            rev_id = revision[0].in_history(branch_from).rev_id
435
425
        else:
436
426
            raise BzrCommandError('bzr pull --revision takes one value.')
437
427
 
438
 
        old_rh = br_to.revision_history()
439
 
        count = tree_to.pull(br_from, overwrite, rev_id)
440
 
 
441
 
        if br_to.get_parent() is None or remember:
442
 
            br_to.set_parent(location)
 
428
        old_rh = branch_to.revision_history()
 
429
        if tree_to is not None:
 
430
            count = tree_to.pull(branch_from, overwrite, rev_id)
 
431
        else:
 
432
            count = branch_to.pull(branch_from, overwrite, rev_id)
443
433
        note('%d revision(s) pulled.' % (count,))
444
434
 
445
435
        if verbose:
446
 
            new_rh = tree_to.branch.revision_history()
 
436
            new_rh = branch_to.revision_history()
447
437
            if old_rh != new_rh:
448
438
                # Something changed
449
439
                from bzrlib.log import show_changed_revisions
450
 
                show_changed_revisions(tree_to.branch, old_rh, new_rh)
 
440
                show_changed_revisions(branch_to, old_rh, new_rh)
451
441
 
452
442
 
453
443
class cmd_push(Command):
454
 
    """Push this branch into another branch.
455
 
    
456
 
    The remote branch will not have its working tree populated because this
457
 
    is both expensive, and may not be supported on the remote file system.
458
 
    
459
 
    Some smart servers or protocols *may* put the working tree in place.
 
444
    """Update a mirror of this branch.
 
445
    
 
446
    The target branch will not have its working tree populated because this
 
447
    is both expensive, and is not supported on remote file systems.
 
448
    
 
449
    Some smart servers or protocols *may* put the working tree in place in
 
450
    the future.
 
451
 
 
452
    This command only works on branches that have not diverged.  Branches are
 
453
    considered diverged if the destination branch's most recent commit is one
 
454
    that has not been merged (directly or indirectly) by the source branch.
 
455
 
 
456
    If branches have diverged, you can use 'bzr push --overwrite' to replace
 
457
    the other branch completely, discarding its unmerged changes.
 
458
    
 
459
    If you want to ensure you have the different changes in the other branch,
 
460
    do a merge (see bzr help merge) from the other branch, and commit that.
 
461
    After that you will be able to do a push without '--overwrite'.
460
462
 
461
463
    If there is no default push location set, the first push will set it.
462
464
    After that, you can omit the location to use the default.  To change the
463
465
    default, use --remember.
464
 
 
465
 
    This command only works on branches that have not diverged.  Branches are
466
 
    considered diverged if the branch being pushed to is not an older version
467
 
    of this branch.
468
 
 
469
 
    If branches have diverged, you can use 'bzr push --overwrite' to replace
470
 
    the other branch completely.
471
 
    
472
 
    If you want to ensure you have the different changes in the other branch,
473
 
    do a merge (see bzr help merge) from the other branch, and commit that
474
 
    before doing a 'push --overwrite'.
475
466
    """
476
467
    takes_options = ['remember', 'overwrite', 
477
468
                     Option('create-prefix', 
494
485
            else:
495
486
                print "Using saved location: %s" % stored_loc
496
487
                location = stored_loc
 
488
        if br_from.get_push_location() is None or remember:
 
489
            br_from.set_push_location(location)
497
490
        try:
498
491
            dir_to = bzrlib.bzrdir.BzrDir.open(location)
499
492
            br_to = dir_to.open_branch()
519
512
                        needed.append((new_transport,
520
513
                                       new_transport.relpath(transport.base)))
521
514
                        if new_transport.base == transport.base:
522
 
                            raise BzrCommandError("Could not creeate "
 
515
                            raise BzrCommandError("Could not create "
523
516
                                                  "path prefix.")
524
517
            dir_to = br_from.bzrdir.clone(location)
525
518
            br_to = dir_to.open_branch()
531
524
                # TODO: This should be updated for branches which don't have a
532
525
                # working tree, as opposed to ones where we just couldn't 
533
526
                # update the tree.
534
 
                warning('Unable to update the working tree of: %s' % (br_to.base,))
 
527
                warning('This transport does not update the working '
 
528
                        'tree of: %s' % (br_to.base,))
535
529
                count = br_to.pull(br_from, overwrite)
536
530
            except NoWorkingTree:
537
531
                count = br_to.pull(br_from, overwrite)
540
534
        except DivergedBranches:
541
535
            raise BzrCommandError("These branches have diverged."
542
536
                                  "  Try a merge then push with overwrite.")
543
 
        if br_from.get_push_location() is None or remember:
544
 
            br_from.set_push_location(location)
545
537
        note('%d revision(s) pushed.' % (count,))
546
538
 
547
539
        if verbose:
635
627
class cmd_checkout(Command):
636
628
    """Create a new checkout of an existing branch.
637
629
 
 
630
    If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
 
631
    the branch found in '.'. This is useful if you have removed the working tree
 
632
    or if it was never created - i.e. if you pushed the branch to its current
 
633
    location using SFTP.
 
634
    
638
635
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
639
636
    be used.  In other words, "checkout ../foo/bar" will attempt to create ./bar.
640
637
 
647
644
    uses the inventory and file contents from the basis branch in preference to the
648
645
    branch being checked out. [Not implemented yet.]
649
646
    """
650
 
    takes_args = ['branch_location', 'to_location?']
 
647
    takes_args = ['branch_location?', 'to_location?']
651
648
    takes_options = ['revision', # , 'basis']
652
649
                     Option('lightweight',
653
650
                            help="perform a lightweight checkout. Lightweight "
658
655
                            ),
659
656
                     ]
660
657
 
661
 
    def run(self, branch_location, to_location=None, revision=None, basis=None,
 
658
    def run(self, branch_location=None, to_location=None, revision=None, basis=None,
662
659
            lightweight=False):
663
660
        if revision is None:
664
661
            revision = [None]
665
662
        elif len(revision) > 1:
666
663
            raise BzrCommandError(
667
664
                'bzr checkout --revision takes exactly 1 revision value')
 
665
        if branch_location is None:
 
666
            branch_location = bzrlib.osutils.getcwd()
 
667
            to_location = branch_location
668
668
        source = Branch.open(branch_location)
669
669
        if len(revision) == 1 and revision[0] is not None:
670
670
            revision_id = revision[0].in_history(source)[1]
672
672
            revision_id = None
673
673
        if to_location is None:
674
674
            to_location = os.path.basename(branch_location.rstrip("/\\"))
 
675
        # if the source and to_location are the same, 
 
676
        # and there is no working tree,
 
677
        # then reconstitute a branch
 
678
        if (bzrlib.osutils.abspath(to_location) == 
 
679
            bzrlib.osutils.abspath(branch_location)):
 
680
            try:
 
681
                source.bzrdir.open_workingtree()
 
682
            except errors.NoWorkingTree:
 
683
                source.bzrdir.create_workingtree()
 
684
                return
675
685
        try:
676
686
            os.mkdir(to_location)
677
687
        except OSError, e:
758
768
class cmd_info(Command):
759
769
    """Show statistical information about a branch."""
760
770
    takes_args = ['branch?']
 
771
    takes_options = ['verbose']
761
772
    
762
773
    @display_command
763
 
    def run(self, branch=None):
 
774
    def run(self, branch=None, verbose=False):
764
775
        import bzrlib.info
765
 
        bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
 
776
        bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0],
 
777
                                     verbose=verbose)
766
778
 
767
779
 
768
780
class cmd_remove(Command):
871
883
    Use this to create an empty branch, or before importing an
872
884
    existing project.
873
885
 
 
886
    If there is a repository in a parent directory of the location, then 
 
887
    the history of the branch will be stored in the repository.  Otherwise
 
888
    init creates a standalone branch which carries its own history in 
 
889
    .bzr.
 
890
 
 
891
    If there is already a branch at the location but it has no working tree,
 
892
    the tree can be populated with 'bzr checkout'.
 
893
 
874
894
    Recipe for importing a tree of files:
875
895
        cd ~/project
876
896
        bzr init
883
903
                     Option('format', 
884
904
                            help='Create a specific format rather than the'
885
905
                                 ' current default format. Currently this '
886
 
                                 ' option only accepts =metadir',
 
906
                                 ' option only accepts "metadir"',
887
907
                            type=get_format_type),
888
908
                     ]
889
909
    def run(self, location=None, format=None):
898
918
            # locations if the user supplies an extended path
899
919
            if not os.path.exists(location):
900
920
                os.mkdir(location)
 
921
        try:
 
922
            existing_bzrdir = bzrdir.BzrDir.open(location)
 
923
        except NotBranchError:
 
924
            # really a NotBzrDir error...
 
925
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
 
926
        else:
 
927
            if existing_bzrdir.has_branch():
 
928
                if existing_bzrdir.has_workingtree():
 
929
                    raise errors.AlreadyBranchError(location)
 
930
                else:
 
931
                    raise errors.BranchExistsWithoutWorkingTree(location)
 
932
            else:
 
933
                existing_bzrdir.create_branch()
 
934
                existing_bzrdir.create_workingtree()
 
935
 
 
936
 
 
937
class cmd_init_repository(Command):
 
938
    """Create a shared repository to hold branches.
 
939
 
 
940
    New branches created under the repository directory will store their revisions
 
941
    in the repository, not in the branch directory, if the branch format supports
 
942
    shared storage.
 
943
 
 
944
    example:
 
945
        bzr init-repo repo
 
946
        bzr init repo/trunk
 
947
        bzr checkout --lightweight repo/trunk trunk-checkout
 
948
        cd trunk-checkout
 
949
        (add files here)
 
950
    """
 
951
    takes_args = ["location"] 
 
952
    takes_options = [Option('format', 
 
953
                            help='Use a specific format rather than the'
 
954
                            ' current default format. Currently this'
 
955
                            ' option accepts "weave", "metadir" and "knit"',
 
956
                            type=get_format_type),
 
957
                     Option('trees',
 
958
                             help='Allows branches in repository to have'
 
959
                             ' a working tree')]
 
960
    aliases = ["init-repo"]
 
961
    def run(self, location, format=None, trees=False):
 
962
        from bzrlib.bzrdir import BzrDirMetaFormat1
 
963
        from bzrlib.transport import get_transport
901
964
        if format is None:
902
 
            # create default
903
 
            bzrdir.BzrDir.create_standalone_workingtree(location)
904
 
        else:
905
 
            new_dir = format.initialize(location)
906
 
            new_dir.create_repository()
907
 
            new_dir.create_branch()
908
 
            # TODO: ask the bzrdir format for the right classs
909
 
            import bzrlib.workingtree
910
 
            bzrlib.workingtree.WorkingTreeFormat3().initialize(new_dir)
 
965
            format = BzrDirMetaFormat1()
 
966
        transport = get_transport(location)
 
967
        if not transport.has('.'):
 
968
            transport.mkdir('')
 
969
        newdir = format.initialize_on_transport(transport)
 
970
        repo = newdir.create_repository(shared=True)
 
971
        repo.set_make_working_trees(trees)
911
972
 
912
973
 
913
974
class cmd_diff(Command):
1045
1106
 
1046
1107
 
1047
1108
class cmd_log(Command):
1048
 
    """Show log of this branch.
 
1109
    """Show log of a branch, file, or directory.
 
1110
 
 
1111
    By default show the log of the branch containing the working directory.
1049
1112
 
1050
1113
    To request a range of logs, you can use the command -r begin..end
1051
1114
    -r revision requests a specific revision, -r ..end or -r begin.. are
1052
1115
    also valid.
 
1116
 
 
1117
    examples:
 
1118
        bzr log
 
1119
        bzr log foo.c
 
1120
        bzr log -r -10.. http://server/branch
1053
1121
    """
1054
1122
 
1055
1123
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
1056
1124
 
1057
 
    takes_args = ['filename?']
 
1125
    takes_args = ['location?']
1058
1126
    takes_options = [Option('forward', 
1059
1127
                            help='show from oldest to newest'),
1060
 
                     'timezone', 'verbose', 
 
1128
                     'timezone', 
 
1129
                     Option('verbose', 
 
1130
                             help='show files changed in each revision'),
1061
1131
                     'show-ids', 'revision',
1062
1132
                     'log-format',
1063
1133
                     'line', 'long', 
1067
1137
                     'short',
1068
1138
                     ]
1069
1139
    @display_command
1070
 
    def run(self, filename=None, timezone='original',
 
1140
    def run(self, location=None, timezone='original',
1071
1141
            verbose=False,
1072
1142
            show_ids=False,
1073
1143
            forward=False,
1085
1155
        
1086
1156
        # log everything
1087
1157
        file_id = None
1088
 
        if filename:
 
1158
        if location:
1089
1159
            # find the file id to log:
1090
1160
 
1091
 
            dir, fp = bzrdir.BzrDir.open_containing(filename)
 
1161
            dir, fp = bzrdir.BzrDir.open_containing(location)
1092
1162
            b = dir.open_branch()
1093
1163
            if fp != '':
1094
1164
                try:
1459
1529
 
1460
1530
    def run(self, message=None, file=None, verbose=True, selected_list=None,
1461
1531
            unchanged=False, strict=False, local=False):
 
1532
        from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
1462
1533
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1463
1534
                StrictCommitFailed)
1464
1535
        from bzrlib.msgeditor import edit_commit_message, \
1492
1563
 
1493
1564
        if message == "":
1494
1565
                raise BzrCommandError("empty commit message specified")
1495
 
            
 
1566
        
 
1567
        if verbose:
 
1568
            reporter = ReportCommitToLog()
 
1569
        else:
 
1570
            reporter = NullCommitReporter()
 
1571
        
1496
1572
        try:
1497
1573
            tree.commit(message, specific_files=selected_list,
1498
 
                        allow_pointless=unchanged, strict=strict, local=local)
 
1574
                        allow_pointless=unchanged, strict=strict, local=local,
 
1575
                        reporter=reporter)
1499
1576
        except PointlessCommit:
1500
1577
            # FIXME: This should really happen before the file is read in;
1501
1578
            # perhaps prepare the commit; get the message; then actually commit
1512
1589
                                  + ' Either unbind, update, or'
1513
1590
                                    ' pass --local to commit.')
1514
1591
 
1515
 
        note('Committed revision %d.' % (tree.branch.revno(),))
1516
 
 
1517
1592
 
1518
1593
class cmd_check(Command):
1519
1594
    """Validate consistency of branch history.
1564
1639
    takes_options = [
1565
1640
                     Option('format', 
1566
1641
                            help='Upgrade to a specific format rather than the'
1567
 
                                 ' current default format. Currently this '
1568
 
                                 ' option only accepts =metadir',
 
1642
                                 ' current default format. Currently this'
 
1643
                                 ' option accepts "weave", "metadir" and'
 
1644
                                 ' "knit".',
1569
1645
                            type=get_format_type),
1570
1646
                    ]
1571
1647
 
1644
1720
        if typestring == "memory":
1645
1721
            from bzrlib.transport.memory import MemoryServer
1646
1722
            return MemoryServer
 
1723
        if typestring == "fakenfs":
 
1724
            from bzrlib.transport.fakenfs import FakeNFSServer
 
1725
            return FakeNFSServer
1647
1726
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1648
1727
            (typestring)
1649
1728
        raise BzrCommandError(msg)
1797
1876
 
1798
1877
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
1799
1878
 
 
1879
    If there is no default branch set, the first merge will set it. After
 
1880
    that, you can omit the branch to use the default.  To change the
 
1881
    default, use --remember.
 
1882
 
1800
1883
    Examples:
1801
1884
 
1802
1885
    To merge the latest revision from bzr.dev
1812
1895
    --force is given.
1813
1896
    """
1814
1897
    takes_args = ['branch?']
1815
 
    takes_options = ['revision', 'force', 'merge-type', 'reprocess',
 
1898
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
1816
1899
                     Option('show-base', help="Show base revision text in "
1817
1900
                            "conflicts")]
1818
1901
 
1819
1902
    def run(self, branch=None, revision=None, force=False, merge_type=None,
1820
 
            show_base=False, reprocess=False):
 
1903
            show_base=False, reprocess=False, remember=False):
1821
1904
        if merge_type is None:
1822
1905
            merge_type = Merge3Merger
 
1906
 
 
1907
        tree = WorkingTree.open_containing(u'.')[0]
 
1908
        stored_loc = tree.branch.get_parent()
1823
1909
        if branch is None:
1824
 
            branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1825
 
            if branch is None:
1826
 
                raise BzrCommandError("No merge location known or specified.")
 
1910
            if stored_loc is None:
 
1911
                raise BzrCommandError("No merge branch known or specified.")
1827
1912
            else:
1828
 
                print "Using saved location: %s" % branch 
 
1913
                print "Using saved branch: %s" % stored_loc
 
1914
                branch = stored_loc
 
1915
 
 
1916
        if tree.branch.get_parent() is None or remember:
 
1917
            tree.branch.set_parent(branch)
 
1918
 
1829
1919
        if revision is None or len(revision) < 1:
1830
1920
            base = [None, None]
1831
1921
            other = [branch, -1]
 
1922
            other_branch, path = Branch.open_containing(branch)
1832
1923
        else:
1833
1924
            if len(revision) == 1:
1834
1925
                base = [None, None]
1835
 
                other_branch = Branch.open_containing(branch)[0]
 
1926
                other_branch, path = Branch.open_containing(branch)
1836
1927
                revno = revision[0].in_history(other_branch).revno
1837
1928
                other = [branch, revno]
1838
1929
            else:
1840
1931
                if None in revision:
1841
1932
                    raise BzrCommandError(
1842
1933
                        "Merge doesn't permit that revision specifier.")
1843
 
                b = Branch.open_containing(branch)[0]
 
1934
                b, path = Branch.open_containing(branch)
1844
1935
 
1845
1936
                base = [branch, revision[0].in_history(b).revno]
1846
1937
                other = [branch, revision[1].in_history(b).revno]
 
1938
        if path != "":
 
1939
            interesting_files = [path]
 
1940
        else:
 
1941
            interesting_files = None
1847
1942
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
1848
1943
        try:
1849
1944
            try:
1851
1946
                                       merge_type=merge_type, 
1852
1947
                                       reprocess=reprocess,
1853
1948
                                       show_base=show_base, 
1854
 
                                       pb=pb)
 
1949
                                       pb=pb, file_list=interesting_files)
1855
1950
            finally:
1856
1951
                pb.finished()
1857
1952
            if conflict_count != 0:
1980
2075
    For a list of all available commands, say 'bzr help commands'."""
1981
2076
    takes_options = [Option('long', 'show help on all commands')]
1982
2077
    takes_args = ['topic?']
1983
 
    aliases = ['?']
 
2078
    aliases = ['?', '--help', '-?', '-h']
1984
2079
    
1985
2080
    @display_command
1986
2081
    def run(self, topic=None, long=False):
2049
2144
                raise BzrCommandError("No missing location known or specified.")
2050
2145
            print "Using last location: " + local_branch.get_parent()
2051
2146
        remote_branch = bzrlib.branch.Branch.open(other_branch)
2052
 
        local_branch.lock_write()
2053
2147
        if remote_branch.base == local_branch.base:
2054
2148
            remote_branch = local_branch
 
2149
        local_branch.lock_read()
2055
2150
        try:
2056
2151
            remote_branch.lock_read()
2057
2152
            try:
2085
2180
                    print "Branches are up to date."
2086
2181
                else:
2087
2182
                    status_code = 1
2088
 
                if parent is None and other_branch is not None:
 
2183
            finally:
 
2184
                remote_branch.unlock()
 
2185
        finally:
 
2186
            local_branch.unlock()
 
2187
        if not status_code and parent is None and other_branch is not None:
 
2188
            local_branch.lock_write()
 
2189
            try:
 
2190
                # handle race conditions - a parent might be set while we run.
 
2191
                if local_branch.get_parent() is None:
2089
2192
                    local_branch.set_parent(other_branch)
2090
 
                return status_code
2091
2193
            finally:
2092
2194
                local_branch.unlock()
2093
 
        finally:
2094
 
            remote_branch.unlock()
 
2195
        return status_code
2095
2196
 
2096
2197
 
2097
2198
class cmd_plugins(Command):
2283
2384
        if location is None:
2284
2385
            location = u'.'
2285
2386
        control, relpath = bzrdir.BzrDir.open_containing(location)
2286
 
        b = control.open_branch()
2287
2387
        try:
2288
2388
            tree = control.open_workingtree()
 
2389
            b = tree.branch
2289
2390
        except (errors.NoWorkingTree, errors.NotLocalUrl):
2290
2391
            tree = None
 
2392
            b = control.open_branch()
2291
2393
 
2292
2394
        if revision is None:
2293
2395
            revno = b.revno()
2333
2435
                                 "don't break it"),
2334
2436
                    ]
2335
2437
    def run(self, location, show=False):
2336
 
        d = bzrdir.BzrDir.open(location)
2337
 
        repo = d.open_repository()
2338
 
        if not repo.is_locked():
2339
 
            raise errors.ObjectNotLocked(repo)
 
2438
        raise NotImplementedError("sorry, break-lock is not complete yet; "
 
2439
                "you can remove the 'held' directory manually to break the lock")
2340
2440
 
2341
2441
 
2342
2442
# command-line interpretation helper for merge-related commands
2379
2479
    if show_base and not merge_type is Merge3Merger:
2380
2480
        raise BzrCommandError("Show-base is not supported for this merge"
2381
2481
                              " type. %s" % merge_type)
2382
 
    if reprocess and not merge_type is Merge3Merger:
2383
 
        raise BzrCommandError("Reprocess is not supported for this merge"
2384
 
                              " type. %s" % merge_type)
 
2482
    if reprocess and not merge_type.supports_reprocess:
 
2483
        raise BzrCommandError("Conflict reduction is not supported for merge"
 
2484
                              " type %s." % merge_type)
2385
2485
    if reprocess and show_base:
2386
 
        raise BzrCommandError("Cannot reprocess and show base.")
 
2486
        raise BzrCommandError("Cannot do conflict reduction and show base.")
2387
2487
    try:
2388
2488
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2389
2489
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2401
2501
        merger.show_base = show_base 
2402
2502
        merger.reprocess = reprocess
2403
2503
        conflicts = merger.do_merge()
2404
 
        merger.set_pending()
 
2504
        if file_list is None:
 
2505
            merger.set_pending()
2405
2506
    finally:
2406
2507
        pb.clear()
2407
2508
    return conflicts
2410
2511
# these get imported and then picked up by the scan for cmd_*
2411
2512
# TODO: Some more consistent way to split command definitions across files;
2412
2513
# we do need to load at least some information about them to know of 
2413
 
# aliases.
 
2514
# aliases.  ideally we would avoid loading the implementation until the
 
2515
# details were needed.
2414
2516
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2415
2517
from bzrlib.sign_my_commits import cmd_sign_my_commits
 
2518
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
 
2519
        cmd_weave_plan_merge, cmd_weave_merge_text