mirror of
https://github.com/casey/just
synced 2024-07-01 07:24:45 +00:00
Compare commits
3 Commits
fac177559a
...
0d83940a8a
Author | SHA1 | Date | |
---|---|---|---|
|
0d83940a8a | ||
|
b8a86a400f | ||
|
215b17015c |
|
@ -1482,6 +1482,22 @@ mod tests {
|
|||
},
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_config_from_working_directory_and_justfile_long_stdin,
|
||||
args: ["--working-directory", "foo", "--justfile", "-"],
|
||||
search_config: SearchConfig::WithStdinAndWorkingDirectory {
|
||||
working_directory: PathBuf::from("foo"),
|
||||
},
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_config_from_working_directory_and_justfile_short_stdin,
|
||||
args: ["--working-directory", "foo", "-f", "-"],
|
||||
search_config: SearchConfig::WithStdinAndWorkingDirectory {
|
||||
working_directory: PathBuf::from("foo"),
|
||||
},
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_config_justfile_long,
|
||||
args: ["--justfile", "foo"],
|
||||
|
@ -1490,6 +1506,12 @@ mod tests {
|
|||
},
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_config_justfile_long_stdin,
|
||||
args: ["--justfile", "-"],
|
||||
search_config: SearchConfig::WithStdin,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_config_justfile_short,
|
||||
args: ["-f", "foo"],
|
||||
|
@ -1498,6 +1520,12 @@ mod tests {
|
|||
},
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_config_justfile_short_stdin,
|
||||
args: ["-f", "-"],
|
||||
search_config: SearchConfig::WithStdin,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: search_directory_parent,
|
||||
args: ["../"],
|
||||
|
|
178
src/search.rs
178
src/search.rs
|
@ -1,14 +1,58 @@
|
|||
use {super::*, std::path::Component};
|
||||
use {
|
||||
super::*,
|
||||
std::{
|
||||
io::{stdin, Read},
|
||||
path::{Component, Display},
|
||||
},
|
||||
};
|
||||
|
||||
const DEFAULT_JUSTFILE_NAME: &str = JUSTFILE_NAMES[0];
|
||||
pub(crate) const JUSTFILE_NAMES: [&str; 2] = ["justfile", ".justfile"];
|
||||
const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"];
|
||||
|
||||
pub(crate) struct Search {
|
||||
pub(crate) justfile: PathBuf,
|
||||
pub(crate) justfile: JustfileKind,
|
||||
pub(crate) working_directory: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum JustfileKind {
|
||||
Path { path: PathBuf },
|
||||
Stdin { data: String },
|
||||
}
|
||||
|
||||
impl JustfileKind {
|
||||
pub fn to_str(&self) -> Option<&str> {
|
||||
match self {
|
||||
JustfileKind::Path { path } => path.to_str(),
|
||||
JustfileKind::Stdin { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display(&self) -> Display<'_> {
|
||||
match self {
|
||||
JustfileKind::Path { path } => path.display(),
|
||||
JustfileKind::Stdin { .. } => Path::new("<STDIN>").display(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<&Path> {
|
||||
match self {
|
||||
JustfileKind::Path { path } => path.parent(),
|
||||
JustfileKind::Stdin { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<PathBuf> for JustfileKind {
|
||||
fn eq(&self, other: &PathBuf) -> bool {
|
||||
match self {
|
||||
JustfileKind::Path { path } => path == other,
|
||||
JustfileKind::Stdin { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Search {
|
||||
fn global_justfile_paths() -> Vec<PathBuf> {
|
||||
let mut paths = Vec::new();
|
||||
|
@ -33,6 +77,7 @@ impl Search {
|
|||
paths
|
||||
}
|
||||
|
||||
/// Search for a Justfile
|
||||
pub(crate) fn find(
|
||||
search_config: &SearchConfig,
|
||||
invocation_directory: &Path,
|
||||
|
@ -41,24 +86,29 @@ impl Search {
|
|||
SearchConfig::FromInvocationDirectory => Self::find_next(invocation_directory),
|
||||
SearchConfig::FromSearchDirectory { search_directory } => {
|
||||
let search_directory = Self::clean(invocation_directory, search_directory);
|
||||
let justfile = Self::justfile(&search_directory)?;
|
||||
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
||||
let path = Self::justfile(&search_directory)?;
|
||||
let working_directory = Self::working_directory_from_justfile(&path)?;
|
||||
let justfile = JustfileKind::Path { path: path.clone() };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
SearchConfig::GlobalJustfile => Ok(Self {
|
||||
justfile: Self::global_justfile_paths()
|
||||
SearchConfig::GlobalJustfile => {
|
||||
let path = Self::global_justfile_paths()
|
||||
.iter()
|
||||
.find(|path| path.exists())
|
||||
.cloned()
|
||||
.ok_or(SearchError::GlobalJustfileNotFound)?,
|
||||
working_directory: Self::project_root(invocation_directory)?,
|
||||
}),
|
||||
.ok_or(SearchError::GlobalJustfileNotFound)?;
|
||||
Ok(Self {
|
||||
justfile: JustfileKind::Path { path },
|
||||
working_directory: Self::project_root(invocation_directory)?,
|
||||
})
|
||||
}
|
||||
SearchConfig::WithJustfile { justfile } => {
|
||||
let justfile = Self::clean(invocation_directory, justfile);
|
||||
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
||||
let path = Self::clean(invocation_directory, justfile);
|
||||
let justfile = JustfileKind::Path { path: path.clone() };
|
||||
let working_directory = Self::working_directory_from_justfile(&path)?;
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
|
@ -67,22 +117,58 @@ impl Search {
|
|||
SearchConfig::WithJustfileAndWorkingDirectory {
|
||||
justfile,
|
||||
working_directory,
|
||||
} => Ok(Self {
|
||||
justfile: Self::clean(invocation_directory, justfile),
|
||||
working_directory: Self::clean(invocation_directory, working_directory),
|
||||
}),
|
||||
} => {
|
||||
let path = Self::clean(invocation_directory, justfile);
|
||||
let justfile = JustfileKind::Path { path };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory: Self::clean(invocation_directory, working_directory),
|
||||
})
|
||||
}
|
||||
SearchConfig::WithStdin => {
|
||||
let working_directory = PathBuf::from(invocation_directory);
|
||||
let mut data = String::new();
|
||||
if let Err(err) = stdin().read_to_string(&mut data) {
|
||||
return Err(SearchError::Io {
|
||||
directory: working_directory,
|
||||
io_error: err,
|
||||
});
|
||||
}
|
||||
let justfile = JustfileKind::Stdin { data };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
SearchConfig::WithStdinAndWorkingDirectory { working_directory } => {
|
||||
let working_directory = working_directory.to_owned();
|
||||
let mut data = String::new();
|
||||
if let Err(err) = stdin().read_to_string(&mut data) {
|
||||
return Err(SearchError::Io {
|
||||
directory: working_directory,
|
||||
io_error: err,
|
||||
});
|
||||
}
|
||||
let justfile = JustfileKind::Stdin { data };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn find_next(starting_dir: &Path) -> SearchResult<Self> {
|
||||
let justfile = Self::justfile(starting_dir)?;
|
||||
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
||||
let path = Self::justfile(starting_dir)?;
|
||||
let justfile = JustfileKind::Path { path: path.clone() };
|
||||
let working_directory = Self::working_directory_from_justfile(&path)?;
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
|
||||
/// Search for a Justfile when running "init" subcommand
|
||||
pub(crate) fn init(
|
||||
search_config: &SearchConfig,
|
||||
invocation_directory: &Path,
|
||||
|
@ -90,7 +176,8 @@ impl Search {
|
|||
match search_config {
|
||||
SearchConfig::FromInvocationDirectory => {
|
||||
let working_directory = Self::project_root(invocation_directory)?;
|
||||
let justfile = working_directory.join(DEFAULT_JUSTFILE_NAME);
|
||||
let path = working_directory.join(DEFAULT_JUSTFILE_NAME);
|
||||
let justfile = JustfileKind::Path { path };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
|
@ -99,7 +186,8 @@ impl Search {
|
|||
SearchConfig::FromSearchDirectory { search_directory } => {
|
||||
let search_directory = Self::clean(invocation_directory, search_directory);
|
||||
let working_directory = Self::project_root(&search_directory)?;
|
||||
let justfile = working_directory.join(DEFAULT_JUSTFILE_NAME);
|
||||
let path = working_directory.join(DEFAULT_JUSTFILE_NAME);
|
||||
let justfile = JustfileKind::Path { path };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
|
@ -107,8 +195,9 @@ impl Search {
|
|||
}
|
||||
SearchConfig::GlobalJustfile => Err(SearchError::GlobalJustfileInit),
|
||||
SearchConfig::WithJustfile { justfile } => {
|
||||
let justfile = Self::clean(invocation_directory, justfile);
|
||||
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
||||
let path = Self::clean(invocation_directory, justfile);
|
||||
let working_directory = Self::working_directory_from_justfile(&path)?;
|
||||
let justfile = JustfileKind::Path { path };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
|
@ -117,14 +206,51 @@ impl Search {
|
|||
SearchConfig::WithJustfileAndWorkingDirectory {
|
||||
justfile,
|
||||
working_directory,
|
||||
} => Ok(Self {
|
||||
justfile: Self::clean(invocation_directory, justfile),
|
||||
working_directory: Self::clean(invocation_directory, working_directory),
|
||||
}),
|
||||
} => {
|
||||
let path = Self::clean(invocation_directory, justfile);
|
||||
let justfile = JustfileKind::Path { path };
|
||||
let working_directory = Self::clean(invocation_directory, working_directory);
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
|
||||
SearchConfig::WithStdin => {
|
||||
let working_directory = Self::project_root(invocation_directory)?;
|
||||
let mut data = String::new();
|
||||
if let Err(err) = io::stdin().read_to_string(&mut data) {
|
||||
return Err(SearchError::Io {
|
||||
directory: working_directory,
|
||||
io_error: err,
|
||||
});
|
||||
}
|
||||
let justfile = JustfileKind::Stdin { data };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
|
||||
SearchConfig::WithStdinAndWorkingDirectory { working_directory } => {
|
||||
let working_directory = working_directory.to_owned();
|
||||
let mut data = String::new();
|
||||
if let Err(err) = io::stdin().read_to_string(&mut data) {
|
||||
return Err(SearchError::Io {
|
||||
directory: working_directory,
|
||||
io_error: err,
|
||||
});
|
||||
}
|
||||
let justfile = JustfileKind::Stdin { data };
|
||||
Ok(Self {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn justfile(directory: &Path) -> SearchResult<PathBuf> {
|
||||
fn justfile(directory: &Path) -> SearchResult<PathBuf> {
|
||||
for directory in directory.ancestors() {
|
||||
let mut candidates = BTreeSet::new();
|
||||
|
||||
|
|
|
@ -19,4 +19,10 @@ pub(crate) enum SearchConfig {
|
|||
justfile: PathBuf,
|
||||
working_directory: PathBuf,
|
||||
},
|
||||
/// Use justfile loaded from stdin by using "-" as justfile name.
|
||||
WithStdin,
|
||||
/// Use justfile loaded from stdin and working directory.
|
||||
WithStdinAndWorkingDirectory {
|
||||
working_directory: PathBuf,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use {super::*, pretty_assertions::assert_eq};
|
||||
use {self::search::JustfileKind, super::*, pretty_assertions::assert_eq};
|
||||
|
||||
pub(crate) fn compile(src: &str) -> Justfile {
|
||||
Compiler::test_compile(src).expect("expected successful compilation")
|
||||
|
@ -17,7 +17,8 @@ pub(crate) fn config(args: &[&str]) -> Config {
|
|||
|
||||
pub(crate) fn search(config: &Config) -> Search {
|
||||
let working_directory = config.invocation_directory.clone();
|
||||
let justfile = working_directory.join("justfile");
|
||||
let path = working_directory.join("justfile");
|
||||
let justfile = JustfileKind::Path { path };
|
||||
|
||||
Search {
|
||||
justfile,
|
||||
|
|
Loading…
Reference in New Issue
Block a user