Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/revlog.py @ 36768:7bf80d9d9543
merge with stable
There were a handful of merge conflicts in the wire protocol code due
to significant refactoring in default. When resolving the conflicts,
I tried to produce the minimal number of changes to make the incoming
security patches work with the new code.
I will send some follow-up commits to get the security patches better
integrated into default.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 06 Mar 2018 14:32:14 -0800 |
parents | 6bacb2f663cb 369aadf7a326 |
children | f0b6fbea00cf |
comparison
equal
deleted
inserted
replaced
36767:4c71a26a4009 | 36768:7bf80d9d9543 |
---|---|
75 REVIDX_ISCENSORED, | 75 REVIDX_ISCENSORED, |
76 REVIDX_ELLIPSIS, | 76 REVIDX_ELLIPSIS, |
77 REVIDX_EXTSTORED, | 77 REVIDX_EXTSTORED, |
78 ] | 78 ] |
79 REVIDX_KNOWN_FLAGS = util.bitsfrom(REVIDX_FLAGS_ORDER) | 79 REVIDX_KNOWN_FLAGS = util.bitsfrom(REVIDX_FLAGS_ORDER) |
80 # bitmark for flags that could cause rawdata content change | |
81 REVIDX_RAWTEXT_CHANGING_FLAGS = REVIDX_ISCENSORED | REVIDX_EXTSTORED | |
80 | 82 |
81 # max size of revlog with inline data | 83 # max size of revlog with inline data |
82 _maxinline = 131072 | 84 _maxinline = 131072 |
83 _chunksize = 1048576 | 85 _chunksize = 1048576 |
84 | 86 |
94 | 96 |
95 def addflagprocessor(flag, processor): | 97 def addflagprocessor(flag, processor): |
96 """Register a flag processor on a revision data flag. | 98 """Register a flag processor on a revision data flag. |
97 | 99 |
98 Invariant: | 100 Invariant: |
99 - Flags need to be defined in REVIDX_KNOWN_FLAGS and REVIDX_FLAGS_ORDER. | 101 - Flags need to be defined in REVIDX_KNOWN_FLAGS and REVIDX_FLAGS_ORDER, |
102 and REVIDX_RAWTEXT_CHANGING_FLAGS if they can alter rawtext. | |
100 - Only one flag processor can be registered on a specific flag. | 103 - Only one flag processor can be registered on a specific flag. |
101 - flagprocessors must be 3-tuples of functions (read, write, raw) with the | 104 - flagprocessors must be 3-tuples of functions (read, write, raw) with the |
102 following signatures: | 105 following signatures: |
103 - (read) f(self, rawtext) -> text, bool | 106 - (read) f(self, rawtext) -> text, bool |
104 - (write) f(self, text) -> rawtext, bool | 107 - (write) f(self, text) -> rawtext, bool |
331 hlen = struct.calcsize(">lll") | 334 hlen = struct.calcsize(">lll") |
332 if delta[:hlen] == mdiff.replacediffheader(revlog.rawsize(baserev), | 335 if delta[:hlen] == mdiff.replacediffheader(revlog.rawsize(baserev), |
333 len(delta) - hlen): | 336 len(delta) - hlen): |
334 btext[0] = delta[hlen:] | 337 btext[0] = delta[hlen:] |
335 else: | 338 else: |
336 basetext = revlog.revision(baserev, _df=fh, raw=True) | 339 # deltabase is rawtext before changed by flag processors, which is |
340 # equivalent to non-raw text | |
341 basetext = revlog.revision(baserev, _df=fh, raw=False) | |
337 btext[0] = mdiff.patch(basetext, delta) | 342 btext[0] = mdiff.patch(basetext, delta) |
338 | 343 |
339 try: | 344 try: |
340 res = revlog._processflags(btext[0], flags, 'read', raw=True) | 345 res = revlog._processflags(btext[0], flags, 'read', raw=True) |
341 btext[0], validatehash = res | 346 btext[0], validatehash = res |
402 | 407 |
403 deltainfo = None | 408 deltainfo = None |
404 for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta): | 409 for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta): |
405 nominateddeltas = [] | 410 nominateddeltas = [] |
406 for candidaterev in candidaterevs: | 411 for candidaterev in candidaterevs: |
412 # no delta for rawtext-changing revs (see "candelta" for why) | |
413 if revlog.flags(candidaterev) & REVIDX_RAWTEXT_CHANGING_FLAGS: | |
414 continue | |
407 candidatedelta = self._builddeltainfo(revinfo, candidaterev, fh) | 415 candidatedelta = self._builddeltainfo(revinfo, candidaterev, fh) |
408 if revlog._isgooddeltainfo(candidatedelta, revinfo.textlen): | 416 if revlog._isgooddeltainfo(candidatedelta, revinfo.textlen): |
409 nominateddeltas.append(candidatedelta) | 417 nominateddeltas.append(candidatedelta) |
410 if nominateddeltas: | 418 if nominateddeltas: |
411 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen) | 419 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen) |
735 try: | 743 try: |
736 self.rev(node) | 744 self.rev(node) |
737 return True | 745 return True |
738 except KeyError: | 746 except KeyError: |
739 return False | 747 return False |
748 | |
749 def candelta(self, baserev, rev): | |
750 """whether two revisions (baserev, rev) can be delta-ed or not""" | |
751 # Disable delta if either rev requires a content-changing flag | |
752 # processor (ex. LFS). This is because such flag processor can alter | |
753 # the rawtext content that the delta will be based on, and two clients | |
754 # could have a same revlog node with different flags (i.e. different | |
755 # rawtext contents) and the delta could be incompatible. | |
756 if ((self.flags(baserev) & REVIDX_RAWTEXT_CHANGING_FLAGS) | |
757 or (self.flags(rev) & REVIDX_RAWTEXT_CHANGING_FLAGS)): | |
758 return False | |
759 return True | |
740 | 760 |
741 def clearcaches(self): | 761 def clearcaches(self): |
742 self._cache = None | 762 self._cache = None |
743 self._chainbasecache.clear() | 763 self._chainbasecache.clear() |
744 self._chunkcache = (0, '') | 764 self._chunkcache = (0, '') |
2076 p1r, p2r = self.rev(p1), self.rev(p2) | 2096 p1r, p2r = self.rev(p1), self.rev(p2) |
2077 | 2097 |
2078 # full versions are inserted when the needed deltas | 2098 # full versions are inserted when the needed deltas |
2079 # become comparable to the uncompressed text | 2099 # become comparable to the uncompressed text |
2080 if rawtext is None: | 2100 if rawtext is None: |
2081 textlen = mdiff.patchedsize(self.rawsize(cachedelta[0]), | 2101 # need rawtext size, before changed by flag processors, which is |
2102 # the non-raw size. use revlog explicitly to avoid filelog's extra | |
2103 # logic that might remove metadata size. | |
2104 textlen = mdiff.patchedsize(revlog.size(self, cachedelta[0]), | |
2082 cachedelta[1]) | 2105 cachedelta[1]) |
2083 else: | 2106 else: |
2084 textlen = len(rawtext) | 2107 textlen = len(rawtext) |
2085 | 2108 |
2086 if deltacomputer is None: | 2109 if deltacomputer is None: |
2087 deltacomputer = _deltacomputer(self) | 2110 deltacomputer = _deltacomputer(self) |
2088 | 2111 |
2089 revinfo = _revisioninfo(node, p1, p2, btext, textlen, cachedelta, flags) | 2112 revinfo = _revisioninfo(node, p1, p2, btext, textlen, cachedelta, flags) |
2090 deltainfo = deltacomputer.finddeltainfo(revinfo, fh) | 2113 |
2114 # no delta for flag processor revision (see "candelta" for why) | |
2115 # not calling candelta since only one revision needs test, also to | |
2116 # avoid overhead fetching flags again. | |
2117 if flags & REVIDX_RAWTEXT_CHANGING_FLAGS: | |
2118 deltainfo = None | |
2119 else: | |
2120 deltainfo = deltacomputer.finddeltainfo(revinfo, fh) | |
2091 | 2121 |
2092 if deltainfo is not None: | 2122 if deltainfo is not None: |
2093 base = deltainfo.base | 2123 base = deltainfo.base |
2094 chainbase = deltainfo.chainbase | 2124 chainbase = deltainfo.chainbase |
2095 data = deltainfo.data | 2125 data = deltainfo.data |