rpk 0.2.2

A lightweight, cross-platform cli package manager.
use std::{
    ffi::OsString,
    fs::{self, File},
    io,
    path::{Path, PathBuf},
};

use anyhow::Context as _;

use super::rm_rf;

pub struct TempFile {
    temp_file: File,
    temp_path: PathBuf,
    orig_path: PathBuf,
}

impl TempFile {
    pub fn new_force(orig_path: impl AsRef<Path>) -> anyhow::Result<Self> {
        let orig_path = orig_path.as_ref().to_owned();
        let dir = orig_path.parent().context("no parent directory")?;
        let orig_name = orig_path.file_name().context("no filename")?;
        let mut temp_name = OsString::from("~");
        temp_name.push(orig_name);

        let temp_path = dir.join(&temp_name);
        rm_rf(&temp_path)?;

        let temp_file = File::create(&temp_path)
            .with_context(|| format!("failed to create temporary file: {:?}", temp_path))?;
        Ok(Self { temp_file, temp_path, orig_path })
    }

    pub fn persist(self) -> io::Result<()> {
        rm_rf(&self.orig_path)?;
        fs::rename(&self.temp_path, &self.orig_path)
    }

    pub fn path(&self) -> &Path {
        &self.temp_path
    }

    pub fn file(&mut self) -> &mut File {
        &mut self.temp_file
    }
}

impl Drop for TempFile {
    fn drop(&mut self) {
        rm_rf(&self.temp_path).expect("failed to delete temporary path");
    }
}