use miette::{Context, IntoDiagnostic};
use std::path::{Path, PathBuf};
pub(super) struct Snapshot {
manifest_bytes: Vec<u8>,
lockfile_bytes: Option<Vec<u8>>,
}
pub(super) fn lockfile_path_for_project(project_dir: &Path) -> PathBuf {
use aube_lockfile::LockfileKind;
let kind =
aube_lockfile::detect_existing_lockfile_kind(project_dir).unwrap_or(LockfileKind::Aube);
let filename = match kind {
LockfileKind::Aube => aube_lockfile::aube_lock_filename(project_dir),
LockfileKind::Pnpm => aube_lockfile::pnpm_lock_filename(project_dir),
other => other.filename().to_string(),
};
project_dir.join(filename)
}
pub(super) fn snapshot_manifest_and_lockfile(
manifest_path: &Path,
lockfile_path: &Path,
) -> miette::Result<Snapshot> {
let manifest_bytes = std::fs::read(manifest_path)
.into_diagnostic()
.wrap_err("failed to snapshot package.json for --no-save")?;
let lockfile_bytes = snapshot_lockfile(lockfile_path)?;
Ok(Snapshot {
manifest_bytes,
lockfile_bytes,
})
}
pub(super) fn snapshot_lockfile(lockfile_path: &Path) -> miette::Result<Option<Vec<u8>>> {
match std::fs::read(lockfile_path) {
Ok(bytes) => Ok(Some(bytes)),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(e) => Err(e)
.into_diagnostic()
.wrap_err("failed to snapshot lockfile"),
}
}
pub(super) fn restore_manifest_and_lockfile(
snapshot: Snapshot,
manifest_path: &Path,
lockfile_path: &Path,
) -> Vec<miette::Report> {
let mut errors = Vec::new();
if let Err(e) = aube_util::fs_atomic::atomic_write(manifest_path, &snapshot.manifest_bytes) {
errors.push(
Result::<(), _>::Err(e)
.into_diagnostic()
.wrap_err("failed to restore original package.json after --no-save")
.unwrap_err(),
);
}
if let Err(e) = restore_lockfile(lockfile_path, &snapshot.lockfile_bytes) {
errors.push(e);
}
errors
}
pub(super) fn restore_lockfile(
lockfile_path: &Path,
snapshot: &Option<Vec<u8>>,
) -> Result<(), miette::Report> {
let result = match snapshot {
Some(bytes) => aube_util::fs_atomic::atomic_write(lockfile_path, bytes),
None => match std::fs::remove_file(lockfile_path) {
Ok(()) => Ok(()),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(e),
},
};
result
.into_diagnostic()
.wrap_err("failed to restore original lockfile")
}