/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/plugins/weave_fmt/workingtree.py

Merge bzr.dev, update to use new hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005-2010 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Weave-era working tree objects."""
 
18
 
 
19
from cStringIO import StringIO
 
20
 
 
21
from bzrlib import (
 
22
    conflicts as _mod_conflicts,
 
23
    errors,
 
24
    inventory,
 
25
    osutils,
 
26
    revision as _mod_revision,
 
27
    transform,
 
28
    xml5,
 
29
    )
 
30
from bzrlib.decorators import needs_read_lock
 
31
from bzrlib.transport.local import LocalTransport
 
32
from bzrlib.workingtree import (
 
33
    WorkingTreeFormat,
 
34
    )
 
35
from bzrlib.workingtree_3 import (
 
36
    PreDirStateWorkingTree,
 
37
    )
 
38
 
 
39
 
 
40
def get_conflicted_stem(path):
 
41
    for suffix in _mod_conflicts.CONFLICT_SUFFIXES:
 
42
        if path.endswith(suffix):
 
43
            return path[:-len(suffix)]
 
44
 
 
45
 
 
46
class WorkingTreeFormat2(WorkingTreeFormat):
 
47
    """The second working tree format.
 
48
 
 
49
    This format modified the hash cache from the format 1 hash cache.
 
50
    """
 
51
 
 
52
    upgrade_recommended = True
 
53
 
 
54
    requires_normalized_unicode_filenames = True
 
55
 
 
56
    case_sensitive_filename = "Branch-FoRMaT"
 
57
 
 
58
    missing_parent_conflicts = False
 
59
 
 
60
    supports_versioned_directories = True
 
61
 
 
62
    def get_format_description(self):
 
63
        """See WorkingTreeFormat.get_format_description()."""
 
64
        return "Working tree format 2"
 
65
 
 
66
    def _stub_initialize_on_transport(self, transport, file_mode):
 
67
        """Workaround: create control files for a remote working tree.
 
68
 
 
69
        This ensures that it can later be updated and dealt with locally,
 
70
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
 
71
        no working tree.  (See bug #43064).
 
72
        """
 
73
        sio = StringIO()
 
74
        inv = inventory.Inventory()
 
75
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
 
76
        sio.seek(0)
 
77
        transport.put_file('inventory', sio, file_mode)
 
78
        transport.put_bytes('pending-merges', '', file_mode)
 
79
 
 
80
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
81
                   accelerator_tree=None, hardlink=False):
 
82
        """See WorkingTreeFormat.initialize()."""
 
83
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
84
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
85
        if from_branch is not None:
 
86
            branch = from_branch
 
87
        else:
 
88
            branch = a_bzrdir.open_branch()
 
89
        if revision_id is None:
 
90
            revision_id = _mod_revision.ensure_null(branch.last_revision())
 
91
        branch.lock_write()
 
92
        try:
 
93
            branch.generate_revision_history(revision_id)
 
94
        finally:
 
95
            branch.unlock()
 
96
        inv = inventory.Inventory()
 
97
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
 
98
                         branch,
 
99
                         inv,
 
100
                         _internal=True,
 
101
                         _format=self,
 
102
                         _bzrdir=a_bzrdir,
 
103
                         _control_files=branch.control_files)
 
104
        basis_tree = branch.repository.revision_tree(revision_id)
 
105
        if basis_tree.inventory.root is not None:
 
106
            wt.set_root_id(basis_tree.get_root_id())
 
107
        # set the parent list and cache the basis tree.
 
108
        if _mod_revision.is_null(revision_id):
 
109
            parent_trees = []
 
110
        else:
 
111
            parent_trees = [(revision_id, basis_tree)]
 
112
        wt.set_parent_trees(parent_trees)
 
113
        transform.build_tree(basis_tree, wt)
 
114
        return wt
 
115
 
 
116
    def __init__(self):
 
117
        super(WorkingTreeFormat2, self).__init__()
 
118
        from bzrlib.plugins.weave_fmt.bzrdir import BzrDirFormat6
 
119
        self._matchingbzrdir = BzrDirFormat6()
 
120
 
 
121
    def open(self, a_bzrdir, _found=False):
 
122
        """Return the WorkingTree object for a_bzrdir
 
123
 
 
124
        _found is a private parameter, do not use it. It is used to indicate
 
125
               if format probing has already been done.
 
126
        """
 
127
        if not _found:
 
128
            # we are being called directly and must probe.
 
129
            raise NotImplementedError
 
130
        if not isinstance(a_bzrdir.transport, LocalTransport):
 
131
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
 
132
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
 
133
                           _internal=True,
 
134
                           _format=self,
 
135
                           _bzrdir=a_bzrdir,
 
136
                           _control_files=a_bzrdir.open_branch().control_files)
 
137
        return wt
 
138
 
 
139
 
 
140
class WorkingTree2(PreDirStateWorkingTree):
 
141
    """This is the Format 2 working tree.
 
142
 
 
143
    This was the first weave based working tree.
 
144
     - uses os locks for locking.
 
145
     - uses the branch last-revision.
 
146
    """
 
147
 
 
148
    def __init__(self, basedir, *args, **kwargs):
 
149
        super(WorkingTree2, self).__init__(basedir, *args, **kwargs)
 
150
        # WorkingTree2 has more of a constraint that self._inventory must
 
151
        # exist. Because this is an older format, we don't mind the overhead
 
152
        # caused by the extra computation here.
 
153
 
 
154
        # Newer WorkingTree's should only have self._inventory set when they
 
155
        # have a read lock.
 
156
        if self._inventory is None:
 
157
            self.read_working_inventory()
 
158
 
 
159
    def _get_check_refs(self):
 
160
        """Return the references needed to perform a check of this tree."""
 
161
        return [('trees', self.last_revision())]
 
162
 
 
163
 
 
164
    def lock_tree_write(self):
 
165
        """See WorkingTree.lock_tree_write().
 
166
 
 
167
        In Format2 WorkingTrees we have a single lock for the branch and tree
 
168
        so lock_tree_write() degrades to lock_write().
 
169
 
 
170
        :return: An object with an unlock method which will release the lock
 
171
            obtained.
 
172
        """
 
173
        self.branch.lock_write()
 
174
        try:
 
175
            self._control_files.lock_write()
 
176
            return self
 
177
        except:
 
178
            self.branch.unlock()
 
179
            raise
 
180
 
 
181
    def unlock(self):
 
182
        # we share control files:
 
183
        if self._control_files._lock_count == 3:
 
184
            # do non-implementation specific cleanup
 
185
            self._cleanup()
 
186
            # _inventory_is_modified is always False during a read lock.
 
187
            if self._inventory_is_modified:
 
188
                self.flush()
 
189
            self._write_hashcache_if_dirty()
 
190
 
 
191
        # reverse order of locking.
 
192
        try:
 
193
            return self._control_files.unlock()
 
194
        finally:
 
195
            self.branch.unlock()
 
196
 
 
197
    def _iter_conflicts(self):
 
198
        conflicted = set()
 
199
        for info in self.list_files():
 
200
            path = info[0]
 
201
            stem = get_conflicted_stem(path)
 
202
            if stem is None:
 
203
                continue
 
204
            if stem not in conflicted:
 
205
                conflicted.add(stem)
 
206
                yield stem
 
207
 
 
208
    @needs_read_lock
 
209
    def conflicts(self):
 
210
        conflicts = _mod_conflicts.ConflictList()
 
211
        for conflicted in self._iter_conflicts():
 
212
            text = True
 
213
            try:
 
214
                if osutils.file_kind(self.abspath(conflicted)) != "file":
 
215
                    text = False
 
216
            except errors.NoSuchFile:
 
217
                text = False
 
218
            if text is True:
 
219
                for suffix in ('.THIS', '.OTHER'):
 
220
                    try:
 
221
                        kind = osutils.file_kind(self.abspath(conflicted+suffix))
 
222
                        if kind != "file":
 
223
                            text = False
 
224
                    except errors.NoSuchFile:
 
225
                        text = False
 
226
                    if text == False:
 
227
                        break
 
228
            ctype = {True: 'text conflict', False: 'contents conflict'}[text]
 
229
            conflicts.append(_mod_conflicts.Conflict.factory(ctype,
 
230
                             path=conflicted,
 
231
                             file_id=self.path2id(conflicted)))
 
232
        return conflicts
 
233
 
 
234
    def set_conflicts(self, arg):
 
235
        raise errors.UnsupportedOperation(self.set_conflicts, self)
 
236
 
 
237
    def add_conflicts(self, arg):
 
238
        raise errors.UnsupportedOperation(self.add_conflicts, self)