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 |