prevent transient leaks of file handle by using new helper functions
These leaks may occur in environments that don't employ a reference
counting GC, i.e. PyPy.
This implies:
- changing opener(...).read() calls to opener.read(...)
- changing opener(...).write() calls to opener.write(...)
- changing open(...).read(...) to util.readfile(...)
- changing open(...).write(...) to util.writefile(...)
--- a/hgext/convert/darcs.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/convert/darcs.py Mon May 02 10:11:18 2011 +0200
@@ -191,7 +191,7 @@
if rev != self.lastrev:
raise util.Abort(_('internal calling inconsistency'))
path = os.path.join(self.tmppath, name)
- data = open(path, 'rb').read()
+ data = util.readfile(path)
mode = os.lstat(path).st_mode
mode = (mode & 0111) and 'x' or ''
return data, mode
--- a/hgext/convert/subversion.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/convert/subversion.py Mon May 02 10:11:18 2011 +0200
@@ -1028,7 +1028,7 @@
os.unlink(filename)
except OSError:
pass
- self.wopener(filename, 'w').write(data)
+ self.wopener.write(filename, data)
if self.is_exec:
was_exec = self.is_exec(self.wjoin(filename))
--- a/hgext/extdiff.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/extdiff.py Mon May 02 10:11:18 2011 +0200
@@ -97,7 +97,7 @@
if 'l' in fctx.flags():
wopener.symlink(data, wfn)
else:
- wopener(wfn, 'w').write(data)
+ wopener.write(wfn, data)
if 'x' in fctx.flags():
util.set_flags(dest, False, True)
if node is None:
--- a/hgext/gpg.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/gpg.py Mon May 02 10:11:18 2011 +0200
@@ -234,7 +234,7 @@
# write it
if opts['local']:
- repo.opener("localsigs", "ab").write(sigmessage)
+ repo.opener.append("localsigs", sigmessage)
return
msigs = match.exact(repo.root, '', ['.hgsigs'])
--- a/hgext/keyword.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/keyword.py Mon May 02 10:11:18 2011 +0200
@@ -413,7 +413,7 @@
demoitems('keywordset', ui.configitems('keywordset'))
demoitems('keywordmaps', kwmaps.iteritems())
keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
- repo.wopener(fn, 'w').write(keywords)
+ repo.wopener.write(fn, keywords)
repo[None].add([fn])
ui.note(_('\nkeywords written to %s:\n') % fn)
ui.note(keywords)
--- a/hgext/mq.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/mq.py Mon May 02 10:11:18 2011 +0200
@@ -291,14 +291,14 @@
elif l.strip():
self.ui.warn(_('malformated mq status line: %s\n') % entry)
# else we ignore empty lines
- lines = self.opener(self.status_path).read().splitlines()
+ lines = self.opener.read(self.status_path).splitlines()
return list(parselines(lines))
return []
@util.propertycache
def full_series(self):
if os.path.exists(self.join(self.series_path)):
- return self.opener(self.series_path).read().splitlines()
+ return self.opener.read(self.series_path).splitlines()
return []
@util.propertycache
@@ -412,7 +412,7 @@
if self.active_guards is None:
self.active_guards = []
try:
- guards = self.opener(self.guards_path).read().split()
+ guards = self.opener.read(self.guards_path).split()
except IOError, err:
if err.errno != errno.ENOENT:
raise
--- a/hgext/transplant.py Mon May 02 10:11:05 2011 +0200
+++ b/hgext/transplant.py Mon May 02 10:11:18 2011 +0200
@@ -39,7 +39,7 @@
def read(self):
abspath = os.path.join(self.path, self.transplantfile)
if self.transplantfile and os.path.exists(abspath):
- for line in self.opener(self.transplantfile).read().splitlines():
+ for line in self.opener.read(self.transplantfile).splitlines():
lnode, rnode = map(revlog.bin, line.split(':'))
list = self.transplants.setdefault(rnode, [])
list.append(transplantentry(lnode, rnode))
@@ -318,7 +318,7 @@
nodes = []
merges = []
cur = nodes
- for line in self.opener('series').read().splitlines():
+ for line in self.opener.read('series').splitlines():
if line.startswith('# Merges'):
cur = merges
continue
--- a/mercurial/bookmarks.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/bookmarks.py Mon May 02 10:11:18 2011 +0200
@@ -72,12 +72,12 @@
refs = repo._bookmarks
try:
- bms = repo.opener('bookmarks').read()
+ bms = repo.opener.read('bookmarks')
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
bms = ''
- repo.opener('undo.bookmarks', 'w').write(bms)
+ repo.opener.write('undo.bookmarks', bms)
if repo._bookmarkcurrent not in refs:
setcurrent(repo, None)
--- a/mercurial/cmdutil.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/cmdutil.py Mon May 02 10:11:18 2011 +0200
@@ -91,7 +91,7 @@
if logfile == '-':
message = sys.stdin.read()
else:
- message = open(logfile).read()
+ message = util.readfile(logfile)
except IOError, inst:
raise util.Abort(_("can't read commit message '%s': %s") %
(logfile, inst.strerror))
--- a/mercurial/commands.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/commands.py Mon May 02 10:11:18 2011 +0200
@@ -1129,7 +1129,7 @@
def debugfsinfo(ui, path = "."):
"""show information detected about current filesystem"""
- open('.debugfsinfo', 'w').write('')
+ util.writefile('.debugfsinfo', '')
ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
@@ -2669,7 +2669,7 @@
raise util.Abort(_('no diffs found'))
if msgs:
- repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
+ repo.opener.write('last-message.txt', '\n* * *\n'.join(msgs))
finally:
release(lock, wlock)
--- a/mercurial/dirstate.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/dirstate.py Mon May 02 10:11:18 2011 +0200
@@ -74,7 +74,7 @@
@propertycache
def _branch(self):
try:
- return self._opener("branch").read().strip() or "default"
+ return self._opener.read("branch").strip() or "default"
except IOError:
return "default"
@@ -220,13 +220,13 @@
if branch in ['tip', '.', 'null']:
raise util.Abort(_('the name \'%s\' is reserved') % branch)
self._branch = encoding.fromlocal(branch)
- self._opener("branch", "w").write(self._branch + '\n')
+ self._opener.write("branch", self._branch + '\n')
def _read(self):
self._map = {}
self._copymap = {}
try:
- st = self._opener("dirstate").read()
+ st = self._opener.read("dirstate")
except IOError, err:
if err.errno != errno.ENOENT:
raise
--- a/mercurial/filemerge.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/filemerge.py Mon May 02 10:11:18 2011 +0200
@@ -113,14 +113,14 @@
def _matcheol(file, origfile):
"Convert EOL markers in a file to match origfile"
- tostyle = _eoltype(open(origfile, "rb").read())
+ tostyle = _eoltype(util.readfile(origfile))
if tostyle:
- data = open(file, "rb").read()
+ data = util.readfile(file)
style = _eoltype(data)
if style:
newdata = data.replace(style, tostyle)
if newdata != data:
- open(file, "wb").write(newdata)
+ util.writefile(file, newdata)
def filemerge(repo, mynode, orig, fcd, fco, fca):
"""perform a 3-way merge in the working directory
--- a/mercurial/help.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/help.py Mon May 02 10:11:18 2011 +0200
@@ -8,6 +8,7 @@
from i18n import gettext, _
import sys, os
import extensions
+import util
def moduledoc(file):
@@ -79,7 +80,7 @@
break
path = os.path.join(docdir, topic + ".txt")
- doc = gettext(open(path).read())
+ doc = gettext(util.readfile(path))
for rewriter in helphooks.get(topic, []):
doc = rewriter(topic, doc)
return doc
--- a/mercurial/hg.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/hg.py Mon May 02 10:11:18 2011 +0200
@@ -137,14 +137,14 @@
requirements = ''
try:
- requirements = srcrepo.opener('requires').read()
+ requirements = srcrepo.opener.read('requires')
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
requirements += 'shared\n'
- file(os.path.join(roothg, 'requires'), 'w').write(requirements)
- file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
+ util.writefile(os.path.join(roothg, 'requires'), requirements)
+ util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
r = repository(ui, root)
--- a/mercurial/localrepo.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/localrepo.py Mon May 02 10:11:18 2011 +0200
@@ -56,7 +56,8 @@
if self.ui.configbool('format', 'dotencode', True):
requirements.append('dotencode')
# create an invalid changelog
- self.opener("00changelog.i", "a").write(
+ self.opener.append(
+ "00changelog.i",
'\0\0\0\2' # represents revlogv2
' dummy changelog to prevent using the old repo layout'
)
@@ -70,7 +71,7 @@
# find requirements
requirements = set()
try:
- requirements = set(self.opener("requires").read().splitlines())
+ requirements = set(self.opener.read("requires").splitlines())
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
@@ -80,7 +81,7 @@
self.sharedpath = self.path
try:
- s = os.path.realpath(self.opener("sharedpath").read())
+ s = os.path.realpath(self.opener.read("sharedpath"))
if not os.path.exists(s):
raise error.RepoError(
_('.hg/sharedpath points to nonexistent directory %s') % s)
@@ -652,7 +653,7 @@
if self._link(filename):
data = os.readlink(self.wjoin(filename))
else:
- data = self.wopener(filename, 'r').read()
+ data = self.wopener.read(filename)
return self._filter(self._encodefilterpats, filename, data)
def wwrite(self, filename, data, flags):
@@ -660,7 +661,7 @@
if 'l' in flags:
self.wopener.symlink(data, filename)
else:
- self.wopener(filename, 'w').write(data)
+ fp = self.wopener.write(filename, data)
if 'x' in flags:
util.set_flags(self.wjoin(filename), False, True)
@@ -679,13 +680,14 @@
# save dirstate for rollback
try:
- ds = self.opener("dirstate").read()
+ ds = self.opener.read("dirstate")
except IOError:
ds = ""
- self.opener("journal.dirstate", "w").write(ds)
- self.opener("journal.branch", "w").write(
- encoding.fromlocal(self.dirstate.branch()))
- self.opener("journal.desc", "w").write("%d\n%s\n" % (len(self), desc))
+ self.opener.write("journal.dirstate", ds)
+ self.opener.write("journal.branch",
+ encoding.fromlocal(self.dirstate.branch()))
+ self.opener.write("journal.desc",
+ "%d\n%s\n" % (len(self), desc))
renames = [(self.sjoin("journal"), self.sjoin("undo")),
(self.join("journal.dirstate"), self.join("undo.dirstate")),
@@ -720,7 +722,7 @@
lock = self.lock()
if os.path.exists(self.sjoin("undo")):
try:
- args = self.opener("undo.desc", "r").read().splitlines()
+ args = self.opener.read("undo.desc").splitlines()
if len(args) >= 3 and self.ui.verbose:
desc = _("repository tip rolled back to revision %s"
" (undo %s: %s)\n") % (
@@ -741,7 +743,7 @@
util.rename(self.join('undo.bookmarks'),
self.join('bookmarks'))
try:
- branch = self.opener("undo.branch").read()
+ branch = self.opener.read("undo.branch")
self.dirstate.setbranch(branch)
except IOError:
self.ui.warn(_("named branch could not be reset, "
--- a/mercurial/match.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/match.py Mon May 02 10:11:18 2011 +0200
@@ -275,7 +275,7 @@
elif kind in ('listfile', 'listfile0'):
delimiter = kind == 'listfile0' and '\0' or '\n'
try:
- files = open(name, 'r').read().split(delimiter)
+ files = util.readfile(name).split(delimiter)
files = [f for f in files if f]
except EnvironmentError:
raise util.Abort(_("unable to read file list (%s)") % name)
--- a/mercurial/merge.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/merge.py Mon May 02 10:11:18 2011 +0200
@@ -47,7 +47,7 @@
self._dirty = False
def add(self, fcl, fco, fca, fd, flags):
hash = util.sha1(fcl.path()).hexdigest()
- self._repo.opener("merge/" + hash, "w").write(fcl.data())
+ self._repo.opener.write("merge/" + hash, fcl.data())
self._state[fd] = ['u', hash, fcl.path(), fca.path(),
hex(fca.filenode()), fco.path(), flags]
self._dirty = True
--- a/mercurial/minirst.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/minirst.py Mon May 02 10:11:18 2011 +0200
@@ -467,7 +467,7 @@
print
return blocks
- text = open(sys.argv[1]).read()
+ text = util.readfile(sys.argv[1])
blocks = debug(findblocks, text)
blocks = debug(findliteralblocks, blocks)
blocks, pruned = debug(prunecontainers, blocks, sys.argv[2:])
--- a/mercurial/statichttprepo.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/statichttprepo.py Mon May 02 10:11:18 2011 +0200
@@ -93,7 +93,7 @@
# find requirements
try:
- requirements = self.opener("requires").read().splitlines()
+ requirements = self.opener.read("requires").splitlines()
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
--- a/mercurial/tags.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/tags.py Mon May 02 10:11:18 2011 +0200
@@ -60,7 +60,7 @@
def readlocaltags(ui, repo, alltags, tagtypes):
'''Read local tags in repo. Update alltags and tagtypes.'''
try:
- data = repo.opener("localtags").read()
+ data = repo.opener.read("localtags")
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
--- a/mercurial/templater.py Mon May 02 10:11:05 2011 +0200
+++ b/mercurial/templater.py Mon May 02 10:11:18 2011 +0200
@@ -311,7 +311,7 @@
'''Get the template for the given template name. Use a local cache.'''
if not t in self.cache:
try:
- self.cache[t] = open(self.map[t][1]).read()
+ self.cache[t] = util.readfile(self.map[t][1])
except KeyError, inst:
raise util.Abort(_('"%s" not in template map') % inst.args[0])
except IOError, inst:
--- a/tests/test-symlink-os-yes-fs-no.py Mon May 02 10:11:05 2011 +0200
+++ b/tests/test-symlink-os-yes-fs-no.py Mon May 02 10:11:18 2011 +0200
@@ -1,5 +1,5 @@
import os, sys, time
-from mercurial import hg, ui, commands
+from mercurial import hg, ui, commands, util
TESTDIR = os.environ["TESTDIR"]
BUNDLEPATH = os.path.join(TESTDIR, 'bundles', 'test-no-symlinks.hg')
@@ -29,7 +29,7 @@
for f in 'test0/a.lnk', 'test0/d/b.lnk':
os.unlink(f)
fp = open(f, 'wb')
- fp.write(open(f[:-4]).read())
+ fp.write(util.readfile(f[:-4]))
fp.close()
# reload repository