##// 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 return [filectx(self._repo, self._path, fileid=x,
1272 return [filectx(self._repo, self._path, fileid=x,
1273 filelog=self._filelog) for x in c]
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 class committablectx(basectx):
1275 class committablectx(basectx):
1359 """A committablectx object provides common functionality for a context that
1276 """A committablectx object provides common functionality for a context that
1360 wants the ability to commit, e.g. workingctx or memctx."""
1277 wants the ability to commit, e.g. workingctx or memctx."""
@@ -11,7 +11,9 b' import heapq'
11
11
12 from . import (
12 from . import (
13 error,
13 error,
14 mdiff,
14 node,
15 node,
16 patch,
15 smartset,
17 smartset,
16 )
18 )
17
19
@@ -140,6 +142,89 b' def reachableroots(repo, roots, heads, i'
140 revs.sort()
142 revs.sort()
141 return revs
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 def toposort(revs, parentsfunc, firstbranch=()):
228 def toposort(revs, parentsfunc, firstbranch=()):
144 """Yield revisions from heads to roots one (topo) branch at a time.
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 from .. import (
29 from .. import (
30 archival,
30 archival,
31 context,
31 dagop,
32 encoding,
32 encoding,
33 error,
33 error,
34 graphmod,
34 graphmod,
@@ -1013,9 +1013,9 b' def filelog(web, req, tmpl):'
1013 # would required a dedicated "revnav" class
1013 # would required a dedicated "revnav" class
1014 nav = None
1014 nav = None
1015 if descend:
1015 if descend:
1016 it = context.blockdescendants(fctx, *lrange)
1016 it = dagop.blockdescendants(fctx, *lrange)
1017 else:
1017 else:
1018 it = context.blockancestors(fctx, *lrange)
1018 it = dagop.blockancestors(fctx, *lrange)
1019 for i, (c, lr) in enumerate(it, 1):
1019 for i, (c, lr) in enumerate(it, 1):
1020 diffs = None
1020 diffs = None
1021 if patch:
1021 if patch:
@@ -827,8 +827,6 b' def followlines(repo, subset, x):'
827 descendants of 'startrev' are returned though renames are (currently) not
827 descendants of 'startrev' are returned though renames are (currently) not
828 followed in this direction.
828 followed in this direction.
829 """
829 """
830 from . import context # avoid circular import issues
831
832 args = getargsdict(x, 'followlines', 'file *lines startrev descend')
830 args = getargsdict(x, 'followlines', 'file *lines startrev descend')
833 if len(args['lines']) != 1:
831 if len(args['lines']) != 1:
834 raise error.ParseError(_("followlines requires a line range"))
832 raise error.ParseError(_("followlines requires a line range"))
@@ -868,12 +866,12 b' def followlines(repo, subset, x):'
868 if descend:
866 if descend:
869 rs = generatorset(
867 rs = generatorset(
870 (c.rev() for c, _linerange
868 (c.rev() for c, _linerange
871 in context.blockdescendants(fctx, fromline, toline)),
869 in dagop.blockdescendants(fctx, fromline, toline)),
872 iterasc=True)
870 iterasc=True)
873 else:
871 else:
874 rs = generatorset(
872 rs = generatorset(
875 (c.rev() for c, _linerange
873 (c.rev() for c, _linerange
876 in context.blockancestors(fctx, fromline, toline)),
874 in dagop.blockancestors(fctx, fromline, toline)),
877 iterasc=False)
875 iterasc=False)
878 return subset & rs
876 return subset & rs
879
877
General Comments 0
You need to be logged in to leave comments. Login now