122 lines
4 KiB
Diff
122 lines
4 KiB
Diff
# UNDF: UNDF-2026-000001125
|
|
diff -r 780af01abd69 mercurial/graphmod.py
|
|
--- a/mercurial/graphmod.py Wed Apr 01 19:48:46 2026 +0200
|
|
+++ b/mercurial/graphmod.py Fri Apr 03 11:03:45 2026 -0400
|
|
@@ -125,6 +125,7 @@
|
|
parents.
|
|
"""
|
|
seen = []
|
|
+ seen_pos = {} # node -> index in seen, O(1) alternative to list.index()
|
|
colors = {}
|
|
newcolor = 1
|
|
config = {}
|
|
@@ -147,19 +148,23 @@
|
|
|
|
for cur, type, data, parents in dag:
|
|
# Compute seen and next
|
|
- if cur not in seen:
|
|
+ if cur not in seen_pos:
|
|
+ seen_pos[cur] = len(seen)
|
|
seen.append(cur) # new head
|
|
colors[cur] = newcolor
|
|
newcolor += 1
|
|
|
|
- col = seen.index(cur)
|
|
+ col = seen_pos[cur]
|
|
color = colors.pop(cur)
|
|
next = seen[:]
|
|
|
|
# Add parents to next
|
|
- addparents = [p for pt, p in parents if p not in next]
|
|
+ addparents = [p for pt, p in parents if p not in seen_pos]
|
|
next[col : col + 1] = addparents
|
|
|
|
+ # Build O(1) position index for next after the splice
|
|
+ next_pos = {n: i for i, n in enumerate(next)}
|
|
+
|
|
# Set colors for the parents
|
|
for i, p in enumerate(addparents):
|
|
if not i:
|
|
@@ -171,12 +176,12 @@
|
|
# Add edges to the graph
|
|
edges = []
|
|
for ecol, eid in enumerate(seen):
|
|
- if eid in next:
|
|
+ if eid in next_pos:
|
|
bconf = getconf(eid)
|
|
edges.append(
|
|
(
|
|
ecol,
|
|
- next.index(eid),
|
|
+ next_pos[eid],
|
|
colors[eid],
|
|
bconf.get(b'width', -1),
|
|
bconf.get(b'color', b''),
|
|
@@ -188,7 +193,7 @@
|
|
edges.append(
|
|
(
|
|
ecol,
|
|
- next.index(p),
|
|
+ next_pos[p],
|
|
color,
|
|
bconf.get(b'width', -1),
|
|
bconf.get(b'color', b''),
|
|
@@ -198,14 +203,17 @@
|
|
# Yield and move on
|
|
yield (cur, type, data, (col, color), edges)
|
|
seen = next
|
|
+ seen_pos = next_pos
|
|
|
|
|
|
def asciiedges(type, char, state, rev, parents):
|
|
"""adds edge info to changelog DAG walk suitable for ascii()"""
|
|
seen = state.seen
|
|
- if rev not in seen:
|
|
+ seen_pos = state.seen_pos
|
|
+ if rev not in seen_pos:
|
|
+ seen_pos[rev] = len(seen)
|
|
seen.append(rev)
|
|
- nodeidx = seen.index(rev)
|
|
+ nodeidx = seen_pos[rev]
|
|
|
|
knownparents = []
|
|
newparents = []
|
|
@@ -213,7 +221,7 @@
|
|
if parent == rev:
|
|
# self reference (should only be seen in null rev)
|
|
continue
|
|
- if parent in seen:
|
|
+ if parent in seen_pos:
|
|
knownparents.append(parent)
|
|
else:
|
|
newparents.append(parent)
|
|
@@ -223,9 +231,11 @@
|
|
width = 1 + ncols * 2
|
|
nextseen = seen[:]
|
|
nextseen[nodeidx : nodeidx + 1] = newparents
|
|
- edges = [(nodeidx, nextseen.index(p)) for p in knownparents]
|
|
+ nextseen_pos = {n: i for i, n in enumerate(nextseen)}
|
|
+ edges = [(nodeidx, nextseen_pos[p]) for p in knownparents]
|
|
|
|
seen[:] = nextseen
|
|
+ state.seen_pos = nextseen_pos
|
|
while len(newparents) > 2:
|
|
# ascii() only knows how to add or remove a single column between two
|
|
# calls. Nodes with more than two parents break this constraint so we
|
|
@@ -365,6 +375,8 @@
|
|
for parent in remove:
|
|
del edgemap[parent]
|
|
seen.remove(parent)
|
|
+ if remove:
|
|
+ state.seen_pos = {n: i for i, n in enumerate(seen)}
|
|
|
|
|
|
@attr.s
|
|
@@ -372,6 +384,7 @@
|
|
"""State of ascii() graph rendering"""
|
|
|
|
seen = attr.ib(init=False, default=attr.Factory(list))
|
|
+ seen_pos = attr.ib(init=False, default=attr.Factory(dict)) # node -> index, O(1) lookup
|
|
edges = attr.ib(init=False, default=attr.Factory(dict))
|
|
lastcoldiff = attr.ib(init=False, default=0)
|
|
lastindex = attr.ib(init=False, default=0)
|