comparison mercurial/utils/storageutil.py @ 40005:fa3dc85a747e

storageutil: extract functionality for resolving strip revisions I found myself having to copy this method as part of implementing a new storage backend. With a little tweaking, we can extract it to a standalone function so it can be reused easily. We'll likely want to implement a better method for removing revisions on the storage interface someday. But until then, let's use what we have. Differential Revision: https://phab.mercurial-scm.org/D4799
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 28 Sep 2018 11:29:05 -0700
parents ad8389ecd3f5
children 1d97a332c6d9
comparison
equal deleted inserted replaced
40004:ad8389ecd3f5 40005:fa3dc85a747e
12 12
13 from ..i18n import _ 13 from ..i18n import _
14 from ..node import ( 14 from ..node import (
15 bin, 15 bin,
16 nullid, 16 nullid,
17 nullrev,
17 ) 18 )
18 from .. import ( 19 from .. import (
19 error, 20 error,
20 pycompat, 21 pycompat,
21 ) 22 )
153 pass 154 pass
154 except (ValueError, OverflowError): 155 except (ValueError, OverflowError):
155 pass 156 pass
156 157
157 raise error.LookupError(fileid, identifier, _('no match found')) 158 raise error.LookupError(fileid, identifier, _('no match found'))
159
160 def resolvestripinfo(minlinkrev, tiprev, headrevs, linkrevfn, parentrevsfn):
161 """Resolve information needed to strip revisions.
162
163 Finds the minimum revision number that must be stripped in order to
164 strip ``minlinkrev``.
165
166 Returns a 2-tuple of the minimum revision number to do that and a set
167 of all revision numbers that have linkrevs that would be broken
168 by that strip.
169
170 ``tiprev`` is the current tip-most revision. It is ``len(store) - 1``.
171 ``headrevs`` is an iterable of head revisions.
172 ``linkrevfn`` is a callable that receives a revision and returns a linked
173 revision.
174 ``parentrevsfn`` is a callable that receives a revision number and returns
175 an iterable of its parent revision numbers.
176 """
177 brokenrevs = set()
178 strippoint = tiprev + 1
179
180 heads = {}
181 futurelargelinkrevs = set()
182 for head in headrevs:
183 headlinkrev = linkrevfn(head)
184 heads[head] = headlinkrev
185 if headlinkrev >= minlinkrev:
186 futurelargelinkrevs.add(headlinkrev)
187
188 # This algorithm involves walking down the rev graph, starting at the
189 # heads. Since the revs are topologically sorted according to linkrev,
190 # once all head linkrevs are below the minlink, we know there are
191 # no more revs that could have a linkrev greater than minlink.
192 # So we can stop walking.
193 while futurelargelinkrevs:
194 strippoint -= 1
195 linkrev = heads.pop(strippoint)
196
197 if linkrev < minlinkrev:
198 brokenrevs.add(strippoint)
199 else:
200 futurelargelinkrevs.remove(linkrev)
201
202 for p in parentrevsfn(strippoint):
203 if p != nullrev:
204 plinkrev = linkrevfn(p)
205 heads[p] = plinkrev
206 if plinkrev >= minlinkrev:
207 futurelargelinkrevs.add(plinkrev)
208
209 return strippoint, brokenrevs