/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

Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
77
77
        """Returns whether version is present."""
78
78
        raise NotImplementedError(self.has_version)
79
79
 
80
 
    def add_delta(self, version_id, parents, delta_parent, sha1, noeol, delta):
81
 
        """Add a text to the versioned file via a pregenerated delta.
82
 
 
83
 
        :param version_id: The version id being added.
84
 
        :param parents: The parents of the version_id.
85
 
        :param delta_parent: The parent this delta was created against.
86
 
        :param sha1: The sha1 of the full text.
87
 
        :param delta: The delta instructions. See get_delta for details.
88
 
        """
89
 
        version_id = osutils.safe_revision_id(version_id)
90
 
        parents = [osutils.safe_revision_id(v) for v in parents]
91
 
        self._check_write_ok()
92
 
        if self.has_version(version_id):
93
 
            raise errors.RevisionAlreadyPresent(version_id, self)
94
 
        return self._add_delta(version_id, parents, delta_parent, sha1, noeol, delta)
95
 
 
96
 
    def _add_delta(self, version_id, parents, delta_parent, sha1, noeol, delta):
97
 
        """Class specific routine to add a delta.
98
 
 
99
 
        This generic version simply applies the delta to the delta_parent and
100
 
        then inserts it.
101
 
        """
102
 
        # strip annotation from delta
103
 
        new_delta = []
104
 
        for start, stop, delta_len, delta_lines in delta:
105
 
            new_delta.append((start, stop, delta_len, [text for origin, text in delta_lines]))
106
 
        if delta_parent is not None:
107
 
            parent_full = self.get_lines(delta_parent)
108
 
        else:
109
 
            parent_full = []
110
 
        new_full = self._apply_delta(parent_full, new_delta)
111
 
        # its impossible to have noeol on an empty file
112
 
        if noeol and new_full[-1][-1] == '\n':
113
 
            new_full[-1] = new_full[-1][:-1]
114
 
        self.add_lines(version_id, parents, new_full)
115
 
 
116
80
    def add_lines(self, version_id, parents, lines, parent_texts=None,
117
 
                  left_matching_blocks=None):
 
81
        left_matching_blocks=None, nostore_sha=None, random_id=False,
 
82
        check_content=True):
118
83
        """Add a single text on top of the versioned file.
119
84
 
120
85
        Must raise RevisionAlreadyPresent if the new version is
122
87
 
123
88
        Must raise RevisionNotPresent if any of the given parents are
124
89
        not present in file history.
 
90
 
 
91
        :param lines: A list of lines. Each line must be a bytestring. And all
 
92
            of them except the last must be terminated with \n and contain no
 
93
            other \n's. The last line may either contain no \n's or a single
 
94
            terminated \n. If the lines list does meet this constraint the add
 
95
            routine may error or may succeed - but you will be unable to read
 
96
            the data back accurately. (Checking the lines have been split
 
97
            correctly is expensive and extremely unlikely to catch bugs so it
 
98
            is not done at runtime unless check_content is True.)
125
99
        :param parent_texts: An optional dictionary containing the opaque 
126
 
             representations of some or all of the parents of 
127
 
             version_id to allow delta optimisations. 
128
 
             VERY IMPORTANT: the texts must be those returned
129
 
             by add_lines or data corruption can be caused.
 
100
            representations of some or all of the parents of version_id to
 
101
            allow delta optimisations.  VERY IMPORTANT: the texts must be those
 
102
            returned by add_lines or data corruption can be caused.
130
103
        :param left_matching_blocks: a hint about which areas are common
131
104
            between the text and its left-hand-parent.  The format is
132
105
            the SequenceMatcher.get_matching_blocks format.
133
 
        :return: An opaque representation of the inserted version which can be
134
 
                 provided back to future add_lines calls in the parent_texts
135
 
                 dictionary.
 
106
        :param nostore_sha: Raise ExistingContent and do not add the lines to
 
107
            the versioned file if the digest of the lines matches this.
 
108
        :param random_id: If True a random id has been selected rather than
 
109
            an id determined by some deterministic process such as a converter
 
110
            from a foreign VCS. When True the backend may choose not to check
 
111
            for uniqueness of the resulting key within the versioned file, so
 
112
            this should only be done when the result is expected to be unique
 
113
            anyway.
 
114
        :param check_content: If True, the lines supplied are verified to be
 
115
            bytestrings that are correctly formed lines.
 
116
        :return: The text sha1, the number of bytes in the text, and an opaque
 
117
                 representation of the inserted version which can be provided
 
118
                 back to future add_lines calls in the parent_texts dictionary.
136
119
        """
137
120
        version_id = osutils.safe_revision_id(version_id)
138
121
        parents = [osutils.safe_revision_id(v) for v in parents]
139
122
        self._check_write_ok()
140
123
        return self._add_lines(version_id, parents, lines, parent_texts,
141
 
                               left_matching_blocks)
 
124
            left_matching_blocks, nostore_sha, random_id, check_content)
142
125
 
143
126
    def _add_lines(self, version_id, parents, lines, parent_texts,
144
 
                   left_matching_blocks):
 
127
        left_matching_blocks, nostore_sha, random_id, check_content):
145
128
        """Helper to do the class specific add_lines."""
146
129
        raise NotImplementedError(self.add_lines)
147
130
 
148
131
    def add_lines_with_ghosts(self, version_id, parents, lines,
149
 
                              parent_texts=None):
 
132
        parent_texts=None, nostore_sha=None, random_id=False,
 
133
        check_content=True):
150
134
        """Add lines to the versioned file, allowing ghosts to be present.
151
135
        
152
 
        This takes the same parameters as add_lines.
 
136
        This takes the same parameters as add_lines and returns the same.
153
137
        """
154
138
        version_id = osutils.safe_revision_id(version_id)
155
139
        parents = [osutils.safe_revision_id(v) for v in parents]
156
140
        self._check_write_ok()
157
141
        return self._add_lines_with_ghosts(version_id, parents, lines,
158
 
                                           parent_texts)
 
142
            parent_texts, nostore_sha, random_id, check_content)
159
143
 
160
 
    def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts):
 
144
    def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts,
 
145
        nostore_sha, random_id, check_content):
161
146
        """Helper to do class specific add_lines_with_ghosts."""
162
147
        raise NotImplementedError(self.add_lines_with_ghosts)
163
148
 
208
193
        already present in file history."""
209
194
        new_version_id = osutils.safe_revision_id(new_version_id)
210
195
        old_version_id = osutils.safe_revision_id(old_version_id)
 
196
        parents = [osutils.safe_revision_id(v) for v in parents]
211
197
        self._check_write_ok()
212
198
        return self._clone_text(new_version_id, old_version_id, parents)
213
199
 
224
210
        """
225
211
        raise NotImplementedError(self.create_empty)
226
212
 
227
 
    def fix_parents(self, version_id, new_parents):
228
 
        """Fix the parents list for version.
229
 
        
230
 
        This is done by appending a new version to the index
231
 
        with identical data except for the parents list.
232
 
        the parents list must be a superset of the current
233
 
        list.
234
 
        """
235
 
        version_id = osutils.safe_revision_id(version_id)
236
 
        new_parents = [osutils.safe_revision_id(p) for p in new_parents]
237
 
        self._check_write_ok()
238
 
        return self._fix_parents(version_id, new_parents)
239
 
 
240
 
    def _fix_parents(self, version_id, new_parents):
241
 
        """Helper for fix_parents."""
242
 
        raise NotImplementedError(self.fix_parents)
243
 
 
244
 
    def get_delta(self, version):
245
 
        """Get a delta for constructing version from some other version.
246
 
        
247
 
        :return: (delta_parent, sha1, noeol, delta)
248
 
        Where delta_parent is a version id or None to indicate no parent.
249
 
        """
250
 
        raise NotImplementedError(self.get_delta)
251
 
 
252
 
    def get_deltas(self, version_ids):
253
 
        """Get multiple deltas at once for constructing versions.
254
 
        
255
 
        :return: dict(version_id:(delta_parent, sha1, noeol, delta))
256
 
        Where delta_parent is a version id or None to indicate no parent, and
257
 
        version_id is the version_id created by that delta.
258
 
        """
259
 
        result = {}
260
 
        for version_id in version_ids:
261
 
            result[version_id] = self.get_delta(version_id)
262
 
        return result
263
 
 
264
213
    def get_format_signature(self):
265
214
        """Get a text description of the data encoding in this file.
266
215
        
267
 
        :since: 0.19
 
216
        :since: 0.90
268
217
        """
269
218
        raise NotImplementedError(self.get_format_signature)
270
219
 
271
220
    def make_mpdiffs(self, version_ids):
272
 
        """Create multiparent diffs for specified versions"""
 
221
        """Create multiparent diffs for specified versions."""
273
222
        knit_versions = set()
274
223
        for version_id in version_ids:
275
224
            knit_versions.add(version_id)
293
242
        return None
294
243
 
295
244
    def add_mpdiffs(self, records):
296
 
        """Add mpdiffs to this versionedfile
 
245
        """Add mpdiffs to this VersionedFile.
297
246
 
298
247
        Records should be iterables of version, parents, expected_sha1,
299
 
        mpdiff.  mpdiff should be a MultiParent instance.
 
248
        mpdiff. mpdiff should be a MultiParent instance.
300
249
        """
 
250
        # Does this need to call self._check_write_ok()? (IanC 20070919)
301
251
        vf_parents = {}
302
252
        mpvf = multiparent.MultiMemoryVersionedFile()
303
253
        versions = []
318
268
                    mpvf.get_diff(parent_ids[0]).num_lines()))
319
269
            else:
320
270
                left_matching_blocks = None
321
 
            version_text = self.add_lines(version, parent_ids, lines,
 
271
            _, _, version_text = self.add_lines(version, parent_ids, lines,
322
272
                vf_parents, left_matching_blocks=left_matching_blocks)
323
273
            vf_parents[version] = version_text
324
274
        for (version, parent_ids, expected_sha1, mpdiff), sha1 in\
329
279
    def get_sha1(self, version_id):
330
280
        """Get the stored sha1 sum for the given revision.
331
281
        
332
 
        :param name: The name of the version to lookup
 
282
        :param version_id: The name of the version to lookup
333
283
        """
334
284
        raise NotImplementedError(self.get_sha1)
335
285
 
339
289
        :param version_ids: The names of the versions to lookup
340
290
        :return: a list of sha1s in order according to the version_ids
341
291
        """
342
 
        raise NotImplementedError(self.get_sha1)
 
292
        raise NotImplementedError(self.get_sha1s)
343
293
 
344
294
    def get_suffixes(self):
345
295
        """Return the file suffixes associated with this versioned file."""
451
401
        """Yield list of (version-id, line) pairs for the specified
452
402
        version.
453
403
 
454
 
        Must raise RevisionNotPresent if any of the given versions are
 
404
        Must raise RevisionNotPresent if the given version is
455
405
        not present in file history.
456
406
        """
457
407
        raise NotImplementedError(self.annotate_iter)
459
409
    def annotate(self, version_id):
460
410
        return list(self.annotate_iter(version_id))
461
411
 
462
 
    def _apply_delta(self, lines, delta):
463
 
        """Apply delta to lines."""
464
 
        lines = list(lines)
465
 
        offset = 0
466
 
        for start, end, count, delta_lines in delta:
467
 
            lines[offset+start:offset+end] = delta_lines
468
 
            offset = offset + (start - end) + count
469
 
        return lines
470
 
 
471
412
    def join(self, other, pb=None, msg=None, version_ids=None,
472
413
             ignore_missing=False):
473
414
        """Integrate versions from other into this versioned file.
476
417
        incorporated into this versioned file.
477
418
 
478
419
        Must raise RevisionNotPresent if any of the specified versions
479
 
        are not present in the other files history unless ignore_missing
480
 
        is supplied when they are silently skipped.
 
420
        are not present in the other file's history unless ignore_missing
 
421
        is supplied in which case they are silently skipped.
481
422
        """
482
423
        self._check_write_ok()
483
424
        return InterVersionedFile.get(other, self).join(
620
561
 
621
562
 
622
563
class WeaveMerge(PlanWeaveMerge):
623
 
    """Weave merge that takes a VersionedFile and two versions as its input"""
 
564
    """Weave merge that takes a VersionedFile and two versions as its input."""
624
565
 
625
566
    def __init__(self, versionedfile, ver_a, ver_b, 
626
567
        a_marker=PlanWeaveMerge.A_MARKER, b_marker=PlanWeaveMerge.B_MARKER):
629
570
 
630
571
 
631
572
class InterVersionedFile(InterObject):
632
 
    """This class represents operations taking place between two versionedfiles..
 
573
    """This class represents operations taking place between two VersionedFiles.
633
574
 
634
575
    Its instances have methods like join, and contain
635
576
    references to the source and target versionedfiles these operations can be 
650
591
        incorporated into this versioned file.
651
592
 
652
593
        Must raise RevisionNotPresent if any of the specified versions
653
 
        are not present in the other files history unless ignore_missing is 
654
 
        supplied when they are silently skipped.
 
594
        are not present in the other file's history unless ignore_missing is 
 
595
        supplied in which case they are silently skipped.
655
596
        """
656
597
        # the default join: 
657
598
        # - if the target is empty, just add all the versions from 
684
625
            # TODO: remove parent texts when they are not relevant any more for 
685
626
            # memory pressure reduction. RBC 20060313
686
627
            # pb.update('Converting versioned data', 0, len(order))
687
 
            # deltas = self.source.get_deltas(order)
 
628
            total = len(order)
688
629
            for index, version in enumerate(order):
689
 
                pb.update('Converting versioned data', index, len(order))
690
 
                parent_text = target.add_lines(version,
 
630
                pb.update('Converting versioned data', index, total)
 
631
                _, _, parent_text = target.add_lines(version,
691
632
                                               self.source.get_parents(version),
692
633
                                               self.source.get_lines(version),
693
634
                                               parent_texts=parent_texts)
694
635
                parent_texts[version] = parent_text
695
 
                #delta_parent, sha1, noeol, delta = deltas[version]
696
 
                #target.add_delta(version,
697
 
                #                 self.source.get_parents(version),
698
 
                #                 delta_parent,
699
 
                #                 sha1,
700
 
                #                 noeol,
701
 
                #                 delta)
702
 
                #target.get_lines(version)
703
636
            
704
637
            # this should hit the native code path for target
705
638
            if target is not self.target:
708
641
                                        msg,
709
642
                                        version_ids,
710
643
                                        ignore_missing)
 
644
            else:
 
645
                return total
711
646
        finally:
712
647
            pb.finished()
713
648