~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Martin Pool
  • Date: 2005-05-11 06:20:05 UTC
  • Revision ID: mbp@sourcefrog.net-20050511062005-297af3451635dae0
- Don't lose first line of command help!

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
 
411
393
        To add  a file to a branch ready to be committed, use Branch.add,
412
394
        which calls this."""
413
395
        if entry.file_id in self._byid:
414
 
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
 
396
            bailout("inventory already contains entry with id {%s}" % entry.file_id)
415
397
 
416
398
        try:
417
399
            parent = self._byid[entry.parent_id]
418
400
        except KeyError:
419
 
            raise BzrError("parent_id {%s} not in inventory" % entry.parent_id)
 
401
            bailout("parent_id {%s} not in inventory" % entry.parent_id)
420
402
 
421
403
        if parent.children.has_key(entry.name):
422
 
            raise BzrError("%s is already versioned" %
 
404
            bailout("%s is already versioned" %
423
405
                    appendpath(self.id2path(parent.file_id), entry.name))
424
406
 
425
407
        self._byid[entry.file_id] = entry
432
414
        The immediate parent must already be versioned"""
433
415
        parts = bzrlib.osutils.splitpath(relpath)
434
416
        if len(parts) == 0:
435
 
            raise BzrError("cannot re-add root of inventory")
 
417
            bailout("cannot re-add root of inventory")
436
418
 
437
419
        if file_id == None:
438
420
            file_id = bzrlib.branch.gen_file_id(relpath)
470
452
        del self[ie.parent_id].children[ie.name]
471
453
 
472
454
 
 
455
    def id_set(self):
 
456
        return Set(self._byid)
 
457
 
 
458
 
473
459
    def to_element(self):
474
460
        """Convert to XML Element"""
475
461
        e = Element('inventory')
498
484
    from_element = classmethod(from_element)
499
485
 
500
486
 
501
 
    def __eq__(self, other):
 
487
    def __cmp__(self, other):
502
488
        """Compare two sets by comparing their contents.
503
489
 
504
490
        >>> i1 = Inventory()
512
498
        >>> i1 == i2
513
499
        True
514
500
        """
 
501
        if self is other:
 
502
            return 0
 
503
        
515
504
        if not isinstance(other, Inventory):
516
505
            return NotImplemented
517
506
 
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
 
 
 
507
        if self.id_set() ^ other.id_set():
 
508
            return 1
 
509
 
 
510
        for file_id in self._byid:
 
511
            c = cmp(self[file_id], other[file_id])
 
512
            if c: return c
 
513
 
 
514
        return 0
532
515
 
533
516
 
534
517
    def get_idpath(self, file_id):
544
527
            try:
545
528
                ie = self._byid[file_id]
546
529
            except KeyError:
547
 
                raise BzrError("file_id {%s} not found in inventory" % file_id)
 
530
                bailout("file_id {%s} not found in inventory" % file_id)
548
531
            p.insert(0, ie.file_id)
549
532
            file_id = ie.parent_id
550
533
        return p
604
587
 
605
588
        This does not move the working file."""
606
589
        if not is_valid_name(new_name):
607
 
            raise BzrError("not an acceptable filename: %r" % new_name)
 
590
            bailout("not an acceptable filename: %r" % new_name)
608
591
 
609
592
        new_parent = self._byid[new_parent_id]
610
593
        if new_name in new_parent.children:
611
 
            raise BzrError("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
 
594
            bailout("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
612
595
 
613
596
        new_parent_idpath = self.get_idpath(new_parent_id)
614
597
        if file_id in new_parent_idpath:
615
 
            raise BzrError("cannot move directory %r into a subdirectory of itself, %r"
 
598
            bailout("cannot move directory %r into a subdirectory of itself, %r"
616
599
                    % (self.id2path(file_id), self.id2path(new_parent_id)))
617
600
 
618
601
        file_ie = self._byid[file_id]