Show More
@@ -26,10 +26,8 b' from .node import (' | |||||
26 | wdirnodes, |
|
26 | wdirnodes, | |
27 | wdirrev, |
|
27 | wdirrev, | |
28 | ) |
|
28 | ) | |
29 | from .thirdparty import ( |
|
|||
30 | attr, |
|
|||
31 | ) |
|
|||
32 | from . import ( |
|
29 | from . import ( | |
|
30 | dagop, | |||
33 | encoding, |
|
31 | encoding, | |
34 | error, |
|
32 | error, | |
35 | fileset, |
|
33 | fileset, | |
@@ -978,6 +976,8 b' class basefilectx(object):' | |||||
978 | the line number at the first appearance in the managed file, otherwise, |
|
976 | the line number at the first appearance in the managed file, otherwise, | |
979 | number has a fixed value of False. |
|
977 | number has a fixed value of False. | |
980 | ''' |
|
978 | ''' | |
|
979 | annotateline = dagop.annotateline | |||
|
980 | _annotatepair = dagop._annotatepair | |||
981 |
|
981 | |||
982 | def lines(text): |
|
982 | def lines(text): | |
983 | if text.endswith("\n"): |
|
983 | if text.endswith("\n"): | |
@@ -1105,74 +1105,6 b' class basefilectx(object):' | |||||
1105 | """ |
|
1105 | """ | |
1106 | return self._repo.wwritedata(self.path(), self.data()) |
|
1106 | return self._repo.wwritedata(self.path(), self.data()) | |
1107 |
|
1107 | |||
1108 | @attr.s(slots=True, frozen=True) |
|
|||
1109 | class annotateline(object): |
|
|||
1110 | fctx = attr.ib() |
|
|||
1111 | lineno = attr.ib(default=False) |
|
|||
1112 | # Whether this annotation was the result of a skip-annotate. |
|
|||
1113 | skip = attr.ib(default=False) |
|
|||
1114 |
|
||||
1115 | def _annotatepair(parents, childfctx, child, skipchild, diffopts): |
|
|||
1116 | r''' |
|
|||
1117 | Given parent and child fctxes and annotate data for parents, for all lines |
|
|||
1118 | in either parent that match the child, annotate the child with the parent's |
|
|||
1119 | data. |
|
|||
1120 |
|
||||
1121 | Additionally, if `skipchild` is True, replace all other lines with parent |
|
|||
1122 | annotate data as well such that child is never blamed for any lines. |
|
|||
1123 |
|
||||
1124 | See test-annotate.py for unit tests. |
|
|||
1125 | ''' |
|
|||
1126 | pblocks = [(parent, mdiff.allblocks(parent[1], child[1], opts=diffopts)) |
|
|||
1127 | for parent in parents] |
|
|||
1128 |
|
||||
1129 | if skipchild: |
|
|||
1130 | # Need to iterate over the blocks twice -- make it a list |
|
|||
1131 | pblocks = [(p, list(blocks)) for (p, blocks) in pblocks] |
|
|||
1132 | # Mercurial currently prefers p2 over p1 for annotate. |
|
|||
1133 | # TODO: change this? |
|
|||
1134 | for parent, blocks in pblocks: |
|
|||
1135 | for (a1, a2, b1, b2), t in blocks: |
|
|||
1136 | # Changed blocks ('!') or blocks made only of blank lines ('~') |
|
|||
1137 | # belong to the child. |
|
|||
1138 | if t == '=': |
|
|||
1139 | child[0][b1:b2] = parent[0][a1:a2] |
|
|||
1140 |
|
||||
1141 | if skipchild: |
|
|||
1142 | # Now try and match up anything that couldn't be matched, |
|
|||
1143 | # Reversing pblocks maintains bias towards p2, matching above |
|
|||
1144 | # behavior. |
|
|||
1145 | pblocks.reverse() |
|
|||
1146 |
|
||||
1147 | # The heuristics are: |
|
|||
1148 | # * Work on blocks of changed lines (effectively diff hunks with -U0). |
|
|||
1149 | # This could potentially be smarter but works well enough. |
|
|||
1150 | # * For a non-matching section, do a best-effort fit. Match lines in |
|
|||
1151 | # diff hunks 1:1, dropping lines as necessary. |
|
|||
1152 | # * Repeat the last line as a last resort. |
|
|||
1153 |
|
||||
1154 | # First, replace as much as possible without repeating the last line. |
|
|||
1155 | remaining = [(parent, []) for parent, _blocks in pblocks] |
|
|||
1156 | for idx, (parent, blocks) in enumerate(pblocks): |
|
|||
1157 | for (a1, a2, b1, b2), _t in blocks: |
|
|||
1158 | if a2 - a1 >= b2 - b1: |
|
|||
1159 | for bk in xrange(b1, b2): |
|
|||
1160 | if child[0][bk].fctx == childfctx: |
|
|||
1161 | ak = min(a1 + (bk - b1), a2 - 1) |
|
|||
1162 | child[0][bk] = attr.evolve(parent[0][ak], skip=True) |
|
|||
1163 | else: |
|
|||
1164 | remaining[idx][1].append((a1, a2, b1, b2)) |
|
|||
1165 |
|
||||
1166 | # Then, look at anything left, which might involve repeating the last |
|
|||
1167 | # line. |
|
|||
1168 | for parent, blocks in remaining: |
|
|||
1169 | for a1, a2, b1, b2 in blocks: |
|
|||
1170 | for bk in xrange(b1, b2): |
|
|||
1171 | if child[0][bk].fctx == childfctx: |
|
|||
1172 | ak = min(a1 + (bk - b1), a2 - 1) |
|
|||
1173 | child[0][bk] = attr.evolve(parent[0][ak], skip=True) |
|
|||
1174 | return child |
|
|||
1175 |
|
||||
1176 | class filectx(basefilectx): |
|
1108 | class filectx(basefilectx): | |
1177 | """A filecontext object makes access to data related to a particular |
|
1109 | """A filecontext object makes access to data related to a particular | |
1178 | filerevision convenient.""" |
|
1110 | filerevision convenient.""" |
@@ -9,6 +9,9 b' from __future__ import absolute_import' | |||||
9 |
|
9 | |||
10 | import heapq |
|
10 | import heapq | |
11 |
|
11 | |||
|
12 | from .thirdparty import ( | |||
|
13 | attr, | |||
|
14 | ) | |||
12 | from . import ( |
|
15 | from . import ( | |
13 | error, |
|
16 | error, | |
14 | mdiff, |
|
17 | mdiff, | |
@@ -358,6 +361,74 b' def blockdescendants(fctx, fromline, tol' | |||||
358 | if inrange: |
|
361 | if inrange: | |
359 | yield c, linerange1 |
|
362 | yield c, linerange1 | |
360 |
|
363 | |||
|
364 | @attr.s(slots=True, frozen=True) | |||
|
365 | class annotateline(object): | |||
|
366 | fctx = attr.ib() | |||
|
367 | lineno = attr.ib(default=False) | |||
|
368 | # Whether this annotation was the result of a skip-annotate. | |||
|
369 | skip = attr.ib(default=False) | |||
|
370 | ||||
|
371 | def _annotatepair(parents, childfctx, child, skipchild, diffopts): | |||
|
372 | r''' | |||
|
373 | Given parent and child fctxes and annotate data for parents, for all lines | |||
|
374 | in either parent that match the child, annotate the child with the parent's | |||
|
375 | data. | |||
|
376 | ||||
|
377 | Additionally, if `skipchild` is True, replace all other lines with parent | |||
|
378 | annotate data as well such that child is never blamed for any lines. | |||
|
379 | ||||
|
380 | See test-annotate.py for unit tests. | |||
|
381 | ''' | |||
|
382 | pblocks = [(parent, mdiff.allblocks(parent[1], child[1], opts=diffopts)) | |||
|
383 | for parent in parents] | |||
|
384 | ||||
|
385 | if skipchild: | |||
|
386 | # Need to iterate over the blocks twice -- make it a list | |||
|
387 | pblocks = [(p, list(blocks)) for (p, blocks) in pblocks] | |||
|
388 | # Mercurial currently prefers p2 over p1 for annotate. | |||
|
389 | # TODO: change this? | |||
|
390 | for parent, blocks in pblocks: | |||
|
391 | for (a1, a2, b1, b2), t in blocks: | |||
|
392 | # Changed blocks ('!') or blocks made only of blank lines ('~') | |||
|
393 | # belong to the child. | |||
|
394 | if t == '=': | |||
|
395 | child[0][b1:b2] = parent[0][a1:a2] | |||
|
396 | ||||
|
397 | if skipchild: | |||
|
398 | # Now try and match up anything that couldn't be matched, | |||
|
399 | # Reversing pblocks maintains bias towards p2, matching above | |||
|
400 | # behavior. | |||
|
401 | pblocks.reverse() | |||
|
402 | ||||
|
403 | # The heuristics are: | |||
|
404 | # * Work on blocks of changed lines (effectively diff hunks with -U0). | |||
|
405 | # This could potentially be smarter but works well enough. | |||
|
406 | # * For a non-matching section, do a best-effort fit. Match lines in | |||
|
407 | # diff hunks 1:1, dropping lines as necessary. | |||
|
408 | # * Repeat the last line as a last resort. | |||
|
409 | ||||
|
410 | # First, replace as much as possible without repeating the last line. | |||
|
411 | remaining = [(parent, []) for parent, _blocks in pblocks] | |||
|
412 | for idx, (parent, blocks) in enumerate(pblocks): | |||
|
413 | for (a1, a2, b1, b2), _t in blocks: | |||
|
414 | if a2 - a1 >= b2 - b1: | |||
|
415 | for bk in xrange(b1, b2): | |||
|
416 | if child[0][bk].fctx == childfctx: | |||
|
417 | ak = min(a1 + (bk - b1), a2 - 1) | |||
|
418 | child[0][bk] = attr.evolve(parent[0][ak], skip=True) | |||
|
419 | else: | |||
|
420 | remaining[idx][1].append((a1, a2, b1, b2)) | |||
|
421 | ||||
|
422 | # Then, look at anything left, which might involve repeating the last | |||
|
423 | # line. | |||
|
424 | for parent, blocks in remaining: | |||
|
425 | for a1, a2, b1, b2 in blocks: | |||
|
426 | for bk in xrange(b1, b2): | |||
|
427 | if child[0][bk].fctx == childfctx: | |||
|
428 | ak = min(a1 + (bk - b1), a2 - 1) | |||
|
429 | child[0][bk] = attr.evolve(parent[0][ak], skip=True) | |||
|
430 | return child | |||
|
431 | ||||
361 | def toposort(revs, parentsfunc, firstbranch=()): |
|
432 | def toposort(revs, parentsfunc, firstbranch=()): | |
362 | """Yield revisions from heads to roots one (topo) branch at a time. |
|
433 | """Yield revisions from heads to roots one (topo) branch at a time. | |
363 |
|
434 |
General Comments 0
You need to be logged in to leave comments.
Login now