/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/versionedfile.py

  • Committer: Andrew Bennetts
  • Date: 2008-04-02 00:14:00 UTC
  • mfrom: (3324 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3756.
  • Revision ID: andrew.bennetts@canonical.com-20080402001400-r1pqse38i03dl97w
Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
    revision,
31
31
    ui,
32
32
    )
 
33
from bzrlib.graph import Graph
33
34
from bzrlib.transport.memory import MemoryTransport
34
35
""")
35
36
 
36
37
from cStringIO import StringIO
37
38
 
38
39
from bzrlib.inter import InterObject
 
40
from bzrlib.symbol_versioning import *
39
41
from bzrlib.textmerge import TextMerge
40
42
 
41
43
 
69
71
        """Return a unsorted list of versions."""
70
72
        raise NotImplementedError(self.versions)
71
73
 
 
74
    @deprecated_method(one_four)
72
75
    def has_ghost(self, version_id):
73
76
        """Returns whether version is present as a ghost."""
74
77
        raise NotImplementedError(self.has_ghost)
128
131
 
129
132
    def add_lines_with_ghosts(self, version_id, parents, lines,
130
133
        parent_texts=None, nostore_sha=None, random_id=False,
131
 
        check_content=True):
 
134
        check_content=True, left_matching_blocks=None):
132
135
        """Add lines to the versioned file, allowing ghosts to be present.
133
136
        
134
137
        This takes the same parameters as add_lines and returns the same.
135
138
        """
136
139
        self._check_write_ok()
137
140
        return self._add_lines_with_ghosts(version_id, parents, lines,
138
 
            parent_texts, nostore_sha, random_id, check_content)
 
141
            parent_texts, nostore_sha, random_id, check_content, left_matching_blocks)
139
142
 
140
143
    def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts,
141
 
        nostore_sha, random_id, check_content):
 
144
        nostore_sha, random_id, check_content, left_matching_blocks):
142
145
        """Helper to do class specific add_lines_with_ghosts."""
143
146
        raise NotImplementedError(self.add_lines_with_ghosts)
144
147
 
213
216
    def make_mpdiffs(self, version_ids):
214
217
        """Create multiparent diffs for specified versions."""
215
218
        knit_versions = set()
 
219
        knit_versions.update(version_ids)
 
220
        parent_map = self.get_parent_map(version_ids)
216
221
        for version_id in version_ids:
217
 
            knit_versions.add(version_id)
218
 
            knit_versions.update(self.get_parents(version_id))
 
222
            try:
 
223
                knit_versions.update(parent_map[version_id])
 
224
            except KeyError:
 
225
                raise RevisionNotPresent(version_id, self)
 
226
        # We need to filter out ghosts, because we can't diff against them.
 
227
        knit_versions = set(self.get_parent_map(knit_versions).keys())
219
228
        lines = dict(zip(knit_versions,
220
229
            self._get_lf_split_line_list(knit_versions)))
221
230
        diffs = []
222
231
        for version_id in version_ids:
223
232
            target = lines[version_id]
224
 
            parents = [lines[p] for p in self.get_parents(version_id)]
 
233
            try:
 
234
                parents = [lines[p] for p in parent_map[version_id] if p in
 
235
                    knit_versions]
 
236
            except KeyError:
 
237
                raise RevisionNotPresent(version_id, self)
225
238
            if len(parents) > 0:
226
239
                left_parent_blocks = self._extract_blocks(version_id,
227
240
                                                          parents[0], target)
251
264
        for version, parent_ids, expected_sha1, mpdiff in records:
252
265
            needed_parents.update(p for p in parent_ids
253
266
                                  if not mpvf.has_version(p))
254
 
        for parent_id, lines in zip(needed_parents,
255
 
                                 self._get_lf_split_line_list(needed_parents)):
 
267
        present_parents = set(self.get_parent_map(needed_parents).keys())
 
268
        for parent_id, lines in zip(present_parents,
 
269
                                 self._get_lf_split_line_list(present_parents)):
256
270
            mpvf.add_version(lines, parent_id, [])
257
271
        for (version, parent_ids, expected_sha1, mpdiff), lines in\
258
272
            zip(records, mpvf.get_line_list(versions)):
261
275
                    mpvf.get_diff(parent_ids[0]).num_lines()))
262
276
            else:
263
277
                left_matching_blocks = None
264
 
            _, _, version_text = self.add_lines(version, parent_ids, lines,
265
 
                vf_parents, left_matching_blocks=left_matching_blocks)
 
278
            try:
 
279
                _, _, version_text = self.add_lines_with_ghosts(version,
 
280
                    parent_ids, lines, vf_parents,
 
281
                    left_matching_blocks=left_matching_blocks)
 
282
            except NotImplementedError:
 
283
                # The vf can't handle ghosts, so add lines normally, which will
 
284
                # (reasonably) fail if there are ghosts in the data.
 
285
                _, _, version_text = self.add_lines(version,
 
286
                    parent_ids, lines, vf_parents,
 
287
                    left_matching_blocks=left_matching_blocks)
266
288
            vf_parents[version] = version_text
267
289
        for (version, parent_ids, expected_sha1, mpdiff), sha1 in\
268
290
             zip(records, self.get_sha1s(versions)):
363
385
                    pending.add(parent)
364
386
        return result
365
387
 
 
388
    @deprecated_method(one_four)
366
389
    def get_graph_with_ghosts(self):
367
390
        """Return a graph for the entire versioned file.
368
391
        
371
394
        """
372
395
        raise NotImplementedError(self.get_graph_with_ghosts)
373
396
 
 
397
    def get_parent_map(self, version_ids):
 
398
        """Get a map of the parents of version_ids.
 
399
 
 
400
        :param version_ids: The version ids to look up parents for.
 
401
        :return: A mapping from version id to parents.
 
402
        """
 
403
        raise NotImplementedError(self.get_parent_map)
 
404
 
 
405
    @deprecated_method(one_four)
374
406
    def get_parents(self, version_id):
375
407
        """Return version names for parents of a version.
376
408
 
377
409
        Must raise RevisionNotPresent if version is not present in
378
410
        file history.
379
411
        """
380
 
        raise NotImplementedError(self.get_parents)
 
412
        try:
 
413
            all = self.get_parent_map([version_id])[version_id]
 
414
        except KeyError:
 
415
            raise errors.RevisionNotPresent(version_id, self)
 
416
        result = []
 
417
        parent_parents = self.get_parent_map(all)
 
418
        for version_id in all:
 
419
            if version_id in parent_parents:
 
420
                result.append(version_id)
 
421
        return result
381
422
 
382
423
    def get_parents_with_ghosts(self, version_id):
383
424
        """Return version names for parents of version_id.
388
429
        Ghosts that are known about will be included in the parent list,
389
430
        but are not explicitly marked.
390
431
        """
391
 
        raise NotImplementedError(self.get_parents_with_ghosts)
 
432
        try:
 
433
            return list(self.get_parent_map([version_id])[version_id])
 
434
        except KeyError:
 
435
            raise errors.RevisionNotPresent(version_id, self)
392
436
 
393
437
    def annotate_iter(self, version_id):
394
438
        """Yield list of (version-id, line) pairs for the specified
451
495
            The order is undefined, allowing for different optimisations in
452
496
            the underlying implementation.
453
497
        """
454
 
        for version_id in version_ids:
455
 
            try:
456
 
                yield version_id, tuple(self.get_parents(version_id))
457
 
            except errors.RevisionNotPresent:
458
 
                pass
 
498
        return self.get_parent_map(version_ids).iteritems()
459
499
 
460
500
    def transaction_finished(self):
461
501
        """The transaction that this file was opened in has finished.
547
587
            raise ValueError('Parents may not be None')
548
588
        if lines is None:
549
589
            raise ValueError('Lines may not be None')
550
 
        self._parents[version_id] = parents
 
590
        self._parents[version_id] = tuple(parents)
551
591
        self._lines[version_id] = lines
552
592
 
553
593
    def get_lines(self, version_id):
590
630
            ancestry.update(self.get_ancestry(parent, topo_sorted=False))
591
631
        return ancestry
592
632
 
593
 
    def get_parents(self, version_id):
594
 
        """See VersionedFile.get_parents"""
595
 
        parents = self._parents.get(version_id)
596
 
        if parents is not None:
597
 
            return parents
 
633
    def get_parent_map(self, version_ids):
 
634
        """See VersionedFile.get_parent_map"""
 
635
        result = {}
 
636
        pending = set(version_ids)
 
637
        for key in version_ids:
 
638
            try:
 
639
                result[key] = self._parents[key]
 
640
            except KeyError:
 
641
                pass
 
642
        pending = pending - set(result.keys())
598
643
        for versionedfile in self.fallback_versionedfiles:
599
 
            try:
600
 
                return versionedfile.get_parents(version_id)
601
 
            except errors.RevisionNotPresent:
602
 
                continue
603
 
        else:
604
 
            raise errors.RevisionNotPresent(version_id, self._file_id)
 
644
            parents = versionedfile.get_parent_map(pending)
 
645
            result.update(parents)
 
646
            pending = pending - set(parents.keys())
 
647
            if not pending:
 
648
                return result
 
649
        return result
605
650
 
606
651
    def _get_graph(self):
607
652
        from bzrlib.graph import (
733
778
            temp_source = self.target.create_empty("temp", MemoryTransport())
734
779
            target = temp_source
735
780
        version_ids = self._get_source_version_ids(version_ids, ignore_missing)
736
 
        graph = self.source.get_graph(version_ids)
737
 
        order = tsort.topo_sort(graph.items())
 
781
        graph = Graph(self.source)
 
782
        search = graph._make_breadth_first_searcher(version_ids)
 
783
        transitive_ids = set()
 
784
        map(transitive_ids.update, list(search))
 
785
        parent_map = self.source.get_parent_map(transitive_ids)
 
786
        order = tsort.topo_sort(parent_map.items())
738
787
        pb = ui.ui_factory.nested_progress_bar()
739
788
        parent_texts = {}
740
789
        try:
755
804
            for index, version in enumerate(order):
756
805
                pb.update('Converting versioned data', index, total)
757
806
                _, _, parent_text = target.add_lines(version,
758
 
                                               self.source.get_parents(version),
 
807
                                               parent_map[version],
759
808
                                               self.source.get_lines(version),
760
809
                                               parent_texts=parent_texts)
761
810
                parent_texts[version] = parent_text