~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Martin Pool
  • Date: 2005-05-10 06:21:07 UTC
  • Revision ID: mbp@sourcefrog.net-20050510062107-8b15b4c6b52d0279
doc

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
24
25
 
25
26
try:
26
27
    from cElementTree import Element, ElementTree, SubElement
27
28
except ImportError:
28
29
    from elementtree.ElementTree import Element, ElementTree, SubElement
29
30
 
30
 
from bzrlib.xml import XMLMixin
31
 
from bzrlib.errors import BzrError, BzrCheckError
 
31
from xml import XMLMixin
 
32
from errors import bailout, BzrError, BzrCheckError
32
33
 
33
34
import bzrlib
34
35
from bzrlib.osutils import uuid, quotefn, splitpath, joinpath, appendpath
68
69
    >>> i.add(InventoryEntry('2323', 'bye.c', 'file', '123'))
69
70
    Traceback (most recent call last):
70
71
    ...
71
 
    BzrError: inventory already contains entry with id {2323}
 
72
    BzrError: ('inventory already contains entry with id {2323}', [])
72
73
    >>> i.add(InventoryEntry('2324', 'bye.c', 'file', '123'))
73
74
    >>> i.add(InventoryEntry('2325', 'wibble', 'directory', '123'))
74
75
    >>> i.path2id('src/wibble')
144
145
                               self.parent_id, text_id=self.text_id)
145
146
        other.text_sha1 = self.text_sha1
146
147
        other.text_size = self.text_size
147
 
        # note that children are *not* copied; they're pulled across when
148
 
        # others are added
149
148
        return other
150
149
 
151
150
 
210
209
 
211
210
    from_element = classmethod(from_element)
212
211
 
213
 
    def __eq__(self, other):
 
212
    def __cmp__(self, other):
 
213
        if self is other:
 
214
            return 0
214
215
        if not isinstance(other, InventoryEntry):
215
216
            return NotImplemented
216
217
 
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')
 
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)
231
225
 
232
226
 
233
227
 
239
233
        self.parent_id = None
240
234
        self.name = ''
241
235
 
242
 
    def __eq__(self, other):
 
236
    def __cmp__(self, other):
 
237
        if self is other:
 
238
            return 0
243
239
        if not isinstance(other, RootEntry):
244
240
            return NotImplemented
245
 
        
246
 
        return (self.file_id == other.file_id) \
247
 
               and (self.children == other.children)
 
241
        return cmp(self.file_id, other.file_id) \
 
242
               or cmp(self.children, other.children)
248
243
 
249
244
 
250
245
 
329
324
            if ie.kind == 'directory':
330
325
                for cn, cie in self.iter_entries(from_dir=ie.file_id):
331
326
                    yield os.path.join(name, cn), cie
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.
 
327
                    
 
328
 
 
329
 
 
330
    def directories(self):
 
331
        """Return (path, entry) pairs for all directories.
338
332
        """
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))
 
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():
346
340
                if ie.kind == 'directory':
347
 
                    descend(ie, child_path)
348
 
 
349
 
        descend(self.root, '')
350
 
        return accum
351
 
 
352
 
 
353
 
    def directories(self):
354
 
        """Return (path, entry) pairs for all directories, including the root.
355
 
        """
356
 
        accum = []
357
 
        def descend(parent_ie, parent_path):
358
 
            accum.append((parent_path, parent_ie))
 
341
                    dn.append((ie.name, ie))
 
342
            dn.sort()
359
343
            
360
 
            kids = [(ie.name, ie) for ie in parent_ie.children.itervalues() if ie.kind == 'directory']
361
 
            kids.sort()
 
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
362
347
 
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
 
348
        for name, ie in descend(self.root):
 
349
            yield name, ie
368
350
        
369
351
 
370
352
 
398
380
                raise BzrError("file_id {%s} not in inventory" % file_id)
399
381
 
400
382
 
401
 
    def get_file_kind(self, file_id):
402
 
        return self._byid[file_id].kind
403
 
 
404
383
    def get_child(self, parent_id, filename):
405
384
        return self[parent_id].children.get(filename)
406
385
 
411
390
        To add  a file to a branch ready to be committed, use Branch.add,
412
391
        which calls this."""
413
392
        if entry.file_id in self._byid:
414
 
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
 
393
            bailout("inventory already contains entry with id {%s}" % entry.file_id)
415
394
 
416
395
        try:
417
396
            parent = self._byid[entry.parent_id]
418
397
        except KeyError:
419
 
            raise BzrError("parent_id {%s} not in inventory" % entry.parent_id)
 
398
            bailout("parent_id {%s} not in inventory" % entry.parent_id)
420
399
 
421
400
        if parent.children.has_key(entry.name):
422
 
            raise BzrError("%s is already versioned" %
 
401
            bailout("%s is already versioned" %
423
402
                    appendpath(self.id2path(parent.file_id), entry.name))
424
403
 
425
404
        self._byid[entry.file_id] = entry
432
411
        The immediate parent must already be versioned"""
433
412
        parts = bzrlib.osutils.splitpath(relpath)
434
413
        if len(parts) == 0:
435
 
            raise BzrError("cannot re-add root of inventory")
 
414
            bailout("cannot re-add root of inventory")
436
415
 
437
416
        if file_id == None:
438
417
            file_id = bzrlib.branch.gen_file_id(relpath)
470
449
        del self[ie.parent_id].children[ie.name]
471
450
 
472
451
 
 
452
    def id_set(self):
 
453
        return Set(self._byid)
 
454
 
 
455
 
473
456
    def to_element(self):
474
457
        """Convert to XML Element"""
475
458
        e = Element('inventory')
498
481
    from_element = classmethod(from_element)
499
482
 
500
483
 
501
 
    def __eq__(self, other):
 
484
    def __cmp__(self, other):
502
485
        """Compare two sets by comparing their contents.
503
486
 
504
487
        >>> i1 = Inventory()
512
495
        >>> i1 == i2
513
496
        True
514
497
        """
 
498
        if self is other:
 
499
            return 0
 
500
        
515
501
        if not isinstance(other, Inventory):
516
502
            return NotImplemented
517
503
 
518
 
        if len(self._byid) != len(other._byid):
519
 
            # shortcut: obviously not the same
520
 
            return False
521
 
 
522
 
        return self._byid == other._byid
523
 
 
524
 
 
525
 
    def __ne__(self, other):
526
 
        return not (self == other)
527
 
 
528
 
 
529
 
    def __hash__(self):
530
 
        raise ValueError('not hashable')
531
 
 
 
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
532
512
 
533
513
 
534
514
    def get_idpath(self, file_id):
544
524
            try:
545
525
                ie = self._byid[file_id]
546
526
            except KeyError:
547
 
                raise BzrError("file_id {%s} not found in inventory" % file_id)
 
527
                bailout("file_id {%s} not found in inventory" % file_id)
548
528
            p.insert(0, ie.file_id)
549
529
            file_id = ie.parent_id
550
530
        return p
604
584
 
605
585
        This does not move the working file."""
606
586
        if not is_valid_name(new_name):
607
 
            raise BzrError("not an acceptable filename: %r" % new_name)
 
587
            bailout("not an acceptable filename: %r" % new_name)
608
588
 
609
589
        new_parent = self._byid[new_parent_id]
610
590
        if new_name in new_parent.children:
611
 
            raise BzrError("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
 
591
            bailout("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
612
592
 
613
593
        new_parent_idpath = self.get_idpath(new_parent_id)
614
594
        if file_id in new_parent_idpath:
615
 
            raise BzrError("cannot move directory %r into a subdirectory of itself, %r"
 
595
            bailout("cannot move directory %r into a subdirectory of itself, %r"
616
596
                    % (self.id2path(file_id), self.id2path(new_parent_id)))
617
597
 
618
598
        file_ie = self._byid[file_id]