Skip to main content

cargo_compatible/
temp_workspace.rs

1use 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}