Multiple code path assume vfs have an options attribute, including the vfs module
itself. So for consistency we explicitly add one to all vfs.
This will prevent various crash in the next changesets.
martinvonz | |
durin42 | |
indygreg |
hg-reviewers |
Multiple code path assume vfs have an options attribute, including the vfs module
itself. So for consistency we explicitly add one to all vfs.
This will prevent various crash in the next changesets.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | contrib/dumprevlog (1 line) | |||
M | mercurial/revlog.py (4 lines) | |||
M | mercurial/statichttprepo.py (1 line) | |||
M | mercurial/vfs.py (1 line) | |||
M | tests/test-parseindex.t (1 line) |
for fp in (sys.stdin, sys.stdout, sys.stderr): | for fp in (sys.stdin, sys.stdout, sys.stderr): | ||||
procutil.setbinary(fp) | procutil.setbinary(fp) | ||||
def binopen(path, mode=b'rb'): | def binopen(path, mode=b'rb'): | ||||
if b'b' not in mode: | if b'b' not in mode: | ||||
mode = mode + b'b' | mode = mode + b'b' | ||||
return open(path, pycompat.sysstr(mode)) | return open(path, pycompat.sysstr(mode)) | ||||
binopen.options = {} | |||||
def printb(data, end=b'\n'): | def printb(data, end=b'\n'): | ||||
sys.stdout.flush() | sys.stdout.flush() | ||||
pycompat.stdout.write(data + end) | pycompat.stdout.write(data + end) | ||||
for f in sys.argv[1:]: | for f in sys.argv[1:]: | ||||
r = revlog.revlog(binopen, encoding.strtolocal(f)) | r = revlog.revlog(binopen, encoding.strtolocal(f)) | ||||
print("file:", f) | print("file:", f) |
# 2-tuple of file handles being used for active writing. | # 2-tuple of file handles being used for active writing. | ||||
self._writinghandles = None | self._writinghandles = None | ||||
self._loadindex() | self._loadindex() | ||||
def _loadindex(self): | def _loadindex(self): | ||||
mmapindexthreshold = None | mmapindexthreshold = None | ||||
opts = getattr(self.opener, 'options', {}) or {} | opts = self.opener.options | ||||
if 'revlogv2' in opts: | if 'revlogv2' in opts: | ||||
newversionflags = REVLOGV2 | FLAG_INLINE_DATA | newversionflags = REVLOGV2 | FLAG_INLINE_DATA | ||||
elif 'revlogv1' in opts: | elif 'revlogv1' in opts: | ||||
newversionflags = REVLOGV1 | FLAG_INLINE_DATA | newversionflags = REVLOGV1 | FLAG_INLINE_DATA | ||||
if 'generaldelta' in opts: | if 'generaldelta' in opts: | ||||
newversionflags |= FLAG_GENERALDELTA | newversionflags |= FLAG_GENERALDELTA | ||||
elif 'revlogv0' in getattr(self.opener, 'options', {}): | elif 'revlogv0' in self.opener.options: | ||||
newversionflags = REVLOGV0 | newversionflags = REVLOGV0 | ||||
else: | else: | ||||
newversionflags = REVLOG_DEFAULT_VERSION | newversionflags = REVLOG_DEFAULT_VERSION | ||||
if 'chunkcachesize' in opts: | if 'chunkcachesize' in opts: | ||||
self._chunkcachesize = opts['chunkcachesize'] | self._chunkcachesize = opts['chunkcachesize'] | ||||
if 'maxchainlen' in opts: | if 'maxchainlen' in opts: | ||||
self._maxchainlen = opts['maxchainlen'] | self._maxchainlen = opts['maxchainlen'] |
def build_opener(ui, authinfo): | def build_opener(ui, authinfo): | ||||
# urllib cannot handle URLs with embedded user or passwd | # urllib cannot handle URLs with embedded user or passwd | ||||
urlopener = url.opener(ui, authinfo) | urlopener = url.opener(ui, authinfo) | ||||
urlopener.add_handler(_HTTPRangeHandler()) | urlopener.add_handler(_HTTPRangeHandler()) | ||||
class statichttpvfs(vfsmod.abstractvfs): | class statichttpvfs(vfsmod.abstractvfs): | ||||
def __init__(self, base): | def __init__(self, base): | ||||
self.base = base | self.base = base | ||||
self.options = {} | |||||
def __call__(self, path, mode='r', *args, **kw): | def __call__(self, path, mode='r', *args, **kw): | ||||
if mode not in ('r', 'rb'): | if mode not in ('r', 'rb'): | ||||
raise IOError('Permission denied') | raise IOError('Permission denied') | ||||
f = "/".join((self.base, urlreq.quote(path))) | f = "/".join((self.base, urlreq.quote(path))) | ||||
return httprangereader(f, urlopener) | return httprangereader(f, urlopener) | ||||
def join(self, path): | def join(self, path): |
self.base = base | self.base = base | ||||
self._audit = audit | self._audit = audit | ||||
if audit: | if audit: | ||||
self.audit = pathutil.pathauditor(self.base, cached=cacheaudited) | self.audit = pathutil.pathauditor(self.base, cached=cacheaudited) | ||||
else: | else: | ||||
self.audit = (lambda path, mode=None: True) | self.audit = (lambda path, mode=None: True) | ||||
self.createmode = None | self.createmode = None | ||||
self._trustnlink = None | self._trustnlink = None | ||||
self.options = {} | |||||
@util.propertycache | @util.propertycache | ||||
def _cansymlink(self): | def _cansymlink(self): | ||||
return util.checklink(self.base) | return util.checklink(self.base) | ||||
@util.propertycache | @util.propertycache | ||||
def _chmod(self): | def _chmod(self): | ||||
return util.checkexec(self.base) | return util.checkexec(self.base) |
> def __exit__(self, *args, **kwargs): | > def __exit__(self, *args, **kwargs): | ||||
> return self.real.__exit__(*args, **kwargs) | > return self.real.__exit__(*args, **kwargs) | ||||
> | > | ||||
> def opener(*args): | > def opener(*args): | ||||
> o = vfs.vfs(*args) | > o = vfs.vfs(*args) | ||||
> def wrapper(*a, **kwargs): | > def wrapper(*a, **kwargs): | ||||
> f = o(*a, **kwargs) | > f = o(*a, **kwargs) | ||||
> return singlebyteread(f) | > return singlebyteread(f) | ||||
> wrapper.options = o.options | |||||
> return wrapper | > return wrapper | ||||
> | > | ||||
> cl = changelog.changelog(opener(b'.hg/store')) | > cl = changelog.changelog(opener(b'.hg/store')) | ||||
> print(len(cl), 'revisions:') | > print(len(cl), 'revisions:') | ||||
> for r in cl: | > for r in cl: | ||||
> print(pycompat.sysstr(node.short(cl.node(r)))) | > print(pycompat.sysstr(node.short(cl.node(r)))) | ||||
> EOF | > EOF | ||||
$ "$PYTHON" test.py | $ "$PYTHON" test.py |