~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2009-08-25 23:47:08 UTC
  • mfrom: (4650 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4651.
  • Revision ID: robertc@robertcollins.net-20090825234708-utgl9u6v12sosp5c
NEWS Conflict.

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
 
340
332
    # cat-revision is more for frontends so should be exact
341
333
    encoding = 'strict'
342
334
 
343
 
    def print_revision(self, revisions, revid):
344
 
        stream = revisions.get_record_stream([(revid,)], 'unordered', True)
345
 
        record = stream.next()
346
 
        if record.storage_kind == 'absent':
347
 
            raise errors.NoSuchRevision(revisions, revid)
348
 
        revtext = record.get_bytes_as('fulltext')
349
 
        self.outf.write(revtext.decode('utf-8'))
350
 
 
351
335
    @display_command
352
336
    def run(self, revision_id=None, revision=None):
353
337
        if revision_id is not None and revision is not None:
358
342
                                         ' --revision or a revision_id')
359
343
        b = WorkingTree.open_containing(u'.')[0].branch
360
344
 
361
 
        revisions = b.repository.revisions
362
 
        if revisions is None:
363
 
            raise errors.BzrCommandError('Repository %r does not support '
364
 
                'access to raw revision texts')
 
345
        # TODO: jam 20060112 should cat-revision always output utf-8?
 
346
        if revision_id is not None:
 
347
            revision_id = osutils.safe_revision_id(revision_id, warn=False)
 
348
            try:
 
349
                self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
350
            except errors.NoSuchRevision:
 
351
                msg = "The repository %s contains no revision %s." % (b.repository.base,
 
352
                    revision_id)
 
353
                raise errors.BzrCommandError(msg)
 
354
        elif revision is not None:
 
355
            for rev in revision:
 
356
                if rev is None:
 
357
                    raise errors.BzrCommandError('You cannot specify a NULL'
 
358
                                                 ' revision.')
 
359
                rev_id = rev.as_revision_id(b)
 
360
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
365
361
 
366
 
        b.repository.lock_read()
367
 
        try:
368
 
            # TODO: jam 20060112 should cat-revision always output utf-8?
369
 
            if revision_id is not None:
370
 
                revision_id = osutils.safe_revision_id(revision_id, warn=False)
371
 
                try:
372
 
                    self.print_revision(revisions, revision_id)
373
 
                except errors.NoSuchRevision:
374
 
                    msg = "The repository %s contains no revision %s." % (
375
 
                        b.repository.base, revision_id)
376
 
                    raise errors.BzrCommandError(msg)
377
 
            elif revision is not None:
378
 
                for rev in revision:
379
 
                    if rev is None:
380
 
                        raise errors.BzrCommandError(
381
 
                            'You cannot specify a NULL revision.')
382
 
                    rev_id = rev.as_revision_id(b)
383
 
                    self.print_revision(revisions, rev_id)
384
 
        finally:
385
 
            b.repository.unlock()
386
 
        
387
362
 
388
363
class cmd_dump_btree(Command):
389
364
    """Dump the contents of a btree index file to stdout.
456
431
        for node in bt.iter_all_entries():
457
432
            # Node is made up of:
458
433
            # (index, key, value, [references])
459
 
            refs_as_tuples = static_tuple.as_tuples(node[3])
460
 
            as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
461
 
            self.outf.write('%s\n' % (as_tuple,))
 
434
            self.outf.write('%s\n' % (node[1:],))
462
435
 
463
436
 
464
437
class cmd_remove_tree(Command):
470
443
    To re-create the working tree, use "bzr checkout".
471
444
    """
472
445
    _see_also = ['checkout', 'working-trees']
473
 
    takes_args = ['location*']
 
446
    takes_args = ['location?']
474
447
    takes_options = [
475
448
        Option('force',
476
449
               help='Remove the working tree even if it has '
477
450
                    'uncommitted changes.'),
478
451
        ]
479
452
 
480
 
    def run(self, location_list, force=False):
481
 
        if not location_list:
482
 
            location_list=['.']
483
 
 
484
 
        for location in location_list:
485
 
            d = bzrdir.BzrDir.open(location)
486
 
            
487
 
            try:
488
 
                working = d.open_workingtree()
489
 
            except errors.NoWorkingTree:
490
 
                raise errors.BzrCommandError("No working tree to remove")
491
 
            except errors.NotLocalUrl:
492
 
                raise errors.BzrCommandError("You cannot remove the working tree"
493
 
                                             " of a remote path")
494
 
            if not force:
495
 
                if (working.has_changes()):
496
 
                    raise errors.UncommittedChanges(working)
497
 
 
498
 
            working_path = working.bzrdir.root_transport.base
499
 
            branch_path = working.branch.bzrdir.root_transport.base
500
 
            if working_path != branch_path:
501
 
                raise errors.BzrCommandError("You cannot remove the working tree"
502
 
                                             " from a lightweight checkout")
503
 
 
504
 
            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()
505
475
 
506
476
 
507
477
class cmd_revno(Command):
524
494
                wt.lock_read()
525
495
            except (errors.NoWorkingTree, errors.NotLocalUrl):
526
496
                raise errors.NoWorkingTree(location)
527
 
            self.add_cleanup(wt.unlock)
528
 
            revid = wt.last_revision()
529
497
            try:
530
 
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
531
 
            except errors.NoSuchRevision:
532
 
                revno_t = ('???',)
533
 
            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()
534
506
        else:
535
507
            b = Branch.open_containing(location)[0]
536
508
            b.lock_read()
537
 
            self.add_cleanup(b.unlock)
538
 
            revno = b.revno()
539
 
        self.cleanup_now()
 
509
            try:
 
510
                revno = b.revno()
 
511
            finally:
 
512
                b.unlock()
 
513
 
540
514
        self.outf.write(str(revno) + '\n')
541
515
 
542
516
 
564
538
            wt = WorkingTree.open_containing(directory)[0]
565
539
            b = wt.branch
566
540
            wt.lock_read()
567
 
            self.add_cleanup(wt.unlock)
568
541
        except (errors.NoWorkingTree, errors.NotLocalUrl):
569
542
            wt = None
570
543
            b = Branch.open_containing(directory)[0]
571
544
            b.lock_read()
572
 
            self.add_cleanup(b.unlock)
573
 
        revision_ids = []
574
 
        if revision is not None:
575
 
            revision_ids.extend(rev.as_revision_id(b) for rev in revision)
576
 
        if revision_info_list is not None:
577
 
            for rev_str in revision_info_list:
578
 
                rev_spec = RevisionSpec.from_string(rev_str)
579
 
                revision_ids.append(rev_spec.as_revision_id(b))
580
 
        # No arguments supplied, default to the last revision
581
 
        if len(revision_ids) == 0:
582
 
            if tree:
583
 
                if wt is None:
584
 
                    raise errors.NoWorkingTree(directory)
585
 
                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()
586
575
            else:
587
 
                revision_ids.append(b.last_revision())
588
 
 
589
 
        revinfos = []
590
 
        maxlen = 0
591
 
        for revision_id in revision_ids:
592
 
            try:
593
 
                dotted_revno = b.revision_id_to_dotted_revno(revision_id)
594
 
                revno = '.'.join(str(i) for i in dotted_revno)
595
 
            except errors.NoSuchRevision:
596
 
                revno = '???'
597
 
            maxlen = max(maxlen, len(revno))
598
 
            revinfos.append([revno, revision_id])
599
 
 
600
 
        self.cleanup_now()
 
576
                wt.unlock()
 
577
 
601
578
        for ri in revinfos:
602
579
            self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
603
580
 
675
652
 
676
653
        if base_tree:
677
654
            base_tree.lock_read()
678
 
            self.add_cleanup(base_tree.unlock)
679
 
        tree, file_list = tree_files_for_add(file_list)
680
 
        added, ignored = tree.smart_add(file_list, not
681
 
            no_recurse, action=action, save=not dry_run)
682
 
        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()
683
663
        if len(ignored) > 0:
684
664
            if verbose:
685
665
                for glob in sorted(ignored.keys()):
749
729
        revision = _get_one_revision('inventory', revision)
750
730
        work_tree, file_list = tree_files(file_list)
751
731
        work_tree.lock_read()
752
 
        self.add_cleanup(work_tree.unlock)
753
 
        if revision is not None:
754
 
            tree = revision.as_tree(work_tree.branch)
755
 
 
756
 
            extra_trees = [work_tree]
757
 
            tree.lock_read()
758
 
            self.add_cleanup(tree.unlock)
759
 
        else:
760
 
            tree = work_tree
761
 
            extra_trees = []
762
 
 
763
 
        if file_list is not None:
764
 
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
765
 
                                      require_versioned=True)
766
 
            # find_ids_across_trees may include some paths that don't
767
 
            # exist in 'tree'.
768
 
            entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
769
 
                             for file_id in file_ids if file_id in tree)
770
 
        else:
771
 
            entries = tree.inventory.entries()
772
 
 
773
 
        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
 
774
756
        for path, entry in entries:
775
757
            if kind and kind != entry.kind:
776
758
                continue
822
804
            raise errors.BzrCommandError("missing file argument")
823
805
        tree, rel_names = tree_files(names_list, canonicalize=False)
824
806
        tree.lock_tree_write()
825
 
        self.add_cleanup(tree.unlock)
826
 
        self._run(tree, names_list, rel_names, after)
 
807
        try:
 
808
            self._run(tree, names_list, rel_names, after)
 
809
        finally:
 
810
            tree.unlock()
827
811
 
828
812
    def run_auto(self, names_list, after, dry_run):
829
813
        if names_list is not None and len(names_list) > 1:
834
818
                                         ' --auto.')
835
819
        work_tree, file_list = tree_files(names_list, default_branch='.')
836
820
        work_tree.lock_tree_write()
837
 
        self.add_cleanup(work_tree.unlock)
838
 
        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()
839
825
 
840
826
    def _run(self, tree, names_list, rel_names, after):
841
827
        into_existing = osutils.isdir(names_list[-1])
862
848
            # All entries reference existing inventory items, so fix them up
863
849
            # for cicp file-systems.
864
850
            rel_names = tree.get_canonical_inventory_paths(rel_names)
865
 
            for src, dest in tree.move(rel_names[:-1], rel_names[-1], after=after):
866
 
                if not is_quiet():
867
 
                    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)
868
853
        else:
869
854
            if len(names_list) != 2:
870
855
                raise errors.BzrCommandError('to mv multiple files the'
914
899
            dest = osutils.pathjoin(dest_parent, dest_tail)
915
900
            mutter("attempting to move %s => %s", src, dest)
916
901
            tree.rename_one(src, dest, after=after)
917
 
            if not is_quiet():
918
 
                self.outf.write("%s => %s\n" % (src, dest))
 
902
            self.outf.write("%s => %s\n" % (src, dest))
919
903
 
920
904
 
921
905
class cmd_pull(Command):
922
906
    """Turn this branch into a mirror of another branch.
923
907
 
924
 
    By default, this command only works on branches that have not diverged.
925
 
    Branches are considered diverged if the destination branch's most recent 
926
 
    commit is one that has not been merged (directly or indirectly) into the 
927
 
    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.
928
911
 
929
912
    If branches have diverged, you can use 'bzr merge' to integrate the changes
930
913
    from one into the other.  Once one branch has merged, the other should
931
914
    be able to pull it again.
932
915
 
933
 
    If you want to replace your local changes and just want your branch to
934
 
    match the remote one, use pull --overwrite. This will work even if the two
935
 
    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.
936
918
 
937
919
    If there is no default location set, the first pull will set it.  After
938
920
    that, you can omit the location to use the default.  To change the
1019
1001
 
1020
1002
        if branch_from is not branch_to:
1021
1003
            branch_from.lock_read()
1022
 
            self.add_cleanup(branch_from.unlock)
1023
 
        if revision is not None:
1024
 
            revision_id = revision.as_revision_id(branch_from)
1025
 
 
1026
 
        branch_to.lock_write()
1027
 
        self.add_cleanup(branch_to.unlock)
1028
 
        if tree_to is not None:
1029
 
            view_info = _get_view_info_for_change_reporter(tree_to)
1030
 
            change_reporter = delta._ChangeReporter(
1031
 
                unversioned_filter=tree_to.is_ignored,
1032
 
                view_info=view_info)
1033
 
            result = tree_to.pull(
1034
 
                branch_from, overwrite, revision_id, change_reporter,
1035
 
                possible_transports=possible_transports, local=local)
1036
 
        else:
1037
 
            result = branch_to.pull(
1038
 
                branch_from, overwrite, revision_id, local=local)
1039
 
 
1040
 
        result.report(self.outf)
1041
 
        if verbose and result.old_revid != result.new_revid:
1042
 
            log.show_branch_change(
1043
 
                branch_to, self.outf, result.old_revno,
1044
 
                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()
1045
1032
 
1046
1033
 
1047
1034
class cmd_push(Command):
1122
1109
        else:
1123
1110
            revision_id = None
1124
1111
        if strict and tree is not None and revision_id is None:
1125
 
            if (tree.has_changes()):
 
1112
            if (tree.has_changes(tree.basis_tree())
 
1113
                or len(tree.get_parent_ids()) > 1):
1126
1114
                raise errors.UncommittedChanges(
1127
1115
                    tree, more='Use --no-strict to force the push.')
1128
1116
            if tree.last_revision() != tree.branch.last_revision():
1202
1190
                    ' directory exists, but does not already'
1203
1191
                    ' have a control directory.  This flag will'
1204
1192
                    ' allow branch to proceed.'),
1205
 
        Option('bind',
1206
 
            help="Bind new branch to from location."),
1207
1193
        ]
1208
1194
    aliases = ['get', 'clone']
1209
1195
 
1210
1196
    def run(self, from_location, to_location=None, revision=None,
1211
1197
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1212
 
            use_existing_dir=False, switch=False, bind=False):
 
1198
            use_existing_dir=False, switch=False):
1213
1199
        from bzrlib import switch as _mod_switch
1214
1200
        from bzrlib.tag import _merge_tags_if_possible
1215
1201
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1216
1202
            from_location)
 
1203
        if (accelerator_tree is not None and
 
1204
            accelerator_tree.supports_content_filtering()):
 
1205
            accelerator_tree = None
1217
1206
        revision = _get_one_revision('branch', revision)
1218
1207
        br_from.lock_read()
1219
 
        self.add_cleanup(br_from.unlock)
1220
 
        if revision is not None:
1221
 
            revision_id = revision.as_revision_id(br_from)
1222
 
        else:
1223
 
            # FIXME - wt.last_revision, fallback to branch, fall back to
1224
 
            # None or perhaps NULL_REVISION to mean copy nothing
1225
 
            # RBC 20060209
1226
 
            revision_id = br_from.last_revision()
1227
 
        if to_location is None:
1228
 
            to_location = urlutils.derive_to_location(from_location)
1229
 
        to_transport = transport.get_transport(to_location)
1230
1208
        try:
1231
 
            to_transport.mkdir('.')
1232
 
        except errors.FileExists:
1233
 
            if not use_existing_dir:
1234
 
                raise errors.BzrCommandError('Target directory "%s" '
1235
 
                    'already exists.' % to_location)
 
1209
            if revision is not None:
 
1210
                revision_id = revision.as_revision_id(br_from)
1236
1211
            else:
1237
 
                try:
1238
 
                    bzrdir.BzrDir.open_from_transport(to_transport)
1239
 
                except errors.NotBranchError:
1240
 
                    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)
1241
1225
                else:
1242
 
                    raise errors.AlreadyBranchError(to_location)
1243
 
        except errors.NoSuchFile:
1244
 
            raise errors.BzrCommandError('Parent of "%s" does not exist.'
1245
 
                                         % to_location)
1246
 
        try:
1247
 
            # preserve whatever source format we have.
1248
 
            dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1249
 
                                        possible_transports=[to_transport],
1250
 
                                        accelerator_tree=accelerator_tree,
1251
 
                                        hardlink=hardlink, stacked=stacked,
1252
 
                                        force_new_repo=standalone,
1253
 
                                        create_tree_if_local=not no_tree,
1254
 
                                        source_branch=br_from)
1255
 
            branch = dir.open_branch()
1256
 
        except errors.NoSuchRevision:
1257
 
            to_transport.delete_tree('.')
1258
 
            msg = "The branch %s has no revision %s." % (from_location,
1259
 
                revision)
1260
 
            raise errors.BzrCommandError(msg)
1261
 
        _merge_tags_if_possible(br_from, branch)
1262
 
        # If the source branch is stacked, the new branch may
1263
 
        # be stacked whether we asked for that explicitly or not.
1264
 
        # We therefore need a try/except here and not just 'if stacked:'
1265
 
        try:
1266
 
            note('Created new stacked branch referring to %s.' %
1267
 
                branch.get_stacked_on_url())
1268
 
        except (errors.NotStacked, errors.UnstackableBranchFormat,
1269
 
            errors.UnstackableRepositoryFormat), e:
1270
 
            note('Branched %d revision(s).' % branch.revno())
1271
 
        if bind:
1272
 
            # Bind to the parent
1273
 
            parent_branch = Branch.open(from_location)
1274
 
            branch.bind(parent_branch)
1275
 
            note('New branch bound to %s' % from_location)
1276
 
        if switch:
1277
 
            # Switch to the new branch
1278
 
            wt, _ = WorkingTree.open_containing('.')
1279
 
            _mod_switch.switch(wt.bzrdir, branch)
1280
 
            note('Switched to branch: %s',
1281
 
                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()
1282
1268
 
1283
1269
 
1284
1270
class cmd_checkout(Command):
1363
1349
    def run(self, dir=u'.'):
1364
1350
        tree = WorkingTree.open_containing(dir)[0]
1365
1351
        tree.lock_read()
1366
 
        self.add_cleanup(tree.unlock)
1367
 
        new_inv = tree.inventory
1368
 
        old_tree = tree.basis_tree()
1369
 
        old_tree.lock_read()
1370
 
        self.add_cleanup(old_tree.unlock)
1371
 
        old_inv = old_tree.inventory
1372
 
        renames = []
1373
 
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1374
 
        for f, paths, c, v, p, n, k, e in iterator:
1375
 
            if paths[0] == paths[1]:
1376
 
                continue
1377
 
            if None in (paths):
1378
 
                continue
1379
 
            renames.append(paths)
1380
 
        renames.sort()
1381
 
        for old_name, new_name in renames:
1382
 
            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()
1383
1373
 
1384
1374
 
1385
1375
class cmd_update(Command):
1391
1381
 
1392
1382
    If you want to discard your local changes, you can just do a
1393
1383
    'bzr revert' instead of 'bzr commit' after the update.
1394
 
 
1395
 
    If the tree's branch is bound to a master branch, it will also update
1396
 
    the branch from the master.
1397
1384
    """
1398
1385
 
1399
1386
    _see_also = ['pull', 'working-trees', 'status-flags']
1400
1387
    takes_args = ['dir?']
1401
 
    takes_options = ['revision']
1402
1388
    aliases = ['up']
1403
1389
 
1404
 
    def run(self, dir='.', revision=None):
1405
 
        if revision is not None and len(revision) != 1:
1406
 
            raise errors.BzrCommandError(
1407
 
                        "bzr update --revision takes exactly one revision")
 
1390
    def run(self, dir='.'):
1408
1391
        tree = WorkingTree.open_containing(dir)[0]
1409
 
        branch = tree.branch
1410
1392
        possible_transports = []
1411
 
        master = branch.get_master_branch(
 
1393
        master = tree.branch.get_master_branch(
1412
1394
            possible_transports=possible_transports)
1413
1395
        if master is not None:
1414
1396
            tree.lock_write()
1415
 
            branch_location = master.base
1416
1397
        else:
1417
1398
            tree.lock_tree_write()
1418
 
            branch_location = tree.branch.base
1419
 
        self.add_cleanup(tree.unlock)
1420
 
        # get rid of the final '/' and be ready for display
1421
 
        branch_location = urlutils.unescape_for_display(branch_location[:-1],
1422
 
                                                        self.outf.encoding)
1423
 
        existing_pending_merges = tree.get_parent_ids()[1:]
1424
 
        if master is None:
1425
 
            old_tip = None
1426
 
        else:
1427
 
            # may need to fetch data into a heavyweight checkout
1428
 
            # XXX: this may take some time, maybe we should display a
1429
 
            # message
1430
 
            old_tip = branch.update(possible_transports)
1431
 
        if revision is not None:
1432
 
            revision_id = revision[0].as_revision_id(branch)
1433
 
        else:
1434
 
            revision_id = branch.last_revision()
1435
 
        if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1436
 
            revno = branch.revision_id_to_revno(revision_id)
1437
 
            note("Tree is up to date at revision %d of branch %s" %
1438
 
                (revno, branch_location))
1439
 
            return 0
1440
 
        view_info = _get_view_info_for_change_reporter(tree)
1441
 
        change_reporter = delta._ChangeReporter(
1442
 
            unversioned_filter=tree.is_ignored,
1443
 
            view_info=view_info)
1444
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)
1445
1411
            conflicts = tree.update(
1446
 
                change_reporter,
1447
 
                possible_transports=possible_transports,
1448
 
                revision=revision_id,
1449
 
                old_tip=old_tip)
1450
 
        except errors.NoSuchRevision, e:
1451
 
            raise errors.BzrCommandError(
1452
 
                                  "branch has no revision %s\n"
1453
 
                                  "bzr update --revision only works"
1454
 
                                  " for a revision in the branch history"
1455
 
                                  % (e.revision))
1456
 
        revno = tree.branch.revision_id_to_revno(
1457
 
            _mod_revision.ensure_null(tree.last_revision()))
1458
 
        note('Updated to revision %d of branch %s' %
1459
 
             (revno, branch_location))
1460
 
        if tree.get_parent_ids()[1:] != existing_pending_merges:
1461
 
            note('Your local commits will now show as pending merges with '
1462
 
                 "'bzr status', and can be committed with 'bzr commit'.")
1463
 
        if conflicts != 0:
1464
 
            return 1
1465
 
        else:
1466
 
            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()
1467
1426
 
1468
1427
 
1469
1428
class cmd_info(Command):
1540
1499
            file_list = [f for f in file_list]
1541
1500
 
1542
1501
        tree.lock_write()
1543
 
        self.add_cleanup(tree.unlock)
1544
 
        # Heuristics should probably all move into tree.remove_smart or
1545
 
        # some such?
1546
 
        if new:
1547
 
            added = tree.changes_from(tree.basis_tree(),
1548
 
                specific_files=file_list).added
1549
 
            file_list = sorted([f[0] for f in added], reverse=True)
1550
 
            if len(file_list) == 0:
1551
 
                raise errors.BzrCommandError('No matching files.')
1552
 
        elif file_list is None:
1553
 
            # missing files show up in iter_changes(basis) as
1554
 
            # versioned-with-no-kind.
1555
 
            missing = []
1556
 
            for change in tree.iter_changes(tree.basis_tree()):
1557
 
                # Find paths in the working tree that have no kind:
1558
 
                if change[1][1] is not None and change[6][1] is None:
1559
 
                    missing.append(change[1][1])
1560
 
            file_list = sorted(missing, reverse=True)
1561
 
            file_deletion_strategy = 'keep'
1562
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1563
 
            keep_files=file_deletion_strategy=='keep',
1564
 
            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()
1565
1526
 
1566
1527
 
1567
1528
class cmd_file_id(Command):
1712
1673
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1713
1674
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1714
1675
                value_switches=True,
1715
 
                title="Branch format",
 
1676
                title="Branch Format",
1716
1677
                ),
1717
1678
         Option('append-revisions-only',
1718
1679
                help='Never change revnos or the existing log.'
1787
1748
 
1788
1749
 
1789
1750
class cmd_init_repository(Command):
1790
 
    """Create a shared repository for branches to share storage space.
 
1751
    """Create a shared repository to hold branches.
1791
1752
 
1792
1753
    New branches created under the repository directory will store their
1793
 
    revisions in the repository, not in the branch directory.  For branches
1794
 
    with shared history, this reduces the amount of storage needed and 
1795
 
    speeds up the creation of new branches.
 
1754
    revisions in the repository, not in the branch directory.
1796
1755
 
1797
 
    If the --no-trees option is given then the branches in the repository
1798
 
    will not have working trees by default.  They will still exist as 
1799
 
    directories on disk, but they will not have separate copies of the 
1800
 
    files at a certain revision.  This can be useful for repositories that
1801
 
    store branches which are interacted with through checkouts or remote
1802
 
    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.
1803
1758
 
1804
1759
    :Examples:
1805
 
        Create a shared repository holding just branches::
 
1760
        Create a shared repositories holding just branches::
1806
1761
 
1807
1762
            bzr init-repo --no-trees repo
1808
1763
            bzr init repo/trunk
1874
1829
 
1875
1830
            bzr diff -r1
1876
1831
 
1877
 
        Difference between revision 3 and revision 1::
1878
 
 
1879
 
            bzr diff -r1..3
1880
 
 
1881
 
        Difference between revision 3 and revision 1 for branch xxx::
1882
 
 
1883
 
            bzr diff -r1..3 xxx
1884
 
 
1885
 
        To see the changes introduced in revision X::
1886
 
        
1887
 
            bzr diff -cX
1888
 
 
1889
 
        Note that in the case of a merge, the -c option shows the changes
1890
 
        compared to the left hand parent. To see the changes against
1891
 
        another parent, use::
1892
 
 
1893
 
            bzr diff -r<chosen_parent>..X
1894
 
 
1895
 
        The changes introduced by revision 2 (equivalent to -r1..2)::
1896
 
 
1897
 
            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
1898
1839
 
1899
1840
        Show just the differences for file NEWS::
1900
1841
 
1946
1887
    @display_command
1947
1888
    def run(self, revision=None, file_list=None, diff_options=None,
1948
1889
            prefix=None, old=None, new=None, using=None):
1949
 
        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
1950
1891
 
1951
1892
        if (prefix is None) or (prefix == '0'):
1952
1893
            # diff -p0 format
1966
1907
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
1967
1908
                                         ' one or two revision specifiers')
1968
1909
 
1969
 
        (old_tree, new_tree,
1970
 
         old_branch, new_branch,
1971
 
         specific_files, extra_trees) = get_trees_and_branches_to_diff(
1972
 
            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)
1973
1913
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1974
1914
                               specific_files=specific_files,
1975
1915
                               external_diff_options=diff_options,
1993
1933
    def run(self, show_ids=False):
1994
1934
        tree = WorkingTree.open_containing(u'.')[0]
1995
1935
        tree.lock_read()
1996
 
        self.add_cleanup(tree.unlock)
1997
 
        old = tree.basis_tree()
1998
 
        old.lock_read()
1999
 
        self.add_cleanup(old.unlock)
2000
 
        for path, ie in old.inventory.iter_entries():
2001
 
            if not tree.has_id(ie.file_id):
2002
 
                self.outf.write(path)
2003
 
                if show_ids:
2004
 
                    self.outf.write(' ')
2005
 
                    self.outf.write(ie.file_id)
2006
 
                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()
2007
1951
 
2008
1952
 
2009
1953
class cmd_modified(Command):
2045
1989
    def run(self, null=False):
2046
1990
        wt = WorkingTree.open_containing(u'.')[0]
2047
1991
        wt.lock_read()
2048
 
        self.add_cleanup(wt.unlock)
2049
 
        basis = wt.basis_tree()
2050
 
        basis.lock_read()
2051
 
        self.add_cleanup(basis.unlock)
2052
 
        basis_inv = basis.inventory
2053
 
        inv = wt.inventory
2054
 
        for file_id in inv:
2055
 
            if file_id in basis_inv:
2056
 
                continue
2057
 
            if inv.is_root(file_id) and len(basis_inv) == 0:
2058
 
                continue
2059
 
            path = inv.id2path(file_id)
2060
 
            if not os.access(osutils.abspath(path), os.F_OK):
2061
 
                continue
2062
 
            if null:
2063
 
                self.outf.write(path + '\0')
2064
 
            else:
2065
 
                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()
2066
2014
 
2067
2015
 
2068
2016
class cmd_root(Command):
2213
2161
    :Tips & tricks:
2214
2162
 
2215
2163
      GUI tools and IDEs are often better at exploring history than command
2216
 
      line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2217
 
      bzr-explorer shell, or the Loggerhead web interface.  See the Plugin
2218
 
      Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2219
 
      <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.
2220
2171
 
2221
2172
      You may find it useful to add the aliases below to ``bazaar.conf``::
2222
2173
 
2325
2276
        filter_by_dir = False
2326
2277
        if file_list:
2327
2278
            # find the file ids to log and check for directory filtering
2328
 
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2329
 
                revision, file_list)
2330
 
            self.add_cleanup(b.unlock)
 
2279
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
 
2280
                file_list)
2331
2281
            for relpath, file_id, kind in file_info_list:
2332
2282
                if file_id is None:
2333
2283
                    raise errors.BzrCommandError(
2351
2301
                location = '.'
2352
2302
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2353
2303
            b = dir.open_branch()
2354
 
            b.lock_read()
2355
 
            self.add_cleanup(b.unlock)
2356
2304
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2357
2305
 
2358
2306
        # Decide on the type of delta & diff filtering to use
2368
2316
        else:
2369
2317
            diff_type = 'full'
2370
2318
 
2371
 
        # Build the log formatter
2372
 
        if log_format is None:
2373
 
            log_format = log.log_formatter_registry.get_default(b)
2374
 
        # Make a non-encoding output to include the diffs - bug 328007
2375
 
        unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2376
 
        lf = log_format(show_ids=show_ids, to_file=self.outf,
2377
 
                        to_exact_file=unencoded_output,
2378
 
                        show_timezone=timezone,
2379
 
                        delta_format=get_verbosity_level(),
2380
 
                        levels=levels,
2381
 
                        show_advice=levels is None)
2382
 
 
2383
 
        # Choose the algorithm for doing the logging. It's annoying
2384
 
        # having multiple code paths like this but necessary until
2385
 
        # the underlying repository format is faster at generating
2386
 
        # deltas or can provide everything we need from the indices.
2387
 
        # The default algorithm - match-using-deltas - works for
2388
 
        # multiple files and directories and is faster for small
2389
 
        # amounts of history (200 revisions say). However, it's too
2390
 
        # slow for logging a single file in a repository with deep
2391
 
        # history, i.e. > 10K revisions. In the spirit of "do no
2392
 
        # evil when adding features", we continue to use the
2393
 
        # original algorithm - per-file-graph - for the "single
2394
 
        # file that isn't a directory without showing a delta" case.
2395
 
        partial_history = revision and b.repository._format.supports_chks
2396
 
        match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2397
 
            or delta_type or partial_history)
2398
 
 
2399
 
        # Build the LogRequest and execute it
2400
 
        if len(file_ids) == 0:
2401
 
            file_ids = None
2402
 
        rqst = make_log_request_dict(
2403
 
            direction=direction, specific_fileids=file_ids,
2404
 
            start_revision=rev1, end_revision=rev2, limit=limit,
2405
 
            message_search=message, delta_type=delta_type,
2406
 
            diff_type=diff_type, _match_using_deltas=match_using_deltas)
2407
 
        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()
2408
2357
 
2409
2358
 
2410
2359
def _get_revision_range(revisionspec_list, branch, command_name):
2474
2423
    @display_command
2475
2424
    def run(self, filename):
2476
2425
        tree, relpath = WorkingTree.open_containing(filename)
 
2426
        b = tree.branch
2477
2427
        file_id = tree.path2id(relpath)
2478
 
        b = tree.branch
2479
 
        b.lock_read()
2480
 
        self.add_cleanup(b.unlock)
2481
 
        touching_revs = log.find_touching_revisions(b, file_id)
2482
 
        for revno, revision_id, what in touching_revs:
 
2428
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2483
2429
            self.outf.write("%6d %s\n" % (revno, what))
2484
2430
 
2485
2431
 
2538
2484
        if from_root:
2539
2485
            if relpath:
2540
2486
                prefix = relpath + '/'
2541
 
        elif fs_path != '.' and not fs_path.endswith('/'):
 
2487
        elif fs_path != '.':
2542
2488
            prefix = fs_path + '/'
2543
2489
 
2544
2490
        if revision is not None or tree is None:
2553
2499
                note("Ignoring files outside view. View is %s" % view_str)
2554
2500
 
2555
2501
        tree.lock_read()
2556
 
        self.add_cleanup(tree.unlock)
2557
 
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2558
 
            from_dir=relpath, recursive=recursive):
2559
 
            # Apply additional masking
2560
 
            if not all and not selection[fc]:
2561
 
                continue
2562
 
            if kind is not None and fkind != kind:
2563
 
                continue
2564
 
            if apply_view:
2565
 
                try:
2566
 
                    if relpath:
2567
 
                        fullpath = osutils.pathjoin(relpath, fp)
2568
 
                    else:
2569
 
                        fullpath = fp
2570
 
                    views.check_path_in_view(tree, fullpath)
2571
 
                except errors.FileOutsideView:
2572
 
                    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
2573
2519
 
2574
 
            # Output the entry
2575
 
            if prefix:
2576
 
                fp = osutils.pathjoin(prefix, fp)
2577
 
            kindch = entry.kind_character()
2578
 
            outstring = fp + kindch
2579
 
            ui.ui_factory.clear_term()
2580
 
            if verbose:
2581
 
                outstring = '%-8s %s' % (fc, outstring)
2582
 
                if show_ids and fid is not None:
2583
 
                    outstring = "%-50s %s" % (outstring, fid)
2584
 
                self.outf.write(outstring + '\n')
2585
 
            elif null:
2586
 
                self.outf.write(fp + '\0')
2587
 
                if show_ids:
2588
 
                    if fid is not None:
2589
 
                        self.outf.write(fid)
2590
 
                    self.outf.write('\0')
2591
 
                self.outf.flush()
2592
 
            else:
2593
 
                if show_ids:
2594
 
                    if fid is not None:
2595
 
                        my_id = fid
2596
 
                    else:
2597
 
                        my_id = ''
2598
 
                    self.outf.write('%-50s %s\n' % (outstring, my_id))
2599
 
                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)
2600
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()
2601
2549
 
2602
2550
 
2603
2551
class cmd_unknowns(Command):
2618
2566
 
2619
2567
    See ``bzr help patterns`` for details on the syntax of patterns.
2620
2568
 
2621
 
    If a .bzrignore file does not exist, the ignore command
2622
 
    will create one and add the specified files or patterns to the newly
2623
 
    created file. The ignore command will also automatically add the 
2624
 
    .bzrignore file to be versioned. Creating a .bzrignore file without
2625
 
    the use of the ignore command will require an explicit add command.
2626
 
 
2627
2569
    To remove patterns from the ignore list, edit the .bzrignore file.
2628
2570
    After adding, editing or deleting that file either indirectly by
2629
2571
    using this command or directly by using an editor, be sure to commit
2630
2572
    it.
2631
 
    
2632
 
    Patterns prefixed with '!' are exceptions to ignore patterns and take
2633
 
    precedence over regular ignores.  Such exceptions are used to specify
2634
 
    files that should be versioned which would otherwise be ignored.
2635
 
    
2636
 
    Patterns prefixed with '!!' act as regular ignore patterns, but have
2637
 
    precedence over the '!' exception patterns.
2638
2573
 
2639
2574
    Note: ignore patterns containing shell wildcards must be quoted from
2640
2575
    the shell on Unix.
2644
2579
 
2645
2580
            bzr ignore ./Makefile
2646
2581
 
2647
 
        Ignore .class files in all directories...::
 
2582
        Ignore class files in all directories::
2648
2583
 
2649
2584
            bzr ignore "*.class"
2650
2585
 
2651
 
        ...but do not ignore "special.class"::
2652
 
 
2653
 
            bzr ignore "!special.class"
2654
 
 
2655
2586
        Ignore .o files under the lib directory::
2656
2587
 
2657
2588
            bzr ignore "lib/**/*.o"
2663
2594
        Ignore everything but the "debian" toplevel directory::
2664
2595
 
2665
2596
            bzr ignore "RE:(?!debian/).*"
2666
 
        
2667
 
        Ignore everything except the "local" toplevel directory,
2668
 
        but always ignore "*~" autosave files, even under local/::
2669
 
        
2670
 
            bzr ignore "*"
2671
 
            bzr ignore "!./local"
2672
 
            bzr ignore "!!*~"
2673
2597
    """
2674
2598
 
2675
2599
    _see_also = ['status', 'ignored', 'patterns']
2733
2657
    def run(self):
2734
2658
        tree = WorkingTree.open_containing(u'.')[0]
2735
2659
        tree.lock_read()
2736
 
        self.add_cleanup(tree.unlock)
2737
 
        for path, file_class, kind, file_id, entry in tree.list_files():
2738
 
            if file_class != 'I':
2739
 
                continue
2740
 
            ## XXX: Slightly inefficient since this was already calculated
2741
 
            pat = tree.is_ignored(path)
2742
 
            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()
2743
2669
 
2744
2670
 
2745
2671
class cmd_lookup_revision(Command):
2848
2774
        tree, branch, relpath = \
2849
2775
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2850
2776
        branch.lock_read()
2851
 
        self.add_cleanup(branch.unlock)
2852
 
        return self._run(tree, branch, relpath, filename, revision,
2853
 
                         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()
2854
2782
 
2855
2783
    def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2856
2784
        filtered):
2857
2785
        if tree is None:
2858
2786
            tree = b.basis_tree()
2859
2787
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2860
 
        rev_tree.lock_read()
2861
 
        self.add_cleanup(rev_tree.unlock)
2862
2788
 
2863
2789
        old_file_id = rev_tree.path2id(relpath)
2864
2790
 
2899
2825
            chunks = content.splitlines(True)
2900
2826
            content = filtered_output_bytes(chunks, filters,
2901
2827
                ContentFilterContext(relpath, rev_tree))
2902
 
            self.cleanup_now()
2903
2828
            self.outf.writelines(content)
2904
2829
        else:
2905
 
            self.cleanup_now()
2906
2830
            self.outf.write(content)
2907
2831
 
2908
2832
 
3015
2939
             Option('strict',
3016
2940
                    help="Refuse to commit if there are unknown "
3017
2941
                    "files in the working tree."),
3018
 
             Option('commit-time', type=str,
3019
 
                    help="Manually set a commit time using commit date "
3020
 
                    "format, e.g. '2009-10-10 08:00:00 +0100'."),
3021
2942
             ListOption('fixes', type=str,
3022
2943
                    help="Mark a bug as being fixed by this revision "
3023
2944
                         "(see \"bzr help bugs\")."),
3030
2951
                         "the master branch until a normal commit "
3031
2952
                         "is performed."
3032
2953
                    ),
3033
 
             Option('show-diff',
3034
 
                    help='When no message is supplied, show the diff along'
3035
 
                    ' 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.'),
3036
2957
             ]
3037
2958
    aliases = ['ci', 'checkin']
3038
2959
 
3057
2978
 
3058
2979
    def run(self, message=None, file=None, verbose=False, selected_list=None,
3059
2980
            unchanged=False, strict=False, local=False, fixes=None,
3060
 
            author=None, show_diff=False, exclude=None, commit_time=None):
 
2981
            author=None, show_diff=False, exclude=None):
3061
2982
        from bzrlib.errors import (
3062
2983
            PointlessCommit,
3063
2984
            ConflictsInTree,
3069
2990
            make_commit_message_template_encoded
3070
2991
        )
3071
2992
 
3072
 
        commit_stamp = offset = None
3073
 
        if commit_time is not None:
3074
 
            try:
3075
 
                commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3076
 
            except ValueError, e:
3077
 
                raise errors.BzrCommandError(
3078
 
                    "Could not parse --commit-time: " + str(e))
3079
 
 
3080
2993
        # TODO: Need a blackbox test for invoking the external editor; may be
3081
2994
        # slightly problematic to run this cross-platform.
3082
2995
 
3102
3015
        if local and not tree.branch.get_bound_location():
3103
3016
            raise errors.LocalRequiresBoundBranch()
3104
3017
 
3105
 
        if message is not None:
3106
 
            try:
3107
 
                file_exists = osutils.lexists(message)
3108
 
            except UnicodeError:
3109
 
                # The commit message contains unicode characters that can't be
3110
 
                # represented in the filesystem encoding, so that can't be a
3111
 
                # file.
3112
 
                file_exists = False
3113
 
            if file_exists:
3114
 
                warning_msg = (
3115
 
                    'The commit message is a file name: "%(f)s".\n'
3116
 
                    '(use --file "%(f)s" to take commit message from that file)'
3117
 
                    % { 'f': message })
3118
 
                ui.ui_factory.show_warning(warning_msg)
3119
 
 
3120
3018
        def get_message(commit_obj):
3121
3019
            """Callback to get commit message"""
3122
3020
            my_message = message
3123
 
            if my_message is not None and '\r' in my_message:
3124
 
                my_message = my_message.replace('\r\n', '\n')
3125
 
                my_message = my_message.replace('\r', '\n')
3126
3021
            if my_message is None and not file:
3127
3022
                t = make_commit_message_template_encoded(tree,
3128
3023
                        selected_list, diff=show_diff,
3152
3047
                        specific_files=selected_list,
3153
3048
                        allow_pointless=unchanged, strict=strict, local=local,
3154
3049
                        reporter=None, verbose=verbose, revprops=properties,
3155
 
                        authors=author, timestamp=commit_stamp,
3156
 
                        timezone=offset,
 
3050
                        authors=author,
3157
3051
                        exclude=safe_relpath_files(tree, exclude))
3158
3052
        except PointlessCommit:
3159
3053
            # FIXME: This should really happen before the file is read in;
3446
3340
    Tests that need working space on disk use a common temporary directory,
3447
3341
    typically inside $TMPDIR or /tmp.
3448
3342
 
3449
 
    If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
3450
 
    into a pdb postmortem session.
3451
 
 
3452
3343
    :Examples:
3453
3344
        Run only tests relating to 'ignore'::
3454
3345
 
3463
3354
    def get_transport_type(typestring):
3464
3355
        """Parse and return a transport specifier."""
3465
3356
        if typestring == "sftp":
3466
 
            from bzrlib.tests import stub_sftp
3467
 
            return stub_sftp.SFTPAbsoluteServer
 
3357
            from bzrlib.transport.sftp import SFTPAbsoluteServer
 
3358
            return SFTPAbsoluteServer
3468
3359
        if typestring == "memory":
3469
 
            from bzrlib.tests import test_server
3470
 
            return memory.MemoryServer
 
3360
            from bzrlib.transport.memory import MemoryServer
 
3361
            return MemoryServer
3471
3362
        if typestring == "fakenfs":
3472
 
            from bzrlib.tests import test_server
3473
 
            return test_server.FakeNFSServer
 
3363
            from bzrlib.transport.fakenfs import FakeNFSServer
 
3364
            return FakeNFSServer
3474
3365
        msg = "No known transport type %s. Supported types are: sftp\n" %\
3475
3366
            (typestring)
3476
3367
        raise errors.BzrCommandError(msg)
3569
3460
            verbose = not is_quiet()
3570
3461
            # TODO: should possibly lock the history file...
3571
3462
            benchfile = open(".perf_history", "at", buffering=1)
3572
 
            self.add_cleanup(benchfile.close)
3573
3463
        else:
3574
3464
            test_suite_factory = None
3575
3465
            benchfile = None
3576
 
        selftest_kwargs = {"verbose": verbose,
3577
 
                          "pattern": pattern,
3578
 
                          "stop_on_failure": one,
3579
 
                          "transport": transport,
3580
 
                          "test_suite_factory": test_suite_factory,
3581
 
                          "lsprof_timed": lsprof_timed,
3582
 
                          "lsprof_tests": lsprof_tests,
3583
 
                          "bench_history": benchfile,
3584
 
                          "matching_tests_first": first,
3585
 
                          "list_only": list_only,
3586
 
                          "random_seed": randomize,
3587
 
                          "exclude_pattern": exclude,
3588
 
                          "strict": strict,
3589
 
                          "load_list": load_list,
3590
 
                          "debug_flags": debugflag,
3591
 
                          "starting_with": starting_with
3592
 
                          }
3593
 
        selftest_kwargs.update(self.additional_selftest_args)
3594
 
        result = selftest(**selftest_kwargs)
 
3466
        try:
 
3467
            selftest_kwargs = {"verbose": verbose,
 
3468
                              "pattern": pattern,
 
3469
                              "stop_on_failure": one,
 
3470
                              "transport": transport,
 
3471
                              "test_suite_factory": test_suite_factory,
 
3472
                              "lsprof_timed": lsprof_timed,
 
3473
                              "lsprof_tests": lsprof_tests,
 
3474
                              "bench_history": benchfile,
 
3475
                              "matching_tests_first": first,
 
3476
                              "list_only": list_only,
 
3477
                              "random_seed": randomize,
 
3478
                              "exclude_pattern": exclude,
 
3479
                              "strict": strict,
 
3480
                              "load_list": load_list,
 
3481
                              "debug_flags": debugflag,
 
3482
                              "starting_with": starting_with
 
3483
                              }
 
3484
            selftest_kwargs.update(self.additional_selftest_args)
 
3485
            result = selftest(**selftest_kwargs)
 
3486
        finally:
 
3487
            if benchfile is not None:
 
3488
                benchfile.close()
3595
3489
        return int(not result)
3596
3490
 
3597
3491
 
3636
3530
        branch1 = Branch.open_containing(branch)[0]
3637
3531
        branch2 = Branch.open_containing(other)[0]
3638
3532
        branch1.lock_read()
3639
 
        self.add_cleanup(branch1.unlock)
3640
 
        branch2.lock_read()
3641
 
        self.add_cleanup(branch2.unlock)
3642
 
        last1 = ensure_null(branch1.last_revision())
3643
 
        last2 = ensure_null(branch2.last_revision())
3644
 
 
3645
 
        graph = branch1.repository.get_graph(branch2.repository)
3646
 
        base_rev_id = graph.find_unique_lca(last1, last2)
3647
 
 
3648
 
        print 'merge base is revision %s' % base_rev_id
 
3533
        try:
 
3534
            branch2.lock_read()
 
3535
            try:
 
3536
                last1 = ensure_null(branch1.last_revision())
 
3537
                last2 = ensure_null(branch2.last_revision())
 
3538
 
 
3539
                graph = branch1.repository.get_graph(branch2.repository)
 
3540
                base_rev_id = graph.find_unique_lca(last1, last2)
 
3541
 
 
3542
                print 'merge base is revision %s' % base_rev_id
 
3543
            finally:
 
3544
                branch2.unlock()
 
3545
        finally:
 
3546
            branch1.unlock()
3649
3547
 
3650
3548
 
3651
3549
class cmd_merge(Command):
3684
3582
    committed to record the result of the merge.
3685
3583
 
3686
3584
    merge refuses to run if there are any uncommitted changes, unless
3687
 
    --force is given. The --force option can also be used to create a
3688
 
    merge revision which has more than two parents.
3689
 
 
3690
 
    If one would like to merge changes from the working tree of the other
3691
 
    branch without merging any committed revisions, the --uncommitted option
3692
 
    can be given.
 
3585
    --force is given.
3693
3586
 
3694
3587
    To select only some changes to merge, use "merge -i", which will prompt
3695
3588
    you to apply each diff hunk and file change, similar to "shelve".
3707
3600
 
3708
3601
            bzr merge -r 81..82 ../bzr.dev
3709
3602
 
3710
 
        To apply a merge directive contained in /tmp/merge::
 
3603
        To apply a merge directive contained in /tmp/merge:
3711
3604
 
3712
3605
            bzr merge /tmp/merge
3713
 
 
3714
 
        To create a merge revision with three parents from two branches
3715
 
        feature1a and feature1b:
3716
 
 
3717
 
            bzr merge ../feature1a
3718
 
            bzr merge ../feature1b --force
3719
 
            bzr commit -m 'revision with three parents'
3720
3606
    """
3721
3607
 
3722
3608
    encoding_type = 'exact'
3767
3653
        verified = 'inapplicable'
3768
3654
        tree = WorkingTree.open_containing(directory)[0]
3769
3655
 
 
3656
        # die as quickly as possible if there are uncommitted changes
3770
3657
        try:
3771
3658
            basis_tree = tree.revision_tree(tree.last_revision())
3772
3659
        except errors.NoSuchRevision:
3773
3660
            basis_tree = tree.basis_tree()
3774
 
 
3775
 
        # die as quickly as possible if there are uncommitted changes
3776
3661
        if not force:
3777
 
            if tree.has_changes():
 
3662
            if tree.has_changes(basis_tree):
3778
3663
                raise errors.UncommittedChanges(tree)
3779
3664
 
3780
3665
        view_info = _get_view_info_for_change_reporter(tree)
3781
3666
        change_reporter = delta._ChangeReporter(
3782
3667
            unversioned_filter=tree.is_ignored, view_info=view_info)
3783
 
        pb = ui.ui_factory.nested_progress_bar()
3784
 
        self.add_cleanup(pb.finished)
3785
 
        tree.lock_write()
3786
 
        self.add_cleanup(tree.unlock)
3787
 
        if location is not None:
3788
 
            try:
3789
 
                mergeable = bundle.read_mergeable_from_url(location,
3790
 
                    possible_transports=possible_transports)
3791
 
            except errors.NotABundle:
3792
 
                mergeable = None
 
3668
        cleanups = []
 
3669
        try:
 
3670
            pb = ui.ui_factory.nested_progress_bar()
 
3671
            cleanups.append(pb.finished)
 
3672
            tree.lock_write()
 
3673
            cleanups.append(tree.unlock)
 
3674
            if location is not None:
 
3675
                try:
 
3676
                    mergeable = bundle.read_mergeable_from_url(location,
 
3677
                        possible_transports=possible_transports)
 
3678
                except errors.NotABundle:
 
3679
                    mergeable = None
 
3680
                else:
 
3681
                    if uncommitted:
 
3682
                        raise errors.BzrCommandError('Cannot use --uncommitted'
 
3683
                            ' with bundles or merge directives.')
 
3684
 
 
3685
                    if revision is not None:
 
3686
                        raise errors.BzrCommandError(
 
3687
                            'Cannot use -r with merge directives or bundles')
 
3688
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
 
3689
                       mergeable, pb)
 
3690
 
 
3691
            if merger is None and uncommitted:
 
3692
                if revision is not None and len(revision) > 0:
 
3693
                    raise errors.BzrCommandError('Cannot use --uncommitted and'
 
3694
                        ' --revision at the same time.')
 
3695
                merger = self.get_merger_from_uncommitted(tree, location, pb,
 
3696
                                                          cleanups)
 
3697
                allow_pending = False
 
3698
 
 
3699
            if merger is None:
 
3700
                merger, allow_pending = self._get_merger_from_branch(tree,
 
3701
                    location, revision, remember, possible_transports, pb)
 
3702
 
 
3703
            merger.merge_type = merge_type
 
3704
            merger.reprocess = reprocess
 
3705
            merger.show_base = show_base
 
3706
            self.sanity_check_merger(merger)
 
3707
            if (merger.base_rev_id == merger.other_rev_id and
 
3708
                merger.other_rev_id is not None):
 
3709
                note('Nothing to do.')
 
3710
                return 0
 
3711
            if pull:
 
3712
                if merger.interesting_files is not None:
 
3713
                    raise errors.BzrCommandError('Cannot pull individual files')
 
3714
                if (merger.base_rev_id == tree.last_revision()):
 
3715
                    result = tree.pull(merger.other_branch, False,
 
3716
                                       merger.other_rev_id)
 
3717
                    result.report(self.outf)
 
3718
                    return 0
 
3719
            merger.check_basis(False)
 
3720
            if preview:
 
3721
                return self._do_preview(merger, cleanups)
 
3722
            elif interactive:
 
3723
                return self._do_interactive(merger, cleanups)
3793
3724
            else:
3794
 
                if uncommitted:
3795
 
                    raise errors.BzrCommandError('Cannot use --uncommitted'
3796
 
                        ' with bundles or merge directives.')
3797
 
 
3798
 
                if revision is not None:
3799
 
                    raise errors.BzrCommandError(
3800
 
                        'Cannot use -r with merge directives or bundles')
3801
 
                merger, verified = _mod_merge.Merger.from_mergeable(tree,
3802
 
                   mergeable, None)
3803
 
 
3804
 
        if merger is None and uncommitted:
3805
 
            if revision is not None and len(revision) > 0:
3806
 
                raise errors.BzrCommandError('Cannot use --uncommitted and'
3807
 
                    ' --revision at the same time.')
3808
 
            merger = self.get_merger_from_uncommitted(tree, location, None)
3809
 
            allow_pending = False
3810
 
 
3811
 
        if merger is None:
3812
 
            merger, allow_pending = self._get_merger_from_branch(tree,
3813
 
                location, revision, remember, possible_transports, None)
3814
 
 
3815
 
        merger.merge_type = merge_type
3816
 
        merger.reprocess = reprocess
3817
 
        merger.show_base = show_base
3818
 
        self.sanity_check_merger(merger)
3819
 
        if (merger.base_rev_id == merger.other_rev_id and
3820
 
            merger.other_rev_id is not None):
3821
 
            note('Nothing to do.')
3822
 
            return 0
3823
 
        if pull:
3824
 
            if merger.interesting_files is not None:
3825
 
                raise errors.BzrCommandError('Cannot pull individual files')
3826
 
            if (merger.base_rev_id == tree.last_revision()):
3827
 
                result = tree.pull(merger.other_branch, False,
3828
 
                                   merger.other_rev_id)
3829
 
                result.report(self.outf)
3830
 
                return 0
3831
 
        if merger.this_basis is None:
3832
 
            raise errors.BzrCommandError(
3833
 
                "This branch has no commits."
3834
 
                " (perhaps you would prefer 'bzr pull')")
3835
 
        if preview:
3836
 
            return self._do_preview(merger)
3837
 
        elif interactive:
3838
 
            return self._do_interactive(merger)
3839
 
        else:
3840
 
            return self._do_merge(merger, change_reporter, allow_pending,
3841
 
                                  verified)
3842
 
 
3843
 
    def _get_preview(self, merger):
 
3725
                return self._do_merge(merger, change_reporter, allow_pending,
 
3726
                                      verified)
 
3727
        finally:
 
3728
            for cleanup in reversed(cleanups):
 
3729
                cleanup()
 
3730
 
 
3731
    def _get_preview(self, merger, cleanups):
3844
3732
        tree_merger = merger.make_merger()
3845
3733
        tt = tree_merger.make_preview_transform()
3846
 
        self.add_cleanup(tt.finalize)
 
3734
        cleanups.append(tt.finalize)
3847
3735
        result_tree = tt.get_preview_tree()
3848
3736
        return result_tree
3849
3737
 
3850
 
    def _do_preview(self, merger):
 
3738
    def _do_preview(self, merger, cleanups):
3851
3739
        from bzrlib.diff import show_diff_trees
3852
 
        result_tree = self._get_preview(merger)
 
3740
        result_tree = self._get_preview(merger, cleanups)
3853
3741
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3854
3742
                        old_label='', new_label='')
3855
3743
 
3865
3753
        else:
3866
3754
            return 0
3867
3755
 
3868
 
    def _do_interactive(self, merger):
 
3756
    def _do_interactive(self, merger, cleanups):
3869
3757
        """Perform an interactive merge.
3870
3758
 
3871
3759
        This works by generating a preview tree of the merge, then using
3873
3761
        and the preview tree.
3874
3762
        """
3875
3763
        from bzrlib import shelf_ui
3876
 
        result_tree = self._get_preview(merger)
 
3764
        result_tree = self._get_preview(merger, cleanups)
3877
3765
        writer = bzrlib.option.diff_writer_registry.get()
3878
3766
        shelver = shelf_ui.Shelver(merger.this_tree, result_tree, destroy=True,
3879
3767
                                   reporter=shelf_ui.ApplyReporter(),
3880
3768
                                   diff_writer=writer(sys.stdout))
3881
 
        try:
3882
 
            shelver.run()
3883
 
        finally:
3884
 
            shelver.finalize()
 
3769
        shelver.run()
3885
3770
 
3886
3771
    def sanity_check_merger(self, merger):
3887
3772
        if (merger.show_base and
3947
3832
            allow_pending = True
3948
3833
        return merger, allow_pending
3949
3834
 
3950
 
    def get_merger_from_uncommitted(self, tree, location, pb):
 
3835
    def get_merger_from_uncommitted(self, tree, location, pb, cleanups):
3951
3836
        """Get a merger for uncommitted changes.
3952
3837
 
3953
3838
        :param tree: The tree the merger should apply to.
3954
3839
        :param location: The location containing uncommitted changes.
3955
3840
        :param pb: The progress bar to use for showing progress.
 
3841
        :param cleanups: A list of operations to perform to clean up the
 
3842
            temporary directories, unfinalized objects, etc.
3956
3843
        """
3957
3844
        location = self._select_branch_location(tree, location)[0]
3958
3845
        other_tree, other_path = WorkingTree.open_containing(location)
4045
3932
            merge_type = _mod_merge.Merge3Merger
4046
3933
        tree, file_list = tree_files(file_list)
4047
3934
        tree.lock_write()
4048
 
        self.add_cleanup(tree.unlock)
4049
 
        parents = tree.get_parent_ids()
4050
 
        if len(parents) != 2:
4051
 
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4052
 
                                         " merges.  Not cherrypicking or"
4053
 
                                         " multi-merges.")
4054
 
        repository = tree.branch.repository
4055
 
        interesting_ids = None
4056
 
        new_conflicts = []
4057
 
        conflicts = tree.conflicts()
4058
 
        if file_list is not None:
4059
 
            interesting_ids = set()
4060
 
            for filename in file_list:
4061
 
                file_id = tree.path2id(filename)
4062
 
                if file_id is None:
4063
 
                    raise errors.NotVersionedError(filename)
4064
 
                interesting_ids.add(file_id)
4065
 
                if tree.kind(file_id) != "directory":
4066
 
                    continue
 
3935
        try:
 
3936
            parents = tree.get_parent_ids()
 
3937
            if len(parents) != 2:
 
3938
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
3939
                                             " merges.  Not cherrypicking or"
 
3940
                                             " multi-merges.")
 
3941
            repository = tree.branch.repository
 
3942
            interesting_ids = None
 
3943
            new_conflicts = []
 
3944
            conflicts = tree.conflicts()
 
3945
            if file_list is not None:
 
3946
                interesting_ids = set()
 
3947
                for filename in file_list:
 
3948
                    file_id = tree.path2id(filename)
 
3949
                    if file_id is None:
 
3950
                        raise errors.NotVersionedError(filename)
 
3951
                    interesting_ids.add(file_id)
 
3952
                    if tree.kind(file_id) != "directory":
 
3953
                        continue
4067
3954
 
4068
 
                for name, ie in tree.inventory.iter_entries(file_id):
4069
 
                    interesting_ids.add(ie.file_id)
4070
 
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4071
 
        else:
4072
 
            # Remerge only supports resolving contents conflicts
4073
 
            allowed_conflicts = ('text conflict', 'contents conflict')
4074
 
            restore_files = [c.path for c in conflicts
4075
 
                             if c.typestring in allowed_conflicts]
4076
 
        _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4077
 
        tree.set_conflicts(ConflictList(new_conflicts))
4078
 
        if file_list is not None:
4079
 
            restore_files = file_list
4080
 
        for filename in restore_files:
 
3955
                    for name, ie in tree.inventory.iter_entries(file_id):
 
3956
                        interesting_ids.add(ie.file_id)
 
3957
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
 
3958
            else:
 
3959
                # Remerge only supports resolving contents conflicts
 
3960
                allowed_conflicts = ('text conflict', 'contents conflict')
 
3961
                restore_files = [c.path for c in conflicts
 
3962
                                 if c.typestring in allowed_conflicts]
 
3963
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
 
3964
            tree.set_conflicts(ConflictList(new_conflicts))
 
3965
            if file_list is not None:
 
3966
                restore_files = file_list
 
3967
            for filename in restore_files:
 
3968
                try:
 
3969
                    restore(tree.abspath(filename))
 
3970
                except errors.NotConflicted:
 
3971
                    pass
 
3972
            # Disable pending merges, because the file texts we are remerging
 
3973
            # have not had those merges performed.  If we use the wrong parents
 
3974
            # list, we imply that the working tree text has seen and rejected
 
3975
            # all the changes from the other tree, when in fact those changes
 
3976
            # have not yet been seen.
 
3977
            pb = ui.ui_factory.nested_progress_bar()
 
3978
            tree.set_parent_ids(parents[:1])
4081
3979
            try:
4082
 
                restore(tree.abspath(filename))
4083
 
            except errors.NotConflicted:
4084
 
                pass
4085
 
        # Disable pending merges, because the file texts we are remerging
4086
 
        # have not had those merges performed.  If we use the wrong parents
4087
 
        # list, we imply that the working tree text has seen and rejected
4088
 
        # all the changes from the other tree, when in fact those changes
4089
 
        # have not yet been seen.
4090
 
        tree.set_parent_ids(parents[:1])
4091
 
        try:
4092
 
            merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4093
 
            merger.interesting_ids = interesting_ids
4094
 
            merger.merge_type = merge_type
4095
 
            merger.show_base = show_base
4096
 
            merger.reprocess = reprocess
4097
 
            conflicts = merger.do_merge()
 
3980
                merger = _mod_merge.Merger.from_revision_ids(pb,
 
3981
                                                             tree, parents[1])
 
3982
                merger.interesting_ids = interesting_ids
 
3983
                merger.merge_type = merge_type
 
3984
                merger.show_base = show_base
 
3985
                merger.reprocess = reprocess
 
3986
                conflicts = merger.do_merge()
 
3987
            finally:
 
3988
                tree.set_parent_ids(parents)
 
3989
                pb.finished()
4098
3990
        finally:
4099
 
            tree.set_parent_ids(parents)
 
3991
            tree.unlock()
4100
3992
        if conflicts > 0:
4101
3993
            return 1
4102
3994
        else:
4124
4016
    name.  If you name a directory, all the contents of that directory will be
4125
4017
    reverted.
4126
4018
 
4127
 
    If you have newly added files since the target revision, they will be
4128
 
    removed.  If the files to be removed have been changed, backups will be
4129
 
    created as above.  Directories containing unknown files will not be
4130
 
    deleted.
 
4019
    Any files that have been newly added since that revision will be deleted,
 
4020
    with a backup kept if appropriate.  Directories containing unknown files
 
4021
    will not be deleted.
4131
4022
 
4132
 
    The working tree contains a list of revisions that have been merged but
4133
 
    not yet committed. These revisions will be included as additional parents
4134
 
    of the next commit.  Normally, using revert clears that list as well as
4135
 
    reverting the files.  If any files are specified, revert leaves the list
4136
 
    of uncommitted merges alone and reverts only the files.  Use ``bzr revert
4137
 
    .`` in the tree root to revert all files but keep the recorded merges,
4138
 
    and ``bzr revert --forget-merges`` to clear the pending merge list without
 
4023
    The working tree contains a list of pending merged revisions, which will
 
4024
    be included as parents in the next commit.  Normally, revert clears that
 
4025
    list as well as reverting the files.  If any files are specified, revert
 
4026
    leaves the pending merge list alone and reverts only the files.  Use "bzr
 
4027
    revert ." in the tree root to revert all files but keep the merge record,
 
4028
    and "bzr revert --forget-merges" to clear the pending merge list without
4139
4029
    reverting any files.
4140
 
 
4141
 
    Using "bzr revert --forget-merges", it is possible to apply all of the
4142
 
    changes from a branch in a single revision.  To do this, perform the merge
4143
 
    as desired.  Then doing revert with the "--forget-merges" option will keep
4144
 
    the content of the tree as it was, but it will clear the list of pending
4145
 
    merges.  The next commit will then contain all of the changes that are
4146
 
    present in the other branch, but without any other parent revisions.
4147
 
    Because this technique forgets where these changes originated, it may
4148
 
    cause additional conflicts on later merges involving the same source and
4149
 
    target branches.
4150
4030
    """
4151
4031
 
4152
4032
    _see_also = ['cat', 'export']
4162
4042
            forget_merges=None):
4163
4043
        tree, file_list = tree_files(file_list)
4164
4044
        tree.lock_write()
4165
 
        self.add_cleanup(tree.unlock)
4166
 
        if forget_merges:
4167
 
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4168
 
        else:
4169
 
            self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
4045
        try:
 
4046
            if forget_merges:
 
4047
                tree.set_parent_ids(tree.get_parent_ids()[:1])
 
4048
            else:
 
4049
                self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
4050
        finally:
 
4051
            tree.unlock()
4170
4052
 
4171
4053
    @staticmethod
4172
4054
    def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4173
4055
        rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4174
 
        tree.revert(file_list, rev_tree, not no_backup, None,
4175
 
            report_changes=True)
 
4056
        pb = ui.ui_factory.nested_progress_bar()
 
4057
        try:
 
4058
            tree.revert(file_list, rev_tree, not no_backup, pb,
 
4059
                report_changes=True)
 
4060
        finally:
 
4061
            pb.finished()
4176
4062
 
4177
4063
 
4178
4064
class cmd_assert_fail(Command):
4227
4113
    To filter on a range of revisions, you can use the command -r begin..end
4228
4114
    -r revision requests a specific revision, -r ..end or -r begin.. are
4229
4115
    also valid.
4230
 
            
4231
 
    :Exit values:
4232
 
        1 - some missing revisions
4233
 
        0 - no missing revisions
4234
4116
 
4235
4117
    :Examples:
4236
4118
 
4319
4201
        if remote_branch.base == local_branch.base:
4320
4202
            remote_branch = local_branch
4321
4203
 
4322
 
        local_branch.lock_read()
4323
 
        self.add_cleanup(local_branch.unlock)
4324
4204
        local_revid_range = _revision_range_to_revid_range(
4325
4205
            _get_revision_range(my_revision, local_branch,
4326
4206
                self.name()))
4327
4207
 
4328
 
        remote_branch.lock_read()
4329
 
        self.add_cleanup(remote_branch.unlock)
4330
4208
        remote_revid_range = _revision_range_to_revid_range(
4331
4209
            _get_revision_range(revision,
4332
4210
                remote_branch, self.name()))
4333
4211
 
4334
 
        local_extra, remote_extra = find_unmerged(
4335
 
            local_branch, remote_branch, restrict,
4336
 
            backward=not reverse,
4337
 
            include_merges=include_merges,
4338
 
            local_revid_range=local_revid_range,
4339
 
            remote_revid_range=remote_revid_range)
4340
 
 
4341
 
        if log_format is None:
4342
 
            registry = log.log_formatter_registry
4343
 
            log_format = registry.get_default(local_branch)
4344
 
        lf = log_format(to_file=self.outf,
4345
 
                        show_ids=show_ids,
4346
 
                        show_timezone='original')
4347
 
 
4348
 
        status_code = 0
4349
 
        if local_extra and not theirs_only:
4350
 
            message("You have %d extra revision(s):\n" %
4351
 
                len(local_extra))
4352
 
            for revision in iter_log_revisions(local_extra,
4353
 
                                local_branch.repository,
4354
 
                                verbose):
4355
 
                lf.log_revision(revision)
4356
 
            printed_local = True
4357
 
            status_code = 1
4358
 
        else:
4359
 
            printed_local = False
4360
 
 
4361
 
        if remote_extra and not mine_only:
4362
 
            if printed_local is True:
4363
 
                message("\n\n\n")
4364
 
            message("You are missing %d revision(s):\n" %
4365
 
                len(remote_extra))
4366
 
            for revision in iter_log_revisions(remote_extra,
4367
 
                                remote_branch.repository,
4368
 
                                verbose):
4369
 
                lf.log_revision(revision)
4370
 
            status_code = 1
4371
 
 
4372
 
        if mine_only and not local_extra:
4373
 
            # We checked local, and found nothing extra
4374
 
            message('This branch is up to date.\n')
4375
 
        elif theirs_only and not remote_extra:
4376
 
            # We checked remote, and found nothing extra
4377
 
            message('Other branch is up to date.\n')
4378
 
        elif not (mine_only or theirs_only or local_extra or
4379
 
                  remote_extra):
4380
 
            # We checked both branches, and neither one had extra
4381
 
            # revisions
4382
 
            message("Branches are up to date.\n")
4383
 
        self.cleanup_now()
 
4212
        local_branch.lock_read()
 
4213
        try:
 
4214
            remote_branch.lock_read()
 
4215
            try:
 
4216
                local_extra, remote_extra = find_unmerged(
 
4217
                    local_branch, remote_branch, restrict,
 
4218
                    backward=not reverse,
 
4219
                    include_merges=include_merges,
 
4220
                    local_revid_range=local_revid_range,
 
4221
                    remote_revid_range=remote_revid_range)
 
4222
 
 
4223
                if log_format is None:
 
4224
                    registry = log.log_formatter_registry
 
4225
                    log_format = registry.get_default(local_branch)
 
4226
                lf = log_format(to_file=self.outf,
 
4227
                                show_ids=show_ids,
 
4228
                                show_timezone='original')
 
4229
 
 
4230
                status_code = 0
 
4231
                if local_extra and not theirs_only:
 
4232
                    message("You have %d extra revision(s):\n" %
 
4233
                        len(local_extra))
 
4234
                    for revision in iter_log_revisions(local_extra,
 
4235
                                        local_branch.repository,
 
4236
                                        verbose):
 
4237
                        lf.log_revision(revision)
 
4238
                    printed_local = True
 
4239
                    status_code = 1
 
4240
                else:
 
4241
                    printed_local = False
 
4242
 
 
4243
                if remote_extra and not mine_only:
 
4244
                    if printed_local is True:
 
4245
                        message("\n\n\n")
 
4246
                    message("You are missing %d revision(s):\n" %
 
4247
                        len(remote_extra))
 
4248
                    for revision in iter_log_revisions(remote_extra,
 
4249
                                        remote_branch.repository,
 
4250
                                        verbose):
 
4251
                        lf.log_revision(revision)
 
4252
                    status_code = 1
 
4253
 
 
4254
                if mine_only and not local_extra:
 
4255
                    # We checked local, and found nothing extra
 
4256
                    message('This branch is up to date.\n')
 
4257
                elif theirs_only and not remote_extra:
 
4258
                    # We checked remote, and found nothing extra
 
4259
                    message('Other branch is up to date.\n')
 
4260
                elif not (mine_only or theirs_only or local_extra or
 
4261
                          remote_extra):
 
4262
                    # We checked both branches, and neither one had extra
 
4263
                    # revisions
 
4264
                    message("Branches are up to date.\n")
 
4265
            finally:
 
4266
                remote_branch.unlock()
 
4267
        finally:
 
4268
            local_branch.unlock()
4384
4269
        if not status_code and parent is None and other_branch is not None:
4385
4270
            local_branch.lock_write()
4386
 
            self.add_cleanup(local_branch.unlock)
4387
 
            # handle race conditions - a parent might be set while we run.
4388
 
            if local_branch.get_parent() is None:
4389
 
                local_branch.set_parent(remote_branch.base)
 
4271
            try:
 
4272
                # handle race conditions - a parent might be set while we run.
 
4273
                if local_branch.get_parent() is None:
 
4274
                    local_branch.set_parent(remote_branch.base)
 
4275
            finally:
 
4276
                local_branch.unlock()
4390
4277
        return status_code
4391
4278
 
4392
4279
 
4420
4307
    adding new commands, providing additional network transports and
4421
4308
    customizing log output.
4422
4309
 
4423
 
    See the Bazaar Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/>
4424
 
    for further information on plugins including where to find them and how to
4425
 
    install them. Instructions are also provided there on how to write new
4426
 
    plugins using the Python programming language.
 
4310
    See the Bazaar web site, http://bazaar-vcs.org, for further
 
4311
    information on plugins including where to find them and how to
 
4312
    install them. Instructions are also provided there on how to
 
4313
    write new plugins using the Python programming language.
4427
4314
    """
4428
4315
    takes_options = ['verbose']
4429
4316
 
4471
4358
        else:
4472
4359
            b = Branch.open(branch)
4473
4360
        b.lock_read()
4474
 
        self.add_cleanup(b.unlock)
4475
 
        if revision is None:
4476
 
            rev_id = b.last_revision()
4477
 
        else:
4478
 
            rev_id = revision[0].as_revision_id(b)
4479
 
        t = testament_class.from_revision(b.repository, rev_id)
4480
 
        if long:
4481
 
            sys.stdout.writelines(t.as_text_lines())
4482
 
        else:
4483
 
            sys.stdout.write(t.as_short_text())
 
4361
        try:
 
4362
            if revision is None:
 
4363
                rev_id = b.last_revision()
 
4364
            else:
 
4365
                rev_id = revision[0].as_revision_id(b)
 
4366
            t = testament_class.from_revision(b.repository, rev_id)
 
4367
            if long:
 
4368
                sys.stdout.writelines(t.as_text_lines())
 
4369
            else:
 
4370
                sys.stdout.write(t.as_short_text())
 
4371
        finally:
 
4372
            b.unlock()
4484
4373
 
4485
4374
 
4486
4375
class cmd_annotate(Command):
4512
4401
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4513
4402
        if wt is not None:
4514
4403
            wt.lock_read()
4515
 
            self.add_cleanup(wt.unlock)
4516
4404
        else:
4517
4405
            branch.lock_read()
4518
 
            self.add_cleanup(branch.unlock)
4519
 
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
4520
 
        tree.lock_read()
4521
 
        self.add_cleanup(tree.unlock)
4522
 
        if wt is not None:
4523
 
            file_id = wt.path2id(relpath)
4524
 
        else:
4525
 
            file_id = tree.path2id(relpath)
4526
 
        if file_id is None:
4527
 
            raise errors.NotVersionedError(filename)
4528
 
        file_version = tree.inventory[file_id].revision
4529
 
        if wt is not None and revision is None:
4530
 
            # If there is a tree and we're not annotating historical
4531
 
            # versions, annotate the working tree's content.
4532
 
            annotate_file_tree(wt, file_id, self.outf, long, all,
4533
 
                show_ids=show_ids)
4534
 
        else:
4535
 
            annotate_file(branch, file_version, file_id, long, all, self.outf,
4536
 
                          show_ids=show_ids)
 
4406
        try:
 
4407
            tree = _get_one_revision_tree('annotate', revision, branch=branch)
 
4408
            if wt is not None:
 
4409
                file_id = wt.path2id(relpath)
 
4410
            else:
 
4411
                file_id = tree.path2id(relpath)
 
4412
            if file_id is None:
 
4413
                raise errors.NotVersionedError(filename)
 
4414
            file_version = tree.inventory[file_id].revision
 
4415
            if wt is not None and revision is None:
 
4416
                # If there is a tree and we're not annotating historical
 
4417
                # versions, annotate the working tree's content.
 
4418
                annotate_file_tree(wt, file_id, self.outf, long, all,
 
4419
                    show_ids=show_ids)
 
4420
            else:
 
4421
                annotate_file(branch, file_version, file_id, long, all, self.outf,
 
4422
                              show_ids=show_ids)
 
4423
        finally:
 
4424
            if wt is not None:
 
4425
                wt.unlock()
 
4426
            else:
 
4427
                branch.unlock()
4537
4428
 
4538
4429
 
4539
4430
class cmd_re_sign(Command):
4551
4442
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4552
4443
        b = WorkingTree.open_containing(u'.')[0].branch
4553
4444
        b.lock_write()
4554
 
        self.add_cleanup(b.unlock)
4555
 
        return self._run(b, revision_id_list, revision)
 
4445
        try:
 
4446
            return self._run(b, revision_id_list, revision)
 
4447
        finally:
 
4448
            b.unlock()
4556
4449
 
4557
4450
    def _run(self, b, revision_id_list, revision):
4558
4451
        import bzrlib.gpg as gpg
4609
4502
    before they will be applied to the local branch.
4610
4503
 
4611
4504
    Bound branches use the nickname of its master branch unless it is set
4612
 
    locally, in which case binding will update the local nickname to be
 
4505
    locally, in which case binding will update the the local nickname to be
4613
4506
    that of the master.
4614
4507
    """
4615
4508
 
4627
4520
                    'This format does not remember old locations.')
4628
4521
            else:
4629
4522
                if location is None:
4630
 
                    if b.get_bound_location() is not None:
4631
 
                        raise errors.BzrCommandError('Branch is already bound')
4632
 
                    else:
4633
 
                        raise errors.BzrCommandError('No location supplied '
4634
 
                            'and no previous location known')
 
4523
                    raise errors.BzrCommandError('No location supplied and no '
 
4524
                        'previous location known')
4635
4525
        b_other = Branch.open(location)
4636
4526
        try:
4637
4527
            b.bind(b_other)
4707
4597
 
4708
4598
        if tree is not None:
4709
4599
            tree.lock_write()
4710
 
            self.add_cleanup(tree.unlock)
4711
4600
        else:
4712
4601
            b.lock_write()
4713
 
            self.add_cleanup(b.unlock)
4714
 
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
 
4602
        try:
 
4603
            return self._run(b, tree, dry_run, verbose, revision, force,
 
4604
                             local=local)
 
4605
        finally:
 
4606
            if tree is not None:
 
4607
                tree.unlock()
 
4608
            else:
 
4609
                b.unlock()
4715
4610
 
4716
4611
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
4717
4612
        from bzrlib.log import log_formatter, show_log
4734
4629
                rev_id = b.get_rev_id(revno)
4735
4630
 
4736
4631
        if rev_id is None or _mod_revision.is_null(rev_id):
4737
 
            ui.ui_factory.note('No revisions to uncommit.')
 
4632
            self.outf.write('No revisions to uncommit.\n')
4738
4633
            return 1
4739
4634
 
4740
 
        log_collector = ui.ui_factory.make_output_stream()
4741
4635
        lf = log_formatter('short',
4742
 
                           to_file=log_collector,
 
4636
                           to_file=self.outf,
4743
4637
                           show_timezone='original')
4744
4638
 
4745
4639
        show_log(b,
4750
4644
                 end_revision=last_revno)
4751
4645
 
4752
4646
        if dry_run:
4753
 
            ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
 
4647
            print 'Dry-run, pretending to remove the above revisions.'
 
4648
            if not force:
 
4649
                val = raw_input('Press <enter> to continue')
4754
4650
        else:
4755
 
            ui.ui_factory.note('The above revision(s) will be removed.')
4756
 
 
4757
 
        if not force:
4758
 
            if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
4759
 
                ui.ui_factory.note('Canceled')
4760
 
                return 0
 
4651
            print 'The above revision(s) will be removed.'
 
4652
            if not force:
 
4653
                val = raw_input('Are you sure [y/N]? ')
 
4654
                if val.lower() not in ('y', 'yes'):
 
4655
                    print 'Canceled'
 
4656
                    return 0
4761
4657
 
4762
4658
        mutter('Uncommitting from {%s} to {%s}',
4763
4659
               last_rev_id, rev_id)
4764
4660
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4765
4661
                 revno=revno, local=local)
4766
 
        ui.ui_factory.note('You can restore the old tip by running:\n'
4767
 
             '  bzr pull . -r revid:%s' % last_rev_id)
 
4662
        note('You can restore the old tip by running:\n'
 
4663
             '  bzr pull . -r revid:%s', last_rev_id)
4768
4664
 
4769
4665
 
4770
4666
class cmd_break_lock(Command):
4773
4669
    CAUTION: Locks should only be broken when you are sure that the process
4774
4670
    holding the lock has been stopped.
4775
4671
 
4776
 
    You can get information on what locks are open via the 'bzr info
4777
 
    [location]' command.
 
4672
    You can get information on what locks are open via the 'bzr info' command.
4778
4673
 
4779
4674
    :Examples:
4780
4675
        bzr break-lock
4781
 
        bzr break-lock bzr+ssh://example.com/bzr/foo
4782
4676
    """
4783
4677
    takes_args = ['location?']
4784
4678
 
4814
4708
    takes_options = [
4815
4709
        Option('inet',
4816
4710
               help='Serve on stdin/out for use from inetd or sshd.'),
4817
 
        RegistryOption('protocol',
4818
 
               help="Protocol to serve.",
 
4711
        RegistryOption('protocol', 
 
4712
               help="Protocol to serve.", 
4819
4713
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
4820
4714
               value_switches=True),
4821
4715
        Option('port',
4830
4724
        Option('allow-writes',
4831
4725
               help='By default the server is a readonly server.  Supplying '
4832
4726
                    '--allow-writes enables write access to the contents of '
4833
 
                    'the served directory and below.  Note that ``bzr serve`` '
4834
 
                    'does not perform authentication, so unless some form of '
4835
 
                    'external authentication is arranged supplying this '
4836
 
                    'option leads to global uncontrolled write access to your '
4837
 
                    'file system.'
 
4727
                    'the served directory and below.'
4838
4728
                ),
4839
4729
        ]
4840
4730
 
5056
4946
      directly from the merge directive, without retrieving data from a
5057
4947
      branch.
5058
4948
 
5059
 
    `bzr send` creates a compact data set that, when applied using bzr
5060
 
    merge, has the same effect as merging from the source branch.  
5061
 
    
5062
 
    By default the merge directive is self-contained and can be applied to any
5063
 
    branch containing submit_branch in its ancestory without needing access to
5064
 
    the source branch.
5065
 
    
5066
 
    If --no-bundle is specified, then Bazaar doesn't send the contents of the
5067
 
    revisions, but only a structured request to merge from the
5068
 
    public_location.  In that case the public_branch is needed and it must be
5069
 
    up-to-date and accessible to the recipient.  The public_branch is always
5070
 
    included if known, so that people can check it later.
5071
 
 
5072
 
    The submit branch defaults to the parent of the source branch, but can be
5073
 
    overridden.  Both submit branch and public branch will be remembered in
5074
 
    branch.conf the first time they are used for a particular branch.  The
5075
 
    source branch defaults to that containing the working directory, but can
5076
 
    be changed using --from.
5077
 
 
5078
 
    In order to calculate those changes, bzr must analyse the submit branch.
5079
 
    Therefore it is most efficient for the submit branch to be a local mirror.
5080
 
    If a public location is known for the submit_branch, that location is used
5081
 
    in the merge directive.
5082
 
 
5083
 
    The default behaviour is to send the merge directive by mail, unless -o is
5084
 
    given, in which case it is sent to a file.
 
4949
    If --no-bundle is specified, then public_branch is needed (and must be
 
4950
    up-to-date), so that the receiver can perform the merge using the
 
4951
    public_branch.  The public_branch is always included if known, so that
 
4952
    people can check it later.
 
4953
 
 
4954
    The submit branch defaults to the parent, but can be overridden.  Both
 
4955
    submit branch and public branch will be remembered if supplied.
 
4956
 
 
4957
    If a public_branch is known for the submit_branch, that public submit
 
4958
    branch is used in the merge instructions.  This means that a local mirror
 
4959
    can be used as your actual submit branch, once you have set public_branch
 
4960
    for that mirror.
5085
4961
 
5086
4962
    Mail is sent using your preferred mail program.  This should be transparent
5087
4963
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
5089
4965
 
5090
4966
    To use a specific mail program, set the mail_client configuration option.
5091
4967
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
5092
 
    specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5093
 
    Mail.app), "mutt", and "thunderbird"; generic options are "default",
5094
 
    "editor", "emacsclient", "mapi", and "xdg-email".  Plugins may also add
5095
 
    supported clients.
 
4968
    specific clients are "claws", "evolution", "kmail", "mutt", and
 
4969
    "thunderbird"; generic options are "default", "editor", "emacsclient",
 
4970
    "mapi", and "xdg-email".  Plugins may also add supported clients.
5096
4971
 
5097
4972
    If mail is being sent, a to address is required.  This can be supplied
5098
4973
    either on the commandline, by setting the submit_to configuration
5107
4982
 
5108
4983
    The merge directives created by bzr send may be applied using bzr merge or
5109
4984
    bzr pull by specifying a file containing a merge directive as the location.
5110
 
 
5111
 
    bzr send makes extensive use of public locations to map local locations into
5112
 
    URLs that can be used by other people.  See `bzr help configuration` to
5113
 
    set them, and use `bzr info` to display them.
5114
4985
    """
5115
4986
 
5116
4987
    encoding_type = 'exact'
5275
5146
            ):
5276
5147
        branch, relpath = Branch.open_containing(directory)
5277
5148
        branch.lock_write()
5278
 
        self.add_cleanup(branch.unlock)
5279
 
        if delete:
5280
 
            branch.tags.delete_tag(tag_name)
5281
 
            self.outf.write('Deleted tag %s.\n' % tag_name)
5282
 
        else:
5283
 
            if revision:
5284
 
                if len(revision) != 1:
5285
 
                    raise errors.BzrCommandError(
5286
 
                        "Tags can only be placed on a single revision, "
5287
 
                        "not on a range")
5288
 
                revision_id = revision[0].as_revision_id(branch)
 
5149
        try:
 
5150
            if delete:
 
5151
                branch.tags.delete_tag(tag_name)
 
5152
                self.outf.write('Deleted tag %s.\n' % tag_name)
5289
5153
            else:
5290
 
                revision_id = branch.last_revision()
5291
 
            if (not force) and branch.tags.has_tag(tag_name):
5292
 
                raise errors.TagAlreadyExists(tag_name)
5293
 
            branch.tags.set_tag(tag_name, revision_id)
5294
 
            self.outf.write('Created tag %s.\n' % tag_name)
 
5154
                if revision:
 
5155
                    if len(revision) != 1:
 
5156
                        raise errors.BzrCommandError(
 
5157
                            "Tags can only be placed on a single revision, "
 
5158
                            "not on a range")
 
5159
                    revision_id = revision[0].as_revision_id(branch)
 
5160
                else:
 
5161
                    revision_id = branch.last_revision()
 
5162
                if (not force) and branch.tags.has_tag(tag_name):
 
5163
                    raise errors.TagAlreadyExists(tag_name)
 
5164
                branch.tags.set_tag(tag_name, revision_id)
 
5165
                self.outf.write('Created tag %s.\n' % tag_name)
 
5166
        finally:
 
5167
            branch.unlock()
5295
5168
 
5296
5169
 
5297
5170
class cmd_tags(Command):
5330
5203
            return
5331
5204
 
5332
5205
        branch.lock_read()
5333
 
        self.add_cleanup(branch.unlock)
5334
 
        if revision:
5335
 
            graph = branch.repository.get_graph()
5336
 
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5337
 
            revid1, revid2 = rev1.rev_id, rev2.rev_id
5338
 
            # only show revisions between revid1 and revid2 (inclusive)
5339
 
            tags = [(tag, revid) for tag, revid in tags if
5340
 
                graph.is_between(revid, revid1, revid2)]
5341
 
        if sort == 'alpha':
5342
 
            tags.sort()
5343
 
        elif sort == 'time':
5344
 
            timestamps = {}
5345
 
            for tag, revid in tags:
5346
 
                try:
5347
 
                    revobj = branch.repository.get_revision(revid)
5348
 
                except errors.NoSuchRevision:
5349
 
                    timestamp = sys.maxint # place them at the end
5350
 
                else:
5351
 
                    timestamp = revobj.timestamp
5352
 
                timestamps[revid] = timestamp
5353
 
            tags.sort(key=lambda x: timestamps[x[1]])
5354
 
        if not show_ids:
5355
 
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5356
 
            for index, (tag, revid) in enumerate(tags):
5357
 
                try:
5358
 
                    revno = branch.revision_id_to_dotted_revno(revid)
5359
 
                    if isinstance(revno, tuple):
5360
 
                        revno = '.'.join(map(str, revno))
5361
 
                except errors.NoSuchRevision:
5362
 
                    # Bad tag data/merges can lead to tagged revisions
5363
 
                    # which are not in this branch. Fail gracefully ...
5364
 
                    revno = '?'
5365
 
                tags[index] = (tag, revno)
5366
 
        self.cleanup_now()
 
5206
        try:
 
5207
            if revision:
 
5208
                graph = branch.repository.get_graph()
 
5209
                rev1, rev2 = _get_revision_range(revision, branch, self.name())
 
5210
                revid1, revid2 = rev1.rev_id, rev2.rev_id
 
5211
                # only show revisions between revid1 and revid2 (inclusive)
 
5212
                tags = [(tag, revid) for tag, revid in tags if
 
5213
                    graph.is_between(revid, revid1, revid2)]
 
5214
            if sort == 'alpha':
 
5215
                tags.sort()
 
5216
            elif sort == 'time':
 
5217
                timestamps = {}
 
5218
                for tag, revid in tags:
 
5219
                    try:
 
5220
                        revobj = branch.repository.get_revision(revid)
 
5221
                    except errors.NoSuchRevision:
 
5222
                        timestamp = sys.maxint # place them at the end
 
5223
                    else:
 
5224
                        timestamp = revobj.timestamp
 
5225
                    timestamps[revid] = timestamp
 
5226
                tags.sort(key=lambda x: timestamps[x[1]])
 
5227
            if not show_ids:
 
5228
                # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
 
5229
                for index, (tag, revid) in enumerate(tags):
 
5230
                    try:
 
5231
                        revno = branch.revision_id_to_dotted_revno(revid)
 
5232
                        if isinstance(revno, tuple):
 
5233
                            revno = '.'.join(map(str, revno))
 
5234
                    except errors.NoSuchRevision:
 
5235
                        # Bad tag data/merges can lead to tagged revisions
 
5236
                        # which are not in this branch. Fail gracefully ...
 
5237
                        revno = '?'
 
5238
                    tags[index] = (tag, revno)
 
5239
        finally:
 
5240
            branch.unlock()
5367
5241
        for tag, revspec in tags:
5368
5242
            self.outf.write('%-20s %s\n' % (tag, revspec))
5369
5243
 
5478
5352
    /path/to/newbranch.
5479
5353
 
5480
5354
    Bound branches use the nickname of its master branch unless it is set
5481
 
    locally, in which case switching will update the local nickname to be
 
5355
    locally, in which case switching will update the the local nickname to be
5482
5356
    that of the master.
5483
5357
    """
5484
5358
 
5485
 
    takes_args = ['to_location?']
 
5359
    takes_args = ['to_location']
5486
5360
    takes_options = [Option('force',
5487
5361
                        help='Switch even if local commits will be lost.'),
5488
 
                     'revision',
5489
5362
                     Option('create-branch', short_name='b',
5490
5363
                        help='Create the target branch from this one before'
5491
5364
                             ' switching to it.'),
5492
 
                    ]
 
5365
                     ]
5493
5366
 
5494
 
    def run(self, to_location=None, force=False, create_branch=False,
5495
 
            revision=None):
 
5367
    def run(self, to_location, force=False, create_branch=False):
5496
5368
        from bzrlib import switch
5497
5369
        tree_location = '.'
5498
 
        revision = _get_one_revision('switch', revision)
5499
5370
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5500
 
        if to_location is None:
5501
 
            if revision is None:
5502
 
                raise errors.BzrCommandError('You must supply either a'
5503
 
                                             ' revision or a location')
5504
 
            to_location = '.'
5505
5371
        try:
5506
5372
            branch = control_dir.open_branch()
5507
5373
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5512
5378
            if branch is None:
5513
5379
                raise errors.BzrCommandError('cannot create branch without'
5514
5380
                                             ' source branch')
5515
 
            to_location = directory_service.directories.dereference(
5516
 
                              to_location)
5517
5381
            if '/' not in to_location and '\\' not in to_location:
5518
5382
                # This path is meant to be relative to the existing branch
5519
5383
                this_url = self._get_branch_location(control_dir)
5521
5385
            to_branch = branch.bzrdir.sprout(to_location,
5522
5386
                                 possible_transports=[branch.bzrdir.root_transport],
5523
5387
                                 source_branch=branch).open_branch()
 
5388
            # try:
 
5389
            #     from_branch = control_dir.open_branch()
 
5390
            # except errors.NotBranchError:
 
5391
            #     raise BzrCommandError('Cannot create a branch from this'
 
5392
            #         ' location when we cannot open this branch')
 
5393
            # from_branch.bzrdir.sprout(
 
5394
            pass
5524
5395
        else:
5525
5396
            try:
5526
5397
                to_branch = Branch.open(to_location)
5528
5399
                this_url = self._get_branch_location(control_dir)
5529
5400
                to_branch = Branch.open(
5530
5401
                    urlutils.join(this_url, '..', to_location))
5531
 
        if revision is not None:
5532
 
            revision = revision.as_revision_id(to_branch)
5533
 
        switch.switch(control_dir, to_branch, force, revision_id=revision)
 
5402
        switch.switch(control_dir, to_branch, force)
5534
5403
        if had_explicit_nick:
5535
5404
            branch = control_dir.open_branch() #get the new branch!
5536
5405
            branch.nick = to_branch.nick
5783
5652
            try:
5784
5653
                shelver.run()
5785
5654
            finally:
5786
 
                shelver.finalize()
 
5655
                shelver.work_tree.unlock()
5787
5656
        except errors.UserAbort:
5788
5657
            return 0
5789
5658
 
5790
5659
    def run_for_list(self):
5791
5660
        tree = WorkingTree.open_containing('.')[0]
5792
5661
        tree.lock_read()
5793
 
        self.add_cleanup(tree.unlock)
5794
 
        manager = tree.get_shelf_manager()
5795
 
        shelves = manager.active_shelves()
5796
 
        if len(shelves) == 0:
5797
 
            note('No shelved changes.')
5798
 
            return 0
5799
 
        for shelf_id in reversed(shelves):
5800
 
            message = manager.get_metadata(shelf_id).get('message')
5801
 
            if message is None:
5802
 
                message = '<no message>'
5803
 
            self.outf.write('%3d: %s\n' % (shelf_id, message))
5804
 
        return 1
 
5662
        try:
 
5663
            manager = tree.get_shelf_manager()
 
5664
            shelves = manager.active_shelves()
 
5665
            if len(shelves) == 0:
 
5666
                note('No shelved changes.')
 
5667
                return 0
 
5668
            for shelf_id in reversed(shelves):
 
5669
                message = manager.get_metadata(shelf_id).get('message')
 
5670
                if message is None:
 
5671
                    message = '<no message>'
 
5672
                self.outf.write('%3d: %s\n' % (shelf_id, message))
 
5673
            return 1
 
5674
        finally:
 
5675
            tree.unlock()
5805
5676
 
5806
5677
 
5807
5678
class cmd_unshelve(Command):
5819
5690
            enum_switch=False, value_switches=True,
5820
5691
            apply="Apply changes and remove from the shelf.",
5821
5692
            dry_run="Show changes, but do not apply or remove them.",
5822
 
            preview="Instead of unshelving the changes, show the diff that "
5823
 
                    "would result from unshelving.",
5824
 
            delete_only="Delete changes without applying them.",
5825
 
            keep="Apply changes but don't delete them.",
 
5693
            delete_only="Delete changes without applying them."
5826
5694
        )
5827
5695
    ]
5828
5696
    _see_also = ['shelve']
5929
5797
    )
5930
5798
from bzrlib.foreign import cmd_dpush
5931
5799
from bzrlib.sign_my_commits import cmd_sign_my_commits
 
5800
from bzrlib.weave_commands import cmd_versionedfile_list, \
 
5801
        cmd_weave_plan_merge, cmd_weave_merge_text