~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: mbp at sourcefrog
  • Date: 2005-03-29 06:58:11 UTC
  • Revision ID: mbp@sourcefrog.net-20050329065811-1a9363119ad79447
remove parallel tree from inventory; 
store children directly in InventoryEntry

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/env python
2
 
# -*- coding: UTF-8 -*-
 
1
# (C) 2005 Canonical Ltd
3
2
 
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
125
124
        self.parent_id = parent_id
126
125
        self.text_sha1 = None
127
126
        self.text_size = None
 
127
        if kind == 'directory':
 
128
            self.children = {}
128
129
 
129
130
 
130
131
    def copy(self):
225
226
    >>> inv.add(InventoryEntry('123-123', 'hello.c'))
226
227
    >>> inv['123-123'].name
227
228
    'hello.c'
228
 
    >>> for file_id in inv: print file_id
229
 
    ...
230
 
    123-123
231
229
 
232
230
    May be treated as an iterator or set to look up file ids:
233
231
    
248
246
 
249
247
    """
250
248
 
251
 
    ## TODO: Clear up handling of files in subdirectories; we probably
252
 
    ## do want to be able to just look them up by name but this
253
 
    ## probably means gradually walking down the path, looking up as we go.
254
 
 
255
249
    ## TODO: Make sure only canonical filenames are stored.
256
250
 
257
251
    ## TODO: Do something sensible about the possible collisions on
258
252
    ## case-losing filesystems.  Perhaps we should just always forbid
259
253
    ## such collisions.
260
254
 
261
 
    ## _tree should probably just be stored as
262
 
    ## InventoryEntry._children on each directory.
 
255
    ## TODO: No special cases for root, rather just give it a file id
 
256
    ## like everything else.
 
257
 
 
258
    ## TODO: Probably change XML serialization to use nesting
263
259
 
264
260
    def __init__(self):
265
261
        """Create or read an inventory.
268
264
        from there.  If the file is specified, read from that. If not,
269
265
        the inventory is created empty.
270
266
        """
271
 
        self._byid = dict()
272
 
 
273
 
        # _tree is indexed by parent_id; at each level a map from name
274
 
        # to ie.  The None entry is the root.
275
 
        self._tree = {None: {}}
 
267
        self._root = InventoryEntry(None, '', kind='directory')
 
268
        self._byid = {None: self._root}
276
269
 
277
270
 
278
271
    def __iter__(self):
286
279
 
287
280
    def iter_entries(self, parent_id=None):
288
281
        """Return (path, entry) pairs, in order by name."""
289
 
        kids = self._tree[parent_id].items()
 
282
        kids = self[parent_id].children.items()
290
283
        kids.sort()
291
284
        for name, ie in kids:
292
285
            yield name, ie
306
299
        
307
300
 
308
301
 
309
 
    def children(self, parent_id):
310
 
        """Return entries that are direct children of parent_id."""
311
 
        return self._tree[parent_id]
312
 
                    
313
 
 
314
 
 
315
 
    # TODO: return all paths and entries
316
 
 
317
 
 
318
302
    def __contains__(self, file_id):
319
303
        """True if this entry contains a file with given id.
320
304
 
339
323
        return self._byid[file_id]
340
324
 
341
325
 
 
326
    def get_child(self, parent_id, filename):
 
327
        if parent_id == None:
 
328
            return self._root.children.get(filename)
 
329
        else:
 
330
            return self[parent_id].children.get(filename)
 
331
 
 
332
 
342
333
    def add(self, entry):
343
334
        """Add entry to inventory.
344
335
 
351
342
            if entry.parent_id not in self:
352
343
                bailout("parent_id %s of new entry not found in inventory"
353
344
                        % entry.parent_id)
 
345
            # TODO: parent must be a directory
354
346
            
355
 
        if self._tree[entry.parent_id].has_key(entry.name):
 
347
        if self[entry.parent_id].children.has_key(entry.name):
356
348
            bailout("%s is already versioned"
357
349
                    % appendpath(self.id2path(entry.parent_id), entry.name))
358
350
 
359
351
        self._byid[entry.file_id] = entry
360
 
        self._tree[entry.parent_id][entry.name] = entry
361
 
 
362
 
        if entry.kind == 'directory':
363
 
            self._tree[entry.file_id] = {}
 
352
        self[entry.parent_id].children[entry.name] = entry
364
353
 
365
354
 
366
355
    def add_path(self, relpath, kind, file_id=None):
393
382
        """
394
383
        ie = self[file_id]
395
384
 
396
 
        assert self._tree[ie.parent_id][ie.name] == ie
 
385
        assert self[ie.parent_id].children[ie.name] == ie
397
386
        
398
387
        # TODO: Test deleting all children; maybe hoist to a separate
399
388
        # deltree method?
400
389
        if ie.kind == 'directory':
401
 
            for cie in self._tree[file_id].values():
 
390
            for cie in ie.children.values():
402
391
                del self[cie.file_id]
403
 
            del self._tree[file_id]
 
392
            del ie.children
404
393
 
405
394
        del self._byid[file_id]
406
 
        del self._tree[ie.parent_id][ie.name]
 
395
        del self[ie.parent_id].children[ie.name]
407
396
 
408
397
 
409
398
    def id_set(self):
491
480
        if isinstance(name, types.StringTypes):
492
481
            name = splitpath(name)
493
482
 
494
 
        parent_id = None
 
483
        parent = self[None]
495
484
        for f in name:
496
485
            try:
497
 
                cie = self._tree[parent_id][f]
 
486
                cie = parent.children[f]
498
487
                assert cie.name == f
499
 
                parent_id = cie.file_id
 
488
                parent = cie
500
489
            except KeyError:
501
490
                # or raise an error?
502
491
                return None
503
492
 
504
 
        return parent_id
505
 
 
506
 
 
507
 
    def get_child(self, parent_id, child_name):
508
 
        return self._tree[parent_id].get(child_name)
 
493
        return parent.file_id
509
494
 
510
495
 
511
496
    def has_filename(self, names):