We introduce a new exception to handle the various failure categories,
rather than relying on RuntimeError.
Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
( )
We introduce a new exception to handle the various failure categories,
rather than relying on RuntimeError.
| No Linters Available |
| No Unit Test Coverage |
| Path | Packages | |||
|---|---|---|---|---|
| M | hgext/remotefilelog/basestore.py (2 lines) | |||
| M | hgext/remotefilelog/shallowutil.py (14 lines) | |||
| M | tests/test-remotefilelog-corrupt-cache.t (2 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| 4720e672d55c | 46a7e1030b97 | Augie Fackler | Jul 7 2021, 11:45 AM |
| offset += size | offset += size | ||||
| datanode = data[offset : offset + 20] | datanode = data[offset : offset + 20] | ||||
| # and compare against the path | # and compare against the path | ||||
| if os.path.basename(path) == hex(datanode): | if os.path.basename(path) == hex(datanode): | ||||
| # Content matches the intended path | # Content matches the intended path | ||||
| return True | return True | ||||
| return False | return False | ||||
| except (ValueError, RuntimeError): | except (ValueError, shallowutil.BadRemotefilelogHeader): | ||||
| pass | pass | ||||
| return False | return False | ||||
| def gc(self, keepkeys): | def gc(self, keepkeys): | ||||
| ui = self.ui | ui = self.ui | ||||
| cachepath = self._path | cachepath = self._path | ||||
| """the reverse of int2bin, convert a binary buffer to an integer""" | """the reverse of int2bin, convert a binary buffer to an integer""" | ||||
| x = 0 | x = 0 | ||||
| for b in bytearray(buf): | for b in bytearray(buf): | ||||
| x <<= 8 | x <<= 8 | ||||
| x |= b | x |= b | ||||
| return x | return x | ||||
| class BadRemotefilelogHeader(error.StorageError): | |||||
| """Exception raised when parsing a remotefilelog blob header fails.""" | |||||
| def parsesizeflags(raw): | def parsesizeflags(raw): | ||||
| """given a remotefilelog blob, return (headersize, rawtextsize, flags) | """given a remotefilelog blob, return (headersize, rawtextsize, flags) | ||||
| see remotefilelogserver.createfileblob for the format. | see remotefilelogserver.createfileblob for the format. | ||||
| raise RuntimeError if the content is illformed. | raise RuntimeError if the content is illformed. | ||||
| """ | """ | ||||
| flags = revlog.REVIDX_DEFAULT_FLAGS | flags = revlog.REVIDX_DEFAULT_FLAGS | ||||
| size = None | size = None | ||||
| try: | try: | ||||
| index = raw.index(b'\0') | index = raw.index(b'\0') | ||||
| header = raw[:index] | header = raw[:index] | ||||
| if header.startswith(b'v'): | if header.startswith(b'v'): | ||||
| # v1 and above, header starts with 'v' | # v1 and above, header starts with 'v' | ||||
| if header.startswith(b'v1\n'): | if header.startswith(b'v1\n'): | ||||
| for s in header.split(b'\n'): | for s in header.split(b'\n'): | ||||
| if s.startswith(constants.METAKEYSIZE): | if s.startswith(constants.METAKEYSIZE): | ||||
| size = int(s[len(constants.METAKEYSIZE) :]) | size = int(s[len(constants.METAKEYSIZE) :]) | ||||
| elif s.startswith(constants.METAKEYFLAG): | elif s.startswith(constants.METAKEYFLAG): | ||||
| flags = int(s[len(constants.METAKEYFLAG) :]) | flags = int(s[len(constants.METAKEYFLAG) :]) | ||||
| else: | else: | ||||
| raise RuntimeError( | raise BadRemotefilelogHeader( | ||||
| b'unsupported remotefilelog header: %s' % header | b'unsupported remotefilelog header: %s' % header | ||||
| ) | ) | ||||
| else: | else: | ||||
| # v0, str(int(size)) is the header | # v0, str(int(size)) is the header | ||||
| size = int(header) | size = int(header) | ||||
| except ValueError: | except ValueError: | ||||
| raise RuntimeError("unexpected remotefilelog header: illegal format") | raise BadRemotefilelogHeader( | ||||
| "unexpected remotefilelog header: illegal format" | |||||
| ) | |||||
| if size is None: | if size is None: | ||||
| raise RuntimeError("unexpected remotefilelog header: no size found") | raise BadRemotefilelogHeader( | ||||
| "unexpected remotefilelog header: no size found" | |||||
| ) | |||||
| return index + 1, size, flags | return index + 1, size, flags | ||||
| def buildfileblobheader(size, flags, version=None): | def buildfileblobheader(size, flags, version=None): | ||||
| """return the header of a remotefilelog blob. | """return the header of a remotefilelog blob. | ||||
| see remotefilelogserver.createfileblob for the format. | see remotefilelogserver.createfileblob for the format. | ||||
| approximately the reverse of parsesizeflags. | approximately the reverse of parsesizeflags. | ||||
| $ hg up -q null | $ hg up -q null | ||||
| $ cat >> .hg/hgrc <<EOF | $ cat >> .hg/hgrc <<EOF | ||||
| > [remotefilelog] | > [remotefilelog] | ||||
| > validatecache=off | > validatecache=off | ||||
| > EOF | > EOF | ||||
| $ chmod u+w $CACHEDIR/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/1406e74118627694268417491f018a4a883152f0 | $ chmod u+w $CACHEDIR/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/1406e74118627694268417491f018a4a883152f0 | ||||
| $ echo x > $CACHEDIR/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/1406e74118627694268417491f018a4a883152f0 | $ echo x > $CACHEDIR/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/1406e74118627694268417491f018a4a883152f0 | ||||
| $ hg up tip 2>&1 | egrep "^[^ ].*unexpected remotefilelog" | $ hg up tip 2>&1 | egrep "^[^ ].*unexpected remotefilelog" | ||||
| RuntimeError: unexpected remotefilelog header: illegal format | hgext.remotefilelog.shallowutil.BadRemotefilelogHeader: unexpected remotefilelog header: illegal format | ||||
| Verify detection and remediation when remotefilelog.validatecachelog is set | Verify detection and remediation when remotefilelog.validatecachelog is set | ||||
| $ cat >> .hg/hgrc <<EOF | $ cat >> .hg/hgrc <<EOF | ||||
| > [remotefilelog] | > [remotefilelog] | ||||
| > validatecachelog=$PWD/.hg/remotefilelog_cache.log | > validatecachelog=$PWD/.hg/remotefilelog_cache.log | ||||
| > validatecache=strict | > validatecache=strict | ||||
| > EOF | > EOF | ||||