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 = |
|
1016 | it = dagop.blockdescendants(fctx, *lrange) | |
1017 | else: |
|
1017 | else: | |
1018 |
it = |
|
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 |
|
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 |
|
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