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

  • Committer: John Arbash Meinel
  • Date: 2011-04-20 14:27:19 UTC
  • mto: This revision was merged to the branch mainline in revision 5837.
  • Revision ID: john@arbash-meinel.com-20110420142719-advs1k5vztqzbrgv
Fix bug #767177. Be more agressive with file.close() calls.

Our test suite gets a number of thread leaks and failures because it happens to get async
SFTPFile.close() calls. (if an SFTPFile closes due to __del__ it is done as an async request,
while if you call SFTPFile.close() it is done as a synchronous request.)
We have a couple other cases, probably. Namely SFTPTransport.get() also does an async
prefetch of the content, so if you don't .read() you'll also leak threads that think they
are doing work that you want.

The biggest change here, though, is using a try/finally in a generator, which is not 
python2.4 compatible.

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
18
18
 
19
19
lazy_import(globals(), """
20
20
import errno
 
21
import gzip
21
22
import itertools
22
23
import os
23
24
from StringIO import StringIO
24
25
 
25
26
from bzrlib import (
 
27
    bencode,
26
28
    errors,
27
29
    patiencediff,
28
 
    trace,
29
30
    ui,
30
31
    )
31
 
from bzrlib import bencode
32
32
""")
33
 
from bzrlib.tuned_gzip import GzipFile
34
33
 
35
34
 
36
35
def topo_iter_keys(vf, keys=None):
76
75
class MultiParent(object):
77
76
    """A multi-parent diff"""
78
77
 
 
78
    __slots__ = ['hunks']
 
79
 
79
80
    def __init__(self, hunks=None):
80
81
        if hunks is not None:
81
82
            self.hunks = hunks
258
259
class NewText(object):
259
260
    """The contents of text that is introduced by this text"""
260
261
 
 
262
    __slots__ = ['lines']
 
263
 
261
264
    def __init__(self, lines):
262
265
        self.lines = lines
263
266
 
279
282
class ParentText(object):
280
283
    """A reference to text present in a parent text"""
281
284
 
 
285
    __slots__ = ['parent', 'parent_pos', 'child_pos', 'num_lines']
 
286
 
282
287
    def __init__(self, parent, parent_pos, child_pos, num_lines):
283
288
        self.parent = parent
284
289
        self.parent_pos = parent_pos
285
290
        self.child_pos = child_pos
286
291
        self.num_lines = num_lines
287
292
 
 
293
    def _as_dict(self):
 
294
        return dict(parent=self.parent, parent_pos=self.parent_pos,
 
295
                    child_pos=self.child_pos, num_lines=self.num_lines)
 
296
 
288
297
    def __repr__(self):
289
 
        return 'ParentText(%(parent)r, %(parent_pos)r, %(child_pos)r,'\
290
 
            ' %(num_lines)r)' % self.__dict__
 
298
        return ('ParentText(%(parent)r, %(parent_pos)r, %(child_pos)r,'
 
299
                ' %(num_lines)r)' % self._as_dict())
291
300
 
292
301
    def __eq__(self, other):
293
302
        if self.__class__ is not other.__class__:
294
303
            return False
295
 
        return (self.__dict__ == other.__dict__)
 
304
        return self._as_dict() == other._as_dict()
296
305
 
297
306
    def to_patch(self):
298
 
        yield 'c %(parent)d %(parent_pos)d %(child_pos)d %(num_lines)d\n'\
299
 
            % self.__dict__
 
307
        yield ('c %(parent)d %(parent_pos)d %(child_pos)d %(num_lines)d\n'
 
308
               % self._as_dict())
300
309
 
301
310
 
302
311
class BaseVersionedFile(object):
551
560
            sio = StringIO(infile.read(count))
552
561
        finally:
553
562
            infile.close()
554
 
        zip_file = GzipFile(None, mode='rb', fileobj=sio)
 
563
        zip_file = gzip.GzipFile(None, mode='rb', fileobj=sio)
555
564
        try:
556
565
            file_version_id = zip_file.readline()
557
 
            return MultiParent.from_patch(zip_file.read())
 
566
            content = zip_file.read()
 
567
            return MultiParent.from_patch(content)
558
568
        finally:
559
569
            zip_file.close()
560
570
 
566
576
                                    # before any write returns 0
567
577
            start = outfile.tell()
568
578
            try:
569
 
                zipfile = GzipFile(None, mode='ab', fileobj=outfile)
 
579
                zipfile = gzip.GzipFile(None, mode='ab', fileobj=outfile)
570
580
                zipfile.writelines(itertools.chain(
571
581
                    ['version %s\n' % version_id], diff.to_patch()))
572
582
            finally:
663
673
 
664
674
def gzip_string(lines):
665
675
    sio = StringIO()
666
 
    data_file = GzipFile(None, mode='wb', fileobj=sio)
 
676
    data_file = gzip.GzipFile(None, mode='wb', fileobj=sio)
667
677
    data_file.writelines(lines)
668
678
    data_file.close()
669
679
    return sio.getvalue()