Topological sort of packages
authorCarl Lerche <me@carllerche.com>
Wed, 30 Apr 2014 20:59:04 +0000 (13:59 -0700)
committerCarl Lerche <me@carllerche.com>
Wed, 30 Apr 2014 23:34:24 +0000 (16:34 -0700)
src/cargo/core/dependency.rs
src/cargo/core/mod.rs
src/cargo/core/package.rs
src/cargo/core/registry.rs
src/cargo/mod.rs
src/cargo/ops/cargo_rustc.rs
src/cargo/util/graph.rs

index 80d2356c505007983698686ca41efcc6453e0bd8..0536acdd65baa285358d9502bc768b724c8e5d54 100644 (file)
@@ -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()
     }
index 99beeb8ffbcbb52e89b9481e6169a00d895e0daf..6fc26e4d8bc8e56a179be1bdedb848138222eafc 100644 (file)
@@ -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;
index 4ddae1ebd5c536c66386f2b9ca36d326287c898f..f585b79476f8a032d3215c427e2e3009a9b51794 100644 (file)
@@ -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<PackageSet> {
+        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()
+  }
+}
index a5efe14baad76c1f89b4658343d3ecd7eae60ddd..cfb41e7e52e8392fc68ed3e2c0472009f101889b 100644 (file)
@@ -14,6 +14,7 @@ pub trait Registry {
  *
  */
 
+/*
 pub struct MemRegistry {
   packages: Vec<Package>
 }
@@ -35,3 +36,4 @@ impl Registry for MemRegistry {
       .collect()
   }
 }
+*/
index 4c5ace6bb1f644f235b325560db6085f204f9353..a4e8bfcc0ecb89e3a52e16b88984a74c30bb4468 100644 (file)
@@ -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;
index 056a479639f78fd59ef0857b7ce53046a87924b4..2f9443cd03e83196c60779ff7c9a2a7b130789c0 100644 (file)
@@ -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<Option<core::Manifest>> {
index 5e888901f8e6e4605ec0eb95f44c0b25f484ca12..974240ebeced8a4b8dcf602f646308a6b40a3fd2 100644 (file)
@@ -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<N> {
+    nodes: HashMap<N, ~[N]>
 }
 
-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<Vec<&'a N>> {
-    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<N: TotalEq + Hash + Clone> Graph<N> {
+    pub fn new() -> Graph<N> {
+        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<Vec<N>> {
+        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<N>, marks: &mut HashMap<N, Mark>) {
+        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);
+    }
 }