/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: 2020-05-06 02:13:25 UTC
  • mfrom: (7490.7.21 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200506021325-awbmmqu1zyorz7sj
Merge 3.1 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 __future__ import absolute_import
18
 
 
19
17
import errno
 
18
from io import (
 
19
    BytesIO,
 
20
    )
20
21
import os
21
22
 
22
23
from .lazy_import import lazy_import
24
25
lazy_import(globals(), """
25
26
import gzip
26
27
import itertools
 
28
import patiencediff
27
29
 
28
30
from breezy import (
29
31
    bencode,
30
 
    errors,
31
 
    patiencediff,
32
32
    ui,
33
33
    )
34
34
""")
35
 
from .sixish import (
36
 
    BytesIO,
37
 
    range,
 
35
from . import (
 
36
    errors,
38
37
    )
 
38
from .i18n import gettext
39
39
 
40
40
 
41
41
def topo_iter_keys(vf, keys=None):
44
44
    parents = vf.get_parent_map(keys)
45
45
    return _topo_iter(parents, keys)
46
46
 
 
47
 
47
48
def topo_iter(vf, versions=None):
48
49
    if versions is None:
49
50
        versions = vf.versions()
50
51
    parents = vf.get_parent_map(versions)
51
52
    return _topo_iter(parents, versions)
52
53
 
 
54
 
53
55
def _topo_iter(parents, versions):
54
56
    seen = set()
55
57
    descendants = {}
 
58
 
56
59
    def pending_parents(version):
57
60
        if parents[version] is None:
58
61
            return []
116
119
        parent_text = []
117
120
        block_iter = [iter(i) for i in parent_comparisons]
118
121
        diff = MultiParent([])
 
122
 
119
123
        def next_block(p):
120
124
            try:
121
125
                return next(block_iter[p])
186
190
                yield line
187
191
 
188
192
    def patch_len(self):
189
 
        return len(''.join(self.to_patch()))
 
193
        return len(b''.join(self.to_patch()))
190
194
 
191
195
    def zipped_patch_len(self):
192
196
        return len(gzip_string(self.to_patch()))
202
206
        line_iter = iter(lines)
203
207
        hunks = []
204
208
        cur_line = None
205
 
        while(True):
 
209
        while True:
206
210
            try:
207
211
                cur_line = next(line_iter)
208
212
            except StopIteration:
209
213
                break
210
 
            if cur_line[0] == 'i':
211
 
                num_lines = int(cur_line.split(' ')[1])
 
214
            first_char = cur_line[0:1]
 
215
            if first_char == b'i':
 
216
                num_lines = int(cur_line.split(b' ')[1])
212
217
                hunk_lines = [next(line_iter) for _ in range(num_lines)]
213
218
                hunk_lines[-1] = hunk_lines[-1][:-1]
214
219
                hunks.append(NewText(hunk_lines))
215
 
            elif cur_line[0] == '\n':
216
 
                hunks[-1].lines[-1] += '\n'
 
220
            elif first_char == b'\n':
 
221
                hunks[-1].lines[-1] += b'\n'
217
222
            else:
218
 
                if not (cur_line[0] == 'c'):
219
 
                    raise AssertionError(cur_line[0])
 
223
                if not (first_char == b'c'):
 
224
                    raise AssertionError(first_char)
220
225
                parent, parent_pos, child_pos, num_lines =\
221
 
                    [int(v) for v in cur_line.split(' ')[1:]]
 
226
                    [int(v) for v in cur_line.split(b' ')[1:]]
222
227
                hunks.append(ParentText(parent, parent_pos, child_pos,
223
228
                                        num_lines))
224
229
        return MultiParent(hunks)
251
256
        extra_n = 0
252
257
        for hunk in reversed(self.hunks):
253
258
            if isinstance(hunk, ParentText):
254
 
               return hunk.child_pos + hunk.num_lines + extra_n
 
259
                return hunk.child_pos + hunk.num_lines + extra_n
255
260
            extra_n += len(hunk.lines)
256
261
        return extra_n
257
262
 
279
284
        return 'NewText(%r)' % self.lines
280
285
 
281
286
    def to_patch(self):
282
 
        yield 'i %d\n' % len(self.lines)
 
287
        yield b'i %d\n' % len(self.lines)
283
288
        for line in self.lines:
284
289
            yield line
285
 
        yield '\n'
 
290
        yield b'\n'
286
291
 
287
292
 
288
293
class ParentText(object):
297
302
        self.num_lines = num_lines
298
303
 
299
304
    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)
 
305
        return {b'parent': self.parent,
 
306
                b'parent_pos': self.parent_pos,
 
307
                b'child_pos': self.child_pos,
 
308
                b'num_lines': self.num_lines}
302
309
 
303
310
    def __repr__(self):
304
311
        return ('ParentText(%(parent)r, %(parent_pos)r, %(child_pos)r,'
310
317
        return self._as_dict() == other._as_dict()
311
318
 
312
319
    def to_patch(self):
313
 
        yield ('c %(parent)d %(parent_pos)d %(child_pos)d %(num_lines)d\n'
 
320
        yield (b'c %(parent)d %(parent_pos)d %(child_pos)d %(num_lines)d\n'
314
321
               % self._as_dict())
315
322
 
316
323
 
335
342
        if self.snapshot_interval is None:
336
343
            return False
337
344
        if self.max_snapshots is not None and\
338
 
            len(self._snapshots) == self.max_snapshots:
 
345
                len(self._snapshots) == self.max_snapshots:
339
346
            return False
340
347
        if len(parent_ids) == 0:
341
348
            return True
403
410
            raise ValueError()
404
411
        revisions = set(vf.versions())
405
412
        total = len(revisions)
406
 
        pb = ui.ui_factory.nested_progress_bar()
407
 
        try:
 
413
        with ui.ui_factory.nested_progress_bar() as pb:
408
414
            while len(revisions) > 0:
409
415
                added = set()
410
416
                for revision in revisions:
411
417
                    parents = vf.get_parents(revision)
412
418
                    if [p for p in parents if p not in self._parents] != []:
413
419
                        continue
414
 
                    lines = [a + ' ' + l for a, l in
 
420
                    lines = [a + b' ' + l for a, l in
415
421
                             vf.annotate(revision)]
416
422
                    if snapshots is None:
417
423
                        force_snapshot = None
430
436
                    pb.update(gettext('Importing revisions'),
431
437
                              (total - len(revisions)) + len(added), total)
432
438
                revisions = [r for r in revisions if r not in added]
433
 
        finally:
434
 
            pb.finished()
435
439
 
436
440
    def select_snapshots(self, vf):
437
441
        """Determine which versions to add as snapshots"""
438
442
        build_ancestors = {}
439
 
        descendants = {}
440
443
        snapshots = set()
441
444
        for version_id in topo_iter(vf):
442
445
            potential_build_ancestors = set(vf.get_parents(version_id))
463
466
    def get_size_ranking(self):
464
467
        """Get versions ranked by size"""
465
468
        versions = []
466
 
        new_snapshots = set()
467
469
        for version_id in self.versions():
468
470
            if version_id in self._snapshots:
469
471
                continue
497
499
        ranking = []
498
500
        while len(available_versions) > 0:
499
501
            available_versions.sort(key=lambda x:
500
 
                len(could_avoid[x]) *
501
 
                len(referenced_by.get(x, [])))
 
502
                                    len(could_avoid[x]) *
 
503
                                    len(referenced_by.get(x, [])))
502
504
            selected = available_versions.pop()
503
505
            ranking.append(selected)
504
506
            for version_id in referenced_by[selected]:
560
562
 
561
563
    def get_diff(self, version_id):
562
564
        start, count = self._diff_offset[version_id]
563
 
        infile = open(self._filename + '.mpknit', 'rb')
564
 
        try:
 
565
        with open(self._filename + '.mpknit', 'rb') as infile:
565
566
            infile.seek(start)
566
567
            sio = BytesIO(infile.read(count))
567
 
        finally:
568
 
            infile.close()
569
 
        zip_file = gzip.GzipFile(None, mode='rb', fileobj=sio)
570
 
        try:
 
568
        with gzip.GzipFile(None, mode='rb', fileobj=sio) as zip_file:
571
569
            file_version_id = zip_file.readline()
572
570
            content = zip_file.read()
573
571
            return MultiParent.from_patch(content)
574
 
        finally:
575
 
            zip_file.close()
576
572
 
577
573
    def add_diff(self, diff, version_id, parent_ids):
578
 
        outfile = open(self._filename + '.mpknit', 'ab')
579
 
        try:
 
574
        with open(self._filename + '.mpknit', 'ab') as outfile:
580
575
            outfile.seek(0, 2)      # workaround for windows bug:
581
 
                                    # .tell() for files opened in 'ab' mode
582
 
                                    # before any write returns 0
 
576
            # .tell() for files opened in 'ab' mode
 
577
            # before any write returns 0
583
578
            start = outfile.tell()
584
 
            try:
585
 
                zipfile = gzip.GzipFile(None, mode='ab', fileobj=outfile)
 
579
            with gzip.GzipFile(None, mode='ab', fileobj=outfile) as zipfile:
586
580
                zipfile.writelines(itertools.chain(
587
 
                    ['version %s\n' % version_id], diff.to_patch()))
588
 
            finally:
589
 
                zipfile.close()
 
581
                    [b'version %s\n' % version_id], diff.to_patch()))
590
582
            end = outfile.tell()
591
 
        finally:
592
 
            outfile.close()
593
 
        self._diff_offset[version_id] = (start, end-start)
 
583
        self._diff_offset[version_id] = (start, end - start)
594
584
        self._parents[version_id] = parent_ids
595
585
 
596
586
    def destroy(self):
679
669
 
680
670
def gzip_string(lines):
681
671
    sio = BytesIO()
682
 
    data_file = gzip.GzipFile(None, mode='wb', fileobj=sio)
683
 
    data_file.writelines(lines)
684
 
    data_file.close()
 
672
    with gzip.GzipFile(None, mode='wb', fileobj=sio) as data_file:
 
673
        data_file.writelines(lines)
685
674
    return sio.getvalue()