diff --git a/README.md b/README.md index 286a1c0..1f52091 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ just `just` is a handy way to save and run commands. -Commands are stored in a file called `justfile` with syntax inspired by `make`: +Commands are stored in a file called `justfile` or `Justfile` with syntax inspired by `make`: ```make test-all: build diff --git a/src/app.rs b/src/app.rs index d47facb..38d2c14 100644 --- a/src/app.rs +++ b/src/app.rs @@ -92,12 +92,18 @@ pub fn app() { die!("Error changing directory to {}: {}", directory, error); } } else { - loop { - match fs::metadata("justfile") { - Ok(metadata) => if metadata.is_file() { break; }, - Err(error) => { - if error.kind() != io::ErrorKind::NotFound { - die!("Error fetching justfile metadata: {}", error) + let name; + 'outer: loop { + for candidate in &["justfile", "Justfile"] { + match fs::metadata(candidate) { + Ok(metadata) => if metadata.is_file() { + name = *candidate; + break 'outer; + }, + Err(error) => { + if error.kind() != io::ErrorKind::NotFound { + die!("Error fetching justfile metadata: {}", error) + } } } } @@ -112,7 +118,7 @@ pub fn app() { } } - text = fs::File::open("justfile") + text = fs::File::open(name) .unwrap_or_else(|error| die!("Error opening justfile: {}", error)) .slurp() .unwrap_or_else(|error| die!("Error reading justfile: {}", error)); diff --git a/src/integration.rs b/src/integration.rs index 27d877a..21ef925 100644 --- a/src/integration.rs +++ b/src/integration.rs @@ -3,7 +3,7 @@ extern crate brev; extern crate regex; use tempdir::TempDir; -use super::std::process::Command; +use super::std::{fs, path, process}; fn integration_test( args: &[&str], @@ -13,13 +13,13 @@ fn integration_test( expected_stderr: &str, ) { let tmp = TempDir::new("just-integration") - .unwrap_or_else(|err| panic!("tmpdir: failed to create temporary directory: {}", err)); + .unwrap_or_else(|err| panic!("integration test: failed to create temporary directory: {}", err)); let mut path = tmp.path().to_path_buf(); path.push("justfile"); brev::dump(path, justfile); let mut binary = super::std::env::current_dir().unwrap(); binary.push("./target/debug/just"); - let output = Command::new(binary) + let output = process::Command::new(binary) .current_dir(tmp.path()) .args(args) .output() @@ -50,6 +50,97 @@ fn integration_test( } } +fn search_test>(path: P) { + let mut binary = super::std::env::current_dir().unwrap(); + binary.push("./target/debug/just"); + let output = process::Command::new(binary) + .current_dir(path) + .output() + .expect("just invocation failed"); + + assert_eq!(output.status.code().unwrap(), 0); + + let stdout = super::std::str::from_utf8(&output.stdout).unwrap(); + assert_eq!(stdout, "ok\n"); + + let stderr = super::std::str::from_utf8(&output.stderr).unwrap(); + assert_eq!(stderr, "echo ok\n"); +} + +#[test] +fn test_justfile_search() { + let tmp = TempDir::new("just-test-justfile-search") + .expect("test justfile search: failed to create temporary directory"); + let mut path = tmp.path().to_path_buf(); + path.push("justfile"); + brev::dump(&path, "default:\n\techo ok"); + path.pop(); + + path.push("a"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("b"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("c"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("d"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + + search_test(path); +} + +#[test] +fn test_capitalized_justfile_search() { + let tmp = TempDir::new("just-test-justfile-search") + .expect("test justfile search: failed to create temporary directory"); + let mut path = tmp.path().to_path_buf(); + path.push("Justfile"); + brev::dump(&path, "default:\n\techo ok"); + path.pop(); + + path.push("a"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("b"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("c"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("d"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + + search_test(path); +} + +#[test] +fn test_capitalization_priority() { + let tmp = TempDir::new("just-test-justfile-search") + .expect("test justfile search: failed to create temporary directory"); + let mut path = tmp.path().to_path_buf(); + path.push("justfile"); + brev::dump(&path, "default:\n\techo ok"); + path.pop(); + path.push("Justfile"); + brev::dump(&path, "default:\n\techo fail"); + path.pop(); + + // if we see "default\n\techo fail" in `justfile` then we're running + // in a case insensitive filesystem, so just bail + path.push("justfile"); + if brev::slurp(&path) == "default:\n\techo fail" { + return; + } + path.pop(); + + path.push("a"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("b"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("c"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + path.push("d"); + fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory"); + + search_test(path); +} + #[test] fn default() { integration_test(