java-topology/defects/mercurial-0001/patch/mercurial-0001.patch

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)