Skip to content

Commit dccddda

Browse files
PantsworthJeanChristopheMorinPerso
authored and
Jose Enriquez
committed
Fix --fail-graph when there is indirect cycles (AcademySoftwareFoundation#1620)
Fix --fail-graph when there is indirect cycles (AcademySoftwareFoundation#1620) Signed-off-by: Michael Nowakowski <[email protected]> Signed-off-by: Jean-Christophe Morin <[email protected]> Co-authored-by: Jean-Christophe Morin <[email protected]> Signed-off-by: Jose Enriquez <[email protected]>
1 parent 1105bbf commit dccddda

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright Contributors to the Rez Project
3+
4+
5+
"""
6+
unit tests for 'utils.resolve_graph' module
7+
"""
8+
from rez.tests.util import TestBase
9+
from rez.utils import resolve_graph
10+
import rez.utils.graph_utils
11+
import unittest
12+
13+
14+
class TestResolveGraph(TestBase):
15+
def test_conflict_graph_with_cycle(self):
16+
""" Tests creating a test digraph which contains a cycle foo-1.0.0 => bar-0.0.1 => !foo-1.0.0
17+
Note that the solver doesn't detect this as a cycle. See #1568
18+
"""
19+
20+
g = '''
21+
digraph g {
22+
_1 [label="foo-1", fontsize="10", fillcolor="#FFFFAA", style="filled,dashed"];
23+
_2 [label="bar", fontsize="10", fillcolor="#FFFFAA", style="filled,dashed"];
24+
_6 [label="foo-1.0.0[]", fontsize="10", fillcolor="#AAFFAA", style="filled"];
25+
_7 [label="bar-0.0.1[]", fontsize="10", fillcolor="#AAFFAA", style="filled"];
26+
_8 [label="!foo-1.0.0", fontsize="10", fillcolor="#F6F6F6", style="filled,dashed"];
27+
_1 -> _6 [arrowsize="0.5"];
28+
_2 -> _7 [arrowsize="0.5"];
29+
_6 -> _2 [arrowsize="0.5"];
30+
_7 -> _8 [arrowsize="0.5"];
31+
_8 -> _6 [arrowsize="1", style="bold", color="red", fontcolor="red", label=CONFLICT];
32+
}
33+
'''
34+
graph = rez.utils.graph_utils.read_graph_from_string(g)
35+
# strip extra quoting from fill color
36+
for k, v in graph.node_attr.items():
37+
for index, a in enumerate(v):
38+
if a[0] == "fillcolor":
39+
stripped_color = a[1].strip("'").strip('"')
40+
v[index] = ("fillcolor", stripped_color)
41+
42+
# attempt to graph result
43+
result = resolve_graph.failure_detail_from_graph(graph)
44+
self.assertTrue("foo-1 --> foo-1.0.0 --> bar-0.0.1 --> !foo-1.0.0" in result)
45+
self.assertTrue("bar --> bar-0.0.1 --> !foo-1.0.0" in result)
46+
47+
48+
if __name__ == '__main__':
49+
unittest.main()

src/rez/utils/resolve_graph.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _cycled_detail_from_graph(graph, cycled_edge):
5353
visited = list()
5454
while True:
5555
visited.append(node)
56-
down = next((ne for ne in graph.node_neighbors[node]), None)
56+
down = next((ne for ne in graph.node_neighbors[node] if ne not in visited), None)
5757
if down in cycled_edge:
5858
visited.append(down)
5959
break
@@ -83,7 +83,7 @@ def _conflicted_detail_from_graph(graph, conflicted_edge):
8383
visited = list()
8484
while True:
8585
visited.append(node)
86-
down = next((ne for ne in graph.node_neighbors[node]), None)
86+
down = next((ne for ne in graph.node_neighbors[node] if ne not in visited), None)
8787
if down is None:
8888
break
8989

0 commit comments

Comments
 (0)