cargo_compatible/
temp_workspace.rs1use anyhow::{Context, Result};
2use std::fs;
3use std::path::{Path, PathBuf};
4use tempfile::TempDir;
5use walkdir::{DirEntry, WalkDir};
6
7pub struct TempWorkspace {
8 _tempdir: TempDir,
9 root: PathBuf,
10}
11
12impl TempWorkspace {
13 pub fn copy_from(workspace_root: &Path) -> Result<Self> {
14 let tempdir = tempfile::tempdir().context("failed to create temp directory")?;
15 let destination_root = tempdir.path().join("workspace");
16 fs::create_dir_all(&destination_root)?;
17 for entry in WalkDir::new(workspace_root)
18 .into_iter()
19 .filter_entry(should_copy)
20 {
21 let entry = entry?;
22 let source = entry.path();
23 let relative = source.strip_prefix(workspace_root)?;
24 if relative.as_os_str().is_empty() {
25 continue;
26 }
27 let destination = destination_root.join(relative);
28 if entry.file_type().is_dir() {
29 fs::create_dir_all(&destination)?;
30 } else {
31 if let Some(parent) = destination.parent() {
32 fs::create_dir_all(parent)?;
33 }
34 fs::copy(source, &destination).with_context(|| {
35 format!(
36 "failed to copy `{}` to `{}`",
37 source.display(),
38 destination.display()
39 )
40 })?;
41 }
42 }
43
44 Ok(Self {
45 _tempdir: tempdir,
46 root: destination_root,
47 })
48 }
49
50 pub fn root(&self) -> &Path {
51 &self.root
52 }
53}
54
55fn should_copy(entry: &DirEntry) -> bool {
56 let name = entry.file_name().to_string_lossy();
57 name != ".git" && name != "target" && name != ".cargo-compatible"
58}