~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Ian Clatworthy
  • Date: 2009-09-09 00:49:50 UTC
  • mto: (4634.37.2 prepare-2.0)
  • mto: This revision was merged to the branch mainline in revision 4689.
  • Revision ID: ian.clatworthy@canonical.com-20090909004950-43z4zdicb5u91iet
tweak quick reference naming to make it consistent with other PDFs

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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
    bundle,
32
32
    btree_index,
33
33
    bzrdir,
34
 
    directory_service,
35
34
    delta,
36
35
    config,
37
36
    errors,
44
43
    reconfigure,
45
44
    rename_map,
46
45
    revision as _mod_revision,
47
 
    static_tuple,
48
46
    symbol_versioning,
49
 
    timestamp,
50
47
    transport,
51
48
    ui,
52
49
    urlutils,
54
51
    )
55
52
from bzrlib.branch import Branch
56
53
from bzrlib.conflicts import ConflictList
57
 
from bzrlib.transport import memory
58
54
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
59
55
from bzrlib.smtp_connection import SMTPConnection
60
56
from bzrlib.workingtree import WorkingTree
261
257
    unknown
262
258
        Not versioned and not matching an ignore pattern.
263
259
 
264
 
    Additionally for directories, symlinks and files with an executable
265
 
    bit, Bazaar indicates their type using a trailing character: '/', '@'
266
 
    or '*' respectively.
267
 
 
268
260
    To see ignored files use 'bzr ignored'.  For details on the
269
261
    changes to file texts, use 'bzr diff'.
270
262
 
439
431
        for node in bt.iter_all_entries():
440
432
            # Node is made up of:
441
433
            # (index, key, value, [references])
442
 
            refs_as_tuples = static_tuple.as_tuples(node[3])
443
 
            as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
444
 
            self.outf.write('%s\n' % (as_tuple,))
 
434
            self.outf.write('%s\n' % (node[1:],))
445
435
 
446
436
 
447
437
class cmd_remove_tree(Command):
453
443
    To re-create the working tree, use "bzr checkout".
454
444
    """
455
445
    _see_also = ['checkout', 'working-trees']
456
 
    takes_args = ['location*']
 
446
    takes_args = ['location?']
457
447
    takes_options = [
458
448
        Option('force',
459
449
               help='Remove the working tree even if it has '
460
450
                    'uncommitted changes.'),
461
451
        ]
462
452
 
463
 
    def run(self, location_list, force=False):
464
 
        if not location_list:
465
 
            location_list=['.']
466
 
 
467
 
        for location in location_list:
468
 
            d = bzrdir.BzrDir.open(location)
469
 
            
470
 
            try:
471
 
                working = d.open_workingtree()
472
 
            except errors.NoWorkingTree:
473
 
                raise errors.BzrCommandError("No working tree to remove")
474
 
            except errors.NotLocalUrl:
475
 
                raise errors.BzrCommandError("You cannot remove the working tree"
476
 
                                             " of a remote path")
477
 
            if not force:
478
 
                if (working.has_changes()):
479
 
                    raise errors.UncommittedChanges(working)
480
 
 
481
 
            working_path = working.bzrdir.root_transport.base
482
 
            branch_path = working.branch.bzrdir.root_transport.base
483
 
            if working_path != branch_path:
484
 
                raise errors.BzrCommandError("You cannot remove the working tree"
485
 
                                             " from a lightweight checkout")
486
 
 
487
 
            d.destroy_workingtree()
 
453
    def run(self, location='.', force=False):
 
454
        d = bzrdir.BzrDir.open(location)
 
455
 
 
456
        try:
 
457
            working = d.open_workingtree()
 
458
        except errors.NoWorkingTree:
 
459
            raise errors.BzrCommandError("No working tree to remove")
 
460
        except errors.NotLocalUrl:
 
461
            raise errors.BzrCommandError("You cannot remove the working tree"
 
462
                                         " of a remote path")
 
463
        if not force:
 
464
            # XXX: What about pending merges ? -- vila 20090629
 
465
            if working.has_changes(working.basis_tree()):
 
466
                raise errors.UncommittedChanges(working)
 
467
 
 
468
        working_path = working.bzrdir.root_transport.base
 
469
        branch_path = working.branch.bzrdir.root_transport.base
 
470
        if working_path != branch_path:
 
471
            raise errors.BzrCommandError("You cannot remove the working tree"
 
472
                                         " from a lightweight checkout")
 
473
 
 
474
        d.destroy_workingtree()
488
475
 
489
476
 
490
477
class cmd_revno(Command):
507
494
                wt.lock_read()
508
495
            except (errors.NoWorkingTree, errors.NotLocalUrl):
509
496
                raise errors.NoWorkingTree(location)
510
 
            self.add_cleanup(wt.unlock)
511
 
            revid = wt.last_revision()
512
497
            try:
513
 
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
514
 
            except errors.NoSuchRevision:
515
 
                revno_t = ('???',)
516
 
            revno = ".".join(str(n) for n in revno_t)
 
498
                revid = wt.last_revision()
 
499
                try:
 
500
                    revno_t = wt.branch.revision_id_to_dotted_revno(revid)
 
501
                except errors.NoSuchRevision:
 
502
                    revno_t = ('???',)
 
503
                revno = ".".join(str(n) for n in revno_t)
 
504
            finally:
 
505
                wt.unlock()
517
506
        else:
518
507
            b = Branch.open_containing(location)[0]
519
508
            b.lock_read()
520
 
            self.add_cleanup(b.unlock)
521
 
            revno = b.revno()
522
 
        self.cleanup_now()
 
509
            try:
 
510
                revno = b.revno()
 
511
            finally:
 
512
                b.unlock()
 
513
 
523
514
        self.outf.write(str(revno) + '\n')
524
515
 
525
516
 
547
538
            wt = WorkingTree.open_containing(directory)[0]
548
539
            b = wt.branch
549
540
            wt.lock_read()
550
 
            self.add_cleanup(wt.unlock)
551
541
        except (errors.NoWorkingTree, errors.NotLocalUrl):
552
542
            wt = None
553
543
            b = Branch.open_containing(directory)[0]
554
544
            b.lock_read()
555
 
            self.add_cleanup(b.unlock)
556
 
        revision_ids = []
557
 
        if revision is not None:
558
 
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
559
 
        if revision_info_list is not None:
560
 
            for rev_str in revision_info_list:
561
 
                rev_spec = RevisionSpec.from_string(rev_str)
562
 
                revision_ids.append(rev_spec.as_revision_id(b))
563
 
        # No arguments supplied, default to the last revision
564
 
        if len(revision_ids) == 0:
565
 
            if tree:
566
 
                if wt is None:
567
 
                    raise errors.NoWorkingTree(directory)
568
 
                revision_ids.append(wt.last_revision())
 
545
        try:
 
546
            revision_ids = []
 
547
            if revision is not None:
 
548
                revision_ids.extend(rev.as_revision_id(b) for rev in revision)
 
549
            if revision_info_list is not None:
 
550
                for rev_str in revision_info_list:
 
551
                    rev_spec = RevisionSpec.from_string(rev_str)
 
552
                    revision_ids.append(rev_spec.as_revision_id(b))
 
553
            # No arguments supplied, default to the last revision
 
554
            if len(revision_ids) == 0:
 
555
                if tree:
 
556
                    if wt is None:
 
557
                        raise errors.NoWorkingTree(directory)
 
558
                    revision_ids.append(wt.last_revision())
 
559
                else:
 
560
                    revision_ids.append(b.last_revision())
 
561
 
 
562
            revinfos = []
 
563
            maxlen = 0
 
564
            for revision_id in revision_ids:
 
565
                try:
 
566
                    dotted_revno = b.revision_id_to_dotted_revno(revision_id)
 
567
                    revno = '.'.join(str(i) for i in dotted_revno)
 
568
                except errors.NoSuchRevision:
 
569
                    revno = '???'
 
570
                maxlen = max(maxlen, len(revno))
 
571
                revinfos.append([revno, revision_id])
 
572
        finally:
 
573
            if wt is None:
 
574
                b.unlock()
569
575
            else:
570
 
                revision_ids.append(b.last_revision())
571
 
 
572
 
        revinfos = []
573
 
        maxlen = 0
574
 
        for revision_id in revision_ids:
575
 
            try:
576
 
                dotted_revno = b.revision_id_to_dotted_revno(revision_id)
577
 
                revno = '.'.join(str(i) for i in dotted_revno)
578
 
            except errors.NoSuchRevision:
579
 
                revno = '???'
580
 
            maxlen = max(maxlen, len(revno))
581
 
            revinfos.append([revno, revision_id])
582
 
 
583
 
        self.cleanup_now()
 
576
                wt.unlock()
 
577
 
584
578
        for ri in revinfos:
585
579
            self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
586
580
 
658
652
 
659
653
        if base_tree:
660
654
            base_tree.lock_read()
661
 
            self.add_cleanup(base_tree.unlock)
662
 
        tree, file_list = tree_files_for_add(file_list)
663
 
        added, ignored = tree.smart_add(file_list, not
664
 
            no_recurse, action=action, save=not dry_run)
665
 
        self.cleanup_now()
 
655
        try:
 
656
            file_list = self._maybe_expand_globs(file_list)
 
657
            tree, file_list = tree_files_for_add(file_list)
 
658
            added, ignored = tree.smart_add(file_list, not
 
659
                no_recurse, action=action, save=not dry_run)
 
660
        finally:
 
661
            if base_tree is not None:
 
662
                base_tree.unlock()
666
663
        if len(ignored) > 0:
667
664
            if verbose:
668
665
                for glob in sorted(ignored.keys()):
732
729
        revision = _get_one_revision('inventory', revision)
733
730
        work_tree, file_list = tree_files(file_list)
734
731
        work_tree.lock_read()
735
 
        self.add_cleanup(work_tree.unlock)
736
 
        if revision is not None:
737
 
            tree = revision.as_tree(work_tree.branch)
738
 
 
739
 
            extra_trees = [work_tree]
740
 
            tree.lock_read()
741
 
            self.add_cleanup(tree.unlock)
742
 
        else:
743
 
            tree = work_tree
744
 
            extra_trees = []
745
 
 
746
 
        if file_list is not None:
747
 
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
748
 
                                      require_versioned=True)
749
 
            # find_ids_across_trees may include some paths that don't
750
 
            # exist in 'tree'.
751
 
            entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
752
 
                             for file_id in file_ids if file_id in tree)
753
 
        else:
754
 
            entries = tree.inventory.entries()
755
 
 
756
 
        self.cleanup_now()
 
732
        try:
 
733
            if revision is not None:
 
734
                tree = revision.as_tree(work_tree.branch)
 
735
 
 
736
                extra_trees = [work_tree]
 
737
                tree.lock_read()
 
738
            else:
 
739
                tree = work_tree
 
740
                extra_trees = []
 
741
 
 
742
            if file_list is not None:
 
743
                file_ids = tree.paths2ids(file_list, trees=extra_trees,
 
744
                                          require_versioned=True)
 
745
                # find_ids_across_trees may include some paths that don't
 
746
                # exist in 'tree'.
 
747
                entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
 
748
                                 for file_id in file_ids if file_id in tree)
 
749
            else:
 
750
                entries = tree.inventory.entries()
 
751
        finally:
 
752
            tree.unlock()
 
753
            if tree is not work_tree:
 
754
                work_tree.unlock()
 
755
 
757
756
        for path, entry in entries:
758
757
            if kind and kind != entry.kind:
759
758
                continue
805
804
            raise errors.BzrCommandError("missing file argument")
806
805
        tree, rel_names = tree_files(names_list, canonicalize=False)
807
806
        tree.lock_tree_write()
808
 
        self.add_cleanup(tree.unlock)
809
 
        self._run(tree, names_list, rel_names, after)
 
807
        try:
 
808
            self._run(tree, names_list, rel_names, after)
 
809
        finally:
 
810
            tree.unlock()
810
811
 
811
812
    def run_auto(self, names_list, after, dry_run):
812
813
        if names_list is not None and len(names_list) > 1:
817
818
                                         ' --auto.')
818
819
        work_tree, file_list = tree_files(names_list, default_branch='.')
819
820
        work_tree.lock_tree_write()
820
 
        self.add_cleanup(work_tree.unlock)
821
 
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
 
821
        try:
 
822
            rename_map.RenameMap.guess_renames(work_tree, dry_run)
 
823
        finally:
 
824
            work_tree.unlock()
822
825
 
823
826
    def _run(self, tree, names_list, rel_names, after):
824
827
        into_existing = osutils.isdir(names_list[-1])
845
848
            # All entries reference existing inventory items, so fix them up
846
849
            # for cicp file-systems.
847
850
            rel_names = tree.get_canonical_inventory_paths(rel_names)
848
 
            for src, dest in tree.move(rel_names[:-1], rel_names[-1], after=after):
849
 
                if not is_quiet():
850
 
                    self.outf.write("%s => %s\n" % (src, dest))
 
851
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
 
852
                self.outf.write("%s => %s\n" % pair)
851
853
        else:
852
854
            if len(names_list) != 2:
853
855
                raise errors.BzrCommandError('to mv multiple files the'
897
899
            dest = osutils.pathjoin(dest_parent, dest_tail)
898
900
            mutter("attempting to move %s => %s", src, dest)
899
901
            tree.rename_one(src, dest, after=after)
900
 
            if not is_quiet():
901
 
                self.outf.write("%s => %s\n" % (src, dest))
 
902
            self.outf.write("%s => %s\n" % (src, dest))
902
903
 
903
904
 
904
905
class cmd_pull(Command):
905
906
    """Turn this branch into a mirror of another branch.
906
907
 
907
 
    By default, this command only works on branches that have not diverged.
908
 
    Branches are considered diverged if the destination branch's most recent 
909
 
    commit is one that has not been merged (directly or indirectly) into the 
910
 
    parent.
 
908
    This command only works on branches that have not diverged.  Branches are
 
909
    considered diverged if the destination branch's most recent commit is one
 
910
    that has not been merged (directly or indirectly) into the parent.
911
911
 
912
912
    If branches have diverged, you can use 'bzr merge' to integrate the changes
913
913
    from one into the other.  Once one branch has merged, the other should
914
914
    be able to pull it again.
915
915
 
916
 
    If you want to replace your local changes and just want your branch to
917
 
    match the remote one, use pull --overwrite. This will work even if the two
918
 
    branches have diverged.
 
916
    If you want to forget your local changes and just update your branch to
 
917
    match the remote one, use pull --overwrite.
919
918
 
920
919
    If there is no default location set, the first pull will set it.  After
921
920
    that, you can omit the location to use the default.  To change the
1002
1001
 
1003
1002
        if branch_from is not branch_to:
1004
1003
            branch_from.lock_read()
1005
 
            self.add_cleanup(branch_from.unlock)
1006
 
        if revision is not None:
1007
 
            revision_id = revision.as_revision_id(branch_from)
1008
 
 
1009
 
        branch_to.lock_write()
1010
 
        self.add_cleanup(branch_to.unlock)
1011
 
        if tree_to is not None:
1012
 
            view_info = _get_view_info_for_change_reporter(tree_to)
1013
 
            change_reporter = delta._ChangeReporter(
1014
 
                unversioned_filter=tree_to.is_ignored,
1015
 
                view_info=view_info)
1016
 
            result = tree_to.pull(
1017
 
                branch_from, overwrite, revision_id, change_reporter,
1018
 
                possible_transports=possible_transports, local=local)
1019
 
        else:
1020
 
            result = branch_to.pull(
1021
 
                branch_from, overwrite, revision_id, local=local)
1022
 
 
1023
 
        result.report(self.outf)
1024
 
        if verbose and result.old_revid != result.new_revid:
1025
 
            log.show_branch_change(
1026
 
                branch_to, self.outf, result.old_revno,
1027
 
                result.old_revid)
 
1004
        try:
 
1005
            if revision is not None:
 
1006
                revision_id = revision.as_revision_id(branch_from)
 
1007
 
 
1008
            branch_to.lock_write()
 
1009
            try:
 
1010
                if tree_to is not None:
 
1011
                    view_info = _get_view_info_for_change_reporter(tree_to)
 
1012
                    change_reporter = delta._ChangeReporter(
 
1013
                        unversioned_filter=tree_to.is_ignored,
 
1014
                        view_info=view_info)
 
1015
                    result = tree_to.pull(
 
1016
                        branch_from, overwrite, revision_id, change_reporter,
 
1017
                        possible_transports=possible_transports, local=local)
 
1018
                else:
 
1019
                    result = branch_to.pull(
 
1020
                        branch_from, overwrite, revision_id, local=local)
 
1021
 
 
1022
                result.report(self.outf)
 
1023
                if verbose and result.old_revid != result.new_revid:
 
1024
                    log.show_branch_change(
 
1025
                        branch_to, self.outf, result.old_revno,
 
1026
                        result.old_revid)
 
1027
            finally:
 
1028
                branch_to.unlock()
 
1029
        finally:
 
1030
            if branch_from is not branch_to:
 
1031
                branch_from.unlock()
1028
1032
 
1029
1033
 
1030
1034
class cmd_push(Command):
1105
1109
        else:
1106
1110
            revision_id = None
1107
1111
        if strict and tree is not None and revision_id is None:
1108
 
            if (tree.has_changes()):
 
1112
            if (tree.has_changes(tree.basis_tree())
 
1113
                or len(tree.get_parent_ids()) > 1):
1109
1114
                raise errors.UncommittedChanges(
1110
1115
                    tree, more='Use --no-strict to force the push.')
1111
1116
            if tree.last_revision() != tree.branch.last_revision():
1185
1190
                    ' directory exists, but does not already'
1186
1191
                    ' have a control directory.  This flag will'
1187
1192
                    ' allow branch to proceed.'),
1188
 
        Option('bind',
1189
 
            help="Bind new branch to from location."),
1190
1193
        ]
1191
1194
    aliases = ['get', 'clone']
1192
1195
 
1193
1196
    def run(self, from_location, to_location=None, revision=None,
1194
1197
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1195
 
            use_existing_dir=False, switch=False, bind=False):
 
1198
            use_existing_dir=False, switch=False):
1196
1199
        from bzrlib import switch as _mod_switch
1197
1200
        from bzrlib.tag import _merge_tags_if_possible
1198
1201
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1199
1202
            from_location)
 
1203
        if (accelerator_tree is not None and
 
1204
            accelerator_tree.supports_content_filtering()):
 
1205
            accelerator_tree = None
1200
1206
        revision = _get_one_revision('branch', revision)
1201
1207
        br_from.lock_read()
1202
 
        self.add_cleanup(br_from.unlock)
1203
 
        if revision is not None:
1204
 
            revision_id = revision.as_revision_id(br_from)
1205
 
        else:
1206
 
            # FIXME - wt.last_revision, fallback to branch, fall back to
1207
 
            # None or perhaps NULL_REVISION to mean copy nothing
1208
 
            # RBC 20060209
1209
 
            revision_id = br_from.last_revision()
1210
 
        if to_location is None:
1211
 
            to_location = urlutils.derive_to_location(from_location)
1212
 
        to_transport = transport.get_transport(to_location)
1213
1208
        try:
1214
 
            to_transport.mkdir('.')
1215
 
        except errors.FileExists:
1216
 
            if not use_existing_dir:
1217
 
                raise errors.BzrCommandError('Target directory "%s" '
1218
 
                    'already exists.' % to_location)
 
1209
            if revision is not None:
 
1210
                revision_id = revision.as_revision_id(br_from)
1219
1211
            else:
1220
 
                try:
1221
 
                    bzrdir.BzrDir.open_from_transport(to_transport)
1222
 
                except errors.NotBranchError:
1223
 
                    pass
 
1212
                # FIXME - wt.last_revision, fallback to branch, fall back to
 
1213
                # None or perhaps NULL_REVISION to mean copy nothing
 
1214
                # RBC 20060209
 
1215
                revision_id = br_from.last_revision()
 
1216
            if to_location is None:
 
1217
                to_location = urlutils.derive_to_location(from_location)
 
1218
            to_transport = transport.get_transport(to_location)
 
1219
            try:
 
1220
                to_transport.mkdir('.')
 
1221
            except errors.FileExists:
 
1222
                if not use_existing_dir:
 
1223
                    raise errors.BzrCommandError('Target directory "%s" '
 
1224
                        'already exists.' % to_location)
1224
1225
                else:
1225
 
                    raise errors.AlreadyBranchError(to_location)
1226
 
        except errors.NoSuchFile:
1227
 
            raise errors.BzrCommandError('Parent of "%s" does not exist.'
1228
 
                                         % to_location)
1229
 
        try:
1230
 
            # preserve whatever source format we have.
1231
 
            dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1232
 
                                        possible_transports=[to_transport],
1233
 
                                        accelerator_tree=accelerator_tree,
1234
 
                                        hardlink=hardlink, stacked=stacked,
1235
 
                                        force_new_repo=standalone,
1236
 
                                        create_tree_if_local=not no_tree,
1237
 
                                        source_branch=br_from)
1238
 
            branch = dir.open_branch()
1239
 
        except errors.NoSuchRevision:
1240
 
            to_transport.delete_tree('.')
1241
 
            msg = "The branch %s has no revision %s." % (from_location,
1242
 
                revision)
1243
 
            raise errors.BzrCommandError(msg)
1244
 
        _merge_tags_if_possible(br_from, branch)
1245
 
        # If the source branch is stacked, the new branch may
1246
 
        # be stacked whether we asked for that explicitly or not.
1247
 
        # We therefore need a try/except here and not just 'if stacked:'
1248
 
        try:
1249
 
            note('Created new stacked branch referring to %s.' %
1250
 
                branch.get_stacked_on_url())
1251
 
        except (errors.NotStacked, errors.UnstackableBranchFormat,
1252
 
            errors.UnstackableRepositoryFormat), e:
1253
 
            note('Branched %d revision(s).' % branch.revno())
1254
 
        if bind:
1255
 
            # Bind to the parent
1256
 
            parent_branch = Branch.open(from_location)
1257
 
            branch.bind(parent_branch)
1258
 
            note('New branch bound to %s' % from_location)
1259
 
        if switch:
1260
 
            # Switch to the new branch
1261
 
            wt, _ = WorkingTree.open_containing('.')
1262
 
            _mod_switch.switch(wt.bzrdir, branch)
1263
 
            note('Switched to branch: %s',
1264
 
                urlutils.unescape_for_display(branch.base, 'utf-8'))
 
1226
                    try:
 
1227
                        bzrdir.BzrDir.open_from_transport(to_transport)
 
1228
                    except errors.NotBranchError:
 
1229
                        pass
 
1230
                    else:
 
1231
                        raise errors.AlreadyBranchError(to_location)
 
1232
            except errors.NoSuchFile:
 
1233
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
1234
                                             % to_location)
 
1235
            try:
 
1236
                # preserve whatever source format we have.
 
1237
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
 
1238
                                            possible_transports=[to_transport],
 
1239
                                            accelerator_tree=accelerator_tree,
 
1240
                                            hardlink=hardlink, stacked=stacked,
 
1241
                                            force_new_repo=standalone,
 
1242
                                            create_tree_if_local=not no_tree,
 
1243
                                            source_branch=br_from)
 
1244
                branch = dir.open_branch()
 
1245
            except errors.NoSuchRevision:
 
1246
                to_transport.delete_tree('.')
 
1247
                msg = "The branch %s has no revision %s." % (from_location,
 
1248
                    revision)
 
1249
                raise errors.BzrCommandError(msg)
 
1250
            _merge_tags_if_possible(br_from, branch)
 
1251
            # If the source branch is stacked, the new branch may
 
1252
            # be stacked whether we asked for that explicitly or not.
 
1253
            # We therefore need a try/except here and not just 'if stacked:'
 
1254
            try:
 
1255
                note('Created new stacked branch referring to %s.' %
 
1256
                    branch.get_stacked_on_url())
 
1257
            except (errors.NotStacked, errors.UnstackableBranchFormat,
 
1258
                errors.UnstackableRepositoryFormat), e:
 
1259
                note('Branched %d revision(s).' % branch.revno())
 
1260
            if switch:
 
1261
                # Switch to the new branch
 
1262
                wt, _ = WorkingTree.open_containing('.')
 
1263
                _mod_switch.switch(wt.bzrdir, branch)
 
1264
                note('Switched to branch: %s',
 
1265
                    urlutils.unescape_for_display(branch.base, 'utf-8'))
 
1266
        finally:
 
1267
            br_from.unlock()
1265
1268
 
1266
1269
 
1267
1270
class cmd_checkout(Command):
1346
1349
    def run(self, dir=u'.'):
1347
1350
        tree = WorkingTree.open_containing(dir)[0]
1348
1351
        tree.lock_read()
1349
 
        self.add_cleanup(tree.unlock)
1350
 
        new_inv = tree.inventory
1351
 
        old_tree = tree.basis_tree()
1352
 
        old_tree.lock_read()
1353
 
        self.add_cleanup(old_tree.unlock)
1354
 
        old_inv = old_tree.inventory
1355
 
        renames = []
1356
 
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1357
 
        for f, paths, c, v, p, n, k, e in iterator:
1358
 
            if paths[0] == paths[1]:
1359
 
                continue
1360
 
            if None in (paths):
1361
 
                continue
1362
 
            renames.append(paths)
1363
 
        renames.sort()
1364
 
        for old_name, new_name in renames:
1365
 
            self.outf.write("%s => %s\n" % (old_name, new_name))
 
1352
        try:
 
1353
            new_inv = tree.inventory
 
1354
            old_tree = tree.basis_tree()
 
1355
            old_tree.lock_read()
 
1356
            try:
 
1357
                old_inv = old_tree.inventory
 
1358
                renames = []
 
1359
                iterator = tree.iter_changes(old_tree, include_unchanged=True)
 
1360
                for f, paths, c, v, p, n, k, e in iterator:
 
1361
                    if paths[0] == paths[1]:
 
1362
                        continue
 
1363
                    if None in (paths):
 
1364
                        continue
 
1365
                    renames.append(paths)
 
1366
                renames.sort()
 
1367
                for old_name, new_name in renames:
 
1368
                    self.outf.write("%s => %s\n" % (old_name, new_name))
 
1369
            finally:
 
1370
                old_tree.unlock()
 
1371
        finally:
 
1372
            tree.unlock()
1366
1373
 
1367
1374
 
1368
1375
class cmd_update(Command):
1374
1381
 
1375
1382
    If you want to discard your local changes, you can just do a
1376
1383
    'bzr revert' instead of 'bzr commit' after the update.
1377
 
 
1378
 
    If the tree's branch is bound to a master branch, it will also update
1379
 
    the branch from the master.
1380
1384
    """
1381
1385
 
1382
1386
    _see_also = ['pull', 'working-trees', 'status-flags']
1383
1387
    takes_args = ['dir?']
1384
 
    takes_options = ['revision']
1385
1388
    aliases = ['up']
1386
1389
 
1387
 
    def run(self, dir='.', revision=None):
1388
 
        if revision is not None and len(revision) != 1:
1389
 
            raise errors.BzrCommandError(
1390
 
                        "bzr update --revision takes exactly one revision")
 
1390
    def run(self, dir='.'):
1391
1391
        tree = WorkingTree.open_containing(dir)[0]
1392
 
        branch = tree.branch
1393
1392
        possible_transports = []
1394
 
        master = branch.get_master_branch(
 
1393
        master = tree.branch.get_master_branch(
1395
1394
            possible_transports=possible_transports)
1396
1395
        if master is not None:
1397
1396
            tree.lock_write()
1398
 
            branch_location = master.base
1399
1397
        else:
1400
1398
            tree.lock_tree_write()
1401
 
            branch_location = tree.branch.base
1402
 
        self.add_cleanup(tree.unlock)
1403
 
        # get rid of the final '/' and be ready for display
1404
 
        branch_location = urlutils.unescape_for_display(branch_location[:-1],
1405
 
                                                        self.outf.encoding)
1406
 
        existing_pending_merges = tree.get_parent_ids()[1:]
1407
 
        if master is None:
1408
 
            old_tip = None
1409
 
        else:
1410
 
            # may need to fetch data into a heavyweight checkout
1411
 
            # XXX: this may take some time, maybe we should display a
1412
 
            # message
1413
 
            old_tip = branch.update(possible_transports)
1414
 
        if revision is not None:
1415
 
            revision_id = revision[0].as_revision_id(branch)
1416
 
        else:
1417
 
            revision_id = branch.last_revision()
1418
 
        if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1419
 
            revno = branch.revision_id_to_revno(revision_id)
1420
 
            note("Tree is up to date at revision %d of branch %s" %
1421
 
                (revno, branch_location))
1422
 
            return 0
1423
 
        view_info = _get_view_info_for_change_reporter(tree)
1424
 
        change_reporter = delta._ChangeReporter(
1425
 
            unversioned_filter=tree.is_ignored,
1426
 
            view_info=view_info)
1427
1399
        try:
 
1400
            existing_pending_merges = tree.get_parent_ids()[1:]
 
1401
            last_rev = _mod_revision.ensure_null(tree.last_revision())
 
1402
            if last_rev == _mod_revision.ensure_null(
 
1403
                tree.branch.last_revision()):
 
1404
                # may be up to date, check master too.
 
1405
                if master is None or last_rev == _mod_revision.ensure_null(
 
1406
                    master.last_revision()):
 
1407
                    revno = tree.branch.revision_id_to_revno(last_rev)
 
1408
                    note("Tree is up to date at revision %d." % (revno,))
 
1409
                    return 0
 
1410
            view_info = _get_view_info_for_change_reporter(tree)
1428
1411
            conflicts = tree.update(
1429
 
                change_reporter,
1430
 
                possible_transports=possible_transports,
1431
 
                revision=revision_id,
1432
 
                old_tip=old_tip)
1433
 
        except errors.NoSuchRevision, e:
1434
 
            raise errors.BzrCommandError(
1435
 
                                  "branch has no revision %s\n"
1436
 
                                  "bzr update --revision only works"
1437
 
                                  " for a revision in the branch history"
1438
 
                                  % (e.revision))
1439
 
        revno = tree.branch.revision_id_to_revno(
1440
 
            _mod_revision.ensure_null(tree.last_revision()))
1441
 
        note('Updated to revision %d of branch %s' %
1442
 
             (revno, branch_location))
1443
 
        if tree.get_parent_ids()[1:] != existing_pending_merges:
1444
 
            note('Your local commits will now show as pending merges with '
1445
 
                 "'bzr status', and can be committed with 'bzr commit'.")
1446
 
        if conflicts != 0:
1447
 
            return 1
1448
 
        else:
1449
 
            return 0
 
1412
                delta._ChangeReporter(unversioned_filter=tree.is_ignored,
 
1413
                view_info=view_info), possible_transports=possible_transports)
 
1414
            revno = tree.branch.revision_id_to_revno(
 
1415
                _mod_revision.ensure_null(tree.last_revision()))
 
1416
            note('Updated to revision %d.' % (revno,))
 
1417
            if tree.get_parent_ids()[1:] != existing_pending_merges:
 
1418
                note('Your local commits will now show as pending merges with '
 
1419
                     "'bzr status', and can be committed with 'bzr commit'.")
 
1420
            if conflicts != 0:
 
1421
                return 1
 
1422
            else:
 
1423
                return 0
 
1424
        finally:
 
1425
            tree.unlock()
1450
1426
 
1451
1427
 
1452
1428
class cmd_info(Command):
1523
1499
            file_list = [f for f in file_list]
1524
1500
 
1525
1501
        tree.lock_write()
1526
 
        self.add_cleanup(tree.unlock)
1527
 
        # Heuristics should probably all move into tree.remove_smart or
1528
 
        # some such?
1529
 
        if new:
1530
 
            added = tree.changes_from(tree.basis_tree(),
1531
 
                specific_files=file_list).added
1532
 
            file_list = sorted([f[0] for f in added], reverse=True)
1533
 
            if len(file_list) == 0:
1534
 
                raise errors.BzrCommandError('No matching files.')
1535
 
        elif file_list is None:
1536
 
            # missing files show up in iter_changes(basis) as
1537
 
            # versioned-with-no-kind.
1538
 
            missing = []
1539
 
            for change in tree.iter_changes(tree.basis_tree()):
1540
 
                # Find paths in the working tree that have no kind:
1541
 
                if change[1][1] is not None and change[6][1] is None:
1542
 
                    missing.append(change[1][1])
1543
 
            file_list = sorted(missing, reverse=True)
1544
 
            file_deletion_strategy = 'keep'
1545
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1546
 
            keep_files=file_deletion_strategy=='keep',
1547
 
            force=file_deletion_strategy=='force')
 
1502
        try:
 
1503
            # Heuristics should probably all move into tree.remove_smart or
 
1504
            # some such?
 
1505
            if new:
 
1506
                added = tree.changes_from(tree.basis_tree(),
 
1507
                    specific_files=file_list).added
 
1508
                file_list = sorted([f[0] for f in added], reverse=True)
 
1509
                if len(file_list) == 0:
 
1510
                    raise errors.BzrCommandError('No matching files.')
 
1511
            elif file_list is None:
 
1512
                # missing files show up in iter_changes(basis) as
 
1513
                # versioned-with-no-kind.
 
1514
                missing = []
 
1515
                for change in tree.iter_changes(tree.basis_tree()):
 
1516
                    # Find paths in the working tree that have no kind:
 
1517
                    if change[1][1] is not None and change[6][1] is None:
 
1518
                        missing.append(change[1][1])
 
1519
                file_list = sorted(missing, reverse=True)
 
1520
                file_deletion_strategy = 'keep'
 
1521
            tree.remove(file_list, verbose=verbose, to_file=self.outf,
 
1522
                keep_files=file_deletion_strategy=='keep',
 
1523
                force=file_deletion_strategy=='force')
 
1524
        finally:
 
1525
            tree.unlock()
1548
1526
 
1549
1527
 
1550
1528
class cmd_file_id(Command):
1695
1673
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1696
1674
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1697
1675
                value_switches=True,
1698
 
                title="Branch format",
 
1676
                title="Branch Format",
1699
1677
                ),
1700
1678
         Option('append-revisions-only',
1701
1679
                help='Never change revnos or the existing log.'
1770
1748
 
1771
1749
 
1772
1750
class cmd_init_repository(Command):
1773
 
    """Create a shared repository for branches to share storage space.
 
1751
    """Create a shared repository to hold branches.
1774
1752
 
1775
1753
    New branches created under the repository directory will store their
1776
 
    revisions in the repository, not in the branch directory.  For branches
1777
 
    with shared history, this reduces the amount of storage needed and 
1778
 
    speeds up the creation of new branches.
 
1754
    revisions in the repository, not in the branch directory.
1779
1755
 
1780
 
    If the --no-trees option is given then the branches in the repository
1781
 
    will not have working trees by default.  They will still exist as 
1782
 
    directories on disk, but they will not have separate copies of the 
1783
 
    files at a certain revision.  This can be useful for repositories that
1784
 
    store branches which are interacted with through checkouts or remote
1785
 
    branches, such as on a server.
 
1756
    If the --no-trees option is used then the branches in the repository
 
1757
    will not have working trees by default.
1786
1758
 
1787
1759
    :Examples:
1788
 
        Create a shared repository holding just branches::
 
1760
        Create a shared repositories holding just branches::
1789
1761
 
1790
1762
            bzr init-repo --no-trees repo
1791
1763
            bzr init repo/trunk
1857
1829
 
1858
1830
            bzr diff -r1
1859
1831
 
1860
 
        Difference between revision 3 and revision 1::
1861
 
 
1862
 
            bzr diff -r1..3
1863
 
 
1864
 
        Difference between revision 3 and revision 1 for branch xxx::
1865
 
 
1866
 
            bzr diff -r1..3 xxx
1867
 
 
1868
 
        To see the changes introduced in revision X::
1869
 
        
1870
 
            bzr diff -cX
1871
 
 
1872
 
        Note that in the case of a merge, the -c option shows the changes
1873
 
        compared to the left hand parent. To see the changes against
1874
 
        another parent, use::
1875
 
 
1876
 
            bzr diff -r<chosen_parent>..X
1877
 
 
1878
 
        The changes introduced by revision 2 (equivalent to -r1..2)::
1879
 
 
1880
 
            bzr diff -c2
 
1832
        Difference between revision 2 and revision 1::
 
1833
 
 
1834
            bzr diff -r1..2
 
1835
 
 
1836
        Difference between revision 2 and revision 1 for branch xxx::
 
1837
 
 
1838
            bzr diff -r1..2 xxx
1881
1839
 
1882
1840
        Show just the differences for file NEWS::
1883
1841
 
1929
1887
    @display_command
1930
1888
    def run(self, revision=None, file_list=None, diff_options=None,
1931
1889
            prefix=None, old=None, new=None, using=None):
1932
 
        from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
 
1890
        from bzrlib.diff import _get_trees_to_diff, show_diff_trees
1933
1891
 
1934
1892
        if (prefix is None) or (prefix == '0'):
1935
1893
            # diff -p0 format
1949
1907
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
1950
1908
                                         ' one or two revision specifiers')
1951
1909
 
1952
 
        (old_tree, new_tree,
1953
 
         old_branch, new_branch,
1954
 
         specific_files, extra_trees) = get_trees_and_branches_to_diff(
1955
 
            file_list, revision, old, new, apply_view=True)
 
1910
        old_tree, new_tree, specific_files, extra_trees = \
 
1911
                _get_trees_to_diff(file_list, revision, old, new,
 
1912
                apply_view=True)
1956
1913
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1957
1914
                               specific_files=specific_files,
1958
1915
                               external_diff_options=diff_options,
1976
1933
    def run(self, show_ids=False):
1977
1934
        tree = WorkingTree.open_containing(u'.')[0]
1978
1935
        tree.lock_read()
1979
 
        self.add_cleanup(tree.unlock)
1980
 
        old = tree.basis_tree()
1981
 
        old.lock_read()
1982
 
        self.add_cleanup(old.unlock)
1983
 
        for path, ie in old.inventory.iter_entries():
1984
 
            if not tree.has_id(ie.file_id):
1985
 
                self.outf.write(path)
1986
 
                if show_ids:
1987
 
                    self.outf.write(' ')
1988
 
                    self.outf.write(ie.file_id)
1989
 
                self.outf.write('\n')
 
1936
        try:
 
1937
            old = tree.basis_tree()
 
1938
            old.lock_read()
 
1939
            try:
 
1940
                for path, ie in old.inventory.iter_entries():
 
1941
                    if not tree.has_id(ie.file_id):
 
1942
                        self.outf.write(path)
 
1943
                        if show_ids:
 
1944
                            self.outf.write(' ')
 
1945
                            self.outf.write(ie.file_id)
 
1946
                        self.outf.write('\n')
 
1947
            finally:
 
1948
                old.unlock()
 
1949
        finally:
 
1950
            tree.unlock()
1990
1951
 
1991
1952
 
1992
1953
class cmd_modified(Command):
2028
1989
    def run(self, null=False):
2029
1990
        wt = WorkingTree.open_containing(u'.')[0]
2030
1991
        wt.lock_read()
2031
 
        self.add_cleanup(wt.unlock)
2032
 
        basis = wt.basis_tree()
2033
 
        basis.lock_read()
2034
 
        self.add_cleanup(basis.unlock)
2035
 
        basis_inv = basis.inventory
2036
 
        inv = wt.inventory
2037
 
        for file_id in inv:
2038
 
            if file_id in basis_inv:
2039
 
                continue
2040
 
            if inv.is_root(file_id) and len(basis_inv) == 0:
2041
 
                continue
2042
 
            path = inv.id2path(file_id)
2043
 
            if not os.access(osutils.abspath(path), os.F_OK):
2044
 
                continue
2045
 
            if null:
2046
 
                self.outf.write(path + '\0')
2047
 
            else:
2048
 
                self.outf.write(osutils.quotefn(path) + '\n')
 
1992
        try:
 
1993
            basis = wt.basis_tree()
 
1994
            basis.lock_read()
 
1995
            try:
 
1996
                basis_inv = basis.inventory
 
1997
                inv = wt.inventory
 
1998
                for file_id in inv:
 
1999
                    if file_id in basis_inv:
 
2000
                        continue
 
2001
                    if inv.is_root(file_id) and len(basis_inv) == 0:
 
2002
                        continue
 
2003
                    path = inv.id2path(file_id)
 
2004
                    if not os.access(osutils.abspath(path), os.F_OK):
 
2005
                        continue
 
2006
                    if null:
 
2007
                        self.outf.write(path + '\0')
 
2008
                    else:
 
2009
                        self.outf.write(osutils.quotefn(path) + '\n')
 
2010
            finally:
 
2011
                basis.unlock()
 
2012
        finally:
 
2013
            wt.unlock()
2049
2014
 
2050
2015
 
2051
2016
class cmd_root(Command):
2196
2161
    :Tips & tricks:
2197
2162
 
2198
2163
      GUI tools and IDEs are often better at exploring history than command
2199
 
      line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2200
 
      bzr-explorer shell, or the Loggerhead web interface.  See the Plugin
2201
 
      Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2202
 
      <http://wiki.bazaar.canonical.com/IDEIntegration>.  
 
2164
      line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
 
2165
      respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
 
2166
      http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
 
2167
 
 
2168
      Web interfaces are often better at exploring history than command line
 
2169
      tools, particularly for branches on servers. You may prefer Loggerhead
 
2170
      or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2203
2171
 
2204
2172
      You may find it useful to add the aliases below to ``bazaar.conf``::
2205
2173
 
2308
2276
        filter_by_dir = False
2309
2277
        if file_list:
2310
2278
            # find the file ids to log and check for directory filtering
2311
 
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2312
 
                revision, file_list)
2313
 
            self.add_cleanup(b.unlock)
 
2279
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
 
2280
                file_list)
2314
2281
            for relpath, file_id, kind in file_info_list:
2315
2282
                if file_id is None:
2316
2283
                    raise errors.BzrCommandError(
2334
2301
                location = '.'
2335
2302
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2336
2303
            b = dir.open_branch()
2337
 
            b.lock_read()
2338
 
            self.add_cleanup(b.unlock)
2339
2304
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2340
2305
 
2341
2306
        # Decide on the type of delta & diff filtering to use
2351
2316
        else:
2352
2317
            diff_type = 'full'
2353
2318
 
2354
 
        # Build the log formatter
2355
 
        if log_format is None:
2356
 
            log_format = log.log_formatter_registry.get_default(b)
2357
 
        # Make a non-encoding output to include the diffs - bug 328007
2358
 
        unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2359
 
        lf = log_format(show_ids=show_ids, to_file=self.outf,
2360
 
                        to_exact_file=unencoded_output,
2361
 
                        show_timezone=timezone,
2362
 
                        delta_format=get_verbosity_level(),
2363
 
                        levels=levels,
2364
 
                        show_advice=levels is None)
2365
 
 
2366
 
        # Choose the algorithm for doing the logging. It's annoying
2367
 
        # having multiple code paths like this but necessary until
2368
 
        # the underlying repository format is faster at generating
2369
 
        # deltas or can provide everything we need from the indices.
2370
 
        # The default algorithm - match-using-deltas - works for
2371
 
        # multiple files and directories and is faster for small
2372
 
        # amounts of history (200 revisions say). However, it's too
2373
 
        # slow for logging a single file in a repository with deep
2374
 
        # history, i.e. > 10K revisions. In the spirit of "do no
2375
 
        # evil when adding features", we continue to use the
2376
 
        # original algorithm - per-file-graph - for the "single
2377
 
        # file that isn't a directory without showing a delta" case.
2378
 
        partial_history = revision and b.repository._format.supports_chks
2379
 
        match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2380
 
            or delta_type or partial_history)
2381
 
 
2382
 
        # Build the LogRequest and execute it
2383
 
        if len(file_ids) == 0:
2384
 
            file_ids = None
2385
 
        rqst = make_log_request_dict(
2386
 
            direction=direction, specific_fileids=file_ids,
2387
 
            start_revision=rev1, end_revision=rev2, limit=limit,
2388
 
            message_search=message, delta_type=delta_type,
2389
 
            diff_type=diff_type, _match_using_deltas=match_using_deltas)
2390
 
        Logger(b, rqst).show(lf)
 
2319
        b.lock_read()
 
2320
        try:
 
2321
            # Build the log formatter
 
2322
            if log_format is None:
 
2323
                log_format = log.log_formatter_registry.get_default(b)
 
2324
            lf = log_format(show_ids=show_ids, to_file=self.outf,
 
2325
                            show_timezone=timezone,
 
2326
                            delta_format=get_verbosity_level(),
 
2327
                            levels=levels,
 
2328
                            show_advice=levels is None)
 
2329
 
 
2330
            # Choose the algorithm for doing the logging. It's annoying
 
2331
            # having multiple code paths like this but necessary until
 
2332
            # the underlying repository format is faster at generating
 
2333
            # deltas or can provide everything we need from the indices.
 
2334
            # The default algorithm - match-using-deltas - works for
 
2335
            # multiple files and directories and is faster for small
 
2336
            # amounts of history (200 revisions say). However, it's too
 
2337
            # slow for logging a single file in a repository with deep
 
2338
            # history, i.e. > 10K revisions. In the spirit of "do no
 
2339
            # evil when adding features", we continue to use the
 
2340
            # original algorithm - per-file-graph - for the "single
 
2341
            # file that isn't a directory without showing a delta" case.
 
2342
            partial_history = revision and b.repository._format.supports_chks
 
2343
            match_using_deltas = (len(file_ids) != 1 or filter_by_dir
 
2344
                or delta_type or partial_history)
 
2345
 
 
2346
            # Build the LogRequest and execute it
 
2347
            if len(file_ids) == 0:
 
2348
                file_ids = None
 
2349
            rqst = make_log_request_dict(
 
2350
                direction=direction, specific_fileids=file_ids,
 
2351
                start_revision=rev1, end_revision=rev2, limit=limit,
 
2352
                message_search=message, delta_type=delta_type,
 
2353
                diff_type=diff_type, _match_using_deltas=match_using_deltas)
 
2354
            Logger(b, rqst).show(lf)
 
2355
        finally:
 
2356
            b.unlock()
2391
2357
 
2392
2358
 
2393
2359
def _get_revision_range(revisionspec_list, branch, command_name):
2457
2423
    @display_command
2458
2424
    def run(self, filename):
2459
2425
        tree, relpath = WorkingTree.open_containing(filename)
 
2426
        b = tree.branch
2460
2427
        file_id = tree.path2id(relpath)
2461
 
        b = tree.branch
2462
 
        b.lock_read()
2463
 
        self.add_cleanup(b.unlock)
2464
 
        touching_revs = log.find_touching_revisions(b, file_id)
2465
 
        for revno, revision_id, what in touching_revs:
 
2428
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2466
2429
            self.outf.write("%6d %s\n" % (revno, what))
2467
2430
 
2468
2431
 
2521
2484
        if from_root:
2522
2485
            if relpath:
2523
2486
                prefix = relpath + '/'
2524
 
        elif fs_path != '.' and not fs_path.endswith('/'):
 
2487
        elif fs_path != '.':
2525
2488
            prefix = fs_path + '/'
2526
2489
 
2527
2490
        if revision is not None or tree is None:
2536
2499
                note("Ignoring files outside view. View is %s" % view_str)
2537
2500
 
2538
2501
        tree.lock_read()
2539
 
        self.add_cleanup(tree.unlock)
2540
 
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2541
 
            from_dir=relpath, recursive=recursive):
2542
 
            # Apply additional masking
2543
 
            if not all and not selection[fc]:
2544
 
                continue
2545
 
            if kind is not None and fkind != kind:
2546
 
                continue
2547
 
            if apply_view:
2548
 
                try:
2549
 
                    if relpath:
2550
 
                        fullpath = osutils.pathjoin(relpath, fp)
2551
 
                    else:
2552
 
                        fullpath = fp
2553
 
                    views.check_path_in_view(tree, fullpath)
2554
 
                except errors.FileOutsideView:
2555
 
                    continue
 
2502
        try:
 
2503
            for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
 
2504
                from_dir=relpath, recursive=recursive):
 
2505
                # Apply additional masking
 
2506
                if not all and not selection[fc]:
 
2507
                    continue
 
2508
                if kind is not None and fkind != kind:
 
2509
                    continue
 
2510
                if apply_view:
 
2511
                    try:
 
2512
                        if relpath:
 
2513
                            fullpath = osutils.pathjoin(relpath, fp)
 
2514
                        else:
 
2515
                            fullpath = fp
 
2516
                        views.check_path_in_view(tree, fullpath)
 
2517
                    except errors.FileOutsideView:
 
2518
                        continue
2556
2519
 
2557
 
            # Output the entry
2558
 
            if prefix:
2559
 
                fp = osutils.pathjoin(prefix, fp)
2560
 
            kindch = entry.kind_character()
2561
 
            outstring = fp + kindch
2562
 
            ui.ui_factory.clear_term()
2563
 
            if verbose:
2564
 
                outstring = '%-8s %s' % (fc, outstring)
2565
 
                if show_ids and fid is not None:
2566
 
                    outstring = "%-50s %s" % (outstring, fid)
2567
 
                self.outf.write(outstring + '\n')
2568
 
            elif null:
2569
 
                self.outf.write(fp + '\0')
2570
 
                if show_ids:
2571
 
                    if fid is not None:
2572
 
                        self.outf.write(fid)
2573
 
                    self.outf.write('\0')
2574
 
                self.outf.flush()
2575
 
            else:
2576
 
                if show_ids:
2577
 
                    if fid is not None:
2578
 
                        my_id = fid
2579
 
                    else:
2580
 
                        my_id = ''
2581
 
                    self.outf.write('%-50s %s\n' % (outstring, my_id))
2582
 
                else:
 
2520
                # Output the entry
 
2521
                if prefix:
 
2522
                    fp = osutils.pathjoin(prefix, fp)
 
2523
                kindch = entry.kind_character()
 
2524
                outstring = fp + kindch
 
2525
                ui.ui_factory.clear_term()
 
2526
                if verbose:
 
2527
                    outstring = '%-8s %s' % (fc, outstring)
 
2528
                    if show_ids and fid is not None:
 
2529
                        outstring = "%-50s %s" % (outstring, fid)
2583
2530
                    self.outf.write(outstring + '\n')
 
2531
                elif null:
 
2532
                    self.outf.write(fp + '\0')
 
2533
                    if show_ids:
 
2534
                        if fid is not None:
 
2535
                            self.outf.write(fid)
 
2536
                        self.outf.write('\0')
 
2537
                    self.outf.flush()
 
2538
                else:
 
2539
                    if show_ids:
 
2540
                        if fid is not None:
 
2541
                            my_id = fid
 
2542
                        else:
 
2543
                            my_id = ''
 
2544
                        self.outf.write('%-50s %s\n' % (outstring, my_id))
 
2545
                    else:
 
2546
                        self.outf.write(outstring + '\n')
 
2547
        finally:
 
2548
            tree.unlock()
2584
2549
 
2585
2550
 
2586
2551
class cmd_unknowns(Command):
2601
2566
 
2602
2567
    See ``bzr help patterns`` for details on the syntax of patterns.
2603
2568
 
2604
 
    If a .bzrignore file does not exist, the ignore command
2605
 
    will create one and add the specified files or patterns to the newly
2606
 
    created file. The ignore command will also automatically add the 
2607
 
    .bzrignore file to be versioned. Creating a .bzrignore file without
2608
 
    the use of the ignore command will require an explicit add command.
2609
 
 
2610
2569
    To remove patterns from the ignore list, edit the .bzrignore file.
2611
2570
    After adding, editing or deleting that file either indirectly by
2612
2571
    using this command or directly by using an editor, be sure to commit
2613
2572
    it.
2614
 
    
2615
 
    Patterns prefixed with '!' are exceptions to ignore patterns and take
2616
 
    precedence over regular ignores.  Such exceptions are used to specify
2617
 
    files that should be versioned which would otherwise be ignored.
2618
 
    
2619
 
    Patterns prefixed with '!!' act as regular ignore patterns, but have
2620
 
    precedence over the '!' exception patterns.
2621
2573
 
2622
2574
    Note: ignore patterns containing shell wildcards must be quoted from
2623
2575
    the shell on Unix.
2627
2579
 
2628
2580
            bzr ignore ./Makefile
2629
2581
 
2630
 
        Ignore .class files in all directories...::
 
2582
        Ignore class files in all directories::
2631
2583
 
2632
2584
            bzr ignore "*.class"
2633
2585
 
2634
 
        ...but do not ignore "special.class"::
2635
 
 
2636
 
            bzr ignore "!special.class"
2637
 
 
2638
2586
        Ignore .o files under the lib directory::
2639
2587
 
2640
2588
            bzr ignore "lib/**/*.o"
2646
2594
        Ignore everything but the "debian" toplevel directory::
2647
2595
 
2648
2596
            bzr ignore "RE:(?!debian/).*"
2649
 
        
2650
 
        Ignore everything except the "local" toplevel directory,
2651
 
        but always ignore "*~" autosave files, even under local/::
2652
 
        
2653
 
            bzr ignore "*"
2654
 
            bzr ignore "!./local"
2655
 
            bzr ignore "!!*~"
2656
2597
    """
2657
2598
 
2658
2599
    _see_also = ['status', 'ignored', 'patterns']
2716
2657
    def run(self):
2717
2658
        tree = WorkingTree.open_containing(u'.')[0]
2718
2659
        tree.lock_read()
2719
 
        self.add_cleanup(tree.unlock)
2720
 
        for path, file_class, kind, file_id, entry in tree.list_files():
2721
 
            if file_class != 'I':
2722
 
                continue
2723
 
            ## XXX: Slightly inefficient since this was already calculated
2724
 
            pat = tree.is_ignored(path)
2725
 
            self.outf.write('%-50s %s\n' % (path, pat))
 
2660
        try:
 
2661
            for path, file_class, kind, file_id, entry in tree.list_files():
 
2662
                if file_class != 'I':
 
2663
                    continue
 
2664
                ## XXX: Slightly inefficient since this was already calculated
 
2665
                pat = tree.is_ignored(path)
 
2666
                self.outf.write('%-50s %s\n' % (path, pat))
 
2667
        finally:
 
2668
            tree.unlock()
2726
2669
 
2727
2670
 
2728
2671
class cmd_lookup_revision(Command):
2831
2774
        tree, branch, relpath = \
2832
2775
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2833
2776
        branch.lock_read()
2834
 
        self.add_cleanup(branch.unlock)
2835
 
        return self._run(tree, branch, relpath, filename, revision,
2836
 
                         name_from_revision, filters)
 
2777
        try:
 
2778
            return self._run(tree, branch, relpath, filename, revision,
 
2779
                             name_from_revision, filters)
 
2780
        finally:
 
2781
            branch.unlock()
2837
2782
 
2838
2783
    def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2839
2784
        filtered):
2840
2785
        if tree is None:
2841
2786
            tree = b.basis_tree()
2842
2787
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2843
 
        rev_tree.lock_read()
2844
 
        self.add_cleanup(rev_tree.unlock)
2845
2788
 
2846
2789
        old_file_id = rev_tree.path2id(relpath)
2847
2790
 
2882
2825
            chunks = content.splitlines(True)
2883
2826
            content = filtered_output_bytes(chunks, filters,
2884
2827
                ContentFilterContext(relpath, rev_tree))
2885
 
            self.cleanup_now()
2886
2828
            self.outf.writelines(content)
2887
2829
        else:
2888
 
            self.cleanup_now()
2889
2830
            self.outf.write(content)
2890
2831
 
2891
2832
 
2998
2939
             Option('strict',
2999
2940
                    help="Refuse to commit if there are unknown "
3000
2941
                    "files in the working tree."),
3001
 
             Option('commit-time', type=str,
3002
 
                    help="Manually set a commit time using commit date "
3003
 
                    "format, e.g. '2009-10-10 08:00:00 +0100'."),
3004
2942
             ListOption('fixes', type=str,
3005
2943
                    help="Mark a bug as being fixed by this revision "
3006
2944
                         "(see \"bzr help bugs\")."),
3013
2951
                         "the master branch until a normal commit "
3014
2952
                         "is performed."
3015
2953
                    ),
3016
 
             Option('show-diff',
3017
 
                    help='When no message is supplied, show the diff along'
3018
 
                    ' with the status summary in the message editor.'),
 
2954
              Option('show-diff',
 
2955
                     help='When no message is supplied, show the diff along'
 
2956
                     ' with the status summary in the message editor.'),
3019
2957
             ]
3020
2958
    aliases = ['ci', 'checkin']
3021
2959
 
3040
2978
 
3041
2979
    def run(self, message=None, file=None, verbose=False, selected_list=None,
3042
2980
            unchanged=False, strict=False, local=False, fixes=None,
3043
 
            author=None, show_diff=False, exclude=None, commit_time=None):
 
2981
            author=None, show_diff=False, exclude=None):
3044
2982
        from bzrlib.errors import (
3045
2983
            PointlessCommit,
3046
2984
            ConflictsInTree,
3052
2990
            make_commit_message_template_encoded
3053
2991
        )
3054
2992
 
3055
 
        commit_stamp = offset = None
3056
 
        if commit_time is not None:
3057
 
            try:
3058
 
                commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3059
 
            except ValueError, e:
3060
 
                raise errors.BzrCommandError(
3061
 
                    "Could not parse --commit-time: " + str(e))
3062
 
 
3063
2993
        # TODO: Need a blackbox test for invoking the external editor; may be
3064
2994
        # slightly problematic to run this cross-platform.
3065
2995
 
3085
3015
        if local and not tree.branch.get_bound_location():
3086
3016
            raise errors.LocalRequiresBoundBranch()
3087
3017
 
3088
 
        if message is not None:
3089
 
            try:
3090
 
                file_exists = osutils.lexists(message)
3091
 
            except UnicodeError:
3092
 
                # The commit message contains unicode characters that can't be
3093
 
                # represented in the filesystem encoding, so that can't be a
3094
 
                # file.
3095
 
                file_exists = False
3096
 
            if file_exists:
3097
 
                warning_msg = (
3098
 
                    'The commit message is a file name: "%(f)s".\n'
3099
 
                    '(use --file "%(f)s" to take commit message from that file)'
3100
 
                    % { 'f': message })
3101
 
                ui.ui_factory.show_warning(warning_msg)
3102
 
 
3103
3018
        def get_message(commit_obj):
3104
3019
            """Callback to get commit message"""
3105
3020
            my_message = message
3106
 
            if my_message is not None and '\r' in my_message:
3107
 
                my_message = my_message.replace('\r\n', '\n')
3108
 
                my_message = my_message.replace('\r', '\n')
3109
3021
            if my_message is None and not file:
3110
3022
                t = make_commit_message_template_encoded(tree,
3111
3023
                        selected_list, diff=show_diff,
3135
3047
                        specific_files=selected_list,
3136
3048
                        allow_pointless=unchanged, strict=strict, local=local,
3137
3049
                        reporter=None, verbose=verbose, revprops=properties,
3138
 
                        authors=author, timestamp=commit_stamp,
3139
 
                        timezone=offset,
 
3050
                        authors=author,
3140
3051
                        exclude=safe_relpath_files(tree, exclude))
3141
3052
        except PointlessCommit:
3142
3053
            # FIXME: This should really happen before the file is read in;
3429
3340
    Tests that need working space on disk use a common temporary directory,
3430
3341
    typically inside $TMPDIR or /tmp.
3431
3342
 
3432
 
    If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
3433
 
    into a pdb postmortem session.
3434
 
 
3435
3343
    :Examples:
3436
3344
        Run only tests relating to 'ignore'::
3437
3345
 
3446
3354
    def get_transport_type(typestring):
3447
3355
        """Parse and return a transport specifier."""
3448
3356
        if typestring == "sftp":
3449
 
            from bzrlib.tests import stub_sftp
3450
 
            return stub_sftp.SFTPAbsoluteServer
 
3357
            from bzrlib.transport.sftp import SFTPAbsoluteServer
 
3358
            return SFTPAbsoluteServer
3451
3359
        if typestring == "memory":
3452
 
            from bzrlib.tests import test_server
3453
 
            return memory.MemoryServer
 
3360
            from bzrlib.transport.memory import MemoryServer
 
3361
            return MemoryServer
3454
3362
        if typestring == "fakenfs":
3455
 
            from bzrlib.tests import test_server
3456
 
            return test_server.FakeNFSServer
 
3363
            from bzrlib.transport.fakenfs import FakeNFSServer
 
3364
            return FakeNFSServer
3457
3365
        msg = "No known transport type %s. Supported types are: sftp\n" %\
3458
3366
            (typestring)
3459
3367
        raise errors.BzrCommandError(msg)
3474
3382
                     Option('lsprof-timed',
3475
3383
                            help='Generate lsprof output for benchmarked'
3476
3384
                                 ' sections of code.'),
3477
 
                     Option('lsprof-tests',
3478
 
                            help='Generate lsprof output for each test.'),
3479
3385
                     Option('cache-dir', type=str,
3480
3386
                            help='Cache intermediate benchmark output in this '
3481
3387
                                 'directory.'),
3522
3428
            first=False, list_only=False,
3523
3429
            randomize=None, exclude=None, strict=False,
3524
3430
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3525
 
            parallel=None, lsprof_tests=False):
 
3431
            parallel=None):
3526
3432
        from bzrlib.tests import selftest
3527
3433
        import bzrlib.benchmarks as benchmarks
3528
3434
        from bzrlib.benchmarks import tree_creator
3552
3458
            verbose = not is_quiet()
3553
3459
            # TODO: should possibly lock the history file...
3554
3460
            benchfile = open(".perf_history", "at", buffering=1)
3555
 
            self.add_cleanup(benchfile.close)
3556
3461
        else:
3557
3462
            test_suite_factory = None
3558
3463
            benchfile = None
3559
 
        selftest_kwargs = {"verbose": verbose,
3560
 
                          "pattern": pattern,
3561
 
                          "stop_on_failure": one,
3562
 
                          "transport": transport,
3563
 
                          "test_suite_factory": test_suite_factory,
3564
 
                          "lsprof_timed": lsprof_timed,
3565
 
                          "lsprof_tests": lsprof_tests,
3566
 
                          "bench_history": benchfile,
3567
 
                          "matching_tests_first": first,
3568
 
                          "list_only": list_only,
3569
 
                          "random_seed": randomize,
3570
 
                          "exclude_pattern": exclude,
3571
 
                          "strict": strict,
3572
 
                          "load_list": load_list,
3573
 
                          "debug_flags": debugflag,
3574
 
                          "starting_with": starting_with
3575
 
                          }
3576
 
        selftest_kwargs.update(self.additional_selftest_args)
3577
 
        result = selftest(**selftest_kwargs)
 
3464
        try:
 
3465
            selftest_kwargs = {"verbose": verbose,
 
3466
                              "pattern": pattern,
 
3467
                              "stop_on_failure": one,
 
3468
                              "transport": transport,
 
3469
                              "test_suite_factory": test_suite_factory,
 
3470
                              "lsprof_timed": lsprof_timed,
 
3471
                              "bench_history": benchfile,
 
3472
                              "matching_tests_first": first,
 
3473
                              "list_only": list_only,
 
3474
                              "random_seed": randomize,
 
3475
                              "exclude_pattern": exclude,
 
3476
                              "strict": strict,
 
3477
                              "load_list": load_list,
 
3478
                              "debug_flags": debugflag,
 
3479
                              "starting_with": starting_with
 
3480
                              }
 
3481
            selftest_kwargs.update(self.additional_selftest_args)
 
3482
            result = selftest(**selftest_kwargs)
 
3483
        finally:
 
3484
            if benchfile is not None:
 
3485
                benchfile.close()
3578
3486
        return int(not result)
3579
3487
 
3580
3488
 
3619
3527
        branch1 = Branch.open_containing(branch)[0]
3620
3528
        branch2 = Branch.open_containing(other)[0]
3621
3529
        branch1.lock_read()
3622
 
        self.add_cleanup(branch1.unlock)
3623
 
        branch2.lock_read()
3624
 
        self.add_cleanup(branch2.unlock)
3625
 
        last1 = ensure_null(branch1.last_revision())
3626
 
        last2 = ensure_null(branch2.last_revision())
3627
 
 
3628
 
        graph = branch1.repository.get_graph(branch2.repository)
3629
 
        base_rev_id = graph.find_unique_lca(last1, last2)
3630
 
 
3631
 
        print 'merge base is revision %s' % base_rev_id
 
3530
        try:
 
3531
            branch2.lock_read()
 
3532
            try:
 
3533
                last1 = ensure_null(branch1.last_revision())
 
3534
                last2 = ensure_null(branch2.last_revision())
 
3535
 
 
3536
                graph = branch1.repository.get_graph(branch2.repository)
 
3537
                base_rev_id = graph.find_unique_lca(last1, last2)
 
3538
 
 
3539
                print 'merge base is revision %s' % base_rev_id
 
3540
            finally:
 
3541
                branch2.unlock()
 
3542
        finally:
 
3543
            branch1.unlock()
3632
3544
 
3633
3545
 
3634
3546
class cmd_merge(Command):
3667
3579
    committed to record the result of the merge.
3668
3580
 
3669
3581
    merge refuses to run if there are any uncommitted changes, unless
3670
 
    --force is given. The --force option can also be used to create a
3671
 
    merge revision which has more than two parents.
3672
 
 
3673
 
    If one would like to merge changes from the working tree of the other
3674
 
    branch without merging any committed revisions, the --uncommitted option
3675
 
    can be given.
 
3582
    --force is given.
3676
3583
 
3677
3584
    To select only some changes to merge, use "merge -i", which will prompt
3678
3585
    you to apply each diff hunk and file change, similar to "shelve".
3690
3597
 
3691
3598
            bzr merge -r 81..82 ../bzr.dev
3692
3599
 
3693
 
        To apply a merge directive contained in /tmp/merge::
 
3600
        To apply a merge directive contained in /tmp/merge:
3694
3601
 
3695
3602
            bzr merge /tmp/merge
3696
 
 
3697
 
        To create a merge revision with three parents from two branches
3698
 
        feature1a and feature1b:
3699
 
 
3700
 
            bzr merge ../feature1a
3701
 
            bzr merge ../feature1b --force
3702
 
            bzr commit -m 'revision with three parents'
3703
3603
    """
3704
3604
 
3705
3605
    encoding_type = 'exact'
3750
3650
        verified = 'inapplicable'
3751
3651
        tree = WorkingTree.open_containing(directory)[0]
3752
3652
 
 
3653
        # die as quickly as possible if there are uncommitted changes
3753
3654
        try:
3754
3655
            basis_tree = tree.revision_tree(tree.last_revision())
3755
3656
        except errors.NoSuchRevision:
3756
3657
            basis_tree = tree.basis_tree()
3757
 
 
3758
 
        # die as quickly as possible if there are uncommitted changes
3759
3658
        if not force:
3760
 
            if tree.has_changes():
 
3659
            if tree.has_changes(basis_tree):
3761
3660
                raise errors.UncommittedChanges(tree)
3762
3661
 
3763
3662
        view_info = _get_view_info_for_change_reporter(tree)
3764
3663
        change_reporter = delta._ChangeReporter(
3765
3664
            unversioned_filter=tree.is_ignored, view_info=view_info)
3766
 
        pb = ui.ui_factory.nested_progress_bar()
3767
 
        self.add_cleanup(pb.finished)
3768
 
        tree.lock_write()
3769
 
        self.add_cleanup(tree.unlock)
3770
 
        if location is not None:
3771
 
            try:
3772
 
                mergeable = bundle.read_mergeable_from_url(location,
3773
 
                    possible_transports=possible_transports)
3774
 
            except errors.NotABundle:
3775
 
                mergeable = None
 
3665
        cleanups = []
 
3666
        try:
 
3667
            pb = ui.ui_factory.nested_progress_bar()
 
3668
            cleanups.append(pb.finished)
 
3669
            tree.lock_write()
 
3670
            cleanups.append(tree.unlock)
 
3671
            if location is not None:
 
3672
                try:
 
3673
                    mergeable = bundle.read_mergeable_from_url(location,
 
3674
                        possible_transports=possible_transports)
 
3675
                except errors.NotABundle:
 
3676
                    mergeable = None
 
3677
                else:
 
3678
                    if uncommitted:
 
3679
                        raise errors.BzrCommandError('Cannot use --uncommitted'
 
3680
                            ' with bundles or merge directives.')
 
3681
 
 
3682
                    if revision is not None:
 
3683
                        raise errors.BzrCommandError(
 
3684
                            'Cannot use -r with merge directives or bundles')
 
3685
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
 
3686
                       mergeable, pb)
 
3687
 
 
3688
            if merger is None and uncommitted:
 
3689
                if revision is not None and len(revision) > 0:
 
3690
                    raise errors.BzrCommandError('Cannot use --uncommitted and'
 
3691
                        ' --revision at the same time.')
 
3692
                merger = self.get_merger_from_uncommitted(tree, location, pb,
 
3693
                                                          cleanups)
 
3694
                allow_pending = False
 
3695
 
 
3696
            if merger is None:
 
3697
                merger, allow_pending = self._get_merger_from_branch(tree,
 
3698
                    location, revision, remember, possible_transports, pb)
 
3699
 
 
3700
            merger.merge_type = merge_type
 
3701
            merger.reprocess = reprocess
 
3702
            merger.show_base = show_base
 
3703
            self.sanity_check_merger(merger)
 
3704
            if (merger.base_rev_id == merger.other_rev_id and
 
3705
                merger.other_rev_id is not None):
 
3706
                note('Nothing to do.')
 
3707
                return 0
 
3708
            if pull:
 
3709
                if merger.interesting_files is not None:
 
3710
                    raise errors.BzrCommandError('Cannot pull individual files')
 
3711
                if (merger.base_rev_id == tree.last_revision()):
 
3712
                    result = tree.pull(merger.other_branch, False,
 
3713
                                       merger.other_rev_id)
 
3714
                    result.report(self.outf)
 
3715
                    return 0
 
3716
            merger.check_basis(False)
 
3717
            if preview:
 
3718
                return self._do_preview(merger, cleanups)
 
3719
            elif interactive:
 
3720
                return self._do_interactive(merger, cleanups)
3776
3721
            else:
3777
 
                if uncommitted:
3778
 
                    raise errors.BzrCommandError('Cannot use --uncommitted'
3779
 
                        ' with bundles or merge directives.')
3780
 
 
3781
 
                if revision is not None:
3782
 
                    raise errors.BzrCommandError(
3783
 
                        'Cannot use -r with merge directives or bundles')
3784
 
                merger, verified = _mod_merge.Merger.from_mergeable(tree,
3785
 
                   mergeable, None)
3786
 
 
3787
 
        if merger is None and uncommitted:
3788
 
            if revision is not None and len(revision) > 0:
3789
 
                raise errors.BzrCommandError('Cannot use --uncommitted and'
3790
 
                    ' --revision at the same time.')
3791
 
            merger = self.get_merger_from_uncommitted(tree, location, None)
3792
 
            allow_pending = False
3793
 
 
3794
 
        if merger is None:
3795
 
            merger, allow_pending = self._get_merger_from_branch(tree,
3796
 
                location, revision, remember, possible_transports, None)
3797
 
 
3798
 
        merger.merge_type = merge_type
3799
 
        merger.reprocess = reprocess
3800
 
        merger.show_base = show_base
3801
 
        self.sanity_check_merger(merger)
3802
 
        if (merger.base_rev_id == merger.other_rev_id and
3803
 
            merger.other_rev_id is not None):
3804
 
            note('Nothing to do.')
3805
 
            return 0
3806
 
        if pull:
3807
 
            if merger.interesting_files is not None:
3808
 
                raise errors.BzrCommandError('Cannot pull individual files')
3809
 
            if (merger.base_rev_id == tree.last_revision()):
3810
 
                result = tree.pull(merger.other_branch, False,
3811
 
                                   merger.other_rev_id)
3812
 
                result.report(self.outf)
3813
 
                return 0
3814
 
        if merger.this_basis is None:
3815
 
            raise errors.BzrCommandError(
3816
 
                "This branch has no commits."
3817
 
                " (perhaps you would prefer 'bzr pull')")
3818
 
        if preview:
3819
 
            return self._do_preview(merger)
3820
 
        elif interactive:
3821
 
            return self._do_interactive(merger)
3822
 
        else:
3823
 
            return self._do_merge(merger, change_reporter, allow_pending,
3824
 
                                  verified)
3825
 
 
3826
 
    def _get_preview(self, merger):
 
3722
                return self._do_merge(merger, change_reporter, allow_pending,
 
3723
                                      verified)
 
3724
        finally:
 
3725
            for cleanup in reversed(cleanups):
 
3726
                cleanup()
 
3727
 
 
3728
    def _get_preview(self, merger, cleanups):
3827
3729
        tree_merger = merger.make_merger()
3828
3730
        tt = tree_merger.make_preview_transform()
3829
 
        self.add_cleanup(tt.finalize)
 
3731
        cleanups.append(tt.finalize)
3830
3732
        result_tree = tt.get_preview_tree()
3831
3733
        return result_tree
3832
3734
 
3833
 
    def _do_preview(self, merger):
 
3735
    def _do_preview(self, merger, cleanups):
3834
3736
        from bzrlib.diff import show_diff_trees
3835
 
        result_tree = self._get_preview(merger)
 
3737
        result_tree = self._get_preview(merger, cleanups)
3836
3738
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3837
3739
                        old_label='', new_label='')
3838
3740
 
3848
3750
        else:
3849
3751
            return 0
3850
3752
 
3851
 
    def _do_interactive(self, merger):
 
3753
    def _do_interactive(self, merger, cleanups):
3852
3754
        """Perform an interactive merge.
3853
3755
 
3854
3756
        This works by generating a preview tree of the merge, then using
3856
3758
        and the preview tree.
3857
3759
        """
3858
3760
        from bzrlib import shelf_ui
3859
 
        result_tree = self._get_preview(merger)
 
3761
        result_tree = self._get_preview(merger, cleanups)
3860
3762
        writer = bzrlib.option.diff_writer_registry.get()
3861
3763
        shelver = shelf_ui.Shelver(merger.this_tree, result_tree, destroy=True,
3862
3764
                                   reporter=shelf_ui.ApplyReporter(),
3863
3765
                                   diff_writer=writer(sys.stdout))
3864
 
        try:
3865
 
            shelver.run()
3866
 
        finally:
3867
 
            shelver.finalize()
 
3766
        shelver.run()
3868
3767
 
3869
3768
    def sanity_check_merger(self, merger):
3870
3769
        if (merger.show_base and
3930
3829
            allow_pending = True
3931
3830
        return merger, allow_pending
3932
3831
 
3933
 
    def get_merger_from_uncommitted(self, tree, location, pb):
 
3832
    def get_merger_from_uncommitted(self, tree, location, pb, cleanups):
3934
3833
        """Get a merger for uncommitted changes.
3935
3834
 
3936
3835
        :param tree: The tree the merger should apply to.
3937
3836
        :param location: The location containing uncommitted changes.
3938
3837
        :param pb: The progress bar to use for showing progress.
 
3838
        :param cleanups: A list of operations to perform to clean up the
 
3839
            temporary directories, unfinalized objects, etc.
3939
3840
        """
3940
3841
        location = self._select_branch_location(tree, location)[0]
3941
3842
        other_tree, other_path = WorkingTree.open_containing(location)
4028
3929
            merge_type = _mod_merge.Merge3Merger
4029
3930
        tree, file_list = tree_files(file_list)
4030
3931
        tree.lock_write()
4031
 
        self.add_cleanup(tree.unlock)
4032
 
        parents = tree.get_parent_ids()
4033
 
        if len(parents) != 2:
4034
 
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4035
 
                                         " merges.  Not cherrypicking or"
4036
 
                                         " multi-merges.")
4037
 
        repository = tree.branch.repository
4038
 
        interesting_ids = None
4039
 
        new_conflicts = []
4040
 
        conflicts = tree.conflicts()
4041
 
        if file_list is not None:
4042
 
            interesting_ids = set()
4043
 
            for filename in file_list:
4044
 
                file_id = tree.path2id(filename)
4045
 
                if file_id is None:
4046
 
                    raise errors.NotVersionedError(filename)
4047
 
                interesting_ids.add(file_id)
4048
 
                if tree.kind(file_id) != "directory":
4049
 
                    continue
 
3932
        try:
 
3933
            parents = tree.get_parent_ids()
 
3934
            if len(parents) != 2:
 
3935
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
3936
                                             " merges.  Not cherrypicking or"
 
3937
                                             " multi-merges.")
 
3938
            repository = tree.branch.repository
 
3939
            interesting_ids = None
 
3940
            new_conflicts = []
 
3941
            conflicts = tree.conflicts()
 
3942
            if file_list is not None:
 
3943
                interesting_ids = set()
 
3944
                for filename in file_list:
 
3945
                    file_id = tree.path2id(filename)
 
3946
                    if file_id is None:
 
3947
                        raise errors.NotVersionedError(filename)
 
3948
                    interesting_ids.add(file_id)
 
3949
                    if tree.kind(file_id) != "directory":
 
3950
                        continue
4050
3951
 
4051
 
                for name, ie in tree.inventory.iter_entries(file_id):
4052
 
                    interesting_ids.add(ie.file_id)
4053
 
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4054
 
        else:
4055
 
            # Remerge only supports resolving contents conflicts
4056
 
            allowed_conflicts = ('text conflict', 'contents conflict')
4057
 
            restore_files = [c.path for c in conflicts
4058
 
                             if c.typestring in allowed_conflicts]
4059
 
        _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4060
 
        tree.set_conflicts(ConflictList(new_conflicts))
4061
 
        if file_list is not None:
4062
 
            restore_files = file_list
4063
 
        for filename in restore_files:
 
3952
                    for name, ie in tree.inventory.iter_entries(file_id):
 
3953
                        interesting_ids.add(ie.file_id)
 
3954
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
 
3955
            else:
 
3956
                # Remerge only supports resolving contents conflicts
 
3957
                allowed_conflicts = ('text conflict', 'contents conflict')
 
3958
                restore_files = [c.path for c in conflicts
 
3959
                                 if c.typestring in allowed_conflicts]
 
3960
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
 
3961
            tree.set_conflicts(ConflictList(new_conflicts))
 
3962
            if file_list is not None:
 
3963
                restore_files = file_list
 
3964
            for filename in restore_files:
 
3965
                try:
 
3966
                    restore(tree.abspath(filename))
 
3967
                except errors.NotConflicted:
 
3968
                    pass
 
3969
            # Disable pending merges, because the file texts we are remerging
 
3970
            # have not had those merges performed.  If we use the wrong parents
 
3971
            # list, we imply that the working tree text has seen and rejected
 
3972
            # all the changes from the other tree, when in fact those changes
 
3973
            # have not yet been seen.
 
3974
            pb = ui.ui_factory.nested_progress_bar()
 
3975
            tree.set_parent_ids(parents[:1])
4064
3976
            try:
4065
 
                restore(tree.abspath(filename))
4066
 
            except errors.NotConflicted:
4067
 
                pass
4068
 
        # Disable pending merges, because the file texts we are remerging
4069
 
        # have not had those merges performed.  If we use the wrong parents
4070
 
        # list, we imply that the working tree text has seen and rejected
4071
 
        # all the changes from the other tree, when in fact those changes
4072
 
        # have not yet been seen.
4073
 
        tree.set_parent_ids(parents[:1])
4074
 
        try:
4075
 
            merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4076
 
            merger.interesting_ids = interesting_ids
4077
 
            merger.merge_type = merge_type
4078
 
            merger.show_base = show_base
4079
 
            merger.reprocess = reprocess
4080
 
            conflicts = merger.do_merge()
 
3977
                merger = _mod_merge.Merger.from_revision_ids(pb,
 
3978
                                                             tree, parents[1])
 
3979
                merger.interesting_ids = interesting_ids
 
3980
                merger.merge_type = merge_type
 
3981
                merger.show_base = show_base
 
3982
                merger.reprocess = reprocess
 
3983
                conflicts = merger.do_merge()
 
3984
            finally:
 
3985
                tree.set_parent_ids(parents)
 
3986
                pb.finished()
4081
3987
        finally:
4082
 
            tree.set_parent_ids(parents)
 
3988
            tree.unlock()
4083
3989
        if conflicts > 0:
4084
3990
            return 1
4085
3991
        else:
4107
4013
    name.  If you name a directory, all the contents of that directory will be
4108
4014
    reverted.
4109
4015
 
4110
 
    If you have newly added files since the target revision, they will be
4111
 
    removed.  If the files to be removed have been changed, backups will be
4112
 
    created as above.  Directories containing unknown files will not be
4113
 
    deleted.
 
4016
    Any files that have been newly added since that revision will be deleted,
 
4017
    with a backup kept if appropriate.  Directories containing unknown files
 
4018
    will not be deleted.
4114
4019
 
4115
 
    The working tree contains a list of revisions that have been merged but
4116
 
    not yet committed. These revisions will be included as additional parents
4117
 
    of the next commit.  Normally, using revert clears that list as well as
4118
 
    reverting the files.  If any files are specified, revert leaves the list
4119
 
    of uncommitted merges alone and reverts only the files.  Use ``bzr revert
4120
 
    .`` in the tree root to revert all files but keep the recorded merges,
4121
 
    and ``bzr revert --forget-merges`` to clear the pending merge list without
 
4020
    The working tree contains a list of pending merged revisions, which will
 
4021
    be included as parents in the next commit.  Normally, revert clears that
 
4022
    list as well as reverting the files.  If any files are specified, revert
 
4023
    leaves the pending merge list alone and reverts only the files.  Use "bzr
 
4024
    revert ." in the tree root to revert all files but keep the merge record,
 
4025
    and "bzr revert --forget-merges" to clear the pending merge list without
4122
4026
    reverting any files.
4123
 
 
4124
 
    Using "bzr revert --forget-merges", it is possible to apply all of the
4125
 
    changes from a branch in a single revision.  To do this, perform the merge
4126
 
    as desired.  Then doing revert with the "--forget-merges" option will keep
4127
 
    the content of the tree as it was, but it will clear the list of pending
4128
 
    merges.  The next commit will then contain all of the changes that are
4129
 
    present in the other branch, but without any other parent revisions.
4130
 
    Because this technique forgets where these changes originated, it may
4131
 
    cause additional conflicts on later merges involving the same source and
4132
 
    target branches.
4133
4027
    """
4134
4028
 
4135
4029
    _see_also = ['cat', 'export']
4145
4039
            forget_merges=None):
4146
4040
        tree, file_list = tree_files(file_list)
4147
4041
        tree.lock_write()
4148
 
        self.add_cleanup(tree.unlock)
4149
 
        if forget_merges:
4150
 
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4151
 
        else:
4152
 
            self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
4042
        try:
 
4043
            if forget_merges:
 
4044
                tree.set_parent_ids(tree.get_parent_ids()[:1])
 
4045
            else:
 
4046
                self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
4047
        finally:
 
4048
            tree.unlock()
4153
4049
 
4154
4050
    @staticmethod
4155
4051
    def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4156
4052
        rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4157
 
        tree.revert(file_list, rev_tree, not no_backup, None,
4158
 
            report_changes=True)
 
4053
        pb = ui.ui_factory.nested_progress_bar()
 
4054
        try:
 
4055
            tree.revert(file_list, rev_tree, not no_backup, pb,
 
4056
                report_changes=True)
 
4057
        finally:
 
4058
            pb.finished()
4159
4059
 
4160
4060
 
4161
4061
class cmd_assert_fail(Command):
4210
4110
    To filter on a range of revisions, you can use the command -r begin..end
4211
4111
    -r revision requests a specific revision, -r ..end or -r begin.. are
4212
4112
    also valid.
4213
 
            
4214
 
    :Exit values:
4215
 
        1 - some missing revisions
4216
 
        0 - no missing revisions
4217
4113
 
4218
4114
    :Examples:
4219
4115
 
4302
4198
        if remote_branch.base == local_branch.base:
4303
4199
            remote_branch = local_branch
4304
4200
 
4305
 
        local_branch.lock_read()
4306
 
        self.add_cleanup(local_branch.unlock)
4307
4201
        local_revid_range = _revision_range_to_revid_range(
4308
4202
            _get_revision_range(my_revision, local_branch,
4309
4203
                self.name()))
4310
4204
 
4311
 
        remote_branch.lock_read()
4312
 
        self.add_cleanup(remote_branch.unlock)
4313
4205
        remote_revid_range = _revision_range_to_revid_range(
4314
4206
            _get_revision_range(revision,
4315
4207
                remote_branch, self.name()))
4316
4208
 
4317
 
        local_extra, remote_extra = find_unmerged(
4318
 
            local_branch, remote_branch, restrict,
4319
 
            backward=not reverse,
4320
 
            include_merges=include_merges,
4321
 
            local_revid_range=local_revid_range,
4322
 
            remote_revid_range=remote_revid_range)
4323
 
 
4324
 
        if log_format is None:
4325
 
            registry = log.log_formatter_registry
4326
 
            log_format = registry.get_default(local_branch)
4327
 
        lf = log_format(to_file=self.outf,
4328
 
                        show_ids=show_ids,
4329
 
                        show_timezone='original')
4330
 
 
4331
 
        status_code = 0
4332
 
        if local_extra and not theirs_only:
4333
 
            message("You have %d extra revision(s):\n" %
4334
 
                len(local_extra))
4335
 
            for revision in iter_log_revisions(local_extra,
4336
 
                                local_branch.repository,
4337
 
                                verbose):
4338
 
                lf.log_revision(revision)
4339
 
            printed_local = True
4340
 
            status_code = 1
4341
 
        else:
4342
 
            printed_local = False
4343
 
 
4344
 
        if remote_extra and not mine_only:
4345
 
            if printed_local is True:
4346
 
                message("\n\n\n")
4347
 
            message("You are missing %d revision(s):\n" %
4348
 
                len(remote_extra))
4349
 
            for revision in iter_log_revisions(remote_extra,
4350
 
                                remote_branch.repository,
4351
 
                                verbose):
4352
 
                lf.log_revision(revision)
4353
 
            status_code = 1
4354
 
 
4355
 
        if mine_only and not local_extra:
4356
 
            # We checked local, and found nothing extra
4357
 
            message('This branch is up to date.\n')
4358
 
        elif theirs_only and not remote_extra:
4359
 
            # We checked remote, and found nothing extra
4360
 
            message('Other branch is up to date.\n')
4361
 
        elif not (mine_only or theirs_only or local_extra or
4362
 
                  remote_extra):
4363
 
            # We checked both branches, and neither one had extra
4364
 
            # revisions
4365
 
            message("Branches are up to date.\n")
4366
 
        self.cleanup_now()
 
4209
        local_branch.lock_read()
 
4210
        try:
 
4211
            remote_branch.lock_read()
 
4212
            try:
 
4213
                local_extra, remote_extra = find_unmerged(
 
4214
                    local_branch, remote_branch, restrict,
 
4215
                    backward=not reverse,
 
4216
                    include_merges=include_merges,
 
4217
                    local_revid_range=local_revid_range,
 
4218
                    remote_revid_range=remote_revid_range)
 
4219
 
 
4220
                if log_format is None:
 
4221
                    registry = log.log_formatter_registry
 
4222
                    log_format = registry.get_default(local_branch)
 
4223
                lf = log_format(to_file=self.outf,
 
4224
                                show_ids=show_ids,
 
4225
                                show_timezone='original')
 
4226
 
 
4227
                status_code = 0
 
4228
                if local_extra and not theirs_only:
 
4229
                    message("You have %d extra revision(s):\n" %
 
4230
                        len(local_extra))
 
4231
                    for revision in iter_log_revisions(local_extra,
 
4232
                                        local_branch.repository,
 
4233
                                        verbose):
 
4234
                        lf.log_revision(revision)
 
4235
                    printed_local = True
 
4236
                    status_code = 1
 
4237
                else:
 
4238
                    printed_local = False
 
4239
 
 
4240
                if remote_extra and not mine_only:
 
4241
                    if printed_local is True:
 
4242
                        message("\n\n\n")
 
4243
                    message("You are missing %d revision(s):\n" %
 
4244
                        len(remote_extra))
 
4245
                    for revision in iter_log_revisions(remote_extra,
 
4246
                                        remote_branch.repository,
 
4247
                                        verbose):
 
4248
                        lf.log_revision(revision)
 
4249
                    status_code = 1
 
4250
 
 
4251
                if mine_only and not local_extra:
 
4252
                    # We checked local, and found nothing extra
 
4253
                    message('This branch is up to date.\n')
 
4254
                elif theirs_only and not remote_extra:
 
4255
                    # We checked remote, and found nothing extra
 
4256
                    message('Other branch is up to date.\n')
 
4257
                elif not (mine_only or theirs_only or local_extra or
 
4258
                          remote_extra):
 
4259
                    # We checked both branches, and neither one had extra
 
4260
                    # revisions
 
4261
                    message("Branches are up to date.\n")
 
4262
            finally:
 
4263
                remote_branch.unlock()
 
4264
        finally:
 
4265
            local_branch.unlock()
4367
4266
        if not status_code and parent is None and other_branch is not None:
4368
4267
            local_branch.lock_write()
4369
 
            self.add_cleanup(local_branch.unlock)
4370
 
            # handle race conditions - a parent might be set while we run.
4371
 
            if local_branch.get_parent() is None:
4372
 
                local_branch.set_parent(remote_branch.base)
 
4268
            try:
 
4269
                # handle race conditions - a parent might be set while we run.
 
4270
                if local_branch.get_parent() is None:
 
4271
                    local_branch.set_parent(remote_branch.base)
 
4272
            finally:
 
4273
                local_branch.unlock()
4373
4274
        return status_code
4374
4275
 
4375
4276
 
4403
4304
    adding new commands, providing additional network transports and
4404
4305
    customizing log output.
4405
4306
 
4406
 
    See the Bazaar Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/>
4407
 
    for further information on plugins including where to find them and how to
4408
 
    install them. Instructions are also provided there on how to write new
4409
 
    plugins using the Python programming language.
 
4307
    See the Bazaar web site, http://bazaar-vcs.org, for further
 
4308
    information on plugins including where to find them and how to
 
4309
    install them. Instructions are also provided there on how to
 
4310
    write new plugins using the Python programming language.
4410
4311
    """
4411
4312
    takes_options = ['verbose']
4412
4313
 
4454
4355
        else:
4455
4356
            b = Branch.open(branch)
4456
4357
        b.lock_read()
4457
 
        self.add_cleanup(b.unlock)
4458
 
        if revision is None:
4459
 
            rev_id = b.last_revision()
4460
 
        else:
4461
 
            rev_id = revision[0].as_revision_id(b)
4462
 
        t = testament_class.from_revision(b.repository, rev_id)
4463
 
        if long:
4464
 
            sys.stdout.writelines(t.as_text_lines())
4465
 
        else:
4466
 
            sys.stdout.write(t.as_short_text())
 
4358
        try:
 
4359
            if revision is None:
 
4360
                rev_id = b.last_revision()
 
4361
            else:
 
4362
                rev_id = revision[0].as_revision_id(b)
 
4363
            t = testament_class.from_revision(b.repository, rev_id)
 
4364
            if long:
 
4365
                sys.stdout.writelines(t.as_text_lines())
 
4366
            else:
 
4367
                sys.stdout.write(t.as_short_text())
 
4368
        finally:
 
4369
            b.unlock()
4467
4370
 
4468
4371
 
4469
4372
class cmd_annotate(Command):
4495
4398
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4496
4399
        if wt is not None:
4497
4400
            wt.lock_read()
4498
 
            self.add_cleanup(wt.unlock)
4499
4401
        else:
4500
4402
            branch.lock_read()
4501
 
            self.add_cleanup(branch.unlock)
4502
 
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4503
 
        tree.lock_read()
4504
 
        self.add_cleanup(tree.unlock)
4505
 
        if wt is not None:
4506
 
            file_id = wt.path2id(relpath)
4507
 
        else:
4508
 
            file_id = tree.path2id(relpath)
4509
 
        if file_id is None:
4510
 
            raise errors.NotVersionedError(filename)
4511
 
        file_version = tree.inventory[file_id].revision
4512
 
        if wt is not None and revision is None:
4513
 
            # If there is a tree and we're not annotating historical
4514
 
            # versions, annotate the working tree's content.
4515
 
            annotate_file_tree(wt, file_id, self.outf, long, all,
4516
 
                show_ids=show_ids)
4517
 
        else:
4518
 
            annotate_file(branch, file_version, file_id, long, all, self.outf,
4519
 
                          show_ids=show_ids)
 
4403
        try:
 
4404
            tree = _get_one_revision_tree('annotate', revision, branch=branch)
 
4405
            if wt is not None:
 
4406
                file_id = wt.path2id(relpath)
 
4407
            else:
 
4408
                file_id = tree.path2id(relpath)
 
4409
            if file_id is None:
 
4410
                raise errors.NotVersionedError(filename)
 
4411
            file_version = tree.inventory[file_id].revision
 
4412
            if wt is not None and revision is None:
 
4413
                # If there is a tree and we're not annotating historical
 
4414
                # versions, annotate the working tree's content.
 
4415
                annotate_file_tree(wt, file_id, self.outf, long, all,
 
4416
                    show_ids=show_ids)
 
4417
            else:
 
4418
                annotate_file(branch, file_version, file_id, long, all, self.outf,
 
4419
                              show_ids=show_ids)
 
4420
        finally:
 
4421
            if wt is not None:
 
4422
                wt.unlock()
 
4423
            else:
 
4424
                branch.unlock()
4520
4425
 
4521
4426
 
4522
4427
class cmd_re_sign(Command):
4534
4439
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4535
4440
        b = WorkingTree.open_containing(u'.')[0].branch
4536
4441
        b.lock_write()
4537
 
        self.add_cleanup(b.unlock)
4538
 
        return self._run(b, revision_id_list, revision)
 
4442
        try:
 
4443
            return self._run(b, revision_id_list, revision)
 
4444
        finally:
 
4445
            b.unlock()
4539
4446
 
4540
4447
    def _run(self, b, revision_id_list, revision):
4541
4448
        import bzrlib.gpg as gpg
4592
4499
    before they will be applied to the local branch.
4593
4500
 
4594
4501
    Bound branches use the nickname of its master branch unless it is set
4595
 
    locally, in which case binding will update the local nickname to be
 
4502
    locally, in which case binding will update the the local nickname to be
4596
4503
    that of the master.
4597
4504
    """
4598
4505
 
4610
4517
                    'This format does not remember old locations.')
4611
4518
            else:
4612
4519
                if location is None:
4613
 
                    if b.get_bound_location() is not None:
4614
 
                        raise errors.BzrCommandError('Branch is already bound')
4615
 
                    else:
4616
 
                        raise errors.BzrCommandError('No location supplied '
4617
 
                            'and no previous location known')
 
4520
                    raise errors.BzrCommandError('No location supplied and no '
 
4521
                        'previous location known')
4618
4522
        b_other = Branch.open(location)
4619
4523
        try:
4620
4524
            b.bind(b_other)
4690
4594
 
4691
4595
        if tree is not None:
4692
4596
            tree.lock_write()
4693
 
            self.add_cleanup(tree.unlock)
4694
4597
        else:
4695
4598
            b.lock_write()
4696
 
            self.add_cleanup(b.unlock)
4697
 
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
 
4599
        try:
 
4600
            return self._run(b, tree, dry_run, verbose, revision, force,
 
4601
                             local=local)
 
4602
        finally:
 
4603
            if tree is not None:
 
4604
                tree.unlock()
 
4605
            else:
 
4606
                b.unlock()
4698
4607
 
4699
4608
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4700
4609
        from bzrlib.log import log_formatter, show_log
4717
4626
                rev_id = b.get_rev_id(revno)
4718
4627
 
4719
4628
        if rev_id is None or _mod_revision.is_null(rev_id):
4720
 
            ui.ui_factory.note('No revisions to uncommit.')
 
4629
            self.outf.write('No revisions to uncommit.\n')
4721
4630
            return 1
4722
4631
 
4723
 
        log_collector = ui.ui_factory.make_output_stream()
4724
4632
        lf = log_formatter('short',
4725
 
                           to_file=log_collector,
 
4633
                           to_file=self.outf,
4726
4634
                           show_timezone='original')
4727
4635
 
4728
4636
        show_log(b,
4733
4641
                 end_revision=last_revno)
4734
4642
 
4735
4643
        if dry_run:
4736
 
            ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
 
4644
            print 'Dry-run, pretending to remove the above revisions.'
 
4645
            if not force:
 
4646
                val = raw_input('Press <enter> to continue')
4737
4647
        else:
4738
 
            ui.ui_factory.note('The above revision(s) will be removed.')
4739
 
 
4740
 
        if not force:
4741
 
            if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
4742
 
                ui.ui_factory.note('Canceled')
4743
 
                return 0
 
4648
            print 'The above revision(s) will be removed.'
 
4649
            if not force:
 
4650
                val = raw_input('Are you sure [y/N]? ')
 
4651
                if val.lower() not in ('y', 'yes'):
 
4652
                    print 'Canceled'
 
4653
                    return 0
4744
4654
 
4745
4655
        mutter('Uncommitting from {%s} to {%s}',
4746
4656
               last_rev_id, rev_id)
4747
4657
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4748
4658
                 revno=revno, local=local)
4749
 
        ui.ui_factory.note('You can restore the old tip by running:\n'
4750
 
             '  bzr pull . -r revid:%s' % last_rev_id)
 
4659
        note('You can restore the old tip by running:\n'
 
4660
             '  bzr pull . -r revid:%s', last_rev_id)
4751
4661
 
4752
4662
 
4753
4663
class cmd_break_lock(Command):
4756
4666
    CAUTION: Locks should only be broken when you are sure that the process
4757
4667
    holding the lock has been stopped.
4758
4668
 
4759
 
    You can get information on what locks are open via the 'bzr info
4760
 
    [location]' command.
 
4669
    You can get information on what locks are open via the 'bzr info' command.
4761
4670
 
4762
4671
    :Examples:
4763
4672
        bzr break-lock
4764
 
        bzr break-lock bzr+ssh://example.com/bzr/foo
4765
4673
    """
4766
4674
    takes_args = ['location?']
4767
4675
 
4797
4705
    takes_options = [
4798
4706
        Option('inet',
4799
4707
               help='Serve on stdin/out for use from inetd or sshd.'),
4800
 
        RegistryOption('protocol',
4801
 
               help="Protocol to serve.",
 
4708
        RegistryOption('protocol', 
 
4709
               help="Protocol to serve.", 
4802
4710
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
4803
4711
               value_switches=True),
4804
4712
        Option('port',
4813
4721
        Option('allow-writes',
4814
4722
               help='By default the server is a readonly server.  Supplying '
4815
4723
                    '--allow-writes enables write access to the contents of '
4816
 
                    'the served directory and below.  Note that ``bzr serve`` '
4817
 
                    'does not perform authentication, so unless some form of '
4818
 
                    'external authentication is arranged supplying this '
4819
 
                    'option leads to global uncontrolled write access to your '
4820
 
                    'file system.'
 
4724
                    'the served directory and below.'
4821
4725
                ),
4822
4726
        ]
4823
4727
 
5039
4943
      directly from the merge directive, without retrieving data from a
5040
4944
      branch.
5041
4945
 
5042
 
    `bzr send` creates a compact data set that, when applied using bzr
5043
 
    merge, has the same effect as merging from the source branch.  
5044
 
    
5045
 
    By default the merge directive is self-contained and can be applied to any
5046
 
    branch containing submit_branch in its ancestory without needing access to
5047
 
    the source branch.
5048
 
    
5049
 
    If --no-bundle is specified, then Bazaar doesn't send the contents of the
5050
 
    revisions, but only a structured request to merge from the
5051
 
    public_location.  In that case the public_branch is needed and it must be
5052
 
    up-to-date and accessible to the recipient.  The public_branch is always
5053
 
    included if known, so that people can check it later.
5054
 
 
5055
 
    The submit branch defaults to the parent of the source branch, but can be
5056
 
    overridden.  Both submit branch and public branch will be remembered in
5057
 
    branch.conf the first time they are used for a particular branch.  The
5058
 
    source branch defaults to that containing the working directory, but can
5059
 
    be changed using --from.
5060
 
 
5061
 
    In order to calculate those changes, bzr must analyse the submit branch.
5062
 
    Therefore it is most efficient for the submit branch to be a local mirror.
5063
 
    If a public location is known for the submit_branch, that location is used
5064
 
    in the merge directive.
5065
 
 
5066
 
    The default behaviour is to send the merge directive by mail, unless -o is
5067
 
    given, in which case it is sent to a file.
 
4946
    If --no-bundle is specified, then public_branch is needed (and must be
 
4947
    up-to-date), so that the receiver can perform the merge using the
 
4948
    public_branch.  The public_branch is always included if known, so that
 
4949
    people can check it later.
 
4950
 
 
4951
    The submit branch defaults to the parent, but can be overridden.  Both
 
4952
    submit branch and public branch will be remembered if supplied.
 
4953
 
 
4954
    If a public_branch is known for the submit_branch, that public submit
 
4955
    branch is used in the merge instructions.  This means that a local mirror
 
4956
    can be used as your actual submit branch, once you have set public_branch
 
4957
    for that mirror.
5068
4958
 
5069
4959
    Mail is sent using your preferred mail program.  This should be transparent
5070
4960
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
5072
4962
 
5073
4963
    To use a specific mail program, set the mail_client configuration option.
5074
4964
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
5075
 
    specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5076
 
    Mail.app), "mutt", and "thunderbird"; generic options are "default",
5077
 
    "editor", "emacsclient", "mapi", and "xdg-email".  Plugins may also add
5078
 
    supported clients.
 
4965
    specific clients are "claws", "evolution", "kmail", "mutt", and
 
4966
    "thunderbird"; generic options are "default", "editor", "emacsclient",
 
4967
    "mapi", and "xdg-email".  Plugins may also add supported clients.
5079
4968
 
5080
4969
    If mail is being sent, a to address is required.  This can be supplied
5081
4970
    either on the commandline, by setting the submit_to configuration
5090
4979
 
5091
4980
    The merge directives created by bzr send may be applied using bzr merge or
5092
4981
    bzr pull by specifying a file containing a merge directive as the location.
5093
 
 
5094
 
    bzr send makes extensive use of public locations to map local locations into
5095
 
    URLs that can be used by other people.  See `bzr help configuration` to
5096
 
    set them, and use `bzr info` to display them.
5097
4982
    """
5098
4983
 
5099
4984
    encoding_type = 'exact'
5258
5143
            ):
5259
5144
        branch, relpath = Branch.open_containing(directory)
5260
5145
        branch.lock_write()
5261
 
        self.add_cleanup(branch.unlock)
5262
 
        if delete:
5263
 
            branch.tags.delete_tag(tag_name)
5264
 
            self.outf.write('Deleted tag %s.\n' % tag_name)
5265
 
        else:
5266
 
            if revision:
5267
 
                if len(revision) != 1:
5268
 
                    raise errors.BzrCommandError(
5269
 
                        "Tags can only be placed on a single revision, "
5270
 
                        "not on a range")
5271
 
                revision_id = revision[0].as_revision_id(branch)
 
5146
        try:
 
5147
            if delete:
 
5148
                branch.tags.delete_tag(tag_name)
 
5149
                self.outf.write('Deleted tag %s.\n' % tag_name)
5272
5150
            else:
5273
 
                revision_id = branch.last_revision()
5274
 
            if (not force) and branch.tags.has_tag(tag_name):
5275
 
                raise errors.TagAlreadyExists(tag_name)
5276
 
            branch.tags.set_tag(tag_name, revision_id)
5277
 
            self.outf.write('Created tag %s.\n' % tag_name)
 
5151
                if revision:
 
5152
                    if len(revision) != 1:
 
5153
                        raise errors.BzrCommandError(
 
5154
                            "Tags can only be placed on a single revision, "
 
5155
                            "not on a range")
 
5156
                    revision_id = revision[0].as_revision_id(branch)
 
5157
                else:
 
5158
                    revision_id = branch.last_revision()
 
5159
                if (not force) and branch.tags.has_tag(tag_name):
 
5160
                    raise errors.TagAlreadyExists(tag_name)
 
5161
                branch.tags.set_tag(tag_name, revision_id)
 
5162
                self.outf.write('Created tag %s.\n' % tag_name)
 
5163
        finally:
 
5164
            branch.unlock()
5278
5165
 
5279
5166
 
5280
5167
class cmd_tags(Command):
5313
5200
            return
5314
5201
 
5315
5202
        branch.lock_read()
5316
 
        self.add_cleanup(branch.unlock)
5317
 
        if revision:
5318
 
            graph = branch.repository.get_graph()
5319
 
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5320
 
            revid1, revid2 = rev1.rev_id, rev2.rev_id
5321
 
            # only show revisions between revid1 and revid2 (inclusive)
5322
 
            tags = [(tag, revid) for tag, revid in tags if
5323
 
                graph.is_between(revid, revid1, revid2)]
5324
 
        if sort == 'alpha':
5325
 
            tags.sort()
5326
 
        elif sort == 'time':
5327
 
            timestamps = {}
5328
 
            for tag, revid in tags:
5329
 
                try:
5330
 
                    revobj = branch.repository.get_revision(revid)
5331
 
                except errors.NoSuchRevision:
5332
 
                    timestamp = sys.maxint # place them at the end
5333
 
                else:
5334
 
                    timestamp = revobj.timestamp
5335
 
                timestamps[revid] = timestamp
5336
 
            tags.sort(key=lambda x: timestamps[x[1]])
5337
 
        if not show_ids:
5338
 
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5339
 
            for index, (tag, revid) in enumerate(tags):
5340
 
                try:
5341
 
                    revno = branch.revision_id_to_dotted_revno(revid)
5342
 
                    if isinstance(revno, tuple):
5343
 
                        revno = '.'.join(map(str, revno))
5344
 
                except errors.NoSuchRevision:
5345
 
                    # Bad tag data/merges can lead to tagged revisions
5346
 
                    # which are not in this branch. Fail gracefully ...
5347
 
                    revno = '?'
5348
 
                tags[index] = (tag, revno)
5349
 
        self.cleanup_now()
 
5203
        try:
 
5204
            if revision:
 
5205
                graph = branch.repository.get_graph()
 
5206
                rev1, rev2 = _get_revision_range(revision, branch, self.name())
 
5207
                revid1, revid2 = rev1.rev_id, rev2.rev_id
 
5208
                # only show revisions between revid1 and revid2 (inclusive)
 
5209
                tags = [(tag, revid) for tag, revid in tags if
 
5210
                    graph.is_between(revid, revid1, revid2)]
 
5211
            if sort == 'alpha':
 
5212
                tags.sort()
 
5213
            elif sort == 'time':
 
5214
                timestamps = {}
 
5215
                for tag, revid in tags:
 
5216
                    try:
 
5217
                        revobj = branch.repository.get_revision(revid)
 
5218
                    except errors.NoSuchRevision:
 
5219
                        timestamp = sys.maxint # place them at the end
 
5220
                    else:
 
5221
                        timestamp = revobj.timestamp
 
5222
                    timestamps[revid] = timestamp
 
5223
                tags.sort(key=lambda x: timestamps[x[1]])
 
5224
            if not show_ids:
 
5225
                # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
 
5226
                for index, (tag, revid) in enumerate(tags):
 
5227
                    try:
 
5228
                        revno = branch.revision_id_to_dotted_revno(revid)
 
5229
                        if isinstance(revno, tuple):
 
5230
                            revno = '.'.join(map(str, revno))
 
5231
                    except errors.NoSuchRevision:
 
5232
                        # Bad tag data/merges can lead to tagged revisions
 
5233
                        # which are not in this branch. Fail gracefully ...
 
5234
                        revno = '?'
 
5235
                    tags[index] = (tag, revno)
 
5236
        finally:
 
5237
            branch.unlock()
5350
5238
        for tag, revspec in tags:
5351
5239
            self.outf.write('%-20s %s\n' % (tag, revspec))
5352
5240
 
5461
5349
    /path/to/newbranch.
5462
5350
 
5463
5351
    Bound branches use the nickname of its master branch unless it is set
5464
 
    locally, in which case switching will update the local nickname to be
 
5352
    locally, in which case switching will update the the local nickname to be
5465
5353
    that of the master.
5466
5354
    """
5467
5355
 
5468
 
    takes_args = ['to_location?']
 
5356
    takes_args = ['to_location']
5469
5357
    takes_options = [Option('force',
5470
5358
                        help='Switch even if local commits will be lost.'),
5471
 
                     'revision',
5472
5359
                     Option('create-branch', short_name='b',
5473
5360
                        help='Create the target branch from this one before'
5474
5361
                             ' switching to it.'),
5475
 
                    ]
 
5362
                     ]
5476
5363
 
5477
 
    def run(self, to_location=None, force=False, create_branch=False,
5478
 
            revision=None):
 
5364
    def run(self, to_location, force=False, create_branch=False):
5479
5365
        from bzrlib import switch
5480
5366
        tree_location = '.'
5481
 
        revision = _get_one_revision('switch', revision)
5482
5367
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5483
 
        if to_location is None:
5484
 
            if revision is None:
5485
 
                raise errors.BzrCommandError('You must supply either a'
5486
 
                                             ' revision or a location')
5487
 
            to_location = '.'
5488
5368
        try:
5489
5369
            branch = control_dir.open_branch()
5490
5370
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5495
5375
            if branch is None:
5496
5376
                raise errors.BzrCommandError('cannot create branch without'
5497
5377
                                             ' source branch')
5498
 
            to_location = directory_service.directories.dereference(
5499
 
                              to_location)
5500
5378
            if '/' not in to_location and '\\' not in to_location:
5501
5379
                # This path is meant to be relative to the existing branch
5502
5380
                this_url = self._get_branch_location(control_dir)
5504
5382
            to_branch = branch.bzrdir.sprout(to_location,
5505
5383
                                 possible_transports=[branch.bzrdir.root_transport],
5506
5384
                                 source_branch=branch).open_branch()
 
5385
            # try:
 
5386
            #     from_branch = control_dir.open_branch()
 
5387
            # except errors.NotBranchError:
 
5388
            #     raise BzrCommandError('Cannot create a branch from this'
 
5389
            #         ' location when we cannot open this branch')
 
5390
            # from_branch.bzrdir.sprout(
 
5391
            pass
5507
5392
        else:
5508
5393
            try:
5509
5394
                to_branch = Branch.open(to_location)
5511
5396
                this_url = self._get_branch_location(control_dir)
5512
5397
                to_branch = Branch.open(
5513
5398
                    urlutils.join(this_url, '..', to_location))
5514
 
        if revision is not None:
5515
 
            revision = revision.as_revision_id(to_branch)
5516
 
        switch.switch(control_dir, to_branch, force, revision_id=revision)
 
5399
        switch.switch(control_dir, to_branch, force)
5517
5400
        if had_explicit_nick:
5518
5401
            branch = control_dir.open_branch() #get the new branch!
5519
5402
            branch.nick = to_branch.nick
5766
5649
            try:
5767
5650
                shelver.run()
5768
5651
            finally:
5769
 
                shelver.finalize()
 
5652
                shelver.work_tree.unlock()
5770
5653
        except errors.UserAbort:
5771
5654
            return 0
5772
5655
 
5773
5656
    def run_for_list(self):
5774
5657
        tree = WorkingTree.open_containing('.')[0]
5775
5658
        tree.lock_read()
5776
 
        self.add_cleanup(tree.unlock)
5777
 
        manager = tree.get_shelf_manager()
5778
 
        shelves = manager.active_shelves()
5779
 
        if len(shelves) == 0:
5780
 
            note('No shelved changes.')
5781
 
            return 0
5782
 
        for shelf_id in reversed(shelves):
5783
 
            message = manager.get_metadata(shelf_id).get('message')
5784
 
            if message is None:
5785
 
                message = '<no message>'
5786
 
            self.outf.write('%3d: %s\n' % (shelf_id, message))
5787
 
        return 1
 
5659
        try:
 
5660
            manager = tree.get_shelf_manager()
 
5661
            shelves = manager.active_shelves()
 
5662
            if len(shelves) == 0:
 
5663
                note('No shelved changes.')
 
5664
                return 0
 
5665
            for shelf_id in reversed(shelves):
 
5666
                message = manager.get_metadata(shelf_id).get('message')
 
5667
                if message is None:
 
5668
                    message = '<no message>'
 
5669
                self.outf.write('%3d: %s\n' % (shelf_id, message))
 
5670
            return 1
 
5671
        finally:
 
5672
            tree.unlock()
5788
5673
 
5789
5674
 
5790
5675
class cmd_unshelve(Command):
5802
5687
            enum_switch=False, value_switches=True,
5803
5688
            apply="Apply changes and remove from the shelf.",
5804
5689
            dry_run="Show changes, but do not apply or remove them.",
5805
 
            preview="Instead of unshelving the changes, show the diff that "
5806
 
                    "would result from unshelving.",
5807
 
            delete_only="Delete changes without applying them.",
5808
 
            keep="Apply changes but don't delete them.",
 
5690
            delete_only="Delete changes without applying them."
5809
5691
        )
5810
5692
    ]
5811
5693
    _see_also = ['shelve']
5912
5794
    )
5913
5795
from bzrlib.foreign import cmd_dpush
5914
5796
from bzrlib.sign_my_commits import cmd_sign_my_commits
 
5797
from bzrlib.weave_commands import cmd_versionedfile_list, \
 
5798
        cmd_weave_plan_merge, cmd_weave_merge_text