use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
use tempfile::{Builder, TempDir};
pub fn tmp_dir() -> std::io::Result<TempDir> {
Builder::new().prefix("cargo-generate").tempdir()
}
#[cfg_attr(not(feature = "git"), allow(dead_code))]
pub fn canonicalize_path(p: impl AsRef<Path>) -> Result<PathBuf> {
let p = p.as_ref();
let p = if p.starts_with("~/") {
home()?.join(p.strip_prefix("~/")?)
} else if p.starts_with("$HOME/") {
home()?.join(p.strip_prefix("$HOME/")?)
} else {
p.to_path_buf()
};
p.canonicalize()
.with_context(|| format!("path does not exist: {}", p.display()))
}
#[cfg_attr(not(feature = "git"), allow(dead_code))]
pub fn home() -> Result<PathBuf> {
home::home_dir().context("$HOME was not set")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tmp_dir_creates_and_drops_a_directory() {
let path = {
let dir = tmp_dir().unwrap();
assert!(dir.path().exists());
assert!(dir.path().is_dir());
assert!(dir
.path()
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("")
.starts_with("cargo-generate"));
dir.path().to_owned()
};
assert!(!path.exists(), "tempdir should clean up on drop");
}
#[test]
fn should_canonicalize() {
#[cfg(target_os = "macos")]
{
assert!(canonicalize_path(PathBuf::from("../"))
.unwrap()
.starts_with("/Users/"));
assert!(canonicalize_path(PathBuf::from("$HOME/"))
.unwrap()
.starts_with("/Users/"));
}
#[cfg(target_os = "linux")]
assert_eq!(
canonicalize_path(PathBuf::from("../")).ok(),
std::env::current_dir()
.unwrap()
.parent()
.map(std::path::Path::to_path_buf)
);
#[cfg(windows)]
assert!(canonicalize_path(PathBuf::from("../"))
.unwrap()
.to_str()
.unwrap()
.starts_with("\\\\?\\"));
}
}