Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the ability to override the default temporary directory #286

Merged
merged 3 commits into from
Jul 29, 2024

Conversation

Stebalien
Copy link
Owner

This adds a new env module with override_temp_dir and temp_dir functions.

  • temp_dir will defer to std::env::temp_dir by default unless the temporary directory has been overridden.
  • override_temp_dir allows the user to override the default temporary directory ONCE. Once this value has been set, it cannot be changed Care should be taken to ensure that the chosen directory is actually writable.

This API is designed for use by the application author when the application may run in an environment without a reliable global temporary directory (e.g., Android).

fixes #285

@Stebalien
Copy link
Owner Author

(needs test)

This adds a new `env` module with `override_temp_dir` and `temp_dir`
functions.

- `temp_dir` will defer to `std::env::temp_dir` by default unless the
temporary directory has been overridden.
- `override_temp_dir` allows the user to override the default temporary
directory ONCE. Once this value has been set, it cannot be changed Care
should be taken to ensure that the chosen directory is actually writable.

This API is designed for use by the application author when the
application may run in an environment without a reliable global
temporary directory (e.g., Android).

fixes #285
@Stebalien Stebalien force-pushed the steb/override-temp-dir branch from 6a12031 to 3d67780 Compare July 26, 2024 18:23
src/env.rs Outdated
/// Only the first call to this function will succeed, returning `Ok(path)`. All further calls will
/// fail with `Err(path)`. In both cases, `path` is the default temporary directory (on success, the
/// new one; on failure, the existing one).
pub fn override_temp_dir(path: &Path) -> Result<&'static Path, &'static Path> {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered treating this as a fallback (TMPDIR -> the override -> "/tmp"), but handling all the platform-specific cases got hairy.

I also considered testing if the various temporary directories were writable.... but honestly, I don't want to be in the position of "guessing" where temporary files should be written (although I'll revisit that later if this keeps coming up).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest Result<(), TempDirAlreadyOverridden> as the return type.

In the success case there is not point in returning the value just passed in.
In the error case it is problematic that Path does not implement Display.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs: Is there a requirement that the directory already exists (I think so) or will it be created (recursively) if non-existent?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the success case there is not point in returning the value just passed in.

It returns a static reference, which could be convenient if you need to know where the temporary directory is. But... it's inconsistent with temp_dir, so it's probably not all that useful.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Ok, I'm going to change it to return Result<(), PathBuf>, but I actually don't want the user to unwrap() this error, they need to handle it.

src/env.rs Outdated
/// Only the first call to this function will succeed, returning `Ok(path)`. All further calls will
/// fail with `Err(path)`. In both cases, `path` is the default temporary directory (on success, the
/// new one; on failure, the existing one).
pub fn override_temp_dir(path: &Path) -> Result<&'static Path, &'static Path> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest Result<(), TempDirAlreadyOverridden> as the return type.

In the success case there is not point in returning the value just passed in.
In the error case it is problematic that Path does not implement Display.

src/env.rs Outdated
/// Only the first call to this function will succeed, returning `Ok(path)`. All further calls will
/// fail with `Err(path)`. In both cases, `path` is the default temporary directory (on success, the
/// new one; on failure, the existing one).
pub fn override_temp_dir(path: &Path) -> Result<&'static Path, &'static Path> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs: Is there a requirement that the directory already exists (I think so) or will it be created (recursively) if non-existent?

@surban
Copy link
Contributor

surban commented Jul 29, 2024

Generally I am not sure if it makes sense to limit the override function to be only called once. Is there a technical reason why you want to prevent it? It was possible before to call set_env multiple times.

For example, a system utility running during boot (initrd) might need to change its temporary directory after mounting some file systems.

@Stebalien
Copy link
Owner Author

I can relax the constraints later if someone presents a strong use-case, but tightening them isn't possible so I'm starting with the strongest constraints.

My reason is that override_temp_dir exists only to handle the case where the OS doesn't set an appropriate temporary directory. It's a last-resort escape hatch. I don't want is multiple libraries calling override_temp_dir, then getting confused when their setting gets clobbered by some other library.

In general, applications needing to put specific files in specific directories should use tempfile_in and friends.

For example, a system utility running during boot (initrd) might need to change its temporary directory after mounting some file systems.

Init systems re-exec themselves for this reason. Changing the tempdir at runtime likely isn't going to have the desired result (old temporary files will still live in the old location).

@Stebalien Stebalien merged commit ce8b147 into master Jul 29, 2024
13 checks passed
@Stebalien Stebalien deleted the steb/override-temp-dir branch July 29, 2024 15:56
@Stebalien
Copy link
Owner Author

Merging this for now. I'll release at the end of the week so we can continue our discussion until then (and possibly iterate on the design).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Set temp directory (override TMPDIR environment)
2 participants