~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revfile.py

  • Committer: mbp at sourcefrog
  • Date: 2005-04-09 05:46:59 UTC
  • Revision ID: mbp@sourcefrog.net-20050409054658-ca33d05257f261997ccd9b2b
limit the number of chained patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
94
94
 
95
95
FL_GZIP = 1
96
96
 
 
97
# maximum number of patches in a row before recording a whole text.
 
98
# intentionally pretty low for testing purposes.
 
99
CHAIN_LIMIT = 2
 
100
 
97
101
 
98
102
class RevfileError(Exception):
99
103
    pass
100
104
 
101
 
 
 
105
class LimitHitException(Exception):
 
106
    pass
102
107
 
103
108
class Revfile:
104
109
    def __init__(self, basename):
199
204
        
200
205
 
201
206
 
202
 
    def _add_full_text(self, text, text_sha):
 
207
    def _add_full_text(self, text, text_sha, compress):
203
208
        """Add a full text to the file.
204
209
 
205
210
        This is not compressed against any reference version.
211
216
    def _add_delta(self, text, text_sha, base, compress):
212
217
        """Add a text stored relative to a previous text."""
213
218
        self._check_index(base)
214
 
        base_text = self.get(base)
 
219
        
 
220
        try:
 
221
            base_text = self.get(base, recursion_limit=CHAIN_LIMIT)
 
222
        except LimitHitException:
 
223
            return self._add_full_text(text, text_sha, compress)
 
224
        
215
225
        data = mdiff.bdiff(base_text, text)
216
226
        
217
227
        # If the delta is larger than the text, we might as well just
253
263
 
254
264
 
255
265
 
256
 
    def get(self, idx):
 
266
    def get(self, idx, recursion_limit=None):
 
267
        """Retrieve text of a previous revision.
 
268
 
 
269
        If recursion_limit is an integer then walk back at most that
 
270
        many revisions and then raise LimitHitException, indicating
 
271
        that we ought to record a new file text instead of another
 
272
        delta.  Don't use this when trying to get out an existing
 
273
        revision."""
 
274
        
257
275
        idxrec = self[idx]
258
276
        base = idxrec[I_BASE]
259
277
        if base == _NO_RECORD:
260
278
            text = self._get_full_text(idx, idxrec)
261
279
        else:
262
 
            text = self._get_patched(idx, idxrec)
 
280
            text = self._get_patched(idx, idxrec, recursion_limit)
263
281
 
264
282
        if sha.new(text).digest() != idxrec[I_SHA]:
265
283
            raise RevfileError("corrupt SHA-1 digest on record %d"
301
319
        return text
302
320
 
303
321
 
304
 
    def _get_patched(self, idx, idxrec):
 
322
    def _get_patched(self, idx, idxrec, recursion_limit):
305
323
        base = idxrec[I_BASE]
306
324
        assert base >= 0
307
325
        assert base < idx    # no loops!
308
326
 
309
 
        base_text = self.get(base)
 
327
        if recursion_limit == None:
 
328
            sub_limit = None
 
329
        else:
 
330
            sub_limit = recursion_limit - 1
 
331
            if sub_limit < 0:
 
332
                raise LimitHitException()
 
333
            
 
334
        base_text = self.get(base, sub_limit)
310
335
        patch = self._get_raw(idx, idxrec)
311
336
 
312
337
        text = mdiff.bpatch(base_text, patch)