summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-01-24 00:12:26 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-01-24 00:12:26 +0100
commit01e3de22a53d30f21a829bf5d7cebc45c4d61ea8 (patch)
treeafef5de137cc473b1e7a37d60fc968b8f85b4ffc
downloadrebel-01e3de22a53d30f21a829bf5d7cebc45c4d61ea8.tar
rebel-01e3de22a53d30f21a829bf5d7cebc45c4d61ea8.zip
Initial task queue
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock5
-rw-r--r--Cargo.toml9
-rw-r--r--rustfmt.toml1
-rw-r--r--src/main.rs97
5 files changed, 113 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..e64fc04
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "rebel"
+version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..7712670
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "rebel"
+version = "0.1.0"
+authors = ["Matthias Schiffer <mschiffer@universe-factory.net>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..218e203
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+hard_tabs = true
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..98d1b8d
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,97 @@
+use std::collections::{HashMap, HashSet};
+// use std::io::{self, Write};
+use std::io;
+// use std::process::Command;
+
+struct Task {
+ // action: String,
+ deps: Vec<String>,
+}
+
+// impl Task {
+// fn run(&self) -> io::Result<()> {
+// let output = Command::new("sh").arg("-c").arg(&self.action).output()?;
+
+// let stdout = io::stdout();
+// let mut handle = stdout.lock();
+// handle.write_all(&output.stdout)?;
+
+// Ok(())
+// }
+// }
+
+fn collect_subtasks<'a>(
+ queued: &HashSet<&'a str>,
+ tasks: &'a HashMap<String, Task>,
+ id: &str,
+) -> io::Result<HashSet<&'a str>> {
+ let (task_id, task) = match tasks.get_key_value(id) {
+ Some(t) => t,
+ None => {
+ return Err(io::Error::new(io::ErrorKind::NotFound, "Task not found"));
+ }
+ };
+
+ if queued.contains(id) {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidData,
+ "Dependency cycle",
+ ));
+ }
+
+ let mut queued_sub = queued.clone();
+ queued_sub.insert(task_id);
+
+ let mut subtasks: HashSet<&'a str> = HashSet::new();
+ subtasks.insert(task_id);
+
+ for dep in &task.deps {
+ let deptasks = collect_subtasks(&queued_sub, tasks, dep)?;
+ subtasks = subtasks.union(&deptasks).copied().collect();
+ }
+
+ Ok(subtasks)
+}
+
+fn collect_tasks<'a>(tasks: &'a HashMap<String, Task>, id: &str) -> io::Result<HashSet<&'a str>> {
+ collect_subtasks(&HashSet::new(), tasks, id)
+}
+
+fn main() -> io::Result<()> {
+ let mut tasks = HashMap::new();
+ tasks.insert(
+ String::from("ls"),
+ Task {
+ // action: String::from("ls"),
+ deps: vec!["foo".to_owned(), "bar".to_owned()],
+ },
+ );
+ tasks.insert(
+ String::from("foo"),
+ Task {
+ // action: String::from("echo foo"),
+ deps: vec!["bar".to_owned()],
+ },
+ );
+ tasks.insert(
+ String::from("bar"),
+ Task {
+ // action: String::from("echo bar"),
+ deps: vec![],
+ },
+ );
+
+ let queue = collect_tasks(&tasks, "ls")?;
+ let (runnable, queued) = queue
+ .into_iter()
+ .partition::<HashSet<_>, _>(|id| tasks.get(*id).unwrap().deps.is_empty());
+
+ for t in &runnable {
+ println!("Runnable: {}", t);
+ }
+ for t in &queued {
+ println!("Queued: {}", t);
+ }
+
+ Ok(())
+}