##// END OF EJS Templates
dagop: move blockancestors() and blockdescendants() from context...
Yuya Nishihara -
r32904:582080a4 default
parent child Browse files
Show More
@@ -1272,89 +1272,6 b' class filectx(basefilectx):'
1272 1272 return [filectx(self._repo, self._path, fileid=x,
1273 1273 filelog=self._filelog) for x in c]
1274 1274
1275 def _changesrange(fctx1, fctx2, linerange2, diffopts):
1276 """Return `(diffinrange, linerange1)` where `diffinrange` is True
1277 if diff from fctx2 to fctx1 has changes in linerange2 and
1278 `linerange1` is the new line range for fctx1.
1279 """
1280 blocks = mdiff.allblocks(fctx1.data(), fctx2.data(), diffopts)
1281 filteredblocks, linerange1 = mdiff.blocksinrange(blocks, linerange2)
1282 diffinrange = any(stype == '!' for _, stype in filteredblocks)
1283 return diffinrange, linerange1
1284
1285 def blockancestors(fctx, fromline, toline, followfirst=False):
1286 """Yield ancestors of `fctx` with respect to the block of lines within
1287 `fromline`-`toline` range.
1288 """
1289 diffopts = patch.diffopts(fctx._repo.ui)
1290 introrev = fctx.introrev()
1291 if fctx.rev() != introrev:
1292 fctx = fctx.filectx(fctx.filenode(), changeid=introrev)
1293 visit = {(fctx.linkrev(), fctx.filenode()): (fctx, (fromline, toline))}
1294 while visit:
1295 c, linerange2 = visit.pop(max(visit))
1296 pl = c.parents()
1297 if followfirst:
1298 pl = pl[:1]
1299 if not pl:
1300 # The block originates from the initial revision.
1301 yield c, linerange2
1302 continue
1303 inrange = False
1304 for p in pl:
1305 inrangep, linerange1 = _changesrange(p, c, linerange2, diffopts)
1306 inrange = inrange or inrangep
1307 if linerange1[0] == linerange1[1]:
1308 # Parent's linerange is empty, meaning that the block got
1309 # introduced in this revision; no need to go futher in this
1310 # branch.
1311 continue
1312 # Set _descendantrev with 'c' (a known descendant) so that, when
1313 # _adjustlinkrev is called for 'p', it receives this descendant
1314 # (as srcrev) instead possibly topmost introrev.
1315 p._descendantrev = c.rev()
1316 visit[p.linkrev(), p.filenode()] = p, linerange1
1317 if inrange:
1318 yield c, linerange2
1319
1320 def blockdescendants(fctx, fromline, toline):
1321 """Yield descendants of `fctx` with respect to the block of lines within
1322 `fromline`-`toline` range.
1323 """
1324 # First possibly yield 'fctx' if it has changes in range with respect to
1325 # its parents.
1326 try:
1327 c, linerange1 = next(blockancestors(fctx, fromline, toline))
1328 except StopIteration:
1329 pass
1330 else:
1331 if c == fctx:
1332 yield c, linerange1
1333
1334 diffopts = patch.diffopts(fctx._repo.ui)
1335 fl = fctx.filelog()
1336 seen = {fctx.filerev(): (fctx, (fromline, toline))}
1337 for i in fl.descendants([fctx.filerev()]):
1338 c = fctx.filectx(i)
1339 inrange = False
1340 for x in fl.parentrevs(i):
1341 try:
1342 p, linerange2 = seen[x]
1343 except KeyError:
1344 # nullrev or other branch
1345 continue
1346 inrangep, linerange1 = _changesrange(c, p, linerange2, diffopts)
1347 inrange = inrange or inrangep
1348 # If revision 'i' has been seen (it's a merge), we assume that its
1349 # line range is the same independently of which parents was used
1350 # to compute it.
1351 assert i not in seen or seen[i][1] == linerange1, (
1352 'computed line range for %s is not consistent between '
1353 'ancestor branches' % c)
1354 seen[i] = c, linerange1
1355 if inrange:
1356 yield c, linerange1
1357
1358 1275 class committablectx(basectx):
1359 1276 """A committablectx object provides common functionality for a context that
1360 1277 wants the ability to commit, e.g. workingctx or memctx."""
@@ -11,7 +11,9 b' import heapq'
11 11
12 12 from . import (
13 13 error,
14 mdiff,
14 15 node,
16 patch,
15 17 smartset,
16 18 )
17 19
@@ -140,6 +142,89 b' def reachableroots(repo, roots, heads, i'
140 142 revs.sort()
141 143 return revs
142 144
145 def _changesrange(fctx1, fctx2, linerange2, diffopts):
146 """Return `(diffinrange, linerange1)` where `diffinrange` is True
147 if diff from fctx2 to fctx1 has changes in linerange2 and
148 `linerange1` is the new line range for fctx1.
149 """
150 blocks = mdiff.allblocks(fctx1.data(), fctx2.data(), diffopts)
151 filteredblocks, linerange1 = mdiff.blocksinrange(blocks, linerange2)
152 diffinrange = any(stype == '!' for _, stype in filteredblocks)
153 return diffinrange, linerange1
154
155 def blockancestors(fctx, fromline, toline, followfirst=False):
156 """Yield ancestors of `fctx` with respect to the block of lines within
157 `fromline`-`toline` range.
158 """
159 diffopts = patch.diffopts(fctx._repo.ui)
160 introrev = fctx.introrev()
161 if fctx.rev() != introrev:
162 fctx = fctx.filectx(fctx.filenode(), changeid=introrev)
163 visit = {(fctx.linkrev(), fctx.filenode()): (fctx, (fromline, toline))}
164 while visit:
165 c, linerange2 = visit.pop(max(visit))
166 pl = c.parents()
167 if followfirst:
168 pl = pl[:1]
169 if not pl:
170 # The block originates from the initial revision.
171 yield c, linerange2
172 continue
173 inrange = False
174 for p in pl:
175 inrangep, linerange1 = _changesrange(p, c, linerange2, diffopts)
176 inrange = inrange or inrangep
177 if linerange1[0] == linerange1[1]:
178 # Parent's linerange is empty, meaning that the block got
179 # introduced in this revision; no need to go futher in this
180 # branch.
181 continue
182 # Set _descendantrev with 'c' (a known descendant) so that, when
183 # _adjustlinkrev is called for 'p', it receives this descendant
184 # (as srcrev) instead possibly topmost introrev.
185 p._descendantrev = c.rev()
186 visit[p.linkrev(), p.filenode()] = p, linerange1
187 if inrange:
188 yield c, linerange2
189
190 def blockdescendants(fctx, fromline, toline):
191 """Yield descendants of `fctx` with respect to the block of lines within
192 `fromline`-`toline` range.
193 """
194 # First possibly yield 'fctx' if it has changes in range with respect to
195 # its parents.
196 try:
197 c, linerange1 = next(blockancestors(fctx, fromline, toline))
198 except StopIteration:
199 pass
200 else:
201 if c == fctx:
202 yield c, linerange1
203
204 diffopts = patch.diffopts(fctx._repo.ui)
205 fl = fctx.filelog()
206 seen = {fctx.filerev(): (fctx, (fromline, toline))}
207 for i in fl.descendants([fctx.filerev()]):
208 c = fctx.filectx(i)
209 inrange = False
210 for x in fl.parentrevs(i):
211 try:
212 p, linerange2 = seen[x]
213 except KeyError:
214 # nullrev or other branch
215 continue
216 inrangep, linerange1 = _changesrange(c, p, linerange2, diffopts)
217 inrange = inrange or inrangep
218 # If revision 'i' has been seen (it's a merge), we assume that its
219 # line range is the same independently of which parents was used
220 # to compute it.
221 assert i not in seen or seen[i][1] == linerange1, (
222 'computed line range for %s is not consistent between '
223 'ancestor branches' % c)
224 seen[i] = c, linerange1
225 if inrange:
226 yield c, linerange1
227
143 228 def toposort(revs, parentsfunc, firstbranch=()):
144 229 """Yield revisions from heads to roots one (topo) branch at a time.
145 230
@@ -28,7 +28,7 b' from .common import ('
28 28
29 29 from .. import (
30 30 archival,
31 context,
31 dagop,
32 32 encoding,
33 33 error,
34 34 graphmod,
@@ -1013,9 +1013,9 b' def filelog(web, req, tmpl):'
1013 1013 # would required a dedicated "revnav" class
1014 1014 nav = None
1015 1015 if descend:
1016 it = context.blockdescendants(fctx, *lrange)
1016 it = dagop.blockdescendants(fctx, *lrange)
1017 1017 else:
1018 it = context.blockancestors(fctx, *lrange)
1018 it = dagop.blockancestors(fctx, *lrange)
1019 1019 for i, (c, lr) in enumerate(it, 1):
1020 1020 diffs = None
1021 1021 if patch:
@@ -827,8 +827,6 b' def followlines(repo, subset, x):'
827 827 descendants of 'startrev' are returned though renames are (currently) not
828 828 followed in this direction.
829 829 """
830 from . import context # avoid circular import issues
831
832 830 args = getargsdict(x, 'followlines', 'file *lines startrev descend')
833 831 if len(args['lines']) != 1:
834 832 raise error.ParseError(_("followlines requires a line range"))
@@ -868,12 +866,12 b' def followlines(repo, subset, x):'
868 866 if descend:
869 867 rs = generatorset(
870 868 (c.rev() for c, _linerange
871 in context.blockdescendants(fctx, fromline, toline)),
869 in dagop.blockdescendants(fctx, fromline, toline)),
872 870 iterasc=True)
873 871 else:
874 872 rs = generatorset(
875 873 (c.rev() for c, _linerange
876 in context.blockancestors(fctx, fromline, toline)),
874 in dagop.blockancestors(fctx, fromline, toline)),
877 875 iterasc=False)
878 876 return subset & rs
879 877
General Comments 0
You need to be logged in to leave comments. Login now