Skip to content

Commit

Permalink
Merge branch 'cswindle-master' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
imp committed Nov 5, 2016
2 parents 7fce49d + ab20f2b commit d074712
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 43 deletions.
69 changes: 47 additions & 22 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[package]
authors = ["Cyril Plisko <[email protected]>",
"Alexander Goldberg <[email protected]>"]
authors = ["Cyril Plisko <[email protected]>", "Alexander Goldberg <[email protected]>"]
description = "Extends cargo to run the given command on multiple crates similar to 'git multi'"
homepage = "https://gitlab.com/imp/cargo-multi"
keywords = ["cargo", "subcommand", "multi"]
Expand All @@ -12,6 +11,7 @@ version = "0.4.5"
[dependencies]
clap = "2.9"
itertools = "0.4"
toml = "0.2.1"
walkdir = "0.1"

[features]
Expand Down
94 changes: 75 additions & 19 deletions src/main.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
extern crate clap;
extern crate itertools;
extern crate walkdir;
extern crate toml;

use std::env;
use std::process::{Command, Output};
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::process::{exit, Command, Output};
use clap::{App, SubCommand, AppSettings};
use itertools::Itertools;
use walkdir::{DirEntry, WalkDirIterator};


Expand All @@ -24,19 +27,23 @@ fn print_ident(buf: Vec<u8>) {
}
}

fn report_output(output: Output) {
fn report_output(output: Output) -> std::process::ExitStatus {
if output.status.success() {
print_ident(output.stdout);
} else {
print_ident(output.stderr);
}

// Always print stderr as warnings from cargo are sent to stderr.
print_ident(output.stderr);

// I am still not sure what is more idiomatic - the 'if' above or the 'match' below
//
// match output.status.success() {
// true => print_ident(output.stdout),
// false => print_ident(output.stderr),
// }
println!("");

output.status
}

const CARGO: &'static str = "cargo";
Expand Down Expand Up @@ -69,20 +76,69 @@ fn main() {
}
}

announce(&banner);
let is_crate = |e: &DirEntry| e.path().join("Cargo.toml").exists();
let display_path = |e: &DirEntry| println!("{}:", e.file_name().to_string_lossy());
let execute = |e: DirEntry| cargo_cmd.current_dir(e.path()).output().ok();

if let Ok(cwd) = env::current_dir() {
announce(&banner);
walkdir::WalkDir::new(cwd)
.min_depth(MIN_DEPTH)
.max_depth(MAX_DEPTH)
.into_iter()
.filter_entry(is_crate)
.filter_map(|e| e.ok())
.inspect(display_path)
.filter_map(execute)
.foreach(report_output);
let display_path = |p: &PathBuf| println!("{}:", p.to_string_lossy());
let execute = |p: PathBuf| cargo_cmd.current_dir(p).output().ok();

// First check if there is a Cargo.toml file with a workspace section in.
let mut workspace_members = match File::open("Cargo.toml") {
Ok(mut file) => {
let mut toml = String::new();
match file.read_to_string(&mut toml) {
Ok(_) => {
let value: toml::Value = toml.parse().expect("Failed to parse Cargo.toml");

match value.lookup("workspace.members") {
Some(members) => {
Some(members.as_slice()
.expect("Failed to read workspace members")
.into_iter()
.map(|m| PathBuf::from(m.as_str().unwrap()))
.collect::<Vec<_>>())
}
None => None,
}
}
Err(_) => None,
}
}
Err(_) => None,
};

// If there was no workspace members present, add each crate directory
// present.
if workspace_members.is_none() {
workspace_members = match env::current_dir() {
Ok(cwd) => {
Some(walkdir::WalkDir::new(cwd)
.min_depth(MIN_DEPTH)
.max_depth(MAX_DEPTH)
.into_iter()
.filter_entry(is_crate)
.filter_map(|e| e.ok())
.map(|m| m.path().to_path_buf())
.collect::<Vec<_>>())
}
Err(_) => None,
}
}

let failed_commands = match workspace_members {
Some(members) => {
members.into_iter()
.inspect(display_path)
.filter_map(execute)
.map(report_output)
.filter(|x| !x.success())
.collect::<Vec<_>>()
}
None => Vec::new(),
};

// If there are any failed commands, return the error code of the
// first of them.
if failed_commands.len() > 0 {
exit(failed_commands[0].code().unwrap());
}
}

0 comments on commit d074712

Please sign in to comment.