Mercurial > public > mercurial-scm > hg
comparison mercurial/revlog.py @ 40008:842ffcf1d42f
storageutil: extract most of emitrevisions() to standalone function
As part of implementing a storage backend, I found myself copying
most of revlog.emitrevisions(). This code is highly nuanced and it
bothered me greatly to be copying such low-level code.
This commit extracts the bulk of revlog.emitrevisions() into a
new standalone function. In order to make the function generally
usable, all "self" function calls that aren't exposed on the
ifilestorage interface are passed in via callable arguments.
No meaningful behavior should have changed as part of the port.
Upcoming commits will tweak behavior to make the code more
generically usable.
Differential Revision: https://phab.mercurial-scm.org/D4803
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Fri, 28 Sep 2018 16:16:22 -0700 |
parents | fa3dc85a747e |
children | f5d819d84461 |
comparison
equal
deleted
inserted
replaced
40007:1470183068b8 | 40008:842ffcf1d42f |
---|---|
2191 | 2191 |
2192 if nodesorder is None and not self._generaldelta: | 2192 if nodesorder is None and not self._generaldelta: |
2193 nodesorder = 'storage' | 2193 nodesorder = 'storage' |
2194 | 2194 |
2195 frev = self.rev | 2195 frev = self.rev |
2196 fnode = self.node | |
2197 | 2196 |
2198 if nodesorder == 'nodes': | 2197 if nodesorder == 'nodes': |
2199 revs = [frev(n) for n in nodes] | 2198 revs = [frev(n) for n in nodes] |
2200 elif nodesorder == 'storage': | 2199 elif nodesorder == 'storage': |
2201 revs = sorted(frev(n) for n in nodes) | 2200 revs = sorted(frev(n) for n in nodes) |
2202 else: | 2201 else: |
2203 assert self._generaldelta | 2202 assert self._generaldelta |
2204 revs = set(frev(n) for n in nodes) | 2203 revs = set(frev(n) for n in nodes) |
2205 revs = dagop.linearize(revs, self.parentrevs) | 2204 revs = dagop.linearize(revs, self.parentrevs) |
2206 | 2205 |
2207 prevrev = None | 2206 return storageutil.emitrevisions( |
2208 | 2207 self, revs, revlogrevisiondelta, |
2209 if deltaprevious or assumehaveparentrevisions: | 2208 deltaparentfn=self.deltaparent, |
2210 prevrev = self.parentrevs(revs[0])[0] | 2209 candeltafn=self.candelta, |
2211 | 2210 rawsizefn=self.rawsize, |
2212 # Set of revs available to delta against. | 2211 revdifffn=self.revdiff, |
2213 available = set() | 2212 flagsfn=self.flags, |
2214 | 2213 sendfulltext=not self._storedeltachains, |
2215 for rev in revs: | 2214 revisiondata=revisiondata, |
2216 if rev == nullrev: | 2215 assumehaveparentrevisions=assumehaveparentrevisions, |
2217 continue | 2216 deltaprevious=deltaprevious) |
2218 | |
2219 node = fnode(rev) | |
2220 deltaparentrev = self.deltaparent(rev) | |
2221 p1rev, p2rev = self.parentrevs(rev) | |
2222 | |
2223 # Forced delta against previous mode. | |
2224 if deltaprevious: | |
2225 baserev = prevrev | |
2226 | |
2227 # Revlog is configured to use full snapshots. Stick to that. | |
2228 elif not self._storedeltachains: | |
2229 baserev = nullrev | |
2230 | |
2231 # There is a delta in storage. We try to use that because it | |
2232 # amounts to effectively copying data from storage and is | |
2233 # therefore the fastest. | |
2234 elif deltaparentrev != nullrev: | |
2235 # Base revision was already emitted in this group. We can | |
2236 # always safely use the delta. | |
2237 if deltaparentrev in available: | |
2238 baserev = deltaparentrev | |
2239 | |
2240 # Base revision is a parent that hasn't been emitted already. | |
2241 # Use it if we can assume the receiver has the parent revision. | |
2242 elif (assumehaveparentrevisions | |
2243 and deltaparentrev in (p1rev, p2rev)): | |
2244 baserev = deltaparentrev | |
2245 | |
2246 # No guarantee the receiver has the delta parent. Send delta | |
2247 # against last revision (if possible), which in the common case | |
2248 # should be similar enough to this revision that the delta is | |
2249 # reasonable. | |
2250 elif prevrev is not None: | |
2251 baserev = prevrev | |
2252 else: | |
2253 baserev = nullrev | |
2254 | |
2255 # Storage has a fulltext revision. | |
2256 | |
2257 # Let's use the previous revision, which is as good a guess as any. | |
2258 # There is definitely room to improve this logic. | |
2259 elif prevrev is not None: | |
2260 baserev = prevrev | |
2261 else: | |
2262 baserev = nullrev | |
2263 | |
2264 # But we can't actually use our chosen delta base for whatever | |
2265 # reason. Reset to fulltext. | |
2266 if baserev != nullrev and not self.candelta(baserev, rev): | |
2267 baserev = nullrev | |
2268 | |
2269 revision = None | |
2270 delta = None | |
2271 baserevisionsize = None | |
2272 | |
2273 if revisiondata: | |
2274 if self.iscensored(baserev) or self.iscensored(rev): | |
2275 try: | |
2276 revision = self.revision(node, raw=True) | |
2277 except error.CensoredNodeError as e: | |
2278 revision = e.tombstone | |
2279 | |
2280 if baserev != nullrev: | |
2281 baserevisionsize = self.rawsize(baserev) | |
2282 | |
2283 elif baserev == nullrev and not deltaprevious: | |
2284 revision = self.revision(node, raw=True) | |
2285 available.add(rev) | |
2286 else: | |
2287 delta = self.revdiff(baserev, rev) | |
2288 available.add(rev) | |
2289 | |
2290 yield revlogrevisiondelta( | |
2291 node=node, | |
2292 p1node=fnode(p1rev), | |
2293 p2node=fnode(p2rev), | |
2294 basenode=fnode(baserev), | |
2295 flags=self.flags(rev), | |
2296 baserevisionsize=baserevisionsize, | |
2297 revision=revision, | |
2298 delta=delta) | |
2299 | |
2300 prevrev = rev | |
2301 | 2217 |
2302 DELTAREUSEALWAYS = 'always' | 2218 DELTAREUSEALWAYS = 'always' |
2303 DELTAREUSESAMEREVS = 'samerevs' | 2219 DELTAREUSESAMEREVS = 'samerevs' |
2304 DELTAREUSENEVER = 'never' | 2220 DELTAREUSENEVER = 'never' |
2305 | 2221 |