1
0
mirror of https://github.com/casey/just synced 2024-07-01 07:24:45 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Marcin Drzymala
0d83940a8a
Merge b8a86a400f into e4564f45a3 2024-06-20 07:31:51 +00:00
Marcin Drzymala
b8a86a400f WIP: Add JustfileKind to Search: Path or Stdin 2024-06-11 02:08:45 +02:00
Marcin Drzymala
215b17015c Add WithStdin variants to SearchConfig 2024-06-11 02:01:53 +02:00
4 changed files with 189 additions and 28 deletions

View File

@ -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: ["../"],

View File

@ -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();

View File

@ -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,
},
}

View File

@ -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,