[PATCH STABLE] posix: insert seek between reads and writes on Solaris (issue4943)
Adrian Buehlmann
adrian at cadifra.com
Mon Nov 16 08:29:49 UTC 2015
On 2015-11-16 00:34, Adrian Buehlmann wrote:
> On 2015-11-15 23:21, Gregory Szorc wrote:
>> Yes, we copied a large block of source code. This is not ideal.
>> However, posix.py and windows.py are very low level modules. There
>> is no obvious existing module we could add the function to without
>> introducing an import cycle. A new module will likely need to be
>> invented. I'm not comfortable doing that on the stable branch.
>> Once this patch is merged into @, we should clean up the duplicated
>> code.
>
> Perhaps you could move mixedfilemodewrapper to util.py and do the
> wrapping there for the Solaris and Windows cases.
>
> Likely not appropriate for stable indeed...
I was thinking of something like this (completely untested):
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -24,6 +24,7 @@
import gc
import bz2
import zlib
+import platform as pyplatform
if os.name == 'nt':
import windows as platform
@@ -91,6 +92,78 @@
def safehasattr(thing, attr):
return getattr(thing, attr, _notset) is not _notset
+class mixedfilemodewrapper(object):
+ """Wraps a file handle when it is opened in read/write mode.
+
+ This class wraps posixfile instances when the file is opened in read/write
+ mode and automatically adds checks or inserts appropriate file positioning
+ calls when necessary.
+ """
+ OPNONE = 0
+ OPREAD = 1
+ OPWRITE = 2
+
+ def __init__(self, fp):
+ object.__setattr__(self, '_fp', fp)
+ object.__setattr__(self, '_lastop', 0)
+
+ def __getattr__(self, name):
+ return getattr(self._fp, name)
+
+ def __setattr__(self, name, value):
+ return self._fp.__setattr__(name, value)
+
+ def _noopseek(self):
+ self._fp.seek(0, os.SEEK_CUR)
+
+ def seek(self, *args, **kwargs):
+ object.__setattr__(self, '_lastop', self.OPNONE)
+ return self._fp.seek(*args, **kwargs)
+
+ def write(self, d):
+ if self._lastop == self.OPREAD:
+ self._noopseek()
+
+ object.__setattr__(self, '_lastop', self.OPWRITE)
+ return self._fp.write(d)
+
+ def writelines(self, *args, **kwargs):
+ if self._lastop == self.OPREAD:
+ self._noopeseek()
+
+ object.__setattr__(self, '_lastop', self.OPWRITE)
+ return self._fp.writelines(*args, **kwargs)
+
+ def read(self, *args, **kwargs):
+ if self._lastop == self.OPWRITE:
+ self._noopseek()
+
+ object.__setattr__(self, '_lastop', self.OPREAD)
+ return self._fp.read(*args, **kwargs)
+
+ def readline(self, *args, **kwargs):
+ if self._lastop == self.OPWRITE:
+ self._noopseek()
+
+ object.__setattr__(self, '_lastop', self.OPREAD)
+ return self._fp.readline(*args, **kwargs)
+
+ def readlines(self, *args, **kwargs):
+ if self._lastop == self.OPWRITE:
+ self._noopseek()
+
+ object.__setattr__(self, '_lastop', self.OPREAD)
+ return self._fp.readlines(*args, **kwargs)
+
+def _wrappedposixfile(name, mode='r', buffering=-1):
+ fp = platform.posixfile(name, mode, buffering)
+ if '+' in mode:
+ return mixedfilemodewrapper(fp)
+ return fp
+
+if os.name == 'nt' or pyplatform.system() == 'SunOS'
+ posixfile = _wrappedposixfile
+
from hashlib import md5, sha1
DIGESTS = {
diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -27,73 +27,6 @@
umask = 0o022
-class mixedfilemodewrapper(object):
- """Wraps a file handle when it is opened in read/write mode.
-
- fopen() and fdopen() on Windows have a specific-to-Windows requirement
- that files opened with mode r+, w+, or a+ make a call to a file positioning
- function when switching between reads and writes. Without this extra call,
- Python will raise a not very intuitive "IOError: [Errno 0] Error."
-
- This class wraps posixfile instances when the file is opened in read/write
- mode and automatically adds checks or inserts appropriate file positioning
- calls when necessary.
- """
- OPNONE = 0
- OPREAD = 1
- OPWRITE = 2
-
- def __init__(self, fp):
- object.__setattr__(self, '_fp', fp)
- object.__setattr__(self, '_lastop', 0)
-
- def __getattr__(self, name):
- return getattr(self._fp, name)
-
- def __setattr__(self, name, value):
- return self._fp.__setattr__(name, value)
-
- def _noopseek(self):
- self._fp.seek(0, os.SEEK_CUR)
-
- def seek(self, *args, **kwargs):
- object.__setattr__(self, '_lastop', self.OPNONE)
- return self._fp.seek(*args, **kwargs)
-
- def write(self, d):
- if self._lastop == self.OPREAD:
- self._noopseek()
-
- object.__setattr__(self, '_lastop', self.OPWRITE)
- return self._fp.write(d)
-
- def writelines(self, *args, **kwargs):
- if self._lastop == self.OPREAD:
- self._noopeseek()
-
- object.__setattr__(self, '_lastop', self.OPWRITE)
- return self._fp.writelines(*args, **kwargs)
-
- def read(self, *args, **kwargs):
- if self._lastop == self.OPWRITE:
- self._noopseek()
-
- object.__setattr__(self, '_lastop', self.OPREAD)
- return self._fp.read(*args, **kwargs)
-
- def readline(self, *args, **kwargs):
- if self._lastop == self.OPWRITE:
- self._noopseek()
-
- object.__setattr__(self, '_lastop', self.OPREAD)
- return self._fp.readline(*args, **kwargs)
-
- def readlines(self, *args, **kwargs):
- if self._lastop == self.OPWRITE:
- self._noopseek()
-
- object.__setattr__(self, '_lastop', self.OPREAD)
- return self._fp.readlines(*args, **kwargs)
def posixfile(name, mode='r', buffering=-1):
'''Open a file with even more POSIX-like semantics'''
@@ -105,9 +38,6 @@
if 'a' in mode:
fp.seek(0, os.SEEK_END)
- if '+' in mode:
- return mixedfilemodewrapper(fp)
-
return fp
except WindowsError as err:
# convert to a friendlier exception
More information about the Mercurial-devel
mailing list