Skip to content

Commit 76f3449

Browse files
authored
tempfile: Delegate tempdir::new to base version (#360)
I was looking at the code here for an unrelated reason, and realized that there's no reason for us to duplicate the code. Because a Dir instance doesn't have a name accessible to the calling code, we just delegate to the non-UTF8 base version. In some presumably very unusual situations the tempdir may have a non-UTF8 name, but that's fine. Signed-off-by: Colin Walters <walters@verbum.org>
1 parent e080102 commit 76f3449

File tree

1 file changed

+17
-69
lines changed

1 file changed

+17
-69
lines changed

cap-tempfile/src/utf8.rs

Lines changed: 17 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
//!
33
//! TODO: This whole scheme is still under development.
44
5+
#[cfg(test)]
56
use camino::Utf8PathBuf;
67
use cap_std::fs_utf8::Dir;
8+
#[cfg(test)]
9+
use std::env;
710
use std::ops::Deref;
8-
use std::{env, fmt, fs, io, mem};
9-
#[cfg(not(target_os = "emscripten"))]
10-
use uuid::Uuid;
11+
use std::{fmt, io, mem};
1112

1213
#[doc(hidden)]
1314
pub use cap_std::ambient_authority_known_at_compile_time;
@@ -28,6 +29,13 @@ pub struct TempDir {
2829
}
2930

3031
impl TempDir {
32+
// Consume a base/non-UTF8 tempdir instance and return a UTF8 version
33+
fn from_cap_std(mut td: super::TempDir) -> Self {
34+
// Take ownership of the underlying Dir instance
35+
let dir = td.dir.take().map(Dir::from_cap_std);
36+
Self { dir }
37+
}
38+
3139
/// Attempts to make a temporary directory inside of `env::temp_dir()`.
3240
///
3341
/// This corresponds to [`tempfile::TempDir::new`].
@@ -39,27 +47,11 @@ impl TempDir {
3947
/// This function makes use of ambient authority to access temporary
4048
/// directories.
4149
pub fn new(ambient_authority: AmbientAuthority) -> io::Result<Self> {
42-
let system_tmp: Utf8PathBuf = env::temp_dir()
43-
.try_into()
44-
.expect("temporary directory path should be valid UTF-8");
45-
for _ in 0..Self::num_iterations() {
46-
let name = system_tmp.join(&Self::new_name());
47-
match fs::create_dir(&name) {
48-
Ok(()) => {
49-
let dir = match Dir::open_ambient_dir(&name, ambient_authority) {
50-
Ok(dir) => dir,
51-
Err(e) => {
52-
fs::remove_dir(name).ok();
53-
return Err(e);
54-
}
55-
};
56-
return Ok(Self { dir: Some(dir) });
57-
}
58-
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
59-
Err(e) => return Err(e),
60-
}
61-
}
62-
Err(Self::already_exists())
50+
// Because a Dir instance doesn't have a name accessible to the calling
51+
// code, we just delegate to the non-UTF8 base version. In some presumably
52+
// very unusual situations the tempdir may have a non-UTF8 name,
53+
// but that's fine.
54+
super::TempDir::new(ambient_authority).map(Self::from_cap_std)
6355
}
6456

6557
/// Create a new temporary directory.
@@ -68,24 +60,7 @@ impl TempDir {
6860
///
6961
/// [`tempfile::TempDir::new_in`]: https://docs.rs/tempfile/latest/tempfile/fn.tempdir_in.html
7062
pub fn new_in(dir: &Dir) -> io::Result<Self> {
71-
for _ in 0..Self::num_iterations() {
72-
let name = &Self::new_name();
73-
match dir.create_dir(name) {
74-
Ok(()) => {
75-
let dir = match dir.open_dir(name) {
76-
Ok(dir) => dir,
77-
Err(e) => {
78-
dir.remove_dir(name).ok();
79-
return Err(e);
80-
}
81-
};
82-
return Ok(Self { dir: Some(dir) });
83-
}
84-
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
85-
Err(e) => return Err(e),
86-
}
87-
}
88-
Err(Self::already_exists())
63+
super::TempDir::new_in(dir.as_cap_std()).map(Self::from_cap_std)
8964
}
9065

9166
/// Closes and removes the temporary directory, returning a `Result`.
@@ -96,33 +71,6 @@ impl TempDir {
9671
pub fn close(mut self) -> io::Result<()> {
9772
mem::take(&mut self.dir).unwrap().remove_open_dir_all()
9873
}
99-
100-
fn new_name() -> String {
101-
#[cfg(not(target_os = "emscripten"))]
102-
{
103-
Uuid::new_v4().to_string()
104-
}
105-
106-
// Uuid doesn't support Emscripten yet, but Emscripten isn't multi-user
107-
// or multi-process yet, so we can do something simple.
108-
#[cfg(target_os = "emscripten")]
109-
{
110-
use rand::RngCore;
111-
let mut r = rand::thread_rng();
112-
format!("cap-primitives.{}", r.next_u32())
113-
}
114-
}
115-
116-
const fn num_iterations() -> i32 {
117-
i32::MAX
118-
}
119-
120-
fn already_exists() -> io::Error {
121-
io::Error::new(
122-
io::ErrorKind::AlreadyExists,
123-
"too many temporary files exist",
124-
)
125-
}
12674
}
12775

12876
impl Deref for TempDir {

0 commit comments

Comments
 (0)