Use cache dir for temporary files (#2067)

Sometimes `/tmp` is mounted with the `noexec` option, which results
causes running shebang recipes to fail.

Instead of `/tmp`, use the cache directory as provided by the
[dirs crate](https://docs.rs/dirs/latest/src/dirs/lib.rs.html#77).
This commit is contained in:
Casey Rodarmor 2024-05-20 17:04:42 -07:00 committed by GitHub
parent 63ad7cc176
commit d3492e6ffe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 7 deletions

View File

@ -20,6 +20,10 @@ pub(crate) enum Error<'src> {
token: Token<'src>, token: Token<'src>,
output_error: OutputError, output_error: OutputError,
}, },
CacheDirIo {
io_error: io::Error,
path: PathBuf,
},
ChooserInvoke { ChooserInvoke {
shell_binary: String, shell_binary: String,
shell_arguments: String, shell_arguments: String,
@ -279,6 +283,9 @@ impl<'src> ColorDisplay for Error<'src> {
}?, }?,
OutputError::Utf8(utf8_error) => write!(f, "Backtick succeeded but stdout was not utf8: {utf8_error}")?, OutputError::Utf8(utf8_error) => write!(f, "Backtick succeeded but stdout was not utf8: {utf8_error}")?,
} }
CacheDirIo { io_error, path } => {
write!(f, "I/O error in cache dir `{}`: {io_error}", path.display())?;
}
ChooserInvoke { shell_binary, shell_arguments, chooser, io_error} => { ChooserInvoke { shell_binary, shell_arguments, chooser, io_error} => {
let chooser = chooser.to_string_lossy(); let chooser = chooser.to_string_lossy();
write!(f, "Chooser `{shell_binary} {shell_arguments} {chooser}` invocation failed: {io_error}")?; write!(f, "Chooser `{shell_binary} {shell_arguments} {chooser}` invocation failed: {io_error}")?;
@ -382,8 +389,7 @@ impl<'src> ColorDisplay for Error<'src> {
}?; }?;
} }
Load { io_error, path } => { Load { io_error, path } => {
let path = path.display(); write!(f, "Failed to read justfile at `{}`: {io_error}", path.display())?;
write!(f, "Failed to read justfile at `{path}`: {io_error}")?;
} }
MissingImportFile { .. } => write!(f, "Could not find source file for import.")?, MissingImportFile { .. } => write!(f, "Could not find source file for import.")?,
MissingModuleFile { module } => write!(f, "Could not find source file for module `{module}`.")?, MissingModuleFile { module } => write!(f, "Could not find source file for module `{module}`.")?,

View File

@ -336,7 +336,18 @@ impl<'src, D> Recipe<'src, D> {
tempdir_builder.prefix("just-"); tempdir_builder.prefix("just-");
let tempdir = match &context.settings.tempdir { let tempdir = match &context.settings.tempdir {
Some(tempdir) => tempdir_builder.tempdir_in(context.search.working_directory.join(tempdir)), Some(tempdir) => tempdir_builder.tempdir_in(context.search.working_directory.join(tempdir)),
None => tempdir_builder.tempdir(), None => {
if let Some(cache_dir) = dirs::cache_dir() {
let path = cache_dir.join("just");
fs::create_dir_all(&path).map_err(|io_error| Error::CacheDirIo {
io_error,
path: path.clone(),
})?;
tempdir_builder.tempdir_in(path)
} else {
tempdir_builder.tempdir()
}
}
} }
.map_err(|error| Error::TempdirIo { .map_err(|error| Error::TempdirIo {
recipe: self.name(), recipe: self.name(),

View File

@ -1,9 +1,17 @@
use super::*; use super::*;
pub(crate) fn tempdir() -> TempDir { pub(crate) fn tempdir() -> TempDir {
tempfile::Builder::new() let mut builder = tempfile::Builder::new();
.prefix("just-test-tempdir")
.tempdir() builder.prefix("just-test-tempdir");
if let Some(cache_dir) = dirs::cache_dir() {
let path = cache_dir.join("just");
fs::create_dir_all(&path).unwrap();
builder.tempdir_in(path)
} else {
builder.tempdir()
}
.expect("failed to create temporary directory") .expect("failed to create temporary directory")
} }