Skip to content

Commit

Permalink
feat: show result summary at the end
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianoliveira committed Jun 9, 2023
1 parent d31c0fc commit 92bf5b0
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 83 deletions.
55 changes: 18 additions & 37 deletions src/cli/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::time::Duration;

use cli::Command;
use cmd;
use rules;
use stdout;
use watches::Watches;

Expand All @@ -29,34 +30,6 @@ impl WatchCommand {

WatchCommand { watches, verbose }
}

fn run(&self, commands: &Vec<String>) -> Result<(), String> {
for command in commands {
stdout::verbose(&format!("struct command: {:?}", command), self.verbose);
stdout::info(&format!("----- command: {} -------", command));
if let Err(err) = cmd::execute(String::from(command)) {
stdout::error(&format!("failed to run command: {:?}", err));
return Err(err);
}
}
Ok(())
}

fn run_rules(&self, rules: Vec<Vec<String>>) -> Result<(), String> {
clear_shell();
let results = rules
.iter()
.map(|rule_cmds| self.run(&rule_cmds))
.find(|r| match r {
Ok(_) => false,
Err(_) => true,
});

match results {
Some(Err(err)) => Err(err),
_ => Ok(()),
}
}
}

impl Command for WatchCommand {
Expand All @@ -74,11 +47,15 @@ impl Command for WatchCommand {
if let Some(rules) = self.watches.run_on_init() {
stdout::info(&format!("Running on init commands."));

if let Err(err) = self.run_rules(rules) {
return Err(err);
}
let results = rules::as_list(rules)
.iter()
.map(|task| {
stdout::info(&format!("---- running: {} ----", task));
cmd::execute(task)
})
.collect::<Vec<Result<(), String>>>();

stdout::info(&"All tasks finished");
stdout::present_results(results);
}

stdout::info(&format!("Watching..."));
Expand All @@ -91,14 +68,18 @@ impl Command for WatchCommand {
self.verbose,
);

self.run_rules(rules)?
let results = rules::as_list(rules)
.iter()
.map(|task| {
stdout::info(&format!("---- running: {} ----", task));
cmd::execute(task)
})
.collect::<Vec<Result<(), String>>>();

stdout::present_results(results);
}
}
}
Ok(())
}
}

fn clear_shell() {
let _ = ShellCommand::new("clear").status();
}
1 change: 0 additions & 1 deletion src/cli/watch_non_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::sync::mpsc::channel;
use std::sync::mpsc::TryRecvError;

use self::notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use std::thread;
use std::time::Duration;

use cli::Command;
Expand Down
33 changes: 19 additions & 14 deletions src/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
use std::process::{Child, Command};
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::thread::JoinHandle;
use stdout;

pub fn execute(command_line: String) -> Result<(), String> {
pub fn execute(command_line: &String) -> Result<(), String> {
let shell = std::env::var("SHELL").unwrap_or(String::from("/bin/sh"));
let mut cmd = Command::new(shell);
match cmd.arg("-c").arg(command_line).status() {
Err(error) => return Err(String::from(error.to_string())),
match cmd.arg("-c").arg(command_line.to_owned()).status() {
Err(error) => Err(format!(
"Command {} has errored with {}",
command_line, error
)),
Ok(status) => {
if status.success() {
return Ok(());
Ok(())
} else {
println!("This task command has failed {}", status);
return Ok(());
Err(format!(
"Command {} has failed with {}",
command_line, status
))
}
}
};
}
}

pub fn spawn_command(command_line: String) -> Result<Child, String> {
let shell = std::env::var("SHELL").unwrap_or(String::from("/bin/sh"));
let mut cmd = Command::new(shell);

match cmd.arg("-c").arg(command_line).spawn() {
match cmd.arg("-c").arg(command_line.to_owned()).spawn() {
Ok(child) => Ok(child),
Err(err) => Err(format!("Error while creating command {}", err)),

Err(error) => Err(format!(
"Command {} has errored with {}",
command_line, error
)),
}
}

Expand All @@ -42,7 +47,7 @@ fn it_spawn_a_command_returning_a_child_ref() {

#[test]
fn it_executes_a_command() {
let result = match execute(String::from("echo 'foo'")) {
let result = match execute(&String::from("echo 'foo'")) {
Ok(_) => true,
Err(err) => panic!("{:?}", err),
};
Expand Down
2 changes: 0 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ fn from_stdin() -> Result<String, String> {
}
});

// read all content from stdin

let mut buffer = String::new();
match stdin.lock().read_to_string(&mut buffer) {
Ok(bytes) => {
Expand Down
14 changes: 11 additions & 3 deletions src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ impl Rules {
run_on_init: bool,
) -> Self {
Rules {
name: name,
commands: commands,
name,
commands,
watch_patterns: watches,
ignore_patterns: ignores,
run_on_init: run_on_init,
run_on_init,
}
}

Expand Down Expand Up @@ -73,6 +73,14 @@ impl Rules {
}
}

pub fn as_list(rules: Vec<Vec<String>>) -> Vec<String> {
rules
.iter()
.map(|rule| rule.iter().cloned().collect::<Vec<String>>())
.flatten()
.collect::<Vec<String>>()
}

pub fn from_yaml(file_content: &str) -> Result<Vec<Rules>, String> {
let items = YamlLoader::load_from_str(file_content).unwrap();
match items[0] {
Expand Down
14 changes: 14 additions & 0 deletions src/stdout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,17 @@ pub fn verbose(msg: &str, verbose: bool) {
println!("Funzzy verbose: {} ", msg);
println!("-----------------------------");
}

pub fn present_results(results: Vec<Result<(), String>>) {
let errors: Vec<Result<(), String>> = results.iter().cloned().filter(|r| r.is_err()).collect();
println!("------------- Funzzy result --------------");
if errors.len() > 0 {
println!("Failed tasks: {:?}", errors.len());
errors.iter().for_each(|err| {
println!(" - {}", err.as_ref().unwrap_err());
});
} else {
println!("All tasks finished successfully.");
}
println!("------------------------------------------");
}
14 changes: 8 additions & 6 deletions src/watches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ impl Watches {
.map(|r| r.commands())
.collect::<Vec<Vec<String>>>();

match cmds.len() {
0 => None,
_ => Some(cmds),
if cmds.len() > 0 {
Some(cmds)
} else {
None
}
}

Expand All @@ -39,9 +40,10 @@ impl Watches {
.map(|r| r.commands())
.collect::<Vec<Vec<String>>>();

match cmds.len() {
0 => None,
_ => Some(cmds),
if cmds.len() > 0 {
Some(cmds)
} else {
None
}
}
}
Expand Down
35 changes: 21 additions & 14 deletions src/workers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use cmd::spawn_command;
use rules;
use std::sync::mpsc::channel;
use std::sync::mpsc::{Sender, TryRecvError};
use std::thread::JoinHandle;
Expand All @@ -21,6 +22,7 @@ impl Worker {

let consumer = std::thread::spawn(move || {
while let Ok(mut tasks) = rscheduler.recv() {
let mut results: Vec<Result<(), String>> = vec![];
let ignored = rcancel.try_recv();
stdout::verbose(&format!("ignored kill: {:?}", ignored), verbose);

Expand Down Expand Up @@ -96,24 +98,35 @@ impl Worker {
}
}
}

Ok(Some(status)) => {
if verbose {
if status.success() {
stdout::info(&format!("---- finished: {:?} ----", task));
} else {
stdout::error(&format!("---- failed: {:?} ----", task));
}
if status.success() {
results.push(Ok(()));
} else {
results.push(Err(format!(
"Command {} has failed with {}",
task, status
)));
}

break;
}

Err(err) => {
stdout::error(&format!("failed while trying to wait: {:?}", err));
results.push(Err(format!(
"Command {} has errored with {}",
task, err
)));

break;
}
};
}
}

if !has_been_cancelled {
stdout::present_results(results);
}
}

stdout::info(&format!("Consumer thread finished."));
Expand All @@ -138,14 +151,8 @@ impl Worker {
}

pub fn schedule(&self, rules: Vec<Vec<String>>) -> Result<(), String> {
let tasks = rules
.iter()
.map(|rule| rule.iter().cloned().collect::<Vec<String>>())
.flatten()
.collect::<Vec<String>>();

if let Some(scheduler) = self.scheduler.as_ref() {
if let Err(err) = scheduler.send(tasks) {
if let Err(err) = scheduler.send(rules::as_list(rules)) {
return Err(format!("{:?}", err));
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/integration/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function assert_equal() {

function report_failure() {
echo "Failed: $TEST_REFERENCE"
cleanup
exit 1
}

Expand Down
12 changes: 6 additions & 6 deletions tests/integration/specs/list-of-commands-task-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ $TEST_DIR/funzzy --config $WORKDIR/.oninit.yaml > $WORKDIR/output.txt &
FUNZZY_PID=$!

assert_file_content_at "$WORKDIR/output.txt" "Running on init commands" 1
assert_file_contains "$WORKDIR/output.txt" "command: echo first"
assert_file_contains "$WORKDIR/output.txt" "command: echo second"
assert_file_contains "$WORKDIR/output.txt" "command: echo complex"
assert_file_contains "$WORKDIR/output.txt" "running: echo first"
assert_file_contains "$WORKDIR/output.txt" "running: echo second"
assert_file_contains "$WORKDIR/output.txt" "running: echo complex"
assert_file_content_at "$WORKDIR/output.txt" "third" 6
assert_file_contains "$WORKDIR/output.txt" "Watching..."

Expand All @@ -41,9 +41,9 @@ FUNZZY_PID=$!
assert_file_contains "$WORKDIR/output.txt" "Watching..."
echo "test" >> $WORKDIR/test.txt
sh -c "vi +%s/test/foo/g +wq $WORKDIR/test.txt -u NONE"
assert_file_contains "$WORKDIR/output.txt" "command: echo 100"
assert_file_contains "$WORKDIR/output.txt" "command: echo 200"
assert_file_contains "$WORKDIR/output.txt" "command: echo 4000"
assert_file_contains "$WORKDIR/output.txt" "running: echo 100"
assert_file_contains "$WORKDIR/output.txt" "running: echo 200"
assert_file_contains "$WORKDIR/output.txt" "running: echo 4000"
assert_file_content_at "$WORKDIR/output.txt" "3333" 6

cleanup
22 changes: 22 additions & 0 deletions tests/integration/specs/show-summary-result-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
source "$HELPERS"

test "it allows a list of commands for the same task (on init)"

echo "
- name: run complex command
run: ['echo first', 'exit 1', 'cat unknow', 'echo complex | sed s/complex/third/g']
change: \"$WORKDIR/**\"
run_on_init: true
" > $WORKDIR/.oninit.yaml

$TEST_DIR/funzzy --config $WORKDIR/.oninit.yaml > $WORKDIR/output.txt &
FUNZZY_PID=$!

assert_file_contains "$WORKDIR/output.txt" "Watching..."
assert_file_contains "$WORKDIR/output.txt" "Funzzy result"
assert_file_contains "$WORKDIR/output.txt" "Failed tasks: 2"
assert_file_contains "$WORKDIR/output.txt" "Command exit 1 has failed with exit status: 1"
assert_file_contains "$WORKDIR/output.txt" "Command cat unknow has failed with exit status: 1"

cleanup

0 comments on commit 92bf5b0

Please sign in to comment.