winbrew_engines\portable/
install.rs

1use anyhow::{Context, Result};
2use std::fs;
3use std::path::{Path, PathBuf};
4
5use crate::core::fs::{cleanup_path, replace_directory};
6
7use crate::models::install::engine::EngineInstallReceipt;
8use crate::models::install::engine::EngineKind;
9
10pub(crate) fn install(
11    download_path: &Path,
12    install_dir: &Path,
13    _package_name: &str,
14) -> Result<EngineInstallReceipt> {
15    let stage_dir = staging_dir_for(install_dir);
16
17    cleanup_path(&stage_dir)?;
18    fs::create_dir_all(&stage_dir)?;
19
20    let file_name = download_path
21        .file_name()
22        .context("download path has no file name")?;
23    let target_path = stage_dir.join(file_name);
24
25    match fs::rename(download_path, &target_path) {
26        Ok(()) => {}
27        Err(_) => {
28            fs::copy(download_path, &target_path).with_context(|| {
29                format!("failed to copy installer to {}", target_path.display())
30            })?;
31        }
32    }
33
34    replace_directory(&stage_dir, install_dir)?;
35
36    Ok(EngineInstallReceipt::new(
37        EngineKind::Portable,
38        install_dir.to_string_lossy().into_owned(),
39        None,
40    ))
41}
42
43fn staging_dir_for(install_dir: &Path) -> PathBuf {
44    install_dir.parent().unwrap_or(install_dir).join("staging")
45}
46
47#[cfg(test)]
48mod tests {
49    use super::install;
50    use std::fs;
51    use std::io::Read;
52    use tempfile::tempdir;
53
54    #[test]
55    fn install_copies_non_zip_installer_into_place() {
56        let temp_root = tempdir().expect("temp root");
57        let download_path = temp_root.path().join("tool.exe");
58        let install_dir = temp_root.path().join("packages").join("Contoso.Portable");
59
60        fs::write(&download_path, b"portable-binary").expect("write download");
61
62        install(&download_path, &install_dir, "Contoso.Portable").expect("portable install");
63
64        let installed_file = install_dir.join("tool.exe");
65        let mut contents = String::default();
66        fs::File::open(&installed_file)
67            .expect("installed file")
68            .read_to_string(&mut contents)
69            .expect("read installed file");
70
71        assert_eq!(contents, "portable-binary");
72    }
73}