equal
deleted
inserted
replaced
988 |
988 |
989 # This algorithm would prefer to be recursive, but Python is a |
989 # This algorithm would prefer to be recursive, but Python is a |
990 # bit recursion-hostile. Instead we do an iterative |
990 # bit recursion-hostile. Instead we do an iterative |
991 # depth-first search. |
991 # depth-first search. |
992 |
992 |
|
993 # 1st DFS pre-calculates pcache and needed |
993 visit = [base] |
994 visit = [base] |
994 hist = {} |
|
995 pcache = {} |
995 pcache = {} |
996 needed = {base: 1} |
996 needed = {base: 1} |
997 while visit: |
997 while visit: |
|
998 f = visit.pop() |
|
999 if f in pcache: |
|
1000 continue |
|
1001 pl = parents(f) |
|
1002 pcache[f] = pl |
|
1003 for p in pl: |
|
1004 needed[p] = needed.get(p, 0) + 1 |
|
1005 if p not in pcache: |
|
1006 visit.append(p) |
|
1007 |
|
1008 # 2nd DFS does the actual annotate |
|
1009 visit[:] = [base] |
|
1010 hist = {} |
|
1011 while visit: |
998 f = visit[-1] |
1012 f = visit[-1] |
999 pcached = f in pcache |
1013 if f in hist: |
1000 if not pcached: |
1014 visit.pop() |
1001 pcache[f] = parents(f) |
1015 continue |
1002 |
1016 |
1003 ready = True |
1017 ready = True |
1004 pl = pcache[f] |
1018 pl = pcache[f] |
1005 for p in pl: |
1019 for p in pl: |
1006 if p not in hist: |
1020 if p not in hist: |
1007 ready = False |
1021 ready = False |
1008 visit.append(p) |
1022 visit.append(p) |
1009 if not pcached: |
|
1010 needed[p] = needed.get(p, 0) + 1 |
|
1011 if ready: |
1023 if ready: |
1012 visit.pop() |
1024 visit.pop() |
1013 reusable = f in hist |
1025 curr = decorate(f.data(), f) |
1014 if reusable: |
|
1015 curr = hist[f] |
|
1016 else: |
|
1017 curr = decorate(f.data(), f) |
|
1018 for p in pl: |
1026 for p in pl: |
1019 if not reusable: |
1027 curr = pair(hist[p], curr) |
1020 curr = pair(hist[p], curr) |
|
1021 if needed[p] == 1: |
1028 if needed[p] == 1: |
1022 del hist[p] |
1029 del hist[p] |
1023 del needed[p] |
1030 del needed[p] |
1024 else: |
1031 else: |
1025 needed[p] -= 1 |
1032 needed[p] -= 1 |
1026 |
1033 |
1027 hist[f] = curr |
1034 hist[f] = curr |
1028 pcache[f] = [] |
1035 del pcache[f] |
1029 |
1036 |
1030 return zip(hist[base][0], hist[base][1].splitlines(True)) |
1037 return zip(hist[base][0], hist[base][1].splitlines(True)) |
1031 |
1038 |
1032 def ancestors(self, followfirst=False): |
1039 def ancestors(self, followfirst=False): |
1033 visit = {} |
1040 visit = {} |