oxide_cli/addons/steps/
copy.rs1use std::path::Path;
2
3use anyhow::{Context, Result};
4use inquire::Confirm;
5
6use crate::addons::manifest::{CopyStep, IfExists};
7
8use super::Rollback;
9
10pub fn execute_copy(
11 step: &CopyStep,
12 addon_dir: &Path,
13 project_root: &Path,
14) -> Result<Vec<Rollback>> {
15 let src = super::safe_join(addon_dir, &step.src, "addon source")?;
16 let dest = super::safe_join(project_root, &step.dest, "copy destination")?;
17
18 let mut rollbacks = Vec::new();
19
20 if dest.exists() {
21 match step.if_exists {
22 IfExists::Skip => return Ok(rollbacks),
23 IfExists::Ask => {
24 let overwrite = Confirm::new(&format!("{} already exists. Overwrite?", step.dest))
25 .with_default(false)
26 .prompt()?;
27 if !overwrite {
28 return Ok(rollbacks);
29 }
30 rollbacks.push(Rollback::RestoreFile {
31 path: dest.clone(),
32 original: std::fs::read(&dest)?,
33 });
34 }
35 IfExists::Overwrite => {
36 rollbacks.push(Rollback::RestoreFile {
37 path: dest.clone(),
38 original: std::fs::read(&dest)?,
39 });
40 }
41 }
42 } else {
43 rollbacks.push(Rollback::DeleteCreatedFile { path: dest.clone() });
44 }
45
46 if let Some(parent) = dest.parent() {
47 std::fs::create_dir_all(parent)?;
48 }
49 std::fs::copy(&src, &dest)
50 .with_context(|| format!("Failed to copy {} to {}", src.display(), dest.display()))?;
51
52 Ok(rollbacks)
53}