Backups Rework (#698)

* wip: Backup al

* wip: Backup

* backup code complete

* wip

* wip

* update types

* wip

* fix errors

* Backups wizard (#699)

* backup adjustments

* fix endpoint arg

* Update prod-key-modal.page.ts

Co-authored-by: Drew Ansbacher <drew.ansbacher@spiredigital.com>
Co-authored-by: Aiden McClelland <me@drbonez.dev>

* build errs addressed

* working

* update backup command input, nix, and apk add

* add ecryptfs-utils

* fix build

* wip

* fixes for macos

* more mac magic

* fix typo

* working

* fixes after rebase

* chore: remove unused imports

Co-authored-by: Justin Miller <dragondef@gmail.com>
Co-authored-by: Drew Ansbacher <drew.ansbacher@gmail.com>
Co-authored-by: Drew Ansbacher <drew.ansbacher@spiredigital.com>
Co-authored-by: Lucy Cifferello <12953208+elvece@users.noreply.github.com>
This commit is contained in:
Aiden McClelland
2021-10-23 22:00:23 -06:00
parent 78dcce7be5
commit 8056285a7f
52 changed files with 2032 additions and 873 deletions

View File

@@ -1,74 +1,63 @@
use std::path::Path;
use std::{path::Path, process::Stdio};
pub fn create_backup<P: AsRef<Path>>(
mountpoint: P,
data_path: P,
app_id: &str,
pub fn create_backup(
mountpoint: impl AsRef<Path>,
data_path: impl AsRef<Path>,
) -> Result<(), anyhow::Error> {
let path = std::fs::canonicalize(mountpoint)?;
let volume_path = Path::new(embassy::VOLUMES).join(app_id);
let mountpoint = std::fs::canonicalize(mountpoint)?;
let data_path = std::fs::canonicalize(data_path)?;
let exclude = if volume_path.is_dir() {
let ignore_path = volume_path.join(".backupignore");
if ignore_path.is_file() {
std::fs::read(ignore_path)?
} else {
Vec::new()
}
let ignore_path = data_path.join(".backupignore");
let exclude = if ignore_path.is_file() {
std::fs::read_to_string(ignore_path)?
} else {
return Err(anyhow::anyhow!("Volume For {} Does Not Exist", app_id))
String::new()
};
let mut data_cmd = std::process::Command::new("duplicity");
for exclude in exclude {
for exclude in exclude.lines().map(|s| s.trim()).filter(|s| !s.is_empty()) {
if exclude.to_string().starts_with('!') {
data_cmd.arg(format!(
"--include={}",
volume_path.join(exclude.to_string().trim_start_matches('!')).display()
data_path
.join(exclude.to_string().trim_start_matches('!'))
.display()
));
} else {
data_cmd.arg(format!("--exclude={}", volume_path.join(exclude.to_string()).display()));
data_cmd.arg(format!(
"--exclude={}",
data_path.join(exclude.to_string()).display()
));
}
}
let data_res = data_cmd
.arg(volume_path)
.arg(format!("file://{}", data_path.as_ref().display().to_string()))
.arg(data_path)
.arg(format!("file://{}", mountpoint.display().to_string()))
.output();
data_res?;
Ok(())
}
pub fn restore_backup<P: AsRef<Path>>(
path: P,
data_path: P,
app_id: &str,
pub fn restore_backup(
mountpoint: impl AsRef<Path>,
data_path: impl AsRef<Path>,
) -> Result<(), anyhow::Error> {
let path = std::fs::canonicalize(path)?;
if !path.is_dir() {
anyhow::anyhow!("Backup Path Must Be Directory");
}
let metadata_path = path.join("metadata.yaml");
let volume_path = Path::new(embassy::VOLUMES).join(app_id);
let mountpoint = std::fs::canonicalize(mountpoint)?;
let data_path = std::fs::canonicalize(data_path)?;
let mut data_cmd = std::process::Command::new("duplicity");
data_cmd
let data_output = std::process::Command::new("duplicity")
.arg("--force")
.arg(format!("file://{:#?}", data_path.as_ref().display().to_string()))
.arg(&volume_path);
let data_output = data_cmd.status()?;
if !data_output.success() {
return Err(anyhow::anyhow!("duplicity error for {}", app_id))
.arg(format!("file://{}", mountpoint.display().to_string()))
.arg(&data_path)
.stderr(Stdio::piped())
.output()?;
if !data_output.status.success() {
return Err(anyhow::anyhow!(
"duplicity error: {}",
String::from_utf8(data_output.stderr).unwrap()
));
}
std::fs::copy(
metadata_path,
Path::new(embassy::VOLUMES)
.join(app_id)
.join("start9")
.join("restore.yaml"),
)?;
Ok(())
}
}