Skip to content

Commit

Permalink
Merge pull request #110 from jmcconnell26/ISSUE-16-CreateGraphModule
Browse files Browse the repository at this point in the history
ISSUE-16 - Create Graph Module
  • Loading branch information
anderejd authored Aug 27, 2020
2 parents 2d66004 + 2241146 commit 75f6680
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 102 deletions.
102 changes: 2 additions & 100 deletions cargo-geiger/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use cargo::CliError;
use crate::format::Pattern;
use crate::Args;
use crate::graph::{Graph, Node};
use cargo::core::compiler::CompileMode;
use cargo::core::compiler::Executor;
use cargo::core::compiler::Unit;
Expand Down Expand Up @@ -41,10 +42,8 @@ use geiger::Count;
use geiger::CounterBlock;
use geiger::IncludeTests;
use geiger::RsFileMetrics;
use petgraph::graph::NodeIndex;
use petgraph::visit::EdgeRef;
use petgraph::EdgeDirection;
use std::collections::hash_map::Entry;
use petgraph::visit::EdgeRef;
use std::collections::{HashMap, HashSet};
use std::ffi::OsString;
use std::io;
Expand All @@ -64,13 +63,6 @@ pub enum Charset {
Ascii,
}

pub enum ExtraDeps {
All,
Build,
Dev,
NoMore,
}

#[derive(Clone, Copy)]
pub enum Prefix {
None,
Expand All @@ -95,18 +87,6 @@ pub struct PrintConfig<'a> {
pub include_tests: IncludeTests,
}

pub struct Node {
id: PackageId,
// TODO: Investigate why this was needed before the separation of printing
// and graph traversal and if it should be added back.
//pack: &'a Package,
}

pub struct Graph {
graph: petgraph::Graph<Node, DepKind>,
nodes: HashMap<PackageId, NodeIndex>,
}

/// TODO: Write proper documentation for this.
/// This function seems to be looking up the active flags for conditional
/// compilation (cargo_platform::Cfg instances).
Expand All @@ -133,72 +113,6 @@ pub fn get_cfgs(
))
}

/// Almost unmodified compared to the original in cargo-tree, should be fairly
/// simple to move this and the dependency graph structure out to a library.
/// TODO: Move this to a module to begin with.
pub fn build_graph<'a>(
resolve: &'a Resolve,
packages: &'a PackageSet,
root: PackageId,
target: Option<&str>,
cfgs: Option<&[Cfg]>,
extra_deps: ExtraDeps,
) -> CargoResult<Graph> {
let mut graph = Graph {
graph: petgraph::Graph::new(),
nodes: HashMap::new(),
};
let node = Node {
id: root,
//pack: packages.get_one(root)?,
};
graph.nodes.insert(root, graph.graph.add_node(node));

let mut pending = vec![root];

while let Some(pkg_id) = pending.pop() {
let idx = graph.nodes[&pkg_id];
let pkg = packages.get_one(pkg_id)?;

for raw_dep_id in resolve.deps_not_replaced(pkg_id) {
let it = pkg
.dependencies()
.iter()
.filter(|d| d.matches_ignoring_source(raw_dep_id.0))
.filter(|d| extra_deps.allows(d.kind()))
.filter(|d| {
d.platform()
.and_then(|p| {
target.map(|t| match cfgs {
None => false,
Some(cfgs) => p.matches(t, cfgs),
})
})
.unwrap_or(true)
});
let dep_id = match resolve.replacement(raw_dep_id.0) {
Some(id) => id,
None => raw_dep_id.0,
};
for dep in it {
let dep_idx = match graph.nodes.entry(dep_id) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
pending.push(dep_id);
let node = Node {
id: dep_id,
//pack: packages.get_one(dep_id)?,
};
*e.insert(graph.graph.add_node(node))
}
};
graph.graph.add_edge(idx, dep_idx, dep.kind());
}
}
}

Ok(graph)
}

pub fn get_workspace(
config: &Config,
Expand Down Expand Up @@ -590,18 +504,6 @@ fn get_kind_group_name(k: DepKind) -> Option<&'static str> {

// ---------- END: Public items ----------

impl ExtraDeps {
fn allows(&self, dep: DepKind) -> bool {
match (self, dep) {
(_, DepKind::Normal) => true,
(ExtraDeps::All, _) => true,
(ExtraDeps::Build, DepKind::Build) => true,
(ExtraDeps::Dev, DepKind::Development) => true,
_ => false,
}
}
}

#[derive(Debug)]
enum RsResolveError {
Walkdir(walkdir::Error),
Expand Down
109 changes: 109 additions & 0 deletions cargo-geiger/src/graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use cargo::core::{PackageId, Resolve};
use cargo::core::dependency::DepKind;
use cargo::core::package::PackageSet;
use cargo::util::CargoResult;
use cargo_platform::Cfg;
use petgraph::graph::NodeIndex;
use std::collections::hash_map::Entry;
use std::collections::{HashMap};

// ---------- BEGIN: Public items ----------

pub enum ExtraDeps {
All,
Build,
Dev,
NoMore,
}

impl ExtraDeps {
pub fn allows(&self, dep: DepKind) -> bool {
match (self, dep) {
(_, DepKind::Normal) => true,
(ExtraDeps::All, _) => true,
(ExtraDeps::Build, DepKind::Build) => true,
(ExtraDeps::Dev, DepKind::Development) => true,
_ => false,
}
}
}

pub struct Graph {
pub graph: petgraph::Graph<Node, DepKind>,
pub nodes: HashMap<PackageId, NodeIndex>,
}

pub struct Node {
pub id: PackageId,
// TODO: Investigate why this was needed before the separation of printing
// and graph traversal and if it should be added back.
//pack: &'a Package,
}

/// Almost unmodified compared to the original in cargo-tree, should be fairly
/// simple to move this and the dependency graph structure out to a library.
pub fn build_graph<'a>(
resolve: &'a Resolve,
packages: &'a PackageSet,
root: PackageId,
target: Option<&str>,
cfgs: Option<&[Cfg]>,
extra_deps: ExtraDeps,
) -> CargoResult<Graph> {
let mut graph = Graph {
graph: petgraph::Graph::new(),
nodes: HashMap::new(),
};
let node = Node {
id: root,
//pack: packages.get_one(root)?,
};
graph.nodes.insert(root, graph.graph.add_node(node));

let mut pending = vec![root];

while let Some(pkg_id) = pending.pop() {
let idx = graph.nodes[&pkg_id];
let pkg = packages.get_one(pkg_id)?;

for raw_dep_id in resolve.deps_not_replaced(pkg_id) {
let it = pkg
.dependencies()
.iter()
.filter(|d| d.matches_ignoring_source(raw_dep_id.0))
.filter(|d| extra_deps.allows(d.kind()))
.filter(|d| {
d.platform()
.and_then(|p| {
target.map(|t| match cfgs {
None => false,
Some(cfgs) => p.matches(t, cfgs),
})
})
.unwrap_or(true)
});
let dep_id = match resolve.replacement(raw_dep_id.0) {
Some(id) => id,
None => raw_dep_id.0,
};
for dep in it {
let dep_idx = match graph.nodes.entry(dep_id) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
pending.push(dep_id);
let node = Node {
id: dep_id,
//pack: packages.get_one(dep_id)?,
};
*e.insert(graph.graph.add_node(node))
}
};
graph.graph.add_edge(idx, dep_idx, dep.kind());
}
}
}

Ok(graph)
}

// ---------- END: Public items ----------
5 changes: 3 additions & 2 deletions cargo-geiger/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@ extern crate petgraph;

mod cli;
mod format;
mod graph;

use crate::cli::build_graph;
use crate::cli::get_cfgs;
use crate::cli::get_registry;
use crate::cli::get_workspace;
use crate::cli::resolve;
use crate::cli::run_scan_mode_default;
use crate::cli::run_scan_mode_forbid_only;
use crate::cli::Charset;
use crate::cli::ExtraDeps;
use crate::cli::Prefix;
use crate::cli::PrintConfig;
use crate::format::Pattern;
use crate::graph::build_graph;
use crate::graph::ExtraDeps;
use cargo::core::shell::Shell;
use cargo::core::shell::Verbosity;
use cargo::util::errors::CliError;
Expand Down

0 comments on commit 75f6680

Please sign in to comment.