comparison mercurial/revlog.py @ 40009: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
40008:1470183068b8 40009: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