From fb2c9c74a324f598d87b835892d4d0471a27561a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bardon?= Date: Sat, 25 May 2024 11:44:52 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=A9=B9=20Recover=20old=20files=20if=20new?= =?UTF-8?q?=20website=20doesn't=20generate=20properly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/helpers/src/generate.rs | 52 ++++++++++++++++++++++++++++---- src/orangutan-server/src/main.rs | 26 +++++++++++----- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/helpers/src/generate.rs b/src/helpers/src/generate.rs index 7b16d2b..873c7d4 100644 --- a/src/helpers/src/generate.rs +++ b/src/helpers/src/generate.rs @@ -24,6 +24,7 @@ static DATA_FILES_GENERATED: AtomicBool = AtomicBool::new(false); lazy_static! { // NOTE: `Arc` prevents race conditions static ref GENERATED_WEBSITES: Arc>> = Arc::new(Mutex::new(HashSet::new())); + static ref TMP_DIR: PathBuf = std::env::temp_dir().join("orangutan-save"); } pub fn generate_default_website() -> Result<(), Error> { @@ -341,9 +342,26 @@ fn empty_index_json(website_dir: &PathBuf) -> Result<(), io::Error> { Ok(()) } -pub fn remove_outdated_websites() -> Result<(), Error> { +pub struct State { + hugo_config_generated: bool, + data_files_generated: bool, + generated_websites: HashSet, + used_profiles: Option<&'static HashSet>, +} + +pub fn trash_outdated_websites() -> Result { + trace!("Trashing outdated websites…"); + // Remove outdated websites - fs::remove_dir_all(DEST_DIR.as_path()).map_err(Error::CannotDeleteOutdatedWebsites)?; + fs::rename(DEST_DIR.as_path(), TMP_DIR.as_path()).map_err(Error::IOError)?; + + // Save caches (in case we need to recover) + let state = State { + hugo_config_generated: HUGO_CONFIG_GENERATED.load(Ordering::Relaxed), + data_files_generated: DATA_FILES_GENERATED.load(Ordering::Relaxed), + generated_websites: GENERATED_WEBSITES.lock().unwrap().to_owned(), + used_profiles: super::USED_PROFILES.lock().unwrap().to_owned(), + }; // Clear caches HUGO_CONFIG_GENERATED.store(false, Ordering::Relaxed); @@ -351,6 +369,30 @@ pub fn remove_outdated_websites() -> Result<(), Error> { GENERATED_WEBSITES.lock().unwrap().clear(); *super::USED_PROFILES.lock().unwrap() = None; + Ok(state) +} + +pub fn recover_trash(state: State) -> Result<(), Error> { + trace!("Recovering trash…"); + + // Reload files + fs::rename(TMP_DIR.as_path(), DEST_DIR.as_path()).map_err(Error::IOError)?; + + // Relaod caches + HUGO_CONFIG_GENERATED.store(state.hugo_config_generated, Ordering::Relaxed); + DATA_FILES_GENERATED.store(state.data_files_generated, Ordering::Relaxed); + *GENERATED_WEBSITES.lock().unwrap() = state.generated_websites; + *super::USED_PROFILES.lock().unwrap() = state.used_profiles; + + Ok(()) +} + +/// NOTE: Needs a `State` to take ownership and make sure we don't keep outdated information. +pub fn empty_trash(_state: State) -> Result<(), Error> { + trace!("Emptying trash…"); + + fs::remove_dir_all(TMP_DIR.as_path()).map_err(Error::IOError)?; + Ok(()) } @@ -361,7 +403,7 @@ pub enum Error { CannotGenerateWebsite(Box), CannotEmptyIndexJson(io::Error), CannotCreateHugoConfigFile(io::Error), - CannotDeleteOutdatedWebsites(io::Error), + IOError(io::Error), } impl fmt::Display for Error { @@ -383,9 +425,7 @@ impl fmt::Display for Error { Error::CannotCreateHugoConfigFile(err) => { write!(f, "Could create hugo config file: {err}") }, - Error::CannotDeleteOutdatedWebsites(err) => { - write!(f, "Cannot delete outdated websites: {err}") - }, + Error::IOError(err) => write!(f, "IO error: {err}"), } } } diff --git a/src/orangutan-server/src/main.rs b/src/orangutan-server/src/main.rs index 12e1d01..549b8e6 100644 --- a/src/orangutan-server/src/main.rs +++ b/src/orangutan-server/src/main.rs @@ -295,12 +295,16 @@ fn update_content_github() -> Result<(), Error> { pull_repository().map_err(Error::CannotPullOutdatedRepository)?; // Remove outdated websites - remove_outdated_websites().map_err(Error::CannotDeleteOutdatedWebsites)?; + let state = trash_outdated_websites().map_err(Error::CannotTrashOutdatedWebsites)?; // Pre-generate default website as we will access it at some point anyway - generate_default_website().map_err(Error::WebsiteGenerationError)?; - - Ok(()) + match generate_default_website().map_err(Error::WebsiteGenerationError) { + Err(err) => { + error!("{err}"); + recover_trash(state).map_err(Error::CannotRecoverTrash) + }, + Ok(()) => empty_trash(state).map_err(Error::CannotEmptyTrash), + } } #[post("/update-content/")] @@ -546,7 +550,9 @@ fn add_padding(base64_string: &str) -> String { enum Error { WebsiteGenerationError(generate::Error), CannotPullOutdatedRepository(generate::Error), - CannotDeleteOutdatedWebsites(generate::Error), + CannotTrashOutdatedWebsites(generate::Error), + CannotRecoverTrash(generate::Error), + CannotEmptyTrash(generate::Error), } impl fmt::Display for Error { @@ -559,8 +565,14 @@ impl fmt::Display for Error { Error::CannotPullOutdatedRepository(err) => { write!(f, "Cannot pull outdated repository: {err}") }, - Error::CannotDeleteOutdatedWebsites(err) => { - write!(f, "Cannot delete outdated websites: {err}") + Error::CannotTrashOutdatedWebsites(err) => { + write!(f, "Cannot trash outdated websites: {err}") + }, + Error::CannotRecoverTrash(err) => { + write!(f, "Cannot recover trash: {err}") + }, + Error::CannotEmptyTrash(err) => { + write!(f, "Cannot empty trash: {err}") }, } }