1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use std::env;
use std::path::{Path, PathBuf};

/// RIIA directory change object.
///
/// Creating an instance of this object represents storing the current
/// directory and then switching to the requested directory.  Dropping it
/// causes the directory to be switched back to the original directory.
///
/// # Notes
/// There's no ergonomic way to return errors from `Drop` handlers.  If it is
/// unable switch back to the original directory, this will be lost to the
/// application, although an error will be printed on stderr.
pub struct DirSwitch {
  old: PathBuf
}

impl DirSwitch {
  /// Switch the current directory, and prepare for returning to the original.
  pub fn switch<P: AsRef<Path>>(newdir: P) -> Result<Self, std::io::Error> {
    let old = env::current_dir()?;
    env::set_current_dir(newdir.as_ref())?;
    Ok(Self { old })
  }
}

impl Drop for DirSwitch {
  /// Return to the original directory.
  fn drop(&mut self) {
    if let Err(e) = env::set_current_dir(&self.old) {
      eprintln!("Unable to return to {}; {}", self.old.display(), e);
    }
  }
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :