Crate current_dir

Source
Expand description

§current_dir

Crates.io Version GitHub Actions Workflow Status docs.rs Code Coverage Minimum

A utility crate that helps using set_current_dir() and current_dir() in a thread safe manner.
This is generally useful for #[test]s that depend on different current working directories each as they are run in multiple threads by default.

§Why can’t I just use set_current_dir() and current_dir() directly?

The current working directory is global to the whole process, so if you only use a single thread or you never change the current working directory, go ahead!
Otherwise, changing the current working directory without synchronising may lead to unexpected behaviour.

§Cwd Example

      use std::env::temp_dir;
      use current_dir::*;

      let mut locked_cwd = Cwd::mutex().lock()?;
      locked_cwd.set(temp_dir())?;
      // cwd == /tmp

or you can just use set_current_dir() and current_dir() with a locked current working directory.

      use std::env::{set_current_dir, temp_dir};
      use current_dir::*;

      let locked_cwd = Cwd::mutex().lock()?;
      set_current_dir(temp_dir())?;
      // cwd == /tmp

§CwdGuard Example

      use std::{env::temp_dir, fs::create_dir_all};
      use current_dir::*;

      let mut locked_cwd = Cwd::mutex().lock()?;
      locked_cwd.set(temp_dir())?;
      // cwd == /tmp
      {
          let mut cwd_guard = CwdGuard::try_from(&mut *locked_cwd)?;
          cwd_guard.set("sub")?;
          // cwd == /tmp/sub
          {
              let mut sub_cwd_guard = CwdGuard::try_from(&mut cwd_guard)?;
              sub_cwd_guard.set("sub")?;
              // cwd == /tmp/sub/sub
              {
                  let mut sub_sub_cwd_guard = CwdGuard::try_from(&mut sub_cwd_guard)?;
                  sub_sub_cwd_guard.set(temp_dir())?;
                  // cwd == /tmp
              }
              // cwd == /tmp/sub/sub
          }
          // cwd == /tmp/sub
      }
      // cwd == /tmp

§Poison cleanup Example

      use std::{
          env::temp_dir,
          error::Error,
          fs::{create_dir_all, remove_dir},
          panic,
      };
      use current_dir::*;

      let test_dir = temp_dir().join("cwd");

      panic::catch_unwind(|| {
          let mut locked_cwd = Cwd::mutex().lock().unwrap();
          locked_cwd.set(&test_dir)?;

          // removing the CWD before the CwdGuard is dropped will cause a panic on drop.
          let cwd_guard = CwdGuard::try_from(&mut *locked_cwd)?;
          remove_dir(&test_dir)?;
          drop(cwd_guard);
      })
      .expect_err("panicked");

      let mut poisoned_locked_cwd = Cwd::mutex().lock().expect_err("cwd poisoned");
      let expected_cwd = poisoned_locked_cwd.get_ref().get_expected().unwrap();

      // Fix poisoned cwd
      create_dir_all(&expected_cwd)?;
      poisoned_locked_cwd.get_mut().set(&expected_cwd)?;
      Cwd::mutex().clear_poison();
      let locked_cwd = poisoned_locked_cwd.into_inner();

Structs§

Cwd
Wrapper type to help the usage of the current working directory for the process.
CwdGuard
A version of Cwd that will reset() the current working directory to it’s previous state on drop().