This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
use std::{
|
||||
env, fs,
|
||||
io::{BufRead, BufReader},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use duct::cmd;
|
||||
use tracing::{error, info, instrument};
|
||||
|
||||
use crate::{GNUTAR, Paths, ZENITY};
|
||||
|
||||
const MESSAGE: &str = "There have been upgrades to affinity-nix!
|
||||
|
||||
Affinity and it's dependencies are no longer installed directly, reducing startup time and manual updating.
|
||||
|
||||
To migrate, we need to delete the old installation. Your registry files and user data won't be touched.";
|
||||
|
||||
fn make_message(backup_location: &Path) -> String {
|
||||
format!(
|
||||
"{MESSAGE} A backup will be created in at {}. Is that OK?",
|
||||
backup_location.display()
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub fn migrate(paths: &Paths) -> anyhow::Result<()> {
|
||||
let Some(revision) = crate::check::read_revision(&paths.upper)? else {
|
||||
info!("revision does not exist, skipping backup");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if revision >= 9 {
|
||||
info!("revision more than or equal to 9, skipping backup");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let backup_path = Path::new(&env::var("HOME").context("finding $HOME var")?).join(format!(
|
||||
"affinity-nix-backup-{}.tar.zst",
|
||||
std::process::id()
|
||||
));
|
||||
|
||||
let question = cmd!(
|
||||
ZENITY,
|
||||
"--question",
|
||||
"--width",
|
||||
"480",
|
||||
format!("--text={}", make_message(&backup_path))
|
||||
)
|
||||
.unchecked()
|
||||
.run()?;
|
||||
|
||||
if !question.status.success() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"User refused to migrate, we cannot continue or there may be data loss."
|
||||
));
|
||||
}
|
||||
|
||||
let tar_handle = cmd!(GNUTAR, "--zstd", "-cvpf", backup_path, &paths.upper)
|
||||
.stdout_to_stderr()
|
||||
.stderr_capture()
|
||||
.reader()?;
|
||||
|
||||
let lines = BufReader::new(&tar_handle).lines();
|
||||
|
||||
for line in lines {
|
||||
let line = line?;
|
||||
info!("{line}");
|
||||
}
|
||||
|
||||
match tar_handle.try_wait()? {
|
||||
Some(output) => {
|
||||
if !output.status.success() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"backing up with tar failed: {:?}",
|
||||
output.status
|
||||
));
|
||||
}
|
||||
|
||||
info!(status = %output.status, "tar ended cleanly");
|
||||
}
|
||||
None => {
|
||||
error!("tar child is still running in some way.");
|
||||
}
|
||||
}
|
||||
|
||||
let drive_c = paths.upper.join("drive_c");
|
||||
|
||||
if !drive_c.is_dir() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for entry in drive_c.read_dir().context("reading drive_c")? {
|
||||
let entry = entry.context("reading drive_c entry")?;
|
||||
|
||||
if entry.file_name() == "users" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let path = entry.path();
|
||||
|
||||
info!(path = ?path, "removing entry");
|
||||
|
||||
if entry
|
||||
.file_type()
|
||||
.context("reading entry filetype")?
|
||||
.is_dir()
|
||||
{
|
||||
fs::remove_dir_all(&path)
|
||||
.with_context(|| format!("removing directory {}", path.display()))?;
|
||||
} else {
|
||||
fs::remove_file(&path).with_context(|| format!("removing file {}", path.display()))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user