/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 breezy/multiparent.py

  • Committer: Jelmer Vernooij
  • Date: 2017-06-10 16:40:42 UTC
  • mfrom: (6653.6.7 rename-controldir)
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170610164042-zrxqgy2htyduvke2
MergeĀ rename-controldirĀ branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
 
1
# Copyright (C) 2007-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from bzrlib.lazy_import import lazy_import
 
17
from __future__ import absolute_import
 
18
 
 
19
import errno
 
20
import os
 
21
 
 
22
from .lazy_import import lazy_import
18
23
 
19
24
lazy_import(globals(), """
20
 
import errno
 
25
import gzip
21
26
import itertools
22
 
import os
23
 
from StringIO import StringIO
24
27
 
25
 
from bzrlib import (
 
28
from breezy import (
 
29
    bencode,
26
30
    errors,
27
31
    patiencediff,
28
 
    trace,
29
32
    ui,
30
33
    )
31
 
from bzrlib import bencode
32
34
""")
33
 
from bzrlib.tuned_gzip import GzipFile
 
35
from .sixish import (
 
36
    BytesIO,
 
37
    range,
 
38
    )
34
39
 
35
40
 
36
41
def topo_iter_keys(vf, keys=None):
76
81
class MultiParent(object):
77
82
    """A multi-parent diff"""
78
83
 
 
84
    __slots__ = ['hunks']
 
85
 
79
86
    def __init__(self, hunks=None):
80
87
        if hunks is not None:
81
88
            self.hunks = hunks
111
118
        diff = MultiParent([])
112
119
        def next_block(p):
113
120
            try:
114
 
                return block_iter[p].next()
 
121
                return next(block_iter[p])
115
122
            except StopIteration:
116
123
                return None
117
124
        cur_block = [next_block(p) for p, i in enumerate(block_iter)]
162
169
        """Contruct a fulltext from this diff and its parents"""
163
170
        mpvf = MultiMemoryVersionedFile()
164
171
        for num, parent in enumerate(parents):
165
 
            mpvf.add_version(StringIO(parent).readlines(), num, [])
166
 
        mpvf.add_diff(self, 'a', range(len(parents)))
 
172
            mpvf.add_version(BytesIO(parent).readlines(), num, [])
 
173
        mpvf.add_diff(self, 'a', list(range(len(parents))))
167
174
        return mpvf.get_line_list(['a'])[0]
168
175
 
169
176
    @classmethod
170
177
    def from_texts(cls, text, parents=()):
171
178
        """Produce a MultiParent from a text and list of parent text"""
172
 
        return cls.from_lines(StringIO(text).readlines(),
173
 
                              [StringIO(p).readlines() for p in parents])
 
179
        return cls.from_lines(BytesIO(text).readlines(),
 
180
                              [BytesIO(p).readlines() for p in parents])
174
181
 
175
182
    def to_patch(self):
176
183
        """Yield text lines for a patch"""
187
194
    @classmethod
188
195
    def from_patch(cls, text):
189
196
        """Create a MultiParent from its string form"""
190
 
        return cls._from_patch(StringIO(text))
 
197
        return cls._from_patch(BytesIO(text))
191
198
 
192
199
    @staticmethod
193
200
    def _from_patch(lines):
197
204
        cur_line = None
198
205
        while(True):
199
206
            try:
200
 
                cur_line = line_iter.next()
 
207
                cur_line = next(line_iter)
201
208
            except StopIteration:
202
209
                break
203
210
            if cur_line[0] == 'i':
204
211
                num_lines = int(cur_line.split(' ')[1])
205
 
                hunk_lines = [line_iter.next() for x in xrange(num_lines)]
 
212
                hunk_lines = [next(line_iter) for _ in range(num_lines)]
206
213
                hunk_lines[-1] = hunk_lines[-1][:-1]
207
214
                hunks.append(NewText(hunk_lines))
208
215
            elif cur_line[0] == '\n':
258
265
class NewText(object):
259
266
    """The contents of text that is introduced by this text"""
260
267
 
 
268
    __slots__ = ['lines']
 
269
 
261
270
    def __init__(self, lines):
262
271
        self.lines = lines
263
272
 
279
288
class ParentText(object):
280
289
    """A reference to text present in a parent text"""
281
290
 
 
291
    __slots__ = ['parent', 'parent_pos', 'child_pos', 'num_lines']
 
292
 
282
293
    def __init__(self, parent, parent_pos, child_pos, num_lines):
283
294
        self.parent = parent
284
295
        self.parent_pos = parent_pos
285
296
        self.child_pos = child_pos
286
297
        self.num_lines = num_lines
287
298
 
 
299
    def _as_dict(self):
 
300
        return dict(parent=self.parent, parent_pos=self.parent_pos,
 
301
                    child_pos=self.child_pos, num_lines=self.num_lines)
 
302
 
288
303
    def __repr__(self):
289
 
        return 'ParentText(%(parent)r, %(parent_pos)r, %(child_pos)r,'\
290
 
            ' %(num_lines)r)' % self.__dict__
 
304
        return ('ParentText(%(parent)r, %(parent_pos)r, %(child_pos)r,'
 
305
                ' %(num_lines)r)' % self._as_dict())
291
306
 
292
307
    def __eq__(self, other):
293
308
        if self.__class__ is not other.__class__:
294
309
            return False
295
 
        return (self.__dict__ == other.__dict__)
 
310
        return self._as_dict() == other._as_dict()
296
311
 
297
312
    def to_patch(self):
298
 
        yield 'c %(parent)d %(parent_pos)d %(child_pos)d %(num_lines)d\n'\
299
 
            % self.__dict__
 
313
        yield ('c %(parent)d %(parent_pos)d %(child_pos)d %(num_lines)d\n'
 
314
               % self._as_dict())
300
315
 
301
316
 
302
317
class BaseVersionedFile(object):
324
339
            return False
325
340
        if len(parent_ids) == 0:
326
341
            return True
327
 
        for ignored in xrange(self.snapshot_interval):
 
342
        for ignored in range(self.snapshot_interval):
328
343
            if len(parent_ids) == 0:
329
344
                return False
330
345
            version_ids = parent_ids
412
427
                            if not (lines == self.get_line_list([revision])[0]):
413
428
                                raise AssertionError()
414
429
                            self.clear_cache()
415
 
                    pb.update('Importing revisions',
 
430
                    pb.update(gettext('Importing revisions'),
416
431
                              (total - len(revisions)) + len(added), total)
417
432
                revisions = [r for r in revisions if r not in added]
418
433
        finally:
548
563
        infile = open(self._filename + '.mpknit', 'rb')
549
564
        try:
550
565
            infile.seek(start)
551
 
            sio = StringIO(infile.read(count))
 
566
            sio = BytesIO(infile.read(count))
552
567
        finally:
553
568
            infile.close()
554
 
        zip_file = GzipFile(None, mode='rb', fileobj=sio)
 
569
        zip_file = gzip.GzipFile(None, mode='rb', fileobj=sio)
555
570
        try:
556
571
            file_version_id = zip_file.readline()
557
 
            return MultiParent.from_patch(zip_file.read())
 
572
            content = zip_file.read()
 
573
            return MultiParent.from_patch(content)
558
574
        finally:
559
575
            zip_file.close()
560
576
 
566
582
                                    # before any write returns 0
567
583
            start = outfile.tell()
568
584
            try:
569
 
                zipfile = GzipFile(None, mode='ab', fileobj=outfile)
 
585
                zipfile = gzip.GzipFile(None, mode='ab', fileobj=outfile)
570
586
                zipfile.writelines(itertools.chain(
571
587
                    ['version %s\n' % version_id], diff.to_patch()))
572
588
            finally:
580
596
    def destroy(self):
581
597
        try:
582
598
            os.unlink(self._filename + '.mpknit')
583
 
        except OSError, e:
 
599
        except OSError as e:
584
600
            if e.errno != errno.ENOENT:
585
601
                raise
586
602
        try:
587
603
            os.unlink(self._filename + '.mpidx')
588
 
        except OSError, e:
 
604
        except OSError as e:
589
605
            if e.errno != errno.ENOENT:
590
606
                raise
591
607
 
631
647
                start, end, kind, data, iterator = self.cursor[req_version_id]
632
648
            except KeyError:
633
649
                iterator = self.diffs.get_diff(req_version_id).range_iterator()
634
 
                start, end, kind, data = iterator.next()
 
650
                start, end, kind, data = next(iterator)
635
651
            if start > req_start:
636
652
                iterator = self.diffs.get_diff(req_version_id).range_iterator()
637
 
                start, end, kind, data = iterator.next()
 
653
                start, end, kind, data = next(iterator)
638
654
 
639
655
            # find the first hunk relevant to the request
640
656
            while end <= req_start:
641
 
                start, end, kind, data = iterator.next()
 
657
                start, end, kind, data = next(iterator)
642
658
            self.cursor[req_version_id] = start, end, kind, data, iterator
643
659
            # if the hunk can't satisfy the whole request, split it in two,
644
660
            # and leave the second half for later.
662
678
 
663
679
 
664
680
def gzip_string(lines):
665
 
    sio = StringIO()
666
 
    data_file = GzipFile(None, mode='wb', fileobj=sio)
 
681
    sio = BytesIO()
 
682
    data_file = gzip.GzipFile(None, mode='wb', fileobj=sio)
667
683
    data_file.writelines(lines)
668
684
    data_file.close()
669
685
    return sio.getvalue()