From: Carl Lerche Date: Wed, 30 Apr 2014 20:59:04 +0000 (-0700) Subject: Topological sort of packages X-Git-Tag: archive/raspbian/0.35.0-2+rpi1~3^2^2^2^2^2^2^2~1101 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=d70ce6b61dac5a55f5b2fa2b0d71a3572dbacb19;p=cargo.git Topological sort of packages --- diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index 80d2356c5..0536acdd6 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -18,6 +18,10 @@ impl Dependency { Dependency { name: core::NameVer::new(name, version) } } + pub fn get_namever<'a>(&'a self) -> &'a core::NameVer { + &self.name + } + pub fn get_name<'a>(&'a self) -> &'a str { self.name.get_name() } diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index 99beeb8ff..6fc26e4d8 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -4,7 +4,6 @@ pub use self::namever::{ pub use self::registry::{ Registry, - MemRegistry }; pub use self::manifest::{ @@ -15,7 +14,8 @@ pub use self::manifest::{ }; pub use self::package::{ - Package + Package, + PackageSet }; pub use self::dependency::Dependency; diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 4ddae1ebd..f585b7947 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -1,8 +1,10 @@ -use std::vec::Vec; +use std::slice; use semver; use core; use core::{NameVer,Dependency}; use core::manifest::{Manifest,LibTarget}; +use core::Registry; +use util::graph; /** * Represents a rust library internally to cargo. This will things like where @@ -61,3 +63,54 @@ impl Package { self.deps.as_slice() } } + +pub struct PackageSet { + packages: ~[Package] +} + +impl PackageSet { + pub fn new(packages: &[Package]) -> PackageSet { + PackageSet { packages: packages.to_owned() } + } + + /** + * Get a package by name out of the set + */ + pub fn get<'a>(&'a self, name: &str) -> &'a Package { + let opts = self.query(name); + assert!(opts.len() == 1, "expected exactly one package named `{}`", name); + *opts.get(0) + } + + // For now, assume that the package set contains only one package with a + // given name + pub fn sort(&self) -> Option { + let mut graph = graph::Graph::new(); + + for pkg in self.packages.iter() { + let deps: ~[&str] = pkg.get_dependencies().iter() + .map(|dep| dep.get_name()) + .collect(); + + graph.add(pkg.get_name(), deps.as_slice()); + } + + let pkgs = some!(graph.sort()).iter().map(|name| self.get(*name).clone()).collect(); + + Some(PackageSet { + packages: pkgs + }) + } + + pub fn iter<'a>(&'a self) -> slice::Items<'a, Package> { + self.packages.iter() + } +} + +impl Registry for PackageSet { + fn query<'a>(&'a self, name: &str) -> Vec<&'a Package> { + self.packages.iter() + .filter(|pkg| name == pkg.get_name()) + .collect() + } +} diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index a5efe14ba..cfb41e7e5 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -14,6 +14,7 @@ pub trait Registry { * */ +/* pub struct MemRegistry { packages: Vec } @@ -35,3 +36,4 @@ impl Registry for MemRegistry { .collect() } } +*/ diff --git a/src/cargo/mod.rs b/src/cargo/mod.rs index 4c5ace6bb..a4e8bfcc0 100644 --- a/src/cargo/mod.rs +++ b/src/cargo/mod.rs @@ -19,6 +19,13 @@ use std::fmt; use std::fmt::{Show,Formatter}; use hammer::{FlagDecoder,FlagConfig,HammerError}; +macro_rules! some( + ($e:expr) => ( + match $e { + Some(e) => e, + None => return None + } + )) pub mod core; pub mod ops; diff --git a/src/cargo/ops/cargo_rustc.rs b/src/cargo/ops/cargo_rustc.rs index 056a47963..2f9443cd0 100644 --- a/src/cargo/ops/cargo_rustc.rs +++ b/src/cargo/ops/cargo_rustc.rs @@ -4,10 +4,25 @@ use std::io; use std::io::process::{Process,ProcessConfig,InheritFd}; use std::path::Path; use {CargoResult,CargoError,ToCargoError,NoFlags,core}; +use core; +pub fn compile(pkgs: &core::PackageSet) { + let sorted = match pkgs.sort() { + Some(pkgs) => pkgs, + None => return + }; + + for pkg in sorted.iter() { + compile_pkg(pkg, pkgs); + } +} -pub fn compile() { +fn compile_pkg(pkg: &core::Package, pkgs: &core::PackageSet) { + +} + +fn rustc() { } pub fn execute(_: NoFlags, manifest: core::Manifest) -> CargoResult> { diff --git a/src/cargo/util/graph.rs b/src/cargo/util/graph.rs index 5e888901f..974240ebe 100644 --- a/src/cargo/util/graph.rs +++ b/src/cargo/util/graph.rs @@ -1,56 +1,47 @@ +use std::hash::Hash; use collections::HashMap; -trait Node<'a, I: Iterator<&'a Self>> { - fn children(&'a self) -> I; +pub struct Graph { + nodes: HashMap } -trait Graph<'a, N: Node<'a, I>, I: Iterator<&'a N>> { - fn nodes(&'a self) -> I; -} - -#[deriving(Clone)] enum Mark { InProgress, Done } -/** - * Returns None in the event of a cycle - */ -pub fn topsort<'a, N: Node<'a, I>, G: Graph<'a, N, I>, I: Iterator<&'a N>>(graph: &'a G) -> Option> { - let mut ret = Vec::new(); - let mut iter: I = graph.nodes(); - let mut stack = Vec::<&'a N>::new(); - let mut marks: HashMap<*N, Mark> = HashMap::new(); - - // Prime the stack - for node in iter { - visit(node, &mut ret, &mut marks); +impl Graph { + pub fn new() -> Graph { + Graph { nodes: HashMap::new() } } - Some(ret) -} - -fn visit<'a, N: Node<'a, I>, I: Iterator<&'a N>>(curr: &'a N, dst: &mut Vec<&'a N>, marks: &mut HashMap<*N, Mark>) { - let ident = curr as *N; - - if marks.contains_key(&ident) { - return; + pub fn add(&mut self, node: N, children: &[N]) { + self.nodes.insert(node, children.to_owned()); } - marks.insert(ident, InProgress); + pub fn sort(&self) -> Option> { + let mut ret = Vec::new(); + let mut marks = HashMap::new(); - let mut iter: I = curr.children(); + for node in self.nodes.keys() { + self.visit(node, &mut ret, &mut marks); + } - for child in iter { - visit::<'a, N, I>(child, dst, marks); + Some(ret) } - dst.push(curr); - marks.insert(ident, Done); -} + fn visit(&self, node: &N, dst: &mut Vec, marks: &mut HashMap) { + if marks.contains_key(node) { + return; + } + + marks.insert(node.clone(), InProgress); -#[cfg(test)] -mod test { - // TODO: tests + for child in self.nodes.get(node).iter() { + self.visit(child, dst, marks); + } + + dst.push(node.clone()); + marks.insert(node.clone(), Done); + } }