~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Martin Pool
  • Date: 2005-06-27 01:39:26 UTC
  • Revision ID: mbp@sourcefrog.net-20050627013926-49413d5928809350
- import effbot.org http client

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
 
23
23
import sys, os.path, types, re
24
 
from sets import Set
25
24
 
26
25
try:
27
26
    from cElementTree import Element, ElementTree, SubElement
28
27
except ImportError:
29
28
    from elementtree.ElementTree import Element, ElementTree, SubElement
30
29
 
31
 
from xml import XMLMixin
32
 
from errors import bailout, BzrError, BzrCheckError
 
30
from bzrlib.xml import XMLMixin
 
31
from bzrlib.errors import BzrError, BzrCheckError
33
32
 
34
33
import bzrlib
35
34
from bzrlib.osutils import uuid, quotefn, splitpath, joinpath, appendpath
69
68
    >>> i.add(InventoryEntry('2323', 'bye.c', 'file', '123'))
70
69
    Traceback (most recent call last):
71
70
    ...
72
 
    BzrError: ('inventory already contains entry with id {2323}', [])
 
71
    BzrError: inventory already contains entry with id {2323}
73
72
    >>> i.add(InventoryEntry('2324', 'bye.c', 'file', '123'))
74
73
    >>> i.add(InventoryEntry('2325', 'wibble', 'directory', '123'))
75
74
    >>> i.path2id('src/wibble')
145
144
                               self.parent_id, text_id=self.text_id)
146
145
        other.text_sha1 = self.text_sha1
147
146
        other.text_size = self.text_size
 
147
        # note that children are *not* copied; they're pulled across when
 
148
        # others are added
148
149
        return other
149
150
 
150
151
 
209
210
 
210
211
    from_element = classmethod(from_element)
211
212
 
212
 
    def __cmp__(self, other):
213
 
        if self is other:
214
 
            return 0
 
213
    def __eq__(self, other):
215
214
        if not isinstance(other, InventoryEntry):
216
215
            return NotImplemented
217
216
 
218
 
        return cmp(self.file_id, other.file_id) \
219
 
               or cmp(self.name, other.name) \
220
 
               or cmp(self.text_sha1, other.text_sha1) \
221
 
               or cmp(self.text_size, other.text_size) \
222
 
               or cmp(self.text_id, other.text_id) \
223
 
               or cmp(self.parent_id, other.parent_id) \
224
 
               or cmp(self.kind, other.kind)
 
217
        return (self.file_id == other.file_id) \
 
218
               and (self.name == other.name) \
 
219
               and (self.text_sha1 == other.text_sha1) \
 
220
               and (self.text_size == other.text_size) \
 
221
               and (self.text_id == other.text_id) \
 
222
               and (self.parent_id == other.parent_id) \
 
223
               and (self.kind == other.kind)
 
224
 
 
225
 
 
226
    def __ne__(self, other):
 
227
        return not (self == other)
 
228
 
 
229
    def __hash__(self):
 
230
        raise ValueError('not hashable')
225
231
 
226
232
 
227
233
 
233
239
        self.parent_id = None
234
240
        self.name = ''
235
241
 
236
 
    def __cmp__(self, other):
237
 
        if self is other:
238
 
            return 0
 
242
    def __eq__(self, other):
239
243
        if not isinstance(other, RootEntry):
240
244
            return NotImplemented
241
 
        return cmp(self.file_id, other.file_id) \
242
 
               or cmp(self.children, other.children)
 
245
        
 
246
        return (self.file_id == other.file_id) \
 
247
               and (self.children == other.children)
243
248
 
244
249
 
245
250
 
324
329
            if ie.kind == 'directory':
325
330
                for cn, cie in self.iter_entries(from_dir=ie.file_id):
326
331
                    yield os.path.join(name, cn), cie
327
 
                    
 
332
 
 
333
 
 
334
    def entries(self):
 
335
        """Return list of (path, ie) for all entries except the root.
 
336
 
 
337
        This may be faster than iter_entries.
 
338
        """
 
339
        accum = []
 
340
        def descend(dir_ie, dir_path):
 
341
            kids = dir_ie.children.items()
 
342
            kids.sort()
 
343
            for name, ie in kids:
 
344
                child_path = os.path.join(dir_path, name)
 
345
                accum.append((child_path, ie))
 
346
                if ie.kind == 'directory':
 
347
                    descend(ie, child_path)
 
348
 
 
349
        descend(self.root, '')
 
350
        return accum
328
351
 
329
352
 
330
353
    def directories(self):
331
 
        """Return (path, entry) pairs for all directories.
 
354
        """Return (path, entry) pairs for all directories, including the root.
332
355
        """
333
 
        def descend(parent_ie):
334
 
            parent_name = parent_ie.name
335
 
            yield parent_name, parent_ie
336
 
 
337
 
            # directory children in sorted order
338
 
            dn = []
339
 
            for ie in parent_ie.children.itervalues():
340
 
                if ie.kind == 'directory':
341
 
                    dn.append((ie.name, ie))
342
 
            dn.sort()
 
356
        accum = []
 
357
        def descend(parent_ie, parent_path):
 
358
            accum.append((parent_path, parent_ie))
343
359
            
344
 
            for name, child_ie in dn:
345
 
                for sub_name, sub_ie in descend(child_ie):
346
 
                    yield appendpath(parent_name, sub_name), sub_ie
 
360
            kids = [(ie.name, ie) for ie in parent_ie.children.itervalues() if ie.kind == 'directory']
 
361
            kids.sort()
347
362
 
348
 
        for name, ie in descend(self.root):
349
 
            yield name, ie
 
363
            for name, child_ie in kids:
 
364
                child_path = os.path.join(parent_path, name)
 
365
                descend(child_ie, child_path)
 
366
        descend(self.root, '')
 
367
        return accum
350
368
        
351
369
 
352
370
 
380
398
                raise BzrError("file_id {%s} not in inventory" % file_id)
381
399
 
382
400
 
 
401
    def get_file_kind(self, file_id):
 
402
        return self._byid[file_id].kind
 
403
 
383
404
    def get_child(self, parent_id, filename):
384
405
        return self[parent_id].children.get(filename)
385
406
 
390
411
        To add  a file to a branch ready to be committed, use Branch.add,
391
412
        which calls this."""
392
413
        if entry.file_id in self._byid:
393
 
            bailout("inventory already contains entry with id {%s}" % entry.file_id)
 
414
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
394
415
 
395
416
        try:
396
417
            parent = self._byid[entry.parent_id]
397
418
        except KeyError:
398
 
            bailout("parent_id {%s} not in inventory" % entry.parent_id)
 
419
            raise BzrError("parent_id {%s} not in inventory" % entry.parent_id)
399
420
 
400
421
        if parent.children.has_key(entry.name):
401
 
            bailout("%s is already versioned" %
 
422
            raise BzrError("%s is already versioned" %
402
423
                    appendpath(self.id2path(parent.file_id), entry.name))
403
424
 
404
425
        self._byid[entry.file_id] = entry
409
430
        """Add entry from a path.
410
431
 
411
432
        The immediate parent must already be versioned"""
 
433
        from bzrlib.errors import NotVersionedError
 
434
        
412
435
        parts = bzrlib.osutils.splitpath(relpath)
413
436
        if len(parts) == 0:
414
 
            bailout("cannot re-add root of inventory")
 
437
            raise BzrError("cannot re-add root of inventory")
415
438
 
416
439
        if file_id == None:
417
440
            file_id = bzrlib.branch.gen_file_id(relpath)
418
441
 
419
 
        parent_id = self.path2id(parts[:-1])
420
 
        assert parent_id != None
 
442
        parent_path = parts[:-1]
 
443
        parent_id = self.path2id(parent_path)
 
444
        if parent_id == None:
 
445
            raise NotVersionedError(parent_path)
 
446
 
421
447
        ie = InventoryEntry(file_id, parts[-1],
422
448
                            kind=kind, parent_id=parent_id)
423
449
        return self.add(ie)
449
475
        del self[ie.parent_id].children[ie.name]
450
476
 
451
477
 
452
 
    def id_set(self):
453
 
        return Set(self._byid)
454
 
 
455
 
 
456
478
    def to_element(self):
457
479
        """Convert to XML Element"""
458
480
        e = Element('inventory')
481
503
    from_element = classmethod(from_element)
482
504
 
483
505
 
484
 
    def __cmp__(self, other):
 
506
    def __eq__(self, other):
485
507
        """Compare two sets by comparing their contents.
486
508
 
487
509
        >>> i1 = Inventory()
495
517
        >>> i1 == i2
496
518
        True
497
519
        """
498
 
        if self is other:
499
 
            return 0
500
 
        
501
520
        if not isinstance(other, Inventory):
502
521
            return NotImplemented
503
522
 
504
 
        if self.id_set() ^ other.id_set():
505
 
            return 1
506
 
 
507
 
        for file_id in self._byid:
508
 
            c = cmp(self[file_id], other[file_id])
509
 
            if c: return c
510
 
 
511
 
        return 0
 
523
        if len(self._byid) != len(other._byid):
 
524
            # shortcut: obviously not the same
 
525
            return False
 
526
 
 
527
        return self._byid == other._byid
 
528
 
 
529
 
 
530
    def __ne__(self, other):
 
531
        return not (self == other)
 
532
 
 
533
 
 
534
    def __hash__(self):
 
535
        raise ValueError('not hashable')
 
536
 
512
537
 
513
538
 
514
539
    def get_idpath(self, file_id):
524
549
            try:
525
550
                ie = self._byid[file_id]
526
551
            except KeyError:
527
 
                bailout("file_id {%s} not found in inventory" % file_id)
 
552
                raise BzrError("file_id {%s} not found in inventory" % file_id)
528
553
            p.insert(0, ie.file_id)
529
554
            file_id = ie.parent_id
530
555
        return p
584
609
 
585
610
        This does not move the working file."""
586
611
        if not is_valid_name(new_name):
587
 
            bailout("not an acceptable filename: %r" % new_name)
 
612
            raise BzrError("not an acceptable filename: %r" % new_name)
588
613
 
589
614
        new_parent = self._byid[new_parent_id]
590
615
        if new_name in new_parent.children:
591
 
            bailout("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
 
616
            raise BzrError("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
592
617
 
593
618
        new_parent_idpath = self.get_idpath(new_parent_id)
594
619
        if file_id in new_parent_idpath:
595
 
            bailout("cannot move directory %r into a subdirectory of itself, %r"
 
620
            raise BzrError("cannot move directory %r into a subdirectory of itself, %r"
596
621
                    % (self.id2path(file_id), self.id2path(new_parent_id)))
597
622
 
598
623
        file_ie = self._byid[file_id]