/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/transform.py

Got conflict handling working when conflicts involve existing files

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import os
2
 
from bzrlib.errors import DuplicateKey, MalformedTransform, NoSuchFile
 
2
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
 
3
                           ReusingTransform)
3
4
from bzrlib.osutils import file_kind, supports_executable
4
5
from bzrlib.inventory import InventoryEntry
 
6
from bzrlib import BZRDIR
5
7
import errno
6
8
 
7
9
ROOT_PARENT = "root-parent"
30
32
        self._tree_path_ids = {}
31
33
        self._tree_id_paths = {}
32
34
        self._new_root = self.get_id_tree(tree.get_root_id())
 
35
        self.__done = False
33
36
 
34
37
    def finalize(self):
35
38
        if self._tree is None:
184
187
        except KeyError:
185
188
            return self.get_tree_parent(trans_id)
186
189
 
187
 
    def find_conflicts(self):
188
 
        """Find any violations of inventory of filesystem invariants"""
 
190
    def final_name(self, trans_id):
 
191
        try:
 
192
            return self._new_name[trans_id]
 
193
        except KeyError:
 
194
            return os.path.basename(self._tree_id_paths[trans_id])
 
195
 
 
196
    def _by_parent(self):
189
197
        by_parent = {}
190
 
        conflicts = []
191
 
        for trans_id, parent_id in self._new_parent.iteritems():
 
198
        items = list(self._new_parent.iteritems())
 
199
        items.extend((t, self.final_parent(t)) for t in self._tree_id_paths)
 
200
        for trans_id, parent_id in items:
192
201
            if parent_id not in by_parent:
193
202
                by_parent[parent_id] = set()
194
203
            by_parent[parent_id].add(trans_id)
 
204
        return by_parent
195
205
 
 
206
    def find_conflicts(self):
 
207
        """Find any violations of inventory of filesystem invariants"""
 
208
        if self.__done is True:
 
209
            raise ReusingTransform()
 
210
        conflicts = []
 
211
        # ensure all children of all existent parents are known
 
212
        # all children of non-existent parents are known, by definition.
 
213
        self._add_tree_children()
 
214
        by_parent = self._by_parent()
196
215
        conflicts.extend(self._unversioned_parents(by_parent))
197
216
        conflicts.extend(self._parent_loops())
198
217
        conflicts.extend(self._duplicate_entries(by_parent))
201
220
        conflicts.extend(self._executability_conflicts())
202
221
        return conflicts
203
222
 
 
223
    def _add_tree_children(self):
 
224
        parents = self._by_parent()
 
225
        for parent_id in parents:
 
226
            try:
 
227
                path = self._tree_id_paths[parent_id]
 
228
            except KeyError:
 
229
                continue
 
230
            try:
 
231
                children = os.listdir(self._tree.abspath(path))
 
232
            except OSError, e:
 
233
                if e.errno != errno.ENOENT:
 
234
                    raise
 
235
                continue
 
236
                
 
237
            for child in children:
 
238
                childpath = joinpath(path, child)
 
239
                if childpath == BZRDIR:
 
240
                    continue
 
241
                self.get_tree_path_id(childpath)
 
242
 
204
243
    def _parent_loops(self):
205
244
        """No entry should be its own ancestor"""
206
245
        conflicts = []
220
259
        """If parent directories are versioned, children must be versioned."""
221
260
        conflicts = []
222
261
        for parent_id, children in by_parent.iteritems():
 
262
            if parent_id is ROOT_PARENT:
 
263
                continue
223
264
            if self.final_file_id(parent_id) is not None:
224
265
                continue
225
266
            for child_id in children:
258
299
        """No directory may have two entries with the same name."""
259
300
        conflicts = []
260
301
        for children in by_parent.itervalues():
261
 
            name_ids = [(self._new_name[t], t) for t in children]
 
302
            name_ids = [(self.final_name(t), t) for t in children]
262
303
            name_ids.sort()
263
304
            last_name = None
264
305
            last_trans_id = None
265
306
            for name, trans_id in name_ids:
266
307
                if name == last_name:
267
 
                    conflicts.append(('duplicate', last_trans_id, trans_id))
 
308
                    conflicts.append(('duplicate', last_trans_id, trans_id,
 
309
                    name))
268
310
                last_name = name
269
311
                last_trans_id = trans_id
270
312
        return conflicts
273
315
        """parents must have directory 'contents'."""
274
316
        conflicts = []
275
317
        for parent_id in by_parent.iterkeys():
 
318
            if parent_id is ROOT_PARENT:
 
319
                continue
276
320
            try:
277
321
                kind = self.final_kind(parent_id)
278
322
            except NoSuchFile:
319
363
                self._set_executability(path, inv, trans_id)
320
364
 
321
365
        self._tree._write_inventory(inv)
 
366
        self.__done = True
322
367
 
323
368
    def _set_executability(self, path, inv, trans_id):
324
369
        file_id = inv.path2id(path)
390
435
        self.create_symlink(target, trans_id)
391
436
        return trans_id
392
437
 
 
438
def joinpath(parent, child):
 
439
    if parent is None or parent == "":
 
440
        return child
 
441
    else:
 
442
        return os.path.join(parent, child)
393
443
 
394
444
class FinalPaths(object):
395
445
    """\
408
458
    def _determine_path(self, trans_id):
409
459
        if trans_id == self.root:
410
460
            return ""
411
 
        name = self._new_name[trans_id]
 
461
        name = self.tree.final_name(trans_id)
412
462
        parent_id = self.tree.final_parent(trans_id)
413
463
        if parent_id == self.root:
414
464
            return name