/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5697.1.1 by Jelmer Vernooij
Move WorkingTreeFormat2 to a separate file.
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 (
5777.5.2 by Jelmer Vernooij
Split inventory-specific methods and WorkingTree interface method
33
    InventoryWorkingTree,
5697.1.1 by Jelmer Vernooij
Move WorkingTreeFormat2 to a separate file.
34
    WorkingTreeFormat,
35
    )
36
37
38
def get_conflicted_stem(path):
39
    for suffix in _mod_conflicts.CONFLICT_SUFFIXES:
40
        if path.endswith(suffix):
41
            return path[:-len(suffix)]
42
43
44
class WorkingTreeFormat2(WorkingTreeFormat):
45
    """The second working tree format.
46
47
    This format modified the hash cache from the format 1 hash cache.
48
    """
49
50
    upgrade_recommended = True
51
52
    requires_normalized_unicode_filenames = True
53
54
    case_sensitive_filename = "Branch-FoRMaT"
55
56
    missing_parent_conflicts = False
57
58
    def get_format_description(self):
59
        """See WorkingTreeFormat.get_format_description()."""
60
        return "Working tree format 2"
61
62
    def _stub_initialize_on_transport(self, transport, file_mode):
63
        """Workaround: create control files for a remote working tree.
64
65
        This ensures that it can later be updated and dealt with locally,
66
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
67
        no working tree.  (See bug #43064).
68
        """
69
        sio = StringIO()
70
        inv = inventory.Inventory()
71
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
72
        sio.seek(0)
73
        transport.put_file('inventory', sio, file_mode)
74
        transport.put_bytes('pending-merges', '', file_mode)
75
76
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
77
                   accelerator_tree=None, hardlink=False):
78
        """See WorkingTreeFormat.initialize()."""
79
        if not isinstance(a_bzrdir.transport, LocalTransport):
80
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
81
        if from_branch is not None:
82
            branch = from_branch
83
        else:
84
            branch = a_bzrdir.open_branch()
85
        if revision_id is None:
86
            revision_id = _mod_revision.ensure_null(branch.last_revision())
87
        branch.lock_write()
88
        try:
89
            branch.generate_revision_history(revision_id)
90
        finally:
91
            branch.unlock()
92
        inv = inventory.Inventory()
93
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
94
                         branch,
95
                         inv,
96
                         _internal=True,
97
                         _format=self,
98
                         _bzrdir=a_bzrdir,
99
                         _control_files=branch.control_files)
100
        basis_tree = branch.repository.revision_tree(revision_id)
101
        if basis_tree.inventory.root is not None:
102
            wt.set_root_id(basis_tree.get_root_id())
103
        # set the parent list and cache the basis tree.
104
        if _mod_revision.is_null(revision_id):
105
            parent_trees = []
106
        else:
107
            parent_trees = [(revision_id, basis_tree)]
108
        wt.set_parent_trees(parent_trees)
109
        transform.build_tree(basis_tree, wt)
110
        return wt
111
112
    def __init__(self):
113
        super(WorkingTreeFormat2, self).__init__()
5582.12.6 by Jelmer Vernooij
merge bzr.dev.
114
        from bzrlib.plugins.weave_fmt.bzrdir import BzrDirFormat6
5697.1.1 by Jelmer Vernooij
Move WorkingTreeFormat2 to a separate file.
115
        self._matchingbzrdir = BzrDirFormat6()
116
117
    def open(self, a_bzrdir, _found=False):
118
        """Return the WorkingTree object for a_bzrdir
119
120
        _found is a private parameter, do not use it. It is used to indicate
121
               if format probing has already been done.
122
        """
123
        if not _found:
124
            # we are being called directly and must probe.
125
            raise NotImplementedError
126
        if not isinstance(a_bzrdir.transport, LocalTransport):
127
            raise errors.NotLocalUrl(a_bzrdir.transport.base)
128
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
129
                           _internal=True,
130
                           _format=self,
131
                           _bzrdir=a_bzrdir,
132
                           _control_files=a_bzrdir.open_branch().control_files)
133
        return wt
134
135
5777.5.2 by Jelmer Vernooij
Split inventory-specific methods and WorkingTree interface method
136
class WorkingTree2(InventoryWorkingTree):
5697.1.1 by Jelmer Vernooij
Move WorkingTreeFormat2 to a separate file.
137
    """This is the Format 2 working tree.
138
139
    This was the first weave based working tree.
140
     - uses os locks for locking.
141
     - uses the branch last-revision.
142
    """
143
144
    def __init__(self, *args, **kwargs):
145
        super(WorkingTree2, self).__init__(*args, **kwargs)
146
        # WorkingTree2 has more of a constraint that self._inventory must
147
        # exist. Because this is an older format, we don't mind the overhead
148
        # caused by the extra computation here.
149
150
        # Newer WorkingTree's should only have self._inventory set when they
151
        # have a read lock.
152
        if self._inventory is None:
153
            self.read_working_inventory()
154
155
    def _get_check_refs(self):
156
        """Return the references needed to perform a check of this tree."""
157
        return [('trees', self.last_revision())]
158
159
    def lock_tree_write(self):
160
        """See WorkingTree.lock_tree_write().
161
162
        In Format2 WorkingTrees we have a single lock for the branch and tree
163
        so lock_tree_write() degrades to lock_write().
164
165
        :return: An object with an unlock method which will release the lock
166
            obtained.
167
        """
168
        self.branch.lock_write()
169
        try:
170
            self._control_files.lock_write()
171
            return self
172
        except:
173
            self.branch.unlock()
174
            raise
175
176
    def unlock(self):
177
        # we share control files:
178
        if self._control_files._lock_count == 3:
5900.1.2 by Jelmer Vernooij
Fix weave plugin.
179
            # do non-implementation specific cleanup
180
            self._cleanup()
5697.1.1 by Jelmer Vernooij
Move WorkingTreeFormat2 to a separate file.
181
            # _inventory_is_modified is always False during a read lock.
182
            if self._inventory_is_modified:
183
                self.flush()
184
            self._write_hashcache_if_dirty()
185
186
        # reverse order of locking.
187
        try:
188
            return self._control_files.unlock()
189
        finally:
190
            self.branch.unlock()
191
192
    def _iter_conflicts(self):
193
        conflicted = set()
194
        for info in self.list_files():
195
            path = info[0]
196
            stem = get_conflicted_stem(path)
197
            if stem is None:
198
                continue
199
            if stem not in conflicted:
200
                conflicted.add(stem)
201
                yield stem
202
203
    @needs_read_lock
204
    def conflicts(self):
205
        conflicts = _mod_conflicts.ConflictList()
206
        for conflicted in self._iter_conflicts():
207
            text = True
208
            try:
209
                if osutils.file_kind(self.abspath(conflicted)) != "file":
210
                    text = False
211
            except errors.NoSuchFile:
212
                text = False
213
            if text is True:
214
                for suffix in ('.THIS', '.OTHER'):
215
                    try:
216
                        kind = osutils.file_kind(self.abspath(conflicted+suffix))
217
                        if kind != "file":
218
                            text = False
219
                    except errors.NoSuchFile:
220
                        text = False
221
                    if text == False:
222
                        break
223
            ctype = {True: 'text conflict', False: 'contents conflict'}[text]
224
            conflicts.append(_mod_conflicts.Conflict.factory(ctype,
225
                             path=conflicted,
226
                             file_id=self.path2id(conflicted)))
227
        return conflicts
228
5816.5.5 by Jelmer Vernooij
Fix conflict handling for wt2.
229
    def set_conflicts(self, arg):
230
        raise errors.UnsupportedOperation(self.set_conflicts, self)
5697.1.1 by Jelmer Vernooij
Move WorkingTreeFormat2 to a separate file.
231
5816.5.5 by Jelmer Vernooij
Fix conflict handling for wt2.
232
    def add_conflicts(self, arg):
233
        raise errors.UnsupportedOperation(self.add_conflicts, self)