Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve graph conflict message when Conan can't show one of the conflicting recipes #13946

Merged
merged 8 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions conan/cli/formatters/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from conan.cli.formatters.graph.info_graph_html import graph_info_html
from conans.client.graph.graph import BINARY_CACHE, \
BINARY_DOWNLOAD, BINARY_BUILD, BINARY_MISSING, BINARY_UPDATE
from conans.client.graph.graph_error import GraphConflictError
from conans.client.installer import build_id
from conans.util.files import load

Expand Down Expand Up @@ -86,11 +87,12 @@ def binary_color(node):
return color


def _render_graph(graph, template, template_folder):
def _render_graph(graph, error, template, template_folder):
graph = _Grapher(graph)
from conans import __version__ as client_version
template = Template(template, autoescape=select_autoescape(['html', 'xml']))
return template.render(graph=graph, base_template_path=template_folder, version=client_version)
return template.render(graph=graph, error=error, base_template_path=template_folder,
version=client_version)


def format_graph_html(result):
Expand All @@ -104,7 +106,15 @@ def format_graph_html(result):
template_folder = os.path.join(conan_api.cache_folder, "templates")
user_template = os.path.join(template_folder, "graph.html")
template = load(user_template) if os.path.isfile(user_template) else graph_info_html
cli_out_write(_render_graph(graph, template, template_folder))
error = None
if isinstance(graph.error, GraphConflictError):
error = {
"label": graph.error.require.ref,
"type": "conflict",
"from": graph.error.node.ref or graph.error.base_previous.ref,
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
"prev_require": graph.error.prev_require.ref
}
cli_out_write(_render_graph(graph, error, template, template_folder))
if graph.error:
raise graph.error

Expand All @@ -120,7 +130,7 @@ def format_graph_dot(result):
template_folder = os.path.join(conan_api.cache_folder, "templates")
user_template = os.path.join(template_folder, "graph.dot")
template = load(user_template) if os.path.isfile(user_template) else graph_info_dot
cli_out_write(_render_graph(graph, template, template_folder))
cli_out_write(_render_graph(graph, None, template, template_folder))
if graph.error:
raise graph.error

Expand Down
33 changes: 29 additions & 4 deletions conan/cli/formatters/graph/info_graph_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<div style="clear:both"></div>

<script type="text/javascript">
var nodes = new vis.DataSet([
var nodes = [
{%- for node in graph.nodes %}
{
id: {{ node.id }},
Expand All @@ -69,12 +69,37 @@
'</ul>'
}{%- if not loop.last %},{% endif %}
{%- endfor %}
]);
var edges = new vis.DataSet([
]
var edges = [
{%- for src, dst in graph.edges %}
{ from: {{ src.id }}, to: {{ dst.id }} }{%- if not loop.last %},{% endif %}
{%- endfor %}
]);
]

{% if error is not none and error["type"] == "conflict" %}
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
nodes.push({
id: "{{ error["type"] }}",
label: "{{ error["label"] }}",
shape: "circle",
font: { color: "white" },
color: "red",
fulllabel: '<h3>{{ error["label"] }}</h3><p>This node creates a conflict in the dependency graph with {{ error["prev_require"] }}</p>',
shapeProperties: { borderDashes: [5, 5] }
})

{% if error["from"] is not none %}
var i = nodes.findIndex(e => e["label"] === "{{ error["from"] }}")
if (i !== -1) {
var conflictOriginId = nodes[i]["id"];
edges.push({from: conflictOriginId, to: "{{ error["type"] }}", color: "red", dashes: true, title: "Conflict"})
}


{% endif %}
{% endif %}

var nodes = new vis.DataSet(nodes);
var edges = new vis.DataSet(edges);

var container = document.getElementById('mynetwork');
var controls = document.getElementById('controls');
Expand Down