2022-12-27 20:16:18 -08:00
|
|
|
use {super::*, std::path::Component};
|
2019-11-19 03:51:44 -08:00
|
|
|
|
2021-07-31 12:25:49 -07:00
|
|
|
const DEFAULT_JUSTFILE_NAME: &str = JUSTFILE_NAMES[0];
|
2024-05-19 02:29:13 -07:00
|
|
|
pub(crate) const JUSTFILE_NAMES: [&str; 2] = ["justfile", ".justfile"];
|
2019-11-19 23:07:44 -08:00
|
|
|
const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"];
|
2019-06-01 22:38:03 -07:00
|
|
|
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
pub(crate) struct Search {
|
2021-09-16 06:44:40 -07:00
|
|
|
pub(crate) justfile: PathBuf,
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
pub(crate) working_directory: PathBuf,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Search {
|
2024-05-19 02:29:13 -07:00
|
|
|
fn global_justfile_paths() -> Vec<PathBuf> {
|
|
|
|
let mut paths = Vec::new();
|
|
|
|
|
|
|
|
if let Some(config_dir) = dirs::config_dir() {
|
|
|
|
paths.push(config_dir.join("just").join(DEFAULT_JUSTFILE_NAME));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(home_dir) = dirs::home_dir() {
|
|
|
|
paths.push(
|
|
|
|
home_dir
|
|
|
|
.join(".config")
|
|
|
|
.join("just")
|
|
|
|
.join(DEFAULT_JUSTFILE_NAME),
|
|
|
|
);
|
|
|
|
|
|
|
|
for justfile_name in JUSTFILE_NAMES {
|
|
|
|
paths.push(home_dir.join(justfile_name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
paths
|
|
|
|
}
|
|
|
|
|
2019-11-19 23:07:44 -08:00
|
|
|
pub(crate) fn find(
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
search_config: &SearchConfig,
|
|
|
|
invocation_directory: &Path,
|
2020-01-15 02:16:13 -08:00
|
|
|
) -> SearchResult<Self> {
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
match search_config {
|
2022-03-30 22:13:59 -07:00
|
|
|
SearchConfig::FromInvocationDirectory => Self::find_next(invocation_directory),
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
SearchConfig::FromSearchDirectory { search_directory } => {
|
2019-11-19 03:51:44 -08:00
|
|
|
let search_directory = Self::clean(invocation_directory, search_directory);
|
Reform positional argument parsing (#523)
This diff makes positional argument parsing much cleaner, along with
adding a bunch of tests. Just's positional argument parsing is rather,
complex, so hopefully this reform allows it to both be correct and stay
correct.
User-visible changes:
- `just ..` is now accepted, with the same effect as `just ../`
- `just .` is also accepted, with the same effect as `just`
- It is now an error to pass arguments or overrides to subcommands
that do not accept them, namely `--dump`, `--edit`, `--list`,
`--show`, and `--summary`. It is also an error to pass arguments to
`--evaluate`, although `--evaluate` does of course still accept
overrides.
(This is a breaking change, but hopefully worth it, as it will allow us
to add arguments to subcommands which did not previously take
them, if we so desire.)
- Subcommands which do not accept arguments may now accept a
single search-directory argument, so `just --list ../` and
`just --dump foo/` are now accepted, with the former starting the
search for the justfile to list in the parent directory, and the latter
starting the search for the justfile to dump in `foo`.
2019-11-10 18:02:36 -08:00
|
|
|
let justfile = Self::justfile(&search_directory)?;
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
2020-01-15 02:16:13 -08:00
|
|
|
Ok(Self {
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
justfile,
|
|
|
|
working_directory,
|
|
|
|
})
|
2021-09-16 06:44:40 -07:00
|
|
|
}
|
2024-05-19 02:29:13 -07:00
|
|
|
SearchConfig::GlobalJustfile => Ok(Self {
|
|
|
|
justfile: Self::global_justfile_paths()
|
|
|
|
.iter()
|
|
|
|
.find(|path| path.exists())
|
|
|
|
.cloned()
|
|
|
|
.ok_or(SearchError::GlobalJustfileNotFound)?,
|
|
|
|
working_directory: Self::project_root(invocation_directory)?,
|
|
|
|
}),
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
SearchConfig::WithJustfile { justfile } => {
|
2019-11-19 03:51:44 -08:00
|
|
|
let justfile = Self::clean(invocation_directory, justfile);
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
2020-01-15 02:16:13 -08:00
|
|
|
Ok(Self {
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
justfile,
|
|
|
|
working_directory,
|
|
|
|
})
|
2021-09-16 06:44:40 -07:00
|
|
|
}
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
SearchConfig::WithJustfileAndWorkingDirectory {
|
|
|
|
justfile,
|
|
|
|
working_directory,
|
2020-01-15 02:16:13 -08:00
|
|
|
} => Ok(Self {
|
2021-09-16 06:44:40 -07:00
|
|
|
justfile: Self::clean(invocation_directory, justfile),
|
2019-11-19 03:51:44 -08:00
|
|
|
working_directory: Self::clean(invocation_directory, working_directory),
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-30 22:13:59 -07:00
|
|
|
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)?;
|
|
|
|
Ok(Self {
|
|
|
|
justfile,
|
|
|
|
working_directory,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-19 23:07:44 -08:00
|
|
|
pub(crate) fn init(
|
|
|
|
search_config: &SearchConfig,
|
|
|
|
invocation_directory: &Path,
|
2020-01-15 02:16:13 -08:00
|
|
|
) -> SearchResult<Self> {
|
2019-11-19 23:07:44 -08:00
|
|
|
match search_config {
|
|
|
|
SearchConfig::FromInvocationDirectory => {
|
2022-01-30 12:16:10 -08:00
|
|
|
let working_directory = Self::project_root(invocation_directory)?;
|
2021-07-31 12:25:49 -07:00
|
|
|
let justfile = working_directory.join(DEFAULT_JUSTFILE_NAME);
|
2020-01-15 02:16:13 -08:00
|
|
|
Ok(Self {
|
2019-11-19 23:07:44 -08:00
|
|
|
justfile,
|
|
|
|
working_directory,
|
|
|
|
})
|
2021-09-16 06:44:40 -07:00
|
|
|
}
|
2019-11-19 23:07:44 -08:00
|
|
|
SearchConfig::FromSearchDirectory { search_directory } => {
|
|
|
|
let search_directory = Self::clean(invocation_directory, search_directory);
|
|
|
|
let working_directory = Self::project_root(&search_directory)?;
|
2021-07-31 12:25:49 -07:00
|
|
|
let justfile = working_directory.join(DEFAULT_JUSTFILE_NAME);
|
2020-01-15 02:16:13 -08:00
|
|
|
Ok(Self {
|
2019-11-19 23:07:44 -08:00
|
|
|
justfile,
|
|
|
|
working_directory,
|
|
|
|
})
|
2021-09-16 06:44:40 -07:00
|
|
|
}
|
2024-05-19 02:29:13 -07:00
|
|
|
SearchConfig::GlobalJustfile => Err(SearchError::GlobalJustfileInit),
|
2019-11-19 23:07:44 -08:00
|
|
|
SearchConfig::WithJustfile { justfile } => {
|
|
|
|
let justfile = Self::clean(invocation_directory, justfile);
|
|
|
|
let working_directory = Self::working_directory_from_justfile(&justfile)?;
|
2020-01-15 02:16:13 -08:00
|
|
|
Ok(Self {
|
2019-11-19 23:07:44 -08:00
|
|
|
justfile,
|
|
|
|
working_directory,
|
|
|
|
})
|
2021-09-16 06:44:40 -07:00
|
|
|
}
|
2019-11-19 23:07:44 -08:00
|
|
|
SearchConfig::WithJustfileAndWorkingDirectory {
|
|
|
|
justfile,
|
|
|
|
working_directory,
|
2020-01-15 02:16:13 -08:00
|
|
|
} => Ok(Self {
|
2021-09-16 06:44:40 -07:00
|
|
|
justfile: Self::clean(invocation_directory, justfile),
|
2019-11-19 23:07:44 -08:00
|
|
|
working_directory: Self::clean(invocation_directory, working_directory),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-27 20:27:15 -08:00
|
|
|
pub(crate) fn justfile(directory: &Path) -> SearchResult<PathBuf> {
|
2019-11-19 23:07:44 -08:00
|
|
|
for directory in directory.ancestors() {
|
2021-07-31 12:25:49 -07:00
|
|
|
let mut candidates = BTreeSet::new();
|
2019-11-19 23:07:44 -08:00
|
|
|
|
|
|
|
let entries = fs::read_dir(directory).map_err(|io_error| SearchError::Io {
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
io_error,
|
|
|
|
directory: directory.to_owned(),
|
|
|
|
})?;
|
2019-11-19 23:07:44 -08:00
|
|
|
for entry in entries {
|
|
|
|
let entry = entry.map_err(|io_error| SearchError::Io {
|
|
|
|
io_error,
|
|
|
|
directory: directory.to_owned(),
|
|
|
|
})?;
|
|
|
|
if let Some(name) = entry.file_name().to_str() {
|
2021-07-31 12:25:49 -07:00
|
|
|
for justfile_name in JUSTFILE_NAMES {
|
|
|
|
if name.eq_ignore_ascii_case(justfile_name) {
|
|
|
|
candidates.insert(entry.path());
|
|
|
|
}
|
2019-11-19 23:07:44 -08:00
|
|
|
}
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
}
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
2020-01-15 01:20:38 -08:00
|
|
|
|
2021-09-16 07:51:45 -07:00
|
|
|
match candidates.len() {
|
|
|
|
0 => {}
|
|
|
|
1 => return Ok(candidates.into_iter().next().unwrap()),
|
|
|
|
_ => return Err(SearchError::MultipleCandidates { candidates }),
|
2019-11-19 23:07:44 -08:00
|
|
|
}
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
2019-11-19 23:07:44 -08:00
|
|
|
|
|
|
|
Err(SearchError::NotFound)
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
|
2019-11-19 03:51:44 -08:00
|
|
|
fn clean(invocation_directory: &Path, path: &Path) -> PathBuf {
|
|
|
|
let path = invocation_directory.join(path);
|
|
|
|
|
|
|
|
let mut clean = Vec::new();
|
|
|
|
|
|
|
|
for component in path.components() {
|
|
|
|
if component == Component::ParentDir {
|
|
|
|
if let Some(Component::Normal(_)) = clean.last() {
|
|
|
|
clean.pop();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
clean.push(component);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clean.into_iter().collect()
|
|
|
|
}
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
|
2019-11-19 23:07:44 -08:00
|
|
|
fn project_root(directory: &Path) -> SearchResult<PathBuf> {
|
|
|
|
for directory in directory.ancestors() {
|
|
|
|
let entries = fs::read_dir(directory).map_err(|io_error| SearchError::Io {
|
|
|
|
io_error,
|
|
|
|
directory: directory.to_owned(),
|
|
|
|
})?;
|
|
|
|
|
|
|
|
for entry in entries {
|
|
|
|
let entry = entry.map_err(|io_error| SearchError::Io {
|
|
|
|
io_error,
|
|
|
|
directory: directory.to_owned(),
|
|
|
|
})?;
|
2022-01-30 12:16:10 -08:00
|
|
|
for project_root_child in PROJECT_ROOT_CHILDREN.iter().copied() {
|
2019-11-19 23:07:44 -08:00
|
|
|
if entry.file_name() == project_root_child {
|
|
|
|
return Ok(directory.to_owned());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(directory.to_owned())
|
|
|
|
}
|
|
|
|
|
2019-11-19 03:51:44 -08:00
|
|
|
fn working_directory_from_justfile(justfile: &Path) -> SearchResult<PathBuf> {
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
Ok(
|
2019-11-19 03:51:44 -08:00
|
|
|
justfile
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
.parent()
|
|
|
|
.ok_or_else(|| SearchError::JustfileHadNoParent {
|
2019-11-19 03:51:44 -08:00
|
|
|
path: justfile.to_path_buf(),
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
})?
|
|
|
|
.to_owned(),
|
|
|
|
)
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2021-07-03 14:26:59 -07:00
|
|
|
use temptree::temptree;
|
2019-06-01 22:38:03 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn not_found() {
|
2019-07-06 20:55:46 -07:00
|
|
|
let tmp = testing::tempdir();
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
match Search::justfile(tmp.path()) {
|
2021-09-16 06:44:40 -07:00
|
|
|
Err(SearchError::NotFound) => {}
|
2019-06-01 22:38:03 -07:00
|
|
|
_ => panic!("No justfile found error was expected"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multiple_candidates() {
|
2019-07-06 20:55:46 -07:00
|
|
|
let tmp = testing::tempdir();
|
2019-06-01 22:38:03 -07:00
|
|
|
let mut path = tmp.path().to_path_buf();
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME);
|
2019-06-01 22:38:03 -07:00
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
path.pop();
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME.to_uppercase());
|
2021-05-07 00:14:38 -07:00
|
|
|
if fs::File::open(path.as_path()).is_ok() {
|
2019-06-01 22:38:03 -07:00
|
|
|
// We are in case-insensitive file system
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
path.pop();
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
match Search::justfile(path.as_path()) {
|
2021-09-16 06:44:40 -07:00
|
|
|
Err(SearchError::MultipleCandidates { .. }) => {}
|
2019-06-01 22:38:03 -07:00
|
|
|
_ => panic!("Multiple candidates error was expected"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn found() {
|
2019-07-06 20:55:46 -07:00
|
|
|
let tmp = testing::tempdir();
|
2019-06-01 22:38:03 -07:00
|
|
|
let mut path = tmp.path().to_path_buf();
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME);
|
2019-06-01 22:38:03 -07:00
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
path.pop();
|
2021-05-07 00:14:38 -07:00
|
|
|
if let Err(err) = Search::justfile(path.as_path()) {
|
2022-12-15 16:53:21 -08:00
|
|
|
panic!("No errors were expected: {err}");
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn found_spongebob_case() {
|
2019-07-06 20:55:46 -07:00
|
|
|
let tmp = testing::tempdir();
|
2019-06-01 22:38:03 -07:00
|
|
|
let mut path = tmp.path().to_path_buf();
|
2021-07-31 12:25:49 -07:00
|
|
|
let spongebob_case = DEFAULT_JUSTFILE_NAME
|
2019-06-01 22:38:03 -07:00
|
|
|
.chars()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, c)| {
|
|
|
|
if i % 2 == 0 {
|
|
|
|
c.to_ascii_uppercase()
|
|
|
|
} else {
|
|
|
|
c
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect::<String>();
|
|
|
|
path.push(spongebob_case);
|
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
path.pop();
|
2021-05-07 00:14:38 -07:00
|
|
|
if let Err(err) = Search::justfile(path.as_path()) {
|
2022-12-15 16:53:21 -08:00
|
|
|
panic!("No errors were expected: {err}");
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn found_from_inner_dir() {
|
2019-07-06 20:55:46 -07:00
|
|
|
let tmp = testing::tempdir();
|
2019-06-01 22:38:03 -07:00
|
|
|
let mut path = tmp.path().to_path_buf();
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME);
|
2019-06-01 22:38:03 -07:00
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
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");
|
2021-05-07 00:14:38 -07:00
|
|
|
if let Err(err) = Search::justfile(path.as_path()) {
|
2022-12-15 16:53:21 -08:00
|
|
|
panic!("No errors were expected: {err}");
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn found_and_stopped_at_first_justfile() {
|
2019-07-06 20:55:46 -07:00
|
|
|
let tmp = testing::tempdir();
|
2019-06-01 22:38:03 -07:00
|
|
|
let mut path = tmp.path().to_path_buf();
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME);
|
2019-06-01 22:38:03 -07:00
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
path.pop();
|
|
|
|
path.push("a");
|
|
|
|
fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory");
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME);
|
2019-06-01 22:38:03 -07:00
|
|
|
fs::write(&path, "default:\n\techo ok").unwrap();
|
|
|
|
path.pop();
|
|
|
|
path.push("b");
|
|
|
|
fs::create_dir(&path).expect("test justfile search: failed to create intermediary directory");
|
Gargantuan refactor (#522)
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
2019-11-09 21:43:20 -08:00
|
|
|
match Search::justfile(path.as_path()) {
|
2019-06-01 22:38:03 -07:00
|
|
|
Ok(found_path) => {
|
|
|
|
path.pop();
|
2021-07-31 12:25:49 -07:00
|
|
|
path.push(DEFAULT_JUSTFILE_NAME);
|
2019-06-01 22:38:03 -07:00
|
|
|
assert_eq!(found_path, path);
|
2021-09-16 06:44:40 -07:00
|
|
|
}
|
2022-12-15 16:53:21 -08:00
|
|
|
Err(err) => panic!("No errors were expected: {err}"),
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|
|
|
|
}
|
2019-11-19 03:51:44 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn justfile_symlink_parent() {
|
2021-07-03 14:26:59 -07:00
|
|
|
let tmp = temptree! {
|
2019-11-19 03:51:44 -08:00
|
|
|
src: "",
|
|
|
|
sub: {},
|
|
|
|
};
|
|
|
|
|
|
|
|
let src = tmp.path().join("src");
|
|
|
|
let sub = tmp.path().join("sub");
|
|
|
|
let justfile = sub.join("justfile");
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
2022-12-15 16:53:21 -08:00
|
|
|
std::os::unix::fs::symlink(src, &justfile).unwrap();
|
2019-11-19 03:51:44 -08:00
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
std::os::windows::fs::symlink_file(&src, &justfile).unwrap();
|
|
|
|
|
|
|
|
let search_config = SearchConfig::FromInvocationDirectory;
|
|
|
|
|
2019-11-19 23:07:44 -08:00
|
|
|
let search = Search::find(&search_config, &sub).unwrap();
|
2019-11-19 03:51:44 -08:00
|
|
|
|
|
|
|
assert_eq!(search.justfile, justfile);
|
|
|
|
assert_eq!(search.working_directory, sub);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn clean() {
|
|
|
|
let cases = &[
|
|
|
|
("/", "foo", "/foo"),
|
|
|
|
("/bar", "/foo", "/foo"),
|
2022-12-15 16:53:21 -08:00
|
|
|
#[cfg(windows)]
|
|
|
|
("//foo", "bar//baz", "//foo\\bar\\baz"),
|
|
|
|
#[cfg(not(windows))]
|
2019-11-19 03:51:44 -08:00
|
|
|
("/", "..", "/"),
|
|
|
|
("/", "/..", "/"),
|
|
|
|
("/..", "", "/"),
|
|
|
|
("/../../../..", "../../../", "/"),
|
|
|
|
("/.", "./", "/"),
|
|
|
|
("/foo/../", "bar", "/bar"),
|
|
|
|
("/foo/bar", "..", "/foo"),
|
|
|
|
("/foo/bar/", "..", "/foo"),
|
|
|
|
];
|
|
|
|
|
|
|
|
for (prefix, suffix, want) in cases {
|
|
|
|
let have = Search::clean(Path::new(prefix), Path::new(suffix));
|
|
|
|
assert_eq!(have, Path::new(want));
|
|
|
|
}
|
|
|
|
}
|
2019-06-01 22:38:03 -07:00
|
|
|
}
|