~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

(jameinel) Handle [:digit:] globbing tests better for python2.7 (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
import re
36
36
import tarfile
37
37
 
38
 
import bzrlib
39
38
from bzrlib import (
40
39
    chk_map,
41
40
    errors,
42
41
    generate_ids,
43
42
    osutils,
44
 
    symbol_versioning,
45
43
    )
46
44
""")
47
45
 
49
47
    BzrCheckError,
50
48
    BzrError,
51
49
    )
52
 
from bzrlib.symbol_versioning import deprecated_in, deprecated_method
53
50
from bzrlib.trace import mutter
54
51
from bzrlib.static_tuple import StaticTuple
55
52
 
131
128
    RENAMED = 'renamed'
132
129
    MODIFIED_AND_RENAMED = 'modified and renamed'
133
130
 
134
 
    __slots__ = []
 
131
    __slots__ = ['file_id', 'revision', 'parent_id', 'name']
 
132
 
 
133
    # Attributes that all InventoryEntry instances are expected to have, but
 
134
    # that don't vary for all kinds of entry.  (e.g. symlink_target is only
 
135
    # relevant to InventoryLink, so there's no reason to make every
 
136
    # InventoryFile instance allocate space to hold a value for it.)
 
137
    # Attributes that only vary for files: executable, text_sha1, text_size,
 
138
    # text_id
 
139
    executable = False
 
140
    text_sha1 = None
 
141
    text_size = None
 
142
    text_id = None
 
143
    # Attributes that only vary for symlinks: symlink_target
 
144
    symlink_target = None
 
145
    # Attributes that only vary for tree-references: reference_revision
 
146
    reference_revision = None
 
147
 
135
148
 
136
149
    def detect_changes(self, old_entry):
137
150
        """Return a (text_modified, meta_modified) from this to old_entry.
176
189
                    candidates[ie.revision] = ie
177
190
        return candidates
178
191
 
179
 
    @deprecated_method(deprecated_in((1, 6, 0)))
180
 
    def get_tar_item(self, root, dp, now, tree):
181
 
        """Get a tarfile item and a file stream for its content."""
182
 
        item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
183
 
        # TODO: would be cool to actually set it to the timestamp of the
184
 
        # revision it was last changed
185
 
        item.mtime = now
186
 
        fileobj = self._put_in_tar(item, tree)
187
 
        return item, fileobj
188
 
 
189
192
    def has_text(self):
190
193
        """Return true if the object this entry represents has textual data.
191
194
 
197
200
        """
198
201
        return False
199
202
 
200
 
    def __init__(self, file_id, name, parent_id, text_id=None):
 
203
    def __init__(self, file_id, name, parent_id):
201
204
        """Create an InventoryEntry
202
205
 
203
206
        The filename must be a single component, relative to the
214
217
        """
215
218
        if '/' in name or '\\' in name:
216
219
            raise errors.InvalidEntryName(name=name)
217
 
        self.executable = False
 
220
        self.file_id = file_id
218
221
        self.revision = None
219
 
        self.text_sha1 = None
220
 
        self.text_size = None
221
 
        self.file_id = file_id
222
222
        self.name = name
223
 
        self.text_id = text_id
224
223
        self.parent_id = parent_id
225
 
        self.symlink_target = None
226
 
        self.reference_revision = None
227
224
 
228
225
    def kind_character(self):
229
226
        """Return a short kind indicator useful for appending to names."""
239
236
        raise BzrError("don't know how to export {%s} of kind %r" %
240
237
                       (self.file_id, self.kind))
241
238
 
242
 
    @deprecated_method(deprecated_in((1, 6, 0)))
243
 
    def put_on_disk(self, dest, dp, tree):
244
 
        """Create a representation of self on disk in the prefix dest.
245
 
 
246
 
        This is a template method - implement _put_on_disk in subclasses.
247
 
        """
248
 
        fullpath = osutils.pathjoin(dest, dp)
249
 
        self._put_on_disk(fullpath, tree)
250
 
        # mutter("  export {%s} kind %s to %s", self.file_id,
251
 
        #         self.kind, fullpath)
252
 
 
253
239
    def _put_on_disk(self, fullpath, tree):
254
240
        """Put this entry onto disk at fullpath, from tree tree."""
255
241
        raise BzrError("don't know how to export {%s} of kind %r" % (self.file_id, self.kind))
397
383
        pass
398
384
 
399
385
 
400
 
class RootEntry(InventoryEntry):
401
 
 
402
 
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
403
 
                 'text_id', 'parent_id', 'children', 'executable',
404
 
                 'revision', 'symlink_target', 'reference_revision']
405
 
 
406
 
    def _check(self, checker, rev_id):
407
 
        """See InventoryEntry._check"""
408
 
 
409
 
    def __init__(self, file_id):
410
 
        self.file_id = file_id
411
 
        self.children = {}
412
 
        self.kind = 'directory'
413
 
        self.parent_id = None
414
 
        self.name = u''
415
 
        self.revision = None
416
 
        symbol_versioning.warn('RootEntry is deprecated as of bzr 0.10.'
417
 
                               '  Please use InventoryDirectory instead.',
418
 
                               DeprecationWarning, stacklevel=2)
419
 
 
420
 
    def __eq__(self, other):
421
 
        if not isinstance(other, RootEntry):
422
 
            return NotImplemented
423
 
 
424
 
        return (self.file_id == other.file_id) \
425
 
               and (self.children == other.children)
426
 
 
427
 
 
428
386
class InventoryDirectory(InventoryEntry):
429
387
    """A directory in an inventory."""
430
388
 
431
 
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
432
 
                 'text_id', 'parent_id', 'children', 'executable',
433
 
                 'revision', 'symlink_target', 'reference_revision']
 
389
    __slots__ = ['children']
 
390
 
 
391
    kind = 'directory'
434
392
 
435
393
    def _check(self, checker, rev_id):
436
394
        """See InventoryEntry._check"""
437
 
        if (self.text_sha1 is not None or self.text_size is not None or
438
 
            self.text_id is not None):
439
 
            checker._report_items.append('directory {%s} has text in revision {%s}'
440
 
                                % (self.file_id, rev_id))
441
395
        # In non rich root repositories we do not expect a file graph for the
442
396
        # root.
443
397
        if self.name == '' and not checker.rich_roots:
459
413
    def __init__(self, file_id, name, parent_id):
460
414
        super(InventoryDirectory, self).__init__(file_id, name, parent_id)
461
415
        self.children = {}
462
 
        self.kind = 'directory'
463
416
 
464
417
    def kind_character(self):
465
418
        """See InventoryEntry.kind_character."""
482
435
class InventoryFile(InventoryEntry):
483
436
    """A file in an inventory."""
484
437
 
485
 
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
486
 
                 'text_id', 'parent_id', 'children', 'executable',
487
 
                 'revision', 'symlink_target', 'reference_revision']
 
438
    __slots__ = ['text_sha1', 'text_size', 'text_id', 'executable']
 
439
 
 
440
    kind = 'file'
 
441
 
 
442
    def __init__(self, file_id, name, parent_id):
 
443
        super(InventoryFile, self).__init__(file_id, name, parent_id)
 
444
        self.text_sha1 = None
 
445
        self.text_size = None
 
446
        self.text_id = None
 
447
        self.executable = False
488
448
 
489
449
    def _check(self, checker, tree_revision_id):
490
450
        """See InventoryEntry._check"""
533
493
        """See InventoryEntry.has_text."""
534
494
        return True
535
495
 
536
 
    def __init__(self, file_id, name, parent_id):
537
 
        super(InventoryFile, self).__init__(file_id, name, parent_id)
538
 
        self.kind = 'file'
539
 
 
540
496
    def kind_character(self):
541
497
        """See InventoryEntry.kind_character."""
542
498
        return ''
595
551
class InventoryLink(InventoryEntry):
596
552
    """A file in an inventory."""
597
553
 
598
 
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
599
 
                 'text_id', 'parent_id', 'children', 'executable',
600
 
                 'revision', 'symlink_target', 'reference_revision']
 
554
    __slots__ = ['symlink_target']
 
555
 
 
556
    kind = 'symlink'
 
557
 
 
558
    def __init__(self, file_id, name, parent_id):
 
559
        super(InventoryLink, self).__init__(file_id, name, parent_id)
 
560
        self.symlink_target = None
601
561
 
602
562
    def _check(self, checker, tree_revision_id):
603
563
        """See InventoryEntry._check"""
604
 
        if self.text_sha1 is not None or self.text_size is not None or self.text_id is not None:
605
 
            checker._report_items.append(
606
 
               'symlink {%s} has text in revision {%s}'
607
 
                    % (self.file_id, tree_revision_id))
608
564
        if self.symlink_target is None:
609
565
            checker._report_items.append(
610
566
                'symlink {%s} has no target in revision {%s}'
648
604
        differ = DiffSymlink(old_tree, new_tree, output_to)
649
605
        return differ.diff_symlink(old_target, new_target)
650
606
 
651
 
    def __init__(self, file_id, name, parent_id):
652
 
        super(InventoryLink, self).__init__(file_id, name, parent_id)
653
 
        self.kind = 'symlink'
654
 
 
655
607
    def kind_character(self):
656
608
        """See InventoryEntry.kind_character."""
657
609
        return ''
689
641
 
690
642
class TreeReference(InventoryEntry):
691
643
 
 
644
    __slots__ = ['reference_revision']
 
645
 
692
646
    kind = 'tree-reference'
693
647
 
694
648
    def __init__(self, file_id, name, parent_id, revision=None,
1652
1606
            # parent_to_children with at least the tree root.)
1653
1607
            return other
1654
1608
        cache = self._fileid_to_entry_cache
1655
 
        try:
1656
 
            remaining_children = collections.deque(parent_to_children[self.root_id])
1657
 
        except:
1658
 
            import pdb; pdb.set_trace()
1659
 
            raise
 
1609
        remaining_children = collections.deque(parent_to_children[self.root_id])
1660
1610
        while remaining_children:
1661
1611
            file_id = remaining_children.popleft()
1662
1612
            ie = cache[file_id]
2245
2195
class CHKInventoryDirectory(InventoryDirectory):
2246
2196
    """A directory in an inventory."""
2247
2197
 
2248
 
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
2249
 
                 'text_id', 'parent_id', '_children', 'executable',
2250
 
                 'revision', 'symlink_target', 'reference_revision',
2251
 
                 '_chk_inventory']
 
2198
    __slots__ = ['_children', '_chk_inventory']
2252
2199
 
2253
2200
    def __init__(self, file_id, name, parent_id, chk_inventory):
2254
2201
        # Don't call InventoryDirectory.__init__ - it isn't right for this
2255
2202
        # class.
2256
2203
        InventoryEntry.__init__(self, file_id, name, parent_id)
2257
2204
        self._children = None
2258
 
        self.kind = 'directory'
2259
2205
        self._chk_inventory = chk_inventory
2260
2206
 
2261
2207
    @property