[PATCH 1 of 2] pure/mpatch: use StringIO in case of mmap error (issue1493)
Martin Geisler
mg at daimi.au.dk
Wed Feb 11 17:37:04 CST 2009
# HG changeset patch
# User Martin Geisler <mg at daimi.au.dk>
# Date 1234395384 -3600
# Node ID 9125eb8632498449a5fcb4ce165ac175861b04d5
# Parent 998fc8f62539ee26601d526803d6da2476129411
pure/mpatch: use StringIO in case of mmap error (issue1493)
This fixes a problem on Windows which obviously does not have
/dev/zero, and on Mac OS X which does not like mmap on /dev/zero.
diff --git a/mercurial/pure/mpatch.py b/mercurial/pure/mpatch.py
--- a/mercurial/pure/mpatch.py
+++ b/mercurial/pure/mpatch.py
@@ -7,8 +7,6 @@
import struct, mmap
-devzero = file("/dev/zero")
-
# This attempts to apply a series of patches in time proportional to
# the total size of the patches, rather than patches * len(text). This
# means rather than shuffling strings around, we shuffle around
@@ -30,7 +28,35 @@
if not tl: return a
- m = mmap.mmap(devzero.fileno(), tl, mmap.MAP_PRIVATE)
+ try:
+ # try to map a piece of anonymous memory first
+ m = mmap.mmap(-1, tl, mmap.MAP_PRIVATE)
+ move = m.move
+ except EnvironmentError:
+ # Python 2.4 and older do not understand fileno = -1, try
+ # mapping /dev/zero instead
+ try:
+ devzero = file("/dev/zero")
+ m = mmap.mmap(devzero.fileno(), tl, mmap.MAP_PRIVATE)
+ move = m.move
+ except (mmap.error, IOError):
+ # fallback to StringIO if /dev/zero is not present or
+ # cannot be mapped
+ try:
+ import cStringIO as StringIO
+ except ImportError:
+ import StringIO
+
+ m = StringIO.StringIO()
+ def move(dest, src, count):
+ """move count bytes from src to dest
+
+ The file pointer is left at the end of dest.
+ """
+ m.seek(src)
+ buf = self.read(count)
+ m.seek(dest)
+ m.write(buf)
# load our original text
m.write(a)
@@ -54,7 +80,7 @@
def collect(buf, list):
start = buf
for l, p in list:
- m.move(buf, p, l)
+ move(buf, p, l)
buf += l
return (buf - start, start)
@@ -68,7 +94,8 @@
end = pos + plen
last = 0
while pos < end:
- p1, p2, l = struct.unpack(">lll", m[pos:pos + 12])
+ m.seek(pos)
+ p1, p2, l = struct.unpack(">lll", m.read(12))
pull(new, frags, p1 - last) # what didn't change
pull([], frags, p2 - p1) # what got deleted
new.append((l, pos + 12)) # what got added
@@ -78,7 +105,8 @@
t = collect(b2, frags)
- return m[t[1]:t[1] + t[0]]
+ m.seek(t[1])
+ return m.read(t[0])
def patchedsize(orig, delta):
outlen, last, bin = 0, 0, 0
More information about the Mercurial-devel
mailing list