~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Martin Pool
  • Date: 2005-09-06 07:39:09 UTC
  • Revision ID: mbp@sourcefrog.net-20050906073909-234eb078dfff15d9
- improved check for branch version

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
from bzrlib.osutils import uuid, quotefn, splitpath, joinpath, appendpath
29
29
from bzrlib.trace import mutter
 
30
from bzrlib.errors import NotVersionedError
 
31
        
30
32
 
31
33
class InventoryEntry(object):
32
34
    """Description of a versioned file.
53
55
    >>> i.path2id('')
54
56
    'TREE_ROOT'
55
57
    >>> i.add(InventoryEntry('123', 'src', 'directory', ROOT_ID))
 
58
    InventoryEntry('123', 'src', kind='directory', parent_id='TREE_ROOT')
56
59
    >>> i.add(InventoryEntry('2323', 'hello.c', 'file', parent_id='123'))
 
60
    InventoryEntry('2323', 'hello.c', kind='file', parent_id='123')
57
61
    >>> for j in i.iter_entries():
58
62
    ...   print j
59
63
    ... 
64
68
    ...
65
69
    BzrError: inventory already contains entry with id {2323}
66
70
    >>> i.add(InventoryEntry('2324', 'bye.c', 'file', '123'))
 
71
    InventoryEntry('2324', 'bye.c', kind='file', parent_id='123')
67
72
    >>> i.add(InventoryEntry('2325', 'wibble', 'directory', '123'))
 
73
    InventoryEntry('2325', 'wibble', kind='directory', parent_id='123')
68
74
    >>> i.path2id('src/wibble')
69
75
    '2325'
70
76
    >>> '2325' in i
71
77
    True
72
78
    >>> i.add(InventoryEntry('2326', 'wibble.c', 'file', '2325'))
 
79
    InventoryEntry('2326', 'wibble.c', kind='file', parent_id='2325')
73
80
    >>> i['2326']
74
81
    InventoryEntry('2326', 'wibble.c', kind='file', parent_id='2325')
75
82
    >>> for j in i.iter_entries():
93
100
    # directories, etc etc.
94
101
 
95
102
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
96
 
                 'text_id', 'parent_id', 'children', ]
 
103
                 'text_id', 'parent_id', 'children',
 
104
                 'text_version', 'entry_version', ]
 
105
 
97
106
 
98
107
    def __init__(self, file_id, name, kind, parent_id, text_id=None):
99
108
        """Create an InventoryEntry
110
119
        Traceback (most recent call last):
111
120
        BzrCheckError: InventoryEntry name 'src/hello.c' is invalid
112
121
        """
 
122
        assert isinstance(name, basestring), name
113
123
        if '/' in name or '\\' in name:
114
124
            raise BzrCheckError('InventoryEntry name %r is invalid' % name)
115
125
        
 
126
        self.text_version = None
 
127
        self.entry_version = None
116
128
        self.text_sha1 = None
117
129
        self.text_size = None
118
 
    
119
130
        self.file_id = file_id
120
131
        self.name = name
121
132
        self.kind = kind
155
166
                   self.parent_id))
156
167
 
157
168
    
158
 
    def to_element(self):
159
 
        """Convert to XML element"""
160
 
        from bzrlib.xml import Element
161
 
        
162
 
        e = Element('entry')
163
 
 
164
 
        e.set('name', self.name)
165
 
        e.set('file_id', self.file_id)
166
 
        e.set('kind', self.kind)
167
 
 
168
 
        if self.text_size != None:
169
 
            e.set('text_size', '%d' % self.text_size)
170
 
            
171
 
        for f in ['text_id', 'text_sha1']:
172
 
            v = getattr(self, f)
173
 
            if v != None:
174
 
                e.set(f, v)
175
 
 
176
 
        # to be conservative, we don't externalize the root pointers
177
 
        # for now, leaving them as null in the xml form.  in a future
178
 
        # version it will be implied by nested elements.
179
 
        if self.parent_id != ROOT_ID:
180
 
            assert isinstance(self.parent_id, basestring)
181
 
            e.set('parent_id', self.parent_id)
182
 
 
183
 
        e.tail = '\n'
184
 
            
185
 
        return e
186
 
 
187
 
 
188
 
    def from_element(cls, elt):
189
 
        assert elt.tag == 'entry'
190
 
 
191
 
        ## original format inventories don't have a parent_id for
192
 
        ## nodes in the root directory, but it's cleaner to use one
193
 
        ## internally.
194
 
        parent_id = elt.get('parent_id')
195
 
        if parent_id == None:
196
 
            parent_id = ROOT_ID
197
 
 
198
 
        self = cls(elt.get('file_id'), elt.get('name'), elt.get('kind'), parent_id)
199
 
        self.text_id = elt.get('text_id')
200
 
        self.text_sha1 = elt.get('text_sha1')
201
 
        
202
 
        ## mutter("read inventoryentry: %r" % (elt.attrib))
203
 
 
204
 
        v = elt.get('text_size')
205
 
        self.text_size = v and int(v)
206
 
 
207
 
        return self
208
 
            
209
 
 
210
 
    from_element = classmethod(from_element)
211
 
 
212
169
    def __eq__(self, other):
213
170
        if not isinstance(other, InventoryEntry):
214
171
            return NotImplemented
219
176
               and (self.text_size == other.text_size) \
220
177
               and (self.text_id == other.text_id) \
221
178
               and (self.parent_id == other.parent_id) \
222
 
               and (self.kind == other.kind)
 
179
               and (self.kind == other.kind) \
 
180
               and (self.text_version == other.text_version) \
 
181
               and (self.entry_version == other.entry_version)
223
182
 
224
183
 
225
184
    def __ne__(self, other):
266
225
 
267
226
    >>> inv = Inventory()
268
227
    >>> inv.add(InventoryEntry('123-123', 'hello.c', 'file', ROOT_ID))
 
228
    InventoryEntry('123-123', 'hello.c', kind='file', parent_id='TREE_ROOT')
269
229
    >>> inv['123-123'].name
270
230
    'hello.c'
271
231
 
282
242
    ['hello.c']
283
243
    >>> inv = Inventory('TREE_ROOT-12345678-12345678')
284
244
    >>> inv.add(InventoryEntry('123-123', 'hello.c', 'file', ROOT_ID))
 
245
    InventoryEntry('123-123', 'hello.c', kind='file', parent_id='TREE_ROOT-12345678-12345678')
285
246
    """
286
247
    def __init__(self, root_id=ROOT_ID):
287
248
        """Create or read an inventory.
369
330
 
370
331
        >>> inv = Inventory()
371
332
        >>> inv.add(InventoryEntry('123', 'foo.c', 'file', ROOT_ID))
 
333
        InventoryEntry('123', 'foo.c', kind='file', parent_id='TREE_ROOT')
372
334
        >>> '123' in inv
373
335
        True
374
336
        >>> '456' in inv
382
344
 
383
345
        >>> inv = Inventory()
384
346
        >>> inv.add(InventoryEntry('123123', 'hello.c', 'file', ROOT_ID))
 
347
        InventoryEntry('123123', 'hello.c', kind='file', parent_id='TREE_ROOT')
385
348
        >>> inv['123123'].name
386
349
        'hello.c'
387
350
        """
405
368
        """Add entry to inventory.
406
369
 
407
370
        To add  a file to a branch ready to be committed, use Branch.add,
408
 
        which calls this."""
 
371
        which calls this.
 
372
 
 
373
        Returns the new entry object.
 
374
        """
409
375
        if entry.file_id in self._byid:
410
376
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
411
377
 
423
389
 
424
390
        self._byid[entry.file_id] = entry
425
391
        parent.children[entry.name] = entry
 
392
        return entry
426
393
 
427
394
 
428
395
    def add_path(self, relpath, kind, file_id=None):
429
396
        """Add entry from a path.
430
397
 
431
 
        The immediate parent must already be versioned"""
432
 
        from bzrlib.errors import NotVersionedError
 
398
        The immediate parent must already be versioned.
 
399
 
 
400
        Returns the new entry object."""
 
401
        from bzrlib.branch import gen_file_id
433
402
        
434
403
        parts = bzrlib.osutils.splitpath(relpath)
435
404
        if len(parts) == 0:
436
405
            raise BzrError("cannot re-add root of inventory")
437
406
 
438
407
        if file_id == None:
439
 
            from bzrlib.branch import gen_file_id
440
408
            file_id = gen_file_id(relpath)
441
409
 
442
410
        parent_path = parts[:-1]
454
422
 
455
423
        >>> inv = Inventory()
456
424
        >>> inv.add(InventoryEntry('123', 'foo.c', 'file', ROOT_ID))
 
425
        InventoryEntry('123', 'foo.c', kind='file', parent_id='TREE_ROOT')
457
426
        >>> '123' in inv
458
427
        True
459
428
        >>> del inv['123']
475
444
        del self[ie.parent_id].children[ie.name]
476
445
 
477
446
 
478
 
    def to_element(self):
479
 
        """Convert to XML Element"""
480
 
        from bzrlib.xml import Element
481
 
        
482
 
        e = Element('inventory')
483
 
        e.text = '\n'
484
 
        if self.root.file_id not in (None, ROOT_ID):
485
 
            e.set('file_id', self.root.file_id)
486
 
        for path, ie in self.iter_entries():
487
 
            e.append(ie.to_element())
488
 
        return e
489
 
    
490
 
 
491
 
    def from_element(cls, elt):
492
 
        """Construct from XML Element
493
 
        
494
 
        >>> inv = Inventory()
495
 
        >>> inv.add(InventoryEntry('foo.c-123981239', 'foo.c', 'file', ROOT_ID))
496
 
        >>> elt = inv.to_element()
497
 
        >>> inv2 = Inventory.from_element(elt)
498
 
        >>> inv2 == inv
499
 
        True
500
 
        """
501
 
        # XXXX: doctest doesn't run this properly under python2.3
502
 
        assert elt.tag == 'inventory'
503
 
        root_id = elt.get('file_id') or ROOT_ID
504
 
        o = cls(root_id)
505
 
        for e in elt:
506
 
            ie = InventoryEntry.from_element(e)
507
 
            if ie.parent_id == ROOT_ID:
508
 
                ie.parent_id = root_id
509
 
            o.add(ie)
510
 
        return o
511
 
        
512
 
    from_element = classmethod(from_element)
513
 
 
514
 
 
515
447
    def __eq__(self, other):
516
448
        """Compare two sets by comparing their contents.
517
449
 
520
452
        >>> i1 == i2
521
453
        True
522
454
        >>> i1.add(InventoryEntry('123', 'foo', 'file', ROOT_ID))
 
455
        InventoryEntry('123', 'foo', kind='file', parent_id='TREE_ROOT')
523
456
        >>> i1 == i2
524
457
        False
525
458
        >>> i2.add(InventoryEntry('123', 'foo', 'file', ROOT_ID))
 
459
        InventoryEntry('123', 'foo', kind='file', parent_id='TREE_ROOT')
526
460
        >>> i1 == i2
527
461
        True
528
462
        """
544
478
        raise ValueError('not hashable')
545
479
 
546
480
 
547
 
 
548
481
    def get_idpath(self, file_id):
549
482
        """Return a list of file_ids for the path to an entry.
550
483
 
643
576
 
644
577
 
645
578
 
646
 
_NAME_RE = re.compile(r'^[^/\\]+$')
 
579
_NAME_RE = None
647
580
 
648
581
def is_valid_name(name):
 
582
    global _NAME_RE
 
583
    if _NAME_RE == None:
 
584
        _NAME_RE = re.compile(r'^[^/\\]+$')
 
585
        
649
586
    return bool(_NAME_RE.match(name))