~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: aaron.bentley at utoronto
  • Date: 2005-08-21 00:08:08 UTC
  • mto: (1092.1.41) (1185.3.4)
  • mto: This revision was merged to the branch mainline in revision 1110.
  • Revision ID: aaron.bentley@utoronto.ca-20050821000808-2a0e6ef95b1bca59
Changed copy_multi to permit failure and return a tuple, tested missing required revisions

Show diffs side-by-side

added added

removed removed

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