Skip to content

Commit

Permalink
global justfile
Browse files Browse the repository at this point in the history
  • Loading branch information
neunenak committed Jan 14, 2024
1 parent 22d462b commit 13521ed
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 63 deletions.
71 changes: 42 additions & 29 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ mod arg {
pub(crate) const DOTENV_PATH: &str = "DOTENV-PATH";
pub(crate) const DRY_RUN: &str = "DRY-RUN";
pub(crate) const DUMP_FORMAT: &str = "DUMP-FORMAT";
pub(crate) const GLOBAL: &str = "GLOBAL";
pub(crate) const HIGHLIGHT: &str = "HIGHLIGHT";
pub(crate) const JUSTFILE: &str = "JUSTFILE";
pub(crate) const LIST_HEADING: &str = "LIST-HEADING";
Expand Down Expand Up @@ -404,7 +405,13 @@ impl Config {
Arg::with_name(arg::ARGUMENTS)
.multiple(true)
.help("Overrides and recipe(s) to run, defaulting to the first recipe in the justfile"),
);
)
.arg(
Arg::with_name(arg::GLOBAL)
.long("global")
.short("g")
.help("Invoke using a global `justfile`")
);

if cfg!(feature = "help4help2man") {
app.version(env!("CARGO_PKG_VERSION")).about(concat!(
Expand Down Expand Up @@ -476,6 +483,38 @@ impl Config {
}
}

fn search_config(matches: &ArgMatches, positional: &Positional) -> ConfigResult<SearchConfig> {
if matches.is_present(arg::GLOBAL) {
return Ok(SearchConfig::Global);
}

let justfile = matches.value_of(arg::JUSTFILE).map(PathBuf::from);
let working_directory = matches.value_of(arg::WORKING_DIRECTORY).map(PathBuf::from);

if let Some(search_directory) = positional.search_directory.as_ref().map(PathBuf::from) {
if justfile.is_some() || working_directory.is_some() {
return Err(ConfigError::SearchDirConflict);
}
Ok(SearchConfig::FromSearchDirectory { search_directory })
} else {
match (justfile, working_directory) {
(None, None) => Ok(SearchConfig::FromInvocationDirectory),
(Some(justfile), None) => Ok(SearchConfig::WithJustfile { justfile }),
(Some(justfile), Some(working_directory)) => {
Ok(SearchConfig::WithJustfileAndWorkingDirectory {
justfile,
working_directory,
})
}
(None, Some(_)) => {
return Err(ConfigError::internal(
"--working-directory set without --justfile",
))
}
}
}
}

pub(crate) fn from_matches(matches: &ArgMatches) -> ConfigResult<Self> {
let invocation_directory = env::current_dir().context(config_error::CurrentDirContext)?;

Expand All @@ -502,37 +541,11 @@ impl Config {

let positional = Positional::from_values(matches.values_of(arg::ARGUMENTS));

for (name, value) in positional.overrides {
for (name, value) in &positional.overrides {
overrides.insert(name.clone(), value.clone());
}

let search_config = {
let justfile = matches.value_of(arg::JUSTFILE).map(PathBuf::from);
let working_directory = matches.value_of(arg::WORKING_DIRECTORY).map(PathBuf::from);

if let Some(search_directory) = positional.search_directory.map(PathBuf::from) {
if justfile.is_some() || working_directory.is_some() {
return Err(ConfigError::SearchDirConflict);
}
SearchConfig::FromSearchDirectory { search_directory }
} else {
match (justfile, working_directory) {
(None, None) => SearchConfig::FromInvocationDirectory,
(Some(justfile), None) => SearchConfig::WithJustfile { justfile },
(Some(justfile), Some(working_directory)) => {
SearchConfig::WithJustfileAndWorkingDirectory {
justfile,
working_directory,
}
}
(None, Some(_)) => {
return Err(ConfigError::internal(
"--working-directory set without --justfile",
))
}
}
}
};
let search_config = Self::search_config(matches, &positional)?;

for subcommand in cmd::ARGLESS {
if matches.is_present(subcommand) {
Expand Down
84 changes: 50 additions & 34 deletions src/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,50 @@ impl Search {
search_config: &SearchConfig,
invocation_directory: &Path,
) -> SearchResult<Self> {
match search_config {
SearchConfig::FromInvocationDirectory => Self::find_next(invocation_directory),
SearchConfig::FromSearchDirectory { search_directory } => {
let search_directory = Self::clean(invocation_directory, search_directory);
use SearchConfig::*;

Ok(match search_config {
FromInvocationDirectory => Self::find_next(invocation_directory)?,
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)?;

Ok(Self {
Self {
justfile,
working_directory,
})
}
}
SearchConfig::WithJustfile { justfile } => {
Global => {
let working_directory = Self::project_root(invocation_directory)?;
let home_dir = dirs::home_dir().ok_or(SearchError::MissingHomeDirectory)?;
let justfile = home_dir.join(DEFAULT_JUSTFILE_NAME);
Self {
working_directory,
justfile
}
},
WithJustfile { justfile } => {
let justfile = Self::clean(invocation_directory, justfile);

let working_directory = Self::working_directory_from_justfile(&justfile)?;

Ok(Self {
Self {
justfile,
working_directory,
})
}
}
SearchConfig::WithJustfileAndWorkingDirectory {
WithJustfileAndWorkingDirectory {
justfile,
working_directory,
} => Ok(Self {
} => Self {
justfile: Self::clean(invocation_directory, justfile),
working_directory: Self::clean(invocation_directory, 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)?;

Ok(Self {
Expand All @@ -63,50 +70,59 @@ impl Search {
search_config: &SearchConfig,
invocation_directory: &Path,
) -> SearchResult<Self> {
match search_config {
SearchConfig::FromInvocationDirectory => {
let working_directory = Self::project_root(invocation_directory)?;
use SearchConfig::*;

Ok(match search_config {
FromInvocationDirectory => {
let working_directory = Self::project_root(invocation_directory)?;
let justfile = working_directory.join(DEFAULT_JUSTFILE_NAME);

Ok(Self {
Self {
justfile,
working_directory,
})
}
}

SearchConfig::FromSearchDirectory { search_directory } => {
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);

Ok(Self {
Self {
justfile,
working_directory,
})
}
}

SearchConfig::WithJustfile { justfile } => {
let justfile = Self::clean(invocation_directory, justfile);
Global => {
let working_directory = Self::project_root(invocation_directory)?;
let home_dir = dirs::home_dir().ok_or(SearchError::MissingHomeDirectory)?;
let justfile = home_dir.join(DEFAULT_JUSTFILE_NAME);

Self {
justfile,
working_directory,
}
}

WithJustfile { justfile } => {
let justfile = Self::clean(invocation_directory, justfile);
let working_directory = Self::working_directory_from_justfile(&justfile)?;

Ok(Self {
Self {
justfile,
working_directory,
})
}
}

SearchConfig::WithJustfileAndWorkingDirectory {
WithJustfileAndWorkingDirectory {
justfile,
working_directory,
} => Ok(Self {
} => Self {
justfile: Self::clean(invocation_directory, justfile),
working_directory: Self::clean(invocation_directory, working_directory),
}),
}
},
})
}

pub(crate) fn justfile(directory: &Path) -> SearchResult<PathBuf> {
Expand Down
6 changes: 6 additions & 0 deletions src/search_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ pub(crate) enum SearchConfig {
/// to the root, setting the working directory to the directory in which the
/// justfile is found.
FromInvocationDirectory,

/// As in `Invocation`, but start from `search_directory`.
FromSearchDirectory { search_directory: PathBuf },

/// Search for a justfile in a well-known global path
Global,

/// Use user-specified justfile, with the working directory set to the
/// directory that contains it.
WithJustfile { justfile: PathBuf },

/// Use user-specified justfile and working directory.
WithJustfileAndWorkingDirectory {
justfile: PathBuf,
Expand Down
4 changes: 4 additions & 0 deletions src/search_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub(crate) enum SearchError {
},
#[snafu(display("Justfile path had no parent: {}", path.display()))]
JustfileHadNoParent { path: PathBuf },

#[snafu(display("Home directory not found"))]
MissingHomeDirectory,

#[snafu(display(
"Multiple candidate justfiles found in `{}`: {}",
candidates.iter().next().unwrap().parent().unwrap().display(),
Expand Down

0 comments on commit 13521ed

Please sign in to comment.