diff --git a/src/lib.rs b/src/lib.rs index 4f5a8bb4d..26873b0da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -171,21 +171,23 @@ pub use crate::spooled::{spooled_tempfile, SpooledData, SpooledTempFile}; /// Create a new temporary file or directory with custom parameters. #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Builder<'a, 'b> { +pub struct Builder<'a, 'b, 'c> { random_len: usize, prefix: &'a OsStr, suffix: &'b OsStr, + dir: Option<&'c Path>, append: bool, permissions: Option, keep: bool, } -impl<'a, 'b> Default for Builder<'a, 'b> { +impl<'a, 'b, 'c> Default for Builder<'a, 'b, 'c> { fn default() -> Self { Builder { random_len: crate::NUM_RAND_CHARS, prefix: OsStr::new(".tmp"), suffix: OsStr::new(""), + dir: None, // Use env::temp_dir(). append: false, permissions: None, keep: false, @@ -193,7 +195,7 @@ impl<'a, 'b> Default for Builder<'a, 'b> { } } -impl<'a, 'b> Builder<'a, 'b> { +impl<'a, 'b, 'c> Builder<'a, 'b, 'c> { /// Create a new `Builder`. /// /// # Examples @@ -304,6 +306,28 @@ impl<'a, 'b> Builder<'a, 'b> { self } + /// Set a directory to create files in. + /// + /// This is an alternative API that achieves essentially the same thing as + /// `tempfile_in` and `tempdir_in`. + /// + /// Default: `env::temp_dir()` + /// + /// # Examples + /// ``` + /// use tempfile::Builder; + /// use tempfile::tempdir; + /// + /// let parent = tempdir()?; + /// let tempfile_in_parent = Builder::new() + /// .parent_dir(parent.path()) + /// .tempfile()?; + /// # Ok::<(), std::io::Error>(()) + pub fn parent_dir + ?Sized>(&mut self, dir: &'c P) -> &mut Self { + self.dir = Some(dir.as_ref()); + self + } + /// Set the number of random bytes. /// /// Default: `6`. @@ -461,7 +485,7 @@ impl<'a, 'b> Builder<'a, 'b> { /// [security]: struct.NamedTempFile.html#security /// [resource-leaking]: struct.NamedTempFile.html#resource-leaking pub fn tempfile(&self) -> io::Result { - self.tempfile_in(env::temp_dir()) + self.tempfile_in(self.dir.unwrap_or(&env::temp_dir())) } /// Create the named temporary file in the specified directory. @@ -530,7 +554,7 @@ impl<'a, 'b> Builder<'a, 'b> { /// /// [resource-leaking]: struct.TempDir.html#resource-leaking pub fn tempdir(&self) -> io::Result { - self.tempdir_in(env::temp_dir()) + self.tempdir_in(self.dir.unwrap_or(&env::temp_dir())) } /// Attempts to make a temporary directory inside of `dir`. diff --git a/tests/tempdir.rs b/tests/tempdir.rs index 864734a61..c29fb5f44 100644 --- a/tests/tempdir.rs +++ b/tests/tempdir.rs @@ -39,6 +39,18 @@ fn test_suffix() { assert!(name.ends_with("suffix")); } +fn test_stored_parent_dir() { + let parent = TempDir::new().unwrap(); + let child = Builder::new().parent_dir(parent.path()).tempdir().unwrap(); + let path_str = child.path().to_str().unwrap(); + assert!( + path_str.starts_with(child.path().to_str().unwrap()), + "{:?} not in {:?}", + child, + parent + ); +} + fn test_customnamed() { let tmpfile = Builder::new() .prefix("prefix") @@ -182,6 +194,8 @@ fn main() { in_tmpdir(test_tempdir); in_tmpdir(test_prefix); in_tmpdir(test_suffix); + in_tmpdir(test_suffix); + in_tmpdir(test_stored_parent_dir); in_tmpdir(test_customnamed); in_tmpdir(test_rm_tempdir); in_tmpdir(test_rm_tempdir_close); diff --git a/tests/tempfile.rs b/tests/tempfile.rs index c2f684438..5c778d666 100644 --- a/tests/tempfile.rs +++ b/tests/tempfile.rs @@ -8,6 +8,8 @@ use std::{ thread, }; +use tempfile::{Builder, TempDir}; + #[test] fn test_basic() { let mut tmpfile = tempfile::tempfile().unwrap(); @@ -18,6 +20,20 @@ fn test_basic() { assert_eq!("abcde", buf); } +#[test] +fn test_stored_parent_dir() { + let parent = TempDir::new().unwrap(); + let child = Builder::new().parent_dir(parent.path()).tempfile().unwrap(); + let path_str = child.path().to_str().unwrap(); + assert!( + path_str.starts_with(child.path().to_str().unwrap()), + "{:?} not in {:?}", + child, + parent + ); +} + + #[test] fn test_cleanup() { let tmpdir = tempfile::tempdir().unwrap();