/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Martin Pool
  • Date: 2009-07-17 10:38:41 UTC
  • mfrom: (4536 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4558.
  • Revision ID: mbp@sourcefrog.net-20090717103841-z35onk04bkiw7zb6
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 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
48
48
import itertools
49
49
import operator
50
50
import stat
51
 
from time import time
52
 
import warnings
53
51
import re
54
52
 
55
53
import bzrlib
57
55
    branch,
58
56
    bzrdir,
59
57
    conflicts as _mod_conflicts,
60
 
    dirstate,
61
58
    errors,
62
59
    generate_ids,
63
60
    globbing,
 
61
    graph as _mod_graph,
64
62
    hashcache,
65
63
    ignores,
 
64
    inventory,
66
65
    merge,
67
66
    revision as _mod_revision,
68
67
    revisiontree,
69
 
    repository,
70
68
    textui,
71
69
    trace,
72
70
    transform,
73
71
    ui,
74
 
    urlutils,
75
72
    views,
76
73
    xml5,
77
 
    xml6,
78
74
    xml7,
79
75
    )
80
76
import bzrlib.branch
81
77
from bzrlib.transport import get_transport
82
 
import bzrlib.ui
83
78
from bzrlib.workingtree_4 import (
84
79
    WorkingTreeFormat4,
85
80
    WorkingTreeFormat5,
89
84
 
90
85
from bzrlib import symbol_versioning
91
86
from bzrlib.decorators import needs_read_lock, needs_write_lock
92
 
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
93
87
from bzrlib.lockable_files import LockableFiles
94
88
from bzrlib.lockdir import LockDir
95
89
import bzrlib.mutabletree
96
90
from bzrlib.mutabletree import needs_tree_write_lock
97
91
from bzrlib import osutils
98
92
from bzrlib.osutils import (
99
 
    compact_date,
100
93
    file_kind,
101
94
    isdir,
102
95
    normpath,
103
96
    pathjoin,
104
 
    rand_chars,
105
97
    realpath,
106
98
    safe_unicode,
107
99
    splitpath,
111
103
from bzrlib.trace import mutter, note
112
104
from bzrlib.transport.local import LocalTransport
113
105
from bzrlib.progress import DummyProgress, ProgressPhase
114
 
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
 
106
from bzrlib.revision import CURRENT_REVISION
115
107
from bzrlib.rio import RioReader, rio_file, Stanza
116
 
from bzrlib.symbol_versioning import (deprecated_passed,
117
 
        deprecated_method,
118
 
        deprecated_function,
119
 
        DEPRECATED_PARAMETER,
120
 
        )
 
108
from bzrlib.symbol_versioning import (
 
109
    deprecated_passed,
 
110
    DEPRECATED_PARAMETER,
 
111
    )
121
112
 
122
113
 
123
114
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
487
478
        incorrectly attributed to CURRENT_REVISION (but after committing, the
488
479
        attribution will be correct).
489
480
        """
490
 
        basis = self.basis_tree()
491
 
        basis.lock_read()
492
 
        try:
493
 
            changes = self.iter_changes(basis, True, [self.id2path(file_id)],
494
 
                require_versioned=True).next()
495
 
            changed_content, kind = changes[2], changes[6]
496
 
            if not changed_content:
497
 
                return basis.annotate_iter(file_id)
498
 
            if kind[1] is None:
499
 
                return None
500
 
            import annotate
501
 
            if kind[0] != 'file':
502
 
                old_lines = []
503
 
            else:
504
 
                old_lines = list(basis.annotate_iter(file_id))
505
 
            old = [old_lines]
506
 
            for tree in self.branch.repository.revision_trees(
507
 
                self.get_parent_ids()[1:]):
508
 
                if file_id not in tree:
509
 
                    continue
510
 
                old.append(list(tree.annotate_iter(file_id)))
511
 
            return annotate.reannotate(old, self.get_file(file_id).readlines(),
512
 
                                       default_revision)
513
 
        finally:
514
 
            basis.unlock()
 
481
        maybe_file_parent_keys = []
 
482
        for parent_id in self.get_parent_ids():
 
483
            try:
 
484
                parent_tree = self.revision_tree(parent_id)
 
485
            except errors.NoSuchRevisionInTree:
 
486
                parent_tree = self.branch.repository.revision_tree(parent_id)
 
487
            parent_tree.lock_read()
 
488
            try:
 
489
                if file_id not in parent_tree:
 
490
                    continue
 
491
                ie = parent_tree.inventory[file_id]
 
492
                if ie.kind != 'file':
 
493
                    # Note: this is slightly unnecessary, because symlinks and
 
494
                    # directories have a "text" which is the empty text, and we
 
495
                    # know that won't mess up annotations. But it seems cleaner
 
496
                    continue
 
497
                parent_text_key = (file_id, ie.revision)
 
498
                if parent_text_key not in maybe_file_parent_keys:
 
499
                    maybe_file_parent_keys.append(parent_text_key)
 
500
            finally:
 
501
                parent_tree.unlock()
 
502
        graph = _mod_graph.Graph(self.branch.repository.texts)
 
503
        heads = graph.heads(maybe_file_parent_keys)
 
504
        file_parent_keys = []
 
505
        for key in maybe_file_parent_keys:
 
506
            if key in heads:
 
507
                file_parent_keys.append(key)
 
508
 
 
509
        # Now we have the parents of this content
 
510
        annotator = self.branch.repository.texts.get_annotator()
 
511
        text = self.get_file(file_id).read()
 
512
        this_key =(file_id, default_revision)
 
513
        annotator.add_special_text(this_key, file_parent_keys, text)
 
514
        annotations = [(key[-1], line)
 
515
                       for key, line in annotator.annotate_flat(this_key)]
 
516
        return annotations
515
517
 
516
518
    def _get_ancestors(self, default_revision):
517
519
        ancestors = set([default_revision])
889
891
            branch.last_revision().
890
892
        """
891
893
        from bzrlib.merge import Merger, Merge3Merger
892
 
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
894
        pb = ui.ui_factory.nested_progress_bar()
893
895
        try:
894
896
            merger = Merger(self.branch, this_tree=self, pb=pb)
895
897
            merger.pp = ProgressPhase("Merge phase", 5, pb)
1081
1083
            branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
1082
1084
        else:
1083
1085
            tree_bzrdir = branch_bzrdir
1084
 
        wt = tree_bzrdir.create_workingtree(NULL_REVISION)
 
1086
        wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1085
1087
        wt.set_parent_ids(self.get_parent_ids())
1086
1088
        my_inv = self.inventory
1087
 
        child_inv = Inventory(root_id=None)
 
1089
        child_inv = inventory.Inventory(root_id=None)
1088
1090
        new_root = my_inv[file_id]
1089
1091
        my_inv.remove_recursive_id(file_id)
1090
1092
        new_root.parent_id = None
1115
1117
    def _kind(self, relpath):
1116
1118
        return osutils.file_kind(self.abspath(relpath))
1117
1119
 
1118
 
    def list_files(self, include_root=False):
1119
 
        """Recursively list all files as (path, class, kind, id, entry).
 
1120
    def list_files(self, include_root=False, from_dir=None, recursive=True):
 
1121
        """List all files as (path, class, kind, id, entry).
1120
1122
 
1121
1123
        Lists, but does not descend into unversioned directories.
1122
 
 
1123
1124
        This does not include files that have been deleted in this
1124
 
        tree.
 
1125
        tree. Skips the control directory.
1125
1126
 
1126
 
        Skips the control directory.
 
1127
        :param include_root: if True, do not return an entry for the root
 
1128
        :param from_dir: start from this directory or None for the root
 
1129
        :param recursive: whether to recurse into subdirectories or not
1127
1130
        """
1128
1131
        # list_files is an iterator, so @needs_read_lock doesn't work properly
1129
1132
        # with it. So callers should be careful to always read_lock the tree.
1131
1134
            raise errors.ObjectNotLocked(self)
1132
1135
 
1133
1136
        inv = self.inventory
1134
 
        if include_root is True:
 
1137
        if from_dir is None and include_root is True:
1135
1138
            yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1136
1139
        # Convert these into local objects to save lookup times
1137
1140
        pathjoin = osutils.pathjoin
1144
1147
        fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1145
1148
 
1146
1149
        # directory file_id, relative path, absolute path, reverse sorted children
1147
 
        children = os.listdir(self.basedir)
 
1150
        if from_dir is not None:
 
1151
            from_dir_id = inv.path2id(from_dir)
 
1152
            if from_dir_id is None:
 
1153
                # Directory not versioned
 
1154
                return
 
1155
            from_dir_abspath = pathjoin(self.basedir, from_dir)
 
1156
        else:
 
1157
            from_dir_id = inv.root.file_id
 
1158
            from_dir_abspath = self.basedir
 
1159
        children = os.listdir(from_dir_abspath)
1148
1160
        children.sort()
1149
1161
        # jam 20060527 The kernel sized tree seems equivalent whether we
1150
1162
        # use a deque and popleft to keep them sorted, or if we use a plain
1151
1163
        # list and just reverse() them.
1152
1164
        children = collections.deque(children)
1153
 
        stack = [(inv.root.file_id, u'', self.basedir, children)]
 
1165
        stack = [(from_dir_id, u'', from_dir_abspath, children)]
1154
1166
        while stack:
1155
1167
            from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1156
1168
 
1214
1226
                if fk != 'directory':
1215
1227
                    continue
1216
1228
 
1217
 
                # But do this child first
1218
 
                new_children = os.listdir(fap)
1219
 
                new_children.sort()
1220
 
                new_children = collections.deque(new_children)
1221
 
                stack.append((f_ie.file_id, fp, fap, new_children))
1222
 
                # Break out of inner loop,
1223
 
                # so that we start outer loop with child
1224
 
                break
 
1229
                # But do this child first if recursing down
 
1230
                if recursive:
 
1231
                    new_children = os.listdir(fap)
 
1232
                    new_children.sort()
 
1233
                    new_children = collections.deque(new_children)
 
1234
                    stack.append((f_ie.file_id, fp, fap, new_children))
 
1235
                    # Break out of inner loop,
 
1236
                    # so that we start outer loop with child
 
1237
                    break
1225
1238
            else:
1226
1239
                # if we finished all children, pop it off the stack
1227
1240
                stack.pop()
1405
1418
        inv = self.inventory
1406
1419
        for entry in moved:
1407
1420
            try:
1408
 
                self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
 
1421
                self._move_entry(WorkingTree._RenameEntry(
 
1422
                    entry.to_rel, entry.from_id,
1409
1423
                    entry.to_tail, entry.to_parent_id, entry.from_rel,
1410
1424
                    entry.from_tail, entry.from_parent_id,
1411
1425
                    entry.only_change_inv))
1562
1576
    @needs_write_lock
1563
1577
    def pull(self, source, overwrite=False, stop_revision=None,
1564
1578
             change_reporter=None, possible_transports=None, local=False):
1565
 
        top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
1579
        top_pb = ui.ui_factory.nested_progress_bar()
1566
1580
        source.lock_read()
1567
1581
        try:
1568
1582
            pp = ProgressPhase("Pull phase", 2, top_pb)
1576
1590
            if new_revision_info != old_revision_info:
1577
1591
                pp.next_phase()
1578
1592
                repository = self.branch.repository
1579
 
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
1593
                pb = ui.ui_factory.nested_progress_bar()
1580
1594
                basis_tree.lock_read()
1581
1595
                try:
1582
1596
                    new_basis_tree = self.branch.basis_tree()
2031
2045
            if filenames is None and len(self.get_parent_ids()) > 1:
2032
2046
                parent_trees = []
2033
2047
                last_revision = self.last_revision()
2034
 
                if last_revision != NULL_REVISION:
 
2048
                if last_revision != _mod_revision.NULL_REVISION:
2035
2049
                    if basis_tree is None:
2036
2050
                        basis_tree = self.basis_tree()
2037
2051
                        basis_tree.lock_read()
2075
2089
    def set_inventory(self, new_inventory_list):
2076
2090
        from bzrlib.inventory import (Inventory,
2077
2091
                                      InventoryDirectory,
2078
 
                                      InventoryEntry,
2079
2092
                                      InventoryFile,
2080
2093
                                      InventoryLink)
2081
2094
        inv = Inventory(self.get_root_id())
2623
2636
 
2624
2637
    def _change_last_revision(self, revision_id):
2625
2638
        """See WorkingTree._change_last_revision."""
2626
 
        if revision_id is None or revision_id == NULL_REVISION:
 
2639
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2627
2640
            try:
2628
2641
                self._transport.delete('last-revision')
2629
2642
            except errors.NoSuchFile:
2793
2806
        no working tree.  (See bug #43064).
2794
2807
        """
2795
2808
        sio = StringIO()
2796
 
        inv = Inventory()
 
2809
        inv = inventory.Inventory()
2797
2810
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2798
2811
        sio.seek(0)
2799
2812
        transport.put_file('inventory', sio, file_mode)
2815
2828
            branch.generate_revision_history(revision_id)
2816
2829
        finally:
2817
2830
            branch.unlock()
2818
 
        inv = Inventory()
 
2831
        inv = inventory.Inventory()
2819
2832
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2820
2833
                         branch,
2821
2834
                         inv,
2938
2951
            # only set an explicit root id if there is one to set.
2939
2952
            if basis_tree.inventory.root is not None:
2940
2953
                wt.set_root_id(basis_tree.get_root_id())
2941
 
            if revision_id == NULL_REVISION:
 
2954
            if revision_id == _mod_revision.NULL_REVISION:
2942
2955
                wt.set_parent_trees([])
2943
2956
            else:
2944
2957
                wt.set_parent_trees([(revision_id, basis_tree)])
2951
2964
        return wt
2952
2965
 
2953
2966
    def _initial_inventory(self):
2954
 
        return Inventory()
 
2967
        return inventory.Inventory()
2955
2968
 
2956
2969
    def __init__(self):
2957
2970
        super(WorkingTreeFormat3, self).__init__()