Show More
@@ -32,7 +32,6 b' from . import (' | |||
|
32 | 32 | error, |
|
33 | 33 | fileset, |
|
34 | 34 | match as matchmod, |
|
35 | mdiff, | |
|
36 | 35 | obsolete as obsmod, |
|
37 | 36 | obsutil, |
|
38 | 37 | patch, |
@@ -976,22 +975,6 b' class basefilectx(object):' | |||
|
976 | 975 | the line number at the first appearance in the managed file, otherwise, |
|
977 | 976 | number has a fixed value of False. |
|
978 | 977 | ''' |
|
979 | annotateline = dagop.annotateline | |
|
980 | _annotatepair = dagop._annotatepair | |
|
981 | ||
|
982 | def lines(text): | |
|
983 | if text.endswith("\n"): | |
|
984 | return text.count("\n") | |
|
985 | return text.count("\n") + int(bool(text)) | |
|
986 | ||
|
987 | if linenumber: | |
|
988 | def decorate(text, rev): | |
|
989 | return ([annotateline(fctx=rev, lineno=i) | |
|
990 | for i in xrange(1, lines(text) + 1)], text) | |
|
991 | else: | |
|
992 | def decorate(text, rev): | |
|
993 | return ([annotateline(fctx=rev)] * lines(text), text) | |
|
994 | ||
|
995 | 978 | getlog = util.lrucachefunc(lambda x: self._repo.file(x)) |
|
996 | 979 | |
|
997 | 980 | def parents(f): |
@@ -1027,60 +1010,8 b' class basefilectx(object):' | |||
|
1027 | 1010 | ac = cl.ancestors([base.rev()], inclusive=True) |
|
1028 | 1011 | base._ancestrycontext = ac |
|
1029 | 1012 | |
|
1030 | # This algorithm would prefer to be recursive, but Python is a | |
|
1031 | # bit recursion-hostile. Instead we do an iterative | |
|
1032 | # depth-first search. | |
|
1033 | ||
|
1034 | # 1st DFS pre-calculates pcache and needed | |
|
1035 | visit = [base] | |
|
1036 | pcache = {} | |
|
1037 | needed = {base: 1} | |
|
1038 | while visit: | |
|
1039 | f = visit.pop() | |
|
1040 | if f in pcache: | |
|
1041 | continue | |
|
1042 | pl = parents(f) | |
|
1043 | pcache[f] = pl | |
|
1044 | for p in pl: | |
|
1045 | needed[p] = needed.get(p, 0) + 1 | |
|
1046 | if p not in pcache: | |
|
1047 | visit.append(p) | |
|
1048 | ||
|
1049 | # 2nd DFS does the actual annotate | |
|
1050 | visit[:] = [base] | |
|
1051 | hist = {} | |
|
1052 | while visit: | |
|
1053 | f = visit[-1] | |
|
1054 | if f in hist: | |
|
1055 | visit.pop() | |
|
1056 | continue | |
|
1057 | ||
|
1058 | ready = True | |
|
1059 | pl = pcache[f] | |
|
1060 | for p in pl: | |
|
1061 | if p not in hist: | |
|
1062 | ready = False | |
|
1063 | visit.append(p) | |
|
1064 | if ready: | |
|
1065 | visit.pop() | |
|
1066 | curr = decorate(f.data(), f) | |
|
1067 | skipchild = False | |
|
1068 | if skiprevs is not None: | |
|
1069 | skipchild = f._changeid in skiprevs | |
|
1070 | curr = _annotatepair([hist[p] for p in pl], f, curr, skipchild, | |
|
1071 | diffopts) | |
|
1072 | for p in pl: | |
|
1073 | if needed[p] == 1: | |
|
1074 | del hist[p] | |
|
1075 | del needed[p] | |
|
1076 | else: | |
|
1077 | needed[p] -= 1 | |
|
1078 | ||
|
1079 | hist[f] = curr | |
|
1080 | del pcache[f] | |
|
1081 | ||
|
1082 | lineattrs, text = hist[base] | |
|
1083 | return pycompat.ziplist(lineattrs, mdiff.splitnewlines(text)) | |
|
1013 | return dagop.annotate(base, parents, linenumber=linenumber, | |
|
1014 | skiprevs=skiprevs, diffopts=diffopts) | |
|
1084 | 1015 | |
|
1085 | 1016 | def ancestors(self, followfirst=False): |
|
1086 | 1017 | visit = {} |
@@ -17,6 +17,7 b' from . import (' | |||
|
17 | 17 | mdiff, |
|
18 | 18 | node, |
|
19 | 19 | patch, |
|
20 | pycompat, | |
|
20 | 21 | smartset, |
|
21 | 22 | ) |
|
22 | 23 | |
@@ -429,6 +430,80 b' def _annotatepair(parents, childfctx, ch' | |||
|
429 | 430 | child[0][bk] = attr.evolve(parent[0][ak], skip=True) |
|
430 | 431 | return child |
|
431 | 432 | |
|
433 | def annotate(base, parents, linenumber=False, skiprevs=None, diffopts=None): | |
|
434 | """Core algorithm for filectx.annotate() | |
|
435 | ||
|
436 | `parents(fctx)` is a function returning a list of parent filectxs. | |
|
437 | """ | |
|
438 | ||
|
439 | def lines(text): | |
|
440 | if text.endswith("\n"): | |
|
441 | return text.count("\n") | |
|
442 | return text.count("\n") + int(bool(text)) | |
|
443 | ||
|
444 | if linenumber: | |
|
445 | def decorate(text, rev): | |
|
446 | return ([annotateline(fctx=rev, lineno=i) | |
|
447 | for i in xrange(1, lines(text) + 1)], text) | |
|
448 | else: | |
|
449 | def decorate(text, rev): | |
|
450 | return ([annotateline(fctx=rev)] * lines(text), text) | |
|
451 | ||
|
452 | # This algorithm would prefer to be recursive, but Python is a | |
|
453 | # bit recursion-hostile. Instead we do an iterative | |
|
454 | # depth-first search. | |
|
455 | ||
|
456 | # 1st DFS pre-calculates pcache and needed | |
|
457 | visit = [base] | |
|
458 | pcache = {} | |
|
459 | needed = {base: 1} | |
|
460 | while visit: | |
|
461 | f = visit.pop() | |
|
462 | if f in pcache: | |
|
463 | continue | |
|
464 | pl = parents(f) | |
|
465 | pcache[f] = pl | |
|
466 | for p in pl: | |
|
467 | needed[p] = needed.get(p, 0) + 1 | |
|
468 | if p not in pcache: | |
|
469 | visit.append(p) | |
|
470 | ||
|
471 | # 2nd DFS does the actual annotate | |
|
472 | visit[:] = [base] | |
|
473 | hist = {} | |
|
474 | while visit: | |
|
475 | f = visit[-1] | |
|
476 | if f in hist: | |
|
477 | visit.pop() | |
|
478 | continue | |
|
479 | ||
|
480 | ready = True | |
|
481 | pl = pcache[f] | |
|
482 | for p in pl: | |
|
483 | if p not in hist: | |
|
484 | ready = False | |
|
485 | visit.append(p) | |
|
486 | if ready: | |
|
487 | visit.pop() | |
|
488 | curr = decorate(f.data(), f) | |
|
489 | skipchild = False | |
|
490 | if skiprevs is not None: | |
|
491 | skipchild = f._changeid in skiprevs | |
|
492 | curr = _annotatepair([hist[p] for p in pl], f, curr, skipchild, | |
|
493 | diffopts) | |
|
494 | for p in pl: | |
|
495 | if needed[p] == 1: | |
|
496 | del hist[p] | |
|
497 | del needed[p] | |
|
498 | else: | |
|
499 | needed[p] -= 1 | |
|
500 | ||
|
501 | hist[f] = curr | |
|
502 | del pcache[f] | |
|
503 | ||
|
504 | lineattrs, text = hist[base] | |
|
505 | return pycompat.ziplist(lineattrs, mdiff.splitnewlines(text)) | |
|
506 | ||
|
432 | 507 | def toposort(revs, parentsfunc, firstbranch=()): |
|
433 | 508 | """Yield revisions from heads to roots one (topo) branch at a time. |
|
434 | 509 |
General Comments 0
You need to be logged in to leave comments.
Login now