~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/weave.py

  • Committer: Martin Pool
  • Date: 2005-09-16 09:19:54 UTC
  • Revision ID: mbp@sourcefrog.net-20050916091954-aee6d7be00db6354
- more docs in commit code

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
 
89
89
import sha
90
90
 
 
91
from cStringIO import StringIO
 
92
 
 
93
from bzrlib.osutils import sha_strings
91
94
 
92
95
 
93
96
class WeaveError(Exception):
181
184
 
182
185
    _name_map
183
186
        For each name, the version number.
 
187
 
 
188
    _weave_name
 
189
        Descriptive name of this weave; typically the filename if known.
 
190
        Set by read_weave.
184
191
    """
185
192
 
186
 
    __slots__ = ['_weave', '_parents', '_sha1s', '_names', '_name_map']
 
193
    __slots__ = ['_weave', '_parents', '_sha1s', '_names', '_name_map',
 
194
                 '_weave_name']
187
195
    
188
 
    def __init__(self):
 
196
    def __init__(self, weave_name=None):
189
197
        self._weave = []
190
198
        self._parents = []
191
199
        self._sha1s = []
192
200
        self._names = []
193
201
        self._name_map = {}
 
202
        self._weave_name = weave_name
194
203
 
195
204
 
196
205
    def __eq__(self, other):
205
214
        return not self.__eq__(other)
206
215
 
207
216
 
 
217
    def maybe_lookup(self, name_or_index):
 
218
        """Convert possible symbolic name to index, or pass through indexes."""
 
219
        if isinstance(name_or_index, (int, long)):
 
220
            return name_or_index
 
221
        else:
 
222
            return self.lookup(name_or_index)
 
223
 
 
224
        
208
225
    def lookup(self, name):
 
226
        """Convert symbolic version name to index."""
209
227
        try:
210
228
            return self._name_map[name]
211
229
        except KeyError:
212
 
            raise WeaveError("name %s not present in weave" % name)
 
230
            raise WeaveError("name %r not present in weave %r" %
 
231
                             (name, self._weave_name))
 
232
 
 
233
 
 
234
    def idx_to_name(self, version):
 
235
        return self._names[version]
 
236
 
 
237
 
 
238
    def _check_repeated_add(self, name, parents, text):
 
239
        """Check that a duplicated add is OK.
 
240
 
 
241
        If it is, return the (old) index; otherwise raise an exception.
 
242
        """
 
243
        idx = self.lookup(name)
 
244
        if sorted(self._parents[idx]) != sorted(parents):
 
245
            raise WeaveError("name \"%s\" already present in weave "
 
246
                             "with different parents" % name)
 
247
        new_sha1 = sha_strings(text)
 
248
        if new_sha1 != self._sha1s[idx]:
 
249
            raise WeaveError("name \"%s\" already present in weave "
 
250
                             "with different text" % name)            
 
251
        return idx
 
252
        
213
253
 
214
254
        
215
255
    def add(self, name, parents, text):
229
269
 
230
270
        assert isinstance(name, basestring)
231
271
        if name in self._name_map:
232
 
            raise WeaveError("name %r already present in weave" % name)
233
 
        
 
272
            return self._check_repeated_add(name, parents, text)
 
273
 
 
274
        parents = map(self.maybe_lookup, parents)
234
275
        self._check_versions(parents)
235
276
        ## self._check_lines(text)
236
277
        new_version = len(self._parents)
237
278
 
238
 
        s = sha.new()
239
 
        map(s.update, text)
240
 
        sha1 = s.hexdigest()
241
 
        del s
 
279
        sha1 = sha_strings(text)
242
280
 
243
281
        # if we abort after here the (in-memory) weave will be corrupt because only
244
282
        # some fields are updated
350
388
            raise ValueError("version %d not present in weave" % v)
351
389
 
352
390
 
 
391
    def parents(self, version):
 
392
        return self._parents[version]
 
393
 
 
394
 
353
395
    def minimal_parents(self, version):
354
396
        """Find the minimal set of parents for the version."""
355
397
        included = self._parents[version]
393
435
                raise IndexError("invalid version number %r" % i)
394
436
 
395
437
    
396
 
    def annotate(self, index):
397
 
        return list(self.annotate_iter(index))
398
 
 
399
 
 
400
 
    def annotate_iter(self, version):
 
438
    def annotate(self, name_or_index):
 
439
        return list(self.annotate_iter(name_or_index))
 
440
 
 
441
 
 
442
    def annotate_iter(self, name_or_index):
401
443
        """Yield list of (index-id, line) pairs for the specified version.
402
444
 
403
445
        The index indicates when the line originated in the weave."""
404
 
        for origin, lineno, text in self._extract([version]):
 
446
        incls = [self.maybe_lookup(name_or_index)]
 
447
        for origin, lineno, text in self._extract(incls):
405
448
            yield origin, text
406
449
 
407
450
 
451
494
 
452
495
        The set typically but not necessarily corresponds to a version.
453
496
        """
 
497
        for i in versions:
 
498
            if not isinstance(i, int):
 
499
                raise ValueError(i)
 
500
            
454
501
        included = self.inclusions(versions)
455
502
 
456
503
        istack = []
501
548
    
502
549
 
503
550
 
504
 
    def get_iter(self, version):
 
551
    def get_iter(self, name_or_index):
505
552
        """Yield lines for the specified version."""
506
 
        for origin, lineno, line in self._extract([version]):
 
553
        incls = [self.maybe_lookup(name_or_index)]
 
554
        for origin, lineno, line in self._extract(incls):
507
555
            yield line
508
556
 
509
557
 
510
 
    def get(self, index):
511
 
        return list(self.get_iter(index))
 
558
    def get_text(self, version):
 
559
        assert isinstance(version, int)
 
560
        s = StringIO()
 
561
        s.writelines(self.get_iter(version))
 
562
        return s.getvalue()
 
563
 
 
564
 
 
565
    def get(self, name_or_index):
 
566
        return list(self.get_iter(name_or_index))
512
567
 
513
568
 
514
569
    def mash_iter(self, included):