/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/weave.py

  • Committer: Martin Pool
  • Date: 2007-09-14 06:31:28 UTC
  • mfrom: (2822 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2823.
  • Revision ID: mbp@sourcefrog.net-20070914063128-0p7mh6zfb4pzdg9p
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
import bzrlib.errors as errors
89
89
from bzrlib.osutils import sha_strings
90
90
import bzrlib.patiencediff
91
 
from bzrlib.symbol_versioning import (deprecated_method,
92
 
        deprecated_function,
93
 
        zero_eight,
94
 
        )
95
91
from bzrlib.tsort import topo_sort
96
92
from bzrlib.versionedfile import VersionedFile, InterVersionedFile
97
93
from bzrlib.weavefile import _read_weave_v5, write_weave_v5
228
224
    def __ne__(self, other):
229
225
        return not self.__eq__(other)
230
226
 
231
 
    @deprecated_method(zero_eight)
232
 
    def idx_to_name(self, index):
233
 
        """Old public interface, the public interface is all names now."""
234
 
        return index
235
 
 
236
227
    def _idx_to_name(self, version):
237
228
        return self._names[version]
238
229
 
239
 
    @deprecated_method(zero_eight)
240
 
    def lookup(self, name):
241
 
        """Backwards compatibility thunk:
242
 
 
243
 
        Return name, as name is valid in the api now, and spew deprecation
244
 
        warnings everywhere.
245
 
        """
246
 
        return name
247
 
 
248
230
    def _lookup(self, name):
249
231
        """Convert symbolic version name to index."""
250
232
        self.check_not_reserved_id(name)
253
235
        except KeyError:
254
236
            raise RevisionNotPresent(name, self._weave_name)
255
237
 
256
 
    @deprecated_method(zero_eight)
257
 
    def iter_names(self):
258
 
        """Deprecated convenience function, please see VersionedFile.names()."""
259
 
        return iter(self.names())
260
 
 
261
 
    @deprecated_method(zero_eight)
262
 
    def names(self):
263
 
        """See Weave.versions for the current api."""
264
 
        return self.versions()
265
 
 
266
238
    def versions(self):
267
239
        """See VersionedFile.versions."""
268
240
        return self._names[:]
273
245
 
274
246
    __contains__ = has_version
275
247
 
276
 
    def get_delta(self, version_id):
277
 
        """See VersionedFile.get_delta."""
278
 
        return self.get_deltas([version_id])[version_id]
279
 
 
280
 
    def get_deltas(self, version_ids):
281
 
        """See VersionedFile.get_deltas."""
282
 
        version_ids = self.get_ancestry(version_ids)
283
 
        for version_id in version_ids:
284
 
            if not self.has_version(version_id):
285
 
                raise RevisionNotPresent(version_id, self)
286
 
        # try extracting all versions; parallel extraction is used
287
 
        nv = self.num_versions()
288
 
        sha1s = {}
289
 
        deltas = {}
290
 
        texts = {}
291
 
        inclusions = {}
292
 
        noeols = {}
293
 
        last_parent_lines = {}
294
 
        parents = {}
295
 
        parent_inclusions = {}
296
 
        parent_linenums = {}
297
 
        parent_noeols = {}
298
 
        current_hunks = {}
299
 
        diff_hunks = {}
300
 
        # its simplest to generate a full set of prepared variables.
301
 
        for i in range(nv):
302
 
            name = self._names[i]
303
 
            sha1s[name] = self.get_sha1(name)
304
 
            parents_list = self.get_parents(name)
305
 
            try:
306
 
                parent = parents_list[0]
307
 
                parents[name] = parent
308
 
                parent_inclusions[name] = inclusions[parent]
309
 
            except IndexError:
310
 
                parents[name] = None
311
 
                parent_inclusions[name] = set()
312
 
            # we want to emit start, finish, replacement_length, replacement_lines tuples.
313
 
            diff_hunks[name] = []
314
 
            current_hunks[name] = [0, 0, 0, []] # #start, finish, repl_length, repl_tuples
315
 
            parent_linenums[name] = 0
316
 
            noeols[name] = False
317
 
            parent_noeols[name] = False
318
 
            last_parent_lines[name] = None
319
 
            new_inc = set([name])
320
 
            for p in self._parents[i]:
321
 
                new_inc.update(inclusions[self._idx_to_name(p)])
322
 
            # debug only, known good so far.
323
 
            #assert set(new_inc) == set(self.get_ancestry(name)), \
324
 
            #    'failed %s != %s' % (set(new_inc), set(self.get_ancestry(name)))
325
 
            inclusions[name] = new_inc
326
 
 
327
 
        nlines = len(self._weave)
328
 
 
329
 
        for lineno, inserted, deletes, line in self._walk_internal():
330
 
            # a line is active in a version if:
331
 
            # insert is in the versions inclusions
332
 
            # and
333
 
            # deleteset & the versions inclusions is an empty set.
334
 
            # so - if we have a included by mapping - version is included by
335
 
            # children, we get a list of children to examine for deletes affect
336
 
            # ing them, which is less than the entire set of children.
337
 
            for version_id in version_ids:  
338
 
                # The active inclusion must be an ancestor,
339
 
                # and no ancestors must have deleted this line,
340
 
                # because we don't support resurrection.
341
 
                parent_inclusion = parent_inclusions[version_id]
342
 
                inclusion = inclusions[version_id]
343
 
                parent_active = inserted in parent_inclusion and not (deletes & parent_inclusion)
344
 
                version_active = inserted in inclusion and not (deletes & inclusion)
345
 
                if not parent_active and not version_active:
346
 
                    # unrelated line of ancestry
347
 
                    continue
348
 
                elif parent_active and version_active:
349
 
                    # shared line
350
 
                    parent_linenum = parent_linenums[version_id]
351
 
                    if current_hunks[version_id] != [parent_linenum, parent_linenum, 0, []]:
352
 
                        diff_hunks[version_id].append(tuple(current_hunks[version_id]))
353
 
                    parent_linenum += 1
354
 
                    current_hunks[version_id] = [parent_linenum, parent_linenum, 0, []]
355
 
                    parent_linenums[version_id] = parent_linenum
356
 
                    try:
357
 
                        if line[-1] != '\n':
358
 
                            noeols[version_id] = True
359
 
                    except IndexError:
360
 
                        pass
361
 
                elif parent_active and not version_active:
362
 
                    # deleted line
363
 
                    current_hunks[version_id][1] += 1
364
 
                    parent_linenums[version_id] += 1
365
 
                    last_parent_lines[version_id] = line
366
 
                elif not parent_active and version_active:
367
 
                    # replacement line
368
 
                    # noeol only occurs at the end of a file because we 
369
 
                    # diff linewise. We want to show noeol changes as a
370
 
                    # empty diff unless the actual eol-less content changed.
371
 
                    theline = line
372
 
                    try:
373
 
                        if last_parent_lines[version_id][-1] != '\n':
374
 
                            parent_noeols[version_id] = True
375
 
                    except (TypeError, IndexError):
376
 
                        pass
377
 
                    try:
378
 
                        if theline[-1] != '\n':
379
 
                            noeols[version_id] = True
380
 
                    except IndexError:
381
 
                        pass
382
 
                    new_line = False
383
 
                    parent_should_go = False
384
 
 
385
 
                    if parent_noeols[version_id] == noeols[version_id]:
386
 
                        # no noeol toggle, so trust the weaves statement
387
 
                        # that this line is changed.
388
 
                        new_line = True
389
 
                        if parent_noeols[version_id]:
390
 
                            theline = theline + '\n'
391
 
                    elif parent_noeols[version_id]:
392
 
                        # parent has no eol, we do:
393
 
                        # our line is new, report as such..
394
 
                        new_line = True
395
 
                    elif noeols[version_id]:
396
 
                        # append a eol so that it looks like
397
 
                        # a normalised delta
398
 
                        theline = theline + '\n'
399
 
                        if parents[version_id] is not None:
400
 
                        #if last_parent_lines[version_id] is not None:
401
 
                            parent_should_go = True
402
 
                        if last_parent_lines[version_id] != theline:
403
 
                            # but changed anyway
404
 
                            new_line = True
405
 
                            #parent_should_go = False
406
 
                    if new_line:
407
 
                        current_hunks[version_id][2] += 1
408
 
                        current_hunks[version_id][3].append((inserted, theline))
409
 
                    if parent_should_go:
410
 
                        # last hunk last parent line is not eaten
411
 
                        current_hunks[version_id][1] -= 1
412
 
                    if current_hunks[version_id][1] < 0:
413
 
                        current_hunks[version_id][1] = 0
414
 
                        # import pdb;pdb.set_trace()
415
 
                    # assert current_hunks[version_id][1] >= 0
416
 
 
417
 
        # flush last hunk
418
 
        for i in range(nv):
419
 
            version = self._idx_to_name(i)
420
 
            if current_hunks[version] != [0, 0, 0, []]:
421
 
                diff_hunks[version].append(tuple(current_hunks[version]))
422
 
        result = {}
423
 
        for version_id in version_ids:
424
 
            result[version_id] = (
425
 
                                  parents[version_id],
426
 
                                  sha1s[version_id],
427
 
                                  noeols[version_id],
428
 
                                  diff_hunks[version_id],
429
 
                                  )
430
 
        return result
431
 
 
432
248
    def get_parents(self, version_id):
433
249
        """See VersionedFile.get_parent."""
434
250
        return map(self._idx_to_name, self._parents[self._lookup(version_id)])
444
260
            raise RevisionAlreadyPresent(name, self._weave_name)
445
261
        return idx
446
262
 
447
 
    @deprecated_method(zero_eight)
448
 
    def add_identical(self, old_rev_id, new_rev_id, parents):
449
 
        """Please use Weave.clone_text now."""
450
 
        return self.clone_text(new_rev_id, old_rev_id, parents)
451
 
 
452
 
    def _add_lines(self, version_id, parents, lines, parent_texts):
 
263
    def _add_lines(self, version_id, parents, lines, parent_texts,
 
264
       left_matching_blocks, nostore_sha, random_id, check_content):
453
265
        """See VersionedFile.add_lines."""
454
 
        return self._add(version_id, lines, map(self._lookup, parents))
455
 
 
456
 
    @deprecated_method(zero_eight)
457
 
    def add(self, name, parents, text, sha1=None):
458
 
        """See VersionedFile.add_lines for the non deprecated api."""
459
 
        return self._add(name, text, map(self._maybe_lookup, parents), sha1)
460
 
 
461
 
    def _add(self, version_id, lines, parents, sha1=None):
 
266
        idx = self._add(version_id, lines, map(self._lookup, parents),
 
267
            nostore_sha=nostore_sha)
 
268
        return sha_strings(lines), sum(map(len, lines)), idx
 
269
 
 
270
    def _add(self, version_id, lines, parents, sha1=None, nostore_sha=None):
462
271
        """Add a single text on top of the weave.
463
272
  
464
273
        Returns the index number of the newly added version.
472
281
            
473
282
        lines
474
283
            Sequence of lines to be added in the new version.
 
284
 
 
285
        :param nostore_sha: See VersionedFile.add_lines.
475
286
        """
476
 
 
477
287
        assert isinstance(version_id, basestring)
478
288
        self._check_lines_not_unicode(lines)
479
289
        self._check_lines_are_lines(lines)
480
290
        if not sha1:
481
291
            sha1 = sha_strings(lines)
 
292
        if sha1 == nostore_sha:
 
293
            raise errors.ExistingContent
482
294
        if version_id in self._name_map:
483
295
            return self._check_repeated_add(version_id, parents, lines, sha1)
484
296
 
528
340
        # another small special case: a merge, producing the same text
529
341
        # as auto-merge
530
342
        if lines == basis_lines:
531
 
            return new_version            
 
343
            return new_version
532
344
 
533
345
        # add a sentinel, because we can also match against the final line
534
346
        basis_lineno.append(len(self._weave))
597
409
        ## except IndexError:
598
410
        ##     raise ValueError("version %d not present in weave" % v)
599
411
 
600
 
    @deprecated_method(zero_eight)
601
 
    def inclusions(self, version_ids):
602
 
        """Deprecated - see VersionedFile.get_ancestry for the replacement."""
603
 
        if not version_ids:
604
 
            return []
605
 
        if isinstance(version_ids[0], int):
606
 
            return [self._idx_to_name(v) for v in self._inclusions(version_ids)]
607
 
        else:
608
 
            return self.get_ancestry(version_ids)
609
 
 
610
412
    def get_ancestry(self, version_ids, topo_sorted=True):
611
413
        """See VersionedFile.get_ancestry."""
612
414
        if isinstance(version_ids, basestring):
649
451
        for origin, lineno, text in self._extract(incls):
650
452
            yield self._idx_to_name(origin), text
651
453
 
652
 
    @deprecated_method(zero_eight)
653
 
    def _walk(self):
654
 
        """_walk has become visit, a supported api."""
655
 
        return self._walk_internal()
656
 
 
657
454
    def iter_lines_added_or_present_in_versions(self, version_ids=None,
658
455
                                                pb=None):
659
456
        """See VersionedFile.iter_lines_added_or_present_in_versions()."""
670
467
            else:
671
468
                yield line
672
469
 
673
 
    #@deprecated_method(zero_eight)
674
 
    def walk(self, version_ids=None):
675
 
        """See VersionedFile.walk."""
676
 
        return self._walk_internal(version_ids)
677
 
 
678
470
    def _walk_internal(self, version_ids=None):
679
471
        """Helper method for weave actions."""
680
472
        
723
515
        inc_b = set(self.get_ancestry([ver_b]))
724
516
        inc_c = inc_a & inc_b
725
517
 
726
 
        for lineno, insert, deleteset, line in\
727
 
            self.walk([ver_a, ver_b]):
 
518
        for lineno, insert, deleteset, line in self._walk_internal([ver_a, ver_b]):
728
519
            if deleteset & inc_c:
729
520
                # killed in parent; can't be in either a or b
730
521
                # not relevant to our work
846
637
                                   % dset)
847
638
        return result
848
639
 
849
 
    @deprecated_method(zero_eight)
850
 
    def get_iter(self, name_or_index):
851
 
        """Deprecated, please do not use. Lookups are not not needed.
852
 
        
853
 
        Please use get_lines now.
854
 
        """
855
 
        return iter(self.get_lines(self._maybe_lookup(name_or_index)))
856
 
 
857
 
    @deprecated_method(zero_eight)
858
 
    def maybe_lookup(self, name_or_index):
859
 
        """Deprecated, please do not use. Lookups are not not needed."""
860
 
        return self._maybe_lookup(name_or_index)
861
 
 
862
640
    def _maybe_lookup(self, name_or_index):
863
641
        """Convert possible symbolic name to index, or pass through indexes.
864
642
        
869
647
        else:
870
648
            return self._lookup(name_or_index)
871
649
 
872
 
    @deprecated_method(zero_eight)
873
 
    def get(self, version_id):
874
 
        """Please use either Weave.get_text or Weave.get_lines as desired."""
875
 
        return self.get_lines(version_id)
876
 
 
877
650
    def get_lines(self, version_id):
878
651
        """See VersionedFile.get_lines()."""
879
652
        int_index = self._maybe_lookup(version_id)
891
664
        """See VersionedFile.get_sha1()."""
892
665
        return self._sha1s[self._lookup(version_id)]
893
666
 
894
 
    @deprecated_method(zero_eight)
895
 
    def numversions(self):
896
 
        """How many versions are in this weave?
897
 
 
898
 
        Deprecated in favour of num_versions.
899
 
        """
900
 
        return self.num_versions()
 
667
    def get_sha1s(self, version_ids):
 
668
        """See VersionedFile.get_sha1s()."""
 
669
        return [self._sha1s[self._lookup(v)] for v in version_ids]
901
670
 
902
671
    def num_versions(self):
903
672
        """How many versions are in this weave?"""
1062
831
        else:
1063
832
            return False
1064
833
 
1065
 
    @deprecated_method(zero_eight)
1066
 
    def reweave(self, other, pb=None, msg=None):
1067
 
        """reweave has been superseded by plain use of join."""
1068
 
        return self.join(other, pb, msg)
1069
 
 
1070
834
    def _reweave(self, other, pb, msg):
1071
835
        """Reweave self with other - internal helper for join().
1072
836
 
1105
869
            # new file, save it
1106
870
            self._save()
1107
871
 
1108
 
    def _add_lines(self, version_id, parents, lines, parent_texts):
 
872
    def _add_lines(self, version_id, parents, lines, parent_texts,
 
873
        left_matching_blocks, nostore_sha, random_id, check_content):
1109
874
        """Add a version and save the weave."""
1110
875
        self.check_not_reserved_id(version_id)
1111
876
        result = super(WeaveFile, self)._add_lines(version_id, parents, lines,
1112
 
                                                   parent_texts)
 
877
            parent_texts, left_matching_blocks, nostore_sha, random_id,
 
878
            check_content)
1113
879
        self._save()
1114
880
        return result
1115
881
 
1151
917
        self._save()
1152
918
 
1153
919
 
1154
 
@deprecated_function(zero_eight)
1155
 
def reweave(wa, wb, pb=None, msg=None):
1156
 
    """reweaving is deprecation, please just use weave.join()."""
1157
 
    _reweave(wa, wb, pb, msg)
1158
 
 
1159
920
def _reweave(wa, wb, pb=None, msg=None):
1160
921
    """Combine two weaves and return the result.
1161
922