1use crate::{
2 config::Config,
3 dep::{DepKind, ResolvedDep},
4 error::{Error, Result},
5 project::RootDepsMap,
6};
7use std::{collections::HashMap, fmt, io::Write};
8
9pub type Node = usize;
10
11#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
12pub struct Edge(pub Node, pub Node);
13
14impl Edge {
15 pub fn label<W: Write>(&self, w: &mut W, dg: &DepGraph) -> Result<()> {
16 use crate::dep::DepKind::{Build, Dev, Optional, Regular, Unknown};
17
18 let parent = dg.get(self.0).unwrap();
19 let child = dg.get(self.1).unwrap();
20
21 let child_kind = if let Some(dep_kinds_map) = &dg.root_deps_map.get(&parent.name) {
25 if let Some(kinds) = dep_kinds_map.get(&child.name) {
26 if kinds.contains(&Regular) {
27 Regular
28 } else if kinds.contains(&Build) {
29 Build
30 } else if kinds.contains(&Dev) {
31 Dev
32 } else if kinds.contains(&Optional) {
33 Optional
34 } else {
35 Unknown
36 }
37 } else {
38 return Err(Error::Generic(format!(
39 "Crate '{}' is not a dependency of a root crate. This is probably a logic \
40 error.",
41 child.name
42 )));
43 }
44 } else {
45 child.kind()
46 };
47
48 match (parent.kind(), child_kind) {
49 (Regular, Regular) => writeln!(w, ";")?,
50 (Build, _) | (Regular, Build) => writeln!(w, " [color=purple, style=dashed];")?,
51 (Dev, _) | (Regular, Dev) => writeln!(w, " [color=blue, style=dashed];")?,
52 (Optional, _) | (Regular, Optional) => writeln!(w, " [color=red, style=dashed];")?,
53 _ => writeln!(w, " [color=orange, style=dashed];")?,
54 }
55
56 Ok(())
57 }
58}
59
60impl fmt::Display for Edge {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 let &Self(il, ir) = self;
63 write!(f, "n{} -> n{}", il, ir)
64 }
65}
66
67#[derive(Debug)]
68pub struct DepGraph {
69 pub nodes: Vec<ResolvedDep>,
72 pub edges: Vec<Edge>,
73 pub root_deps_map: RootDepsMap,
74 pub cfg: Config,
75}
76
77impl DepGraph {
78 pub fn new(cfg: Config) -> Self {
79 Self {
80 nodes: vec![],
81 edges: vec![],
82 root_deps_map: HashMap::new(),
83 cfg,
84 }
85 }
86
87 pub fn topological_sort(&mut self) -> Result<()> {
89 let mut graph_nodes = self.nodes.clone();
93 let mut l: Vec<Node> = vec![];
95 let mut s: Vec<Node> = vec![];
97
98 for (i, node) in self.nodes.iter().enumerate() {
100 if node.parents.is_empty() {
101 s.push(i);
102 }
103 }
104
105 while let Some(n) = s.pop() {
106 l.push(n);
107
108 while let Some(child) = graph_nodes[n].children.pop() {
109 assert_ne!(n, child);
110
111 let edge_index = self
113 .edges
114 .iter()
115 .position(|Edge(a, b)| a == &n && b == &child)
116 .unwrap();
117 self.edges.remove(edge_index);
118 let node_index = graph_nodes[child]
119 .parents
120 .iter()
121 .position(|node| *node == n)
122 .unwrap();
123 graph_nodes[child].parents.remove(node_index);
124
125 if graph_nodes[child].parents.is_empty() {
127 s.push(child);
128 }
129 }
130 }
131
132 if self.edges.is_empty() {
133 for n in l.iter() {
135 'child_loop: for child in self.nodes[*n].children.iter() {
136 if !self.cfg.transitive_deps {
140 for c in self.nodes[*n].children.iter().filter(|c| *c != child) {
141 if self.transitive_dep(*c, *child) {
142 continue 'child_loop;
143 }
144 }
145 }
146 self.edges.push(Edge(*n, *child));
147 }
148 }
149
150 Ok(())
151 } else {
152 Err(Error::Generic("Cycle detected in dependency graph".into()))
153 }
154 }
155
156 pub fn set_resolved_kind(&mut self) -> Result<()> {
158 for node in self.nodes.iter_mut() {
160 if self.root_deps_map.contains_key(&node.name) {
161 node.is_regular = true;
162 }
163 }
164
165 for ed in self.edges.iter() {
167 let (
170 parent_name,
171 parent_depth,
172 parent_regular,
173 parent_build,
174 parent_dev,
175 parent_optional,
176 ) = {
177 let parent = &mut self.nodes[ed.0];
178
179 if parent.depth.is_none() {
181 parent.depth = Some(0);
182 }
183
184 (
185 parent.name.to_string(),
186 parent.depth,
187 parent.is_regular,
188 parent.is_build,
189 parent.is_dev,
190 parent.is_optional,
191 )
192 };
193 let mut child = &mut self.nodes[ed.1];
194
195 if child.depth.is_none() {
197 child.depth = Some(parent_depth.unwrap() + 1);
198 }
199
200 if let Some(dep_kinds_map) = self.root_deps_map.get(&parent_name) {
201 if let Some(kinds) = dep_kinds_map.get(&child.name) {
204 for kind in kinds {
205 match *kind {
206 DepKind::Regular => child.is_regular = true,
207 DepKind::Build => child.is_build = true,
208 DepKind::Dev => child.is_dev = true,
209 DepKind::Optional => child.is_optional = true,
210 _ => (),
211 }
212 }
213 } else {
214 return Err(Error::Generic(format!(
215 "Crate '{}' is not a dependency of a root crate. This is probably a logic \
216 error.",
217 child.name
218 )));
219 }
220 } else {
221 if parent_regular {
228 child.is_regular = true;
229 }
230 if parent_build {
231 child.is_build = true;
232 }
233 if parent_dev {
234 child.is_dev = true;
235 }
236 if parent_optional {
237 child.is_optional = true;
238 }
239 }
240 }
241
242 Ok(())
243 }
244
245 pub fn show_version_on_duplicates(&mut self) {
248 let dep_ids_sorted_by_name = {
250 let mut deps = self.nodes.iter().enumerate().collect::<Vec<_>>();
251 deps.sort_by_key(|dep| &*dep.1.name);
252 deps.iter().map(|dep| dep.0).collect::<Vec<_>>()
253 };
254
255 for (i, &dep_id_i) in dep_ids_sorted_by_name
256 .iter()
257 .enumerate()
258 .take(dep_ids_sorted_by_name.len() - 1)
259 {
260 for (j, &dep) in dep_ids_sorted_by_name
263 .iter()
264 .enumerate()
265 .take(dep_ids_sorted_by_name.len() + 1)
266 .skip(i + 1)
267 {
268 if j >= dep_ids_sorted_by_name.len()
271 || self.nodes[dep_id_i].name != self.nodes[dep].name
272 {
273 if j >= i + 2 {
275 for &dep_id_k in dep_ids_sorted_by_name.iter().take(j).skip(i) {
280 self.nodes[dep_id_k].force_write_ver = true;
281 }
282 }
283
284 break;
285 }
286 }
287 }
288 }
289
290 pub fn add_child(
291 &mut self,
292 parent: usize,
293 dep_name: &str,
294 dep_ver: &str,
295 registry: &Option<String>,
296 ) {
297 let child = self.find_or_add(dep_name, dep_ver, registry);
298
299 if parent == child {
300 return;
301 }
302
303 self.edges.push(Edge(parent, child));
304
305 self.nodes[parent].children.push(child);
306 self.nodes[child].parents.push(parent);
307 }
308
309 pub fn get(&self, id: usize) -> Option<&ResolvedDep> {
310 if id < self.nodes.len() {
311 return Some(&self.nodes[id]);
312 }
313 None
314 }
315
316 pub fn find(&self, name: &str, ver: &str) -> Option<usize> {
317 for (i, d) in self.nodes.iter().enumerate() {
318 if d.name == name && d.ver == ver {
319 return Some(i);
320 }
321 }
322 None
323 }
324
325 pub fn find_or_add(&mut self, name: &str, ver: &str, registry: &Option<String>) -> usize {
326 if let Some(i) = self.find(name, ver) {
327 return i;
328 }
329 self.nodes.push(ResolvedDep::new(
330 name.to_owned(),
331 ver.to_owned(),
332 registry.clone(),
333 ));
334 self.nodes.len() - 1
335 }
336
337 pub fn render_to<W: Write>(self, output: &mut W) -> Result<()> {
338 let mut nodes_added = vec![];
340
341 writeln!(output, "digraph dependencies {{")?;
342
343 for (i, dep) in self.nodes.iter().enumerate() {
345 if let Some(sub_deps) = &self.cfg.subgraph {
347 if sub_deps.contains(&dep.name) {
348 continue;
349 }
350 }
351
352 if let Some(depth) = self.cfg.depth {
355 if dep.depth.is_none() || dep.depth.unwrap() > depth {
357 continue;
358 }
359 }
360
361 if !self.cfg.include_orphans {
364 if let DepKind::Unknown = dep.kind() {
365 continue;
366 }
367 }
368
369 if let Some(registries) = &self.cfg.registries {
371 if let Some(registry) = &dep.registry {
372 if !registries.contains(registry) {
373 continue;
374 }
375 } else {
376 continue;
377 }
378 }
379
380 write!(output, "\tn{}", i)?;
382 dep.label(output, &self)?;
383 nodes_added.push(i);
384 }
385 writeln!(output)?;
386
387 if let Some(sub_deps) = &self.cfg.subgraph {
389 writeln!(output, "\tsubgraph cluster_subgraph {{")?;
390 if let Some(sub_name) = &self.cfg.subgraph_name {
391 writeln!(output, "\t\tlabel=\"{}\";", sub_name)?;
392 }
393 writeln!(output, "\t\tcolor=brown;")?;
394 writeln!(output, "\t\tstyle=dashed;")?;
395 writeln!(output)?;
396
397 for (i, dep) in self.nodes.iter().enumerate() {
398 if sub_deps.contains(&dep.name) {
399 write!(output, "\t\tn{}", i)?;
400 dep.label(output, &self)?;
401
402 nodes_added.push(i);
403 }
404 }
405
406 writeln!(output, "\t}}\n")?;
407 }
408
409 for ed in &self.edges {
411 if !(nodes_added.contains(&ed.0) && nodes_added.contains(&ed.1)) {
413 continue;
414 }
415
416 write!(output, "\t{}", ed)?;
417 ed.label(output, &self)?;
418 }
419
420 writeln!(output, "}}")?;
421
422 Ok(())
423 }
424
425 fn transitive_dep(&self, parent: usize, child: usize) -> bool {
431 for c in self.nodes[parent].children.iter() {
432 if *c == child || self.transitive_dep(*c, child) {
433 return true;
434 }
435 }
436 false
437 }
438}