From 42a7c8bce4d8aabb510f9725c1bd37082ef87382 Mon Sep 17 00:00:00 2001 From: Caleb Owens Date: Fri, 24 May 2024 12:09:15 +0200 Subject: [PATCH] Update Oplog State to better use SystemTime --- crates/gitbutler-core/src/ops/oplog.rs | 14 ++++---- crates/gitbutler-core/src/ops/state.rs | 48 +++++++++++++++++++------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/crates/gitbutler-core/src/ops/oplog.rs b/crates/gitbutler-core/src/ops/oplog.rs index 73014209c..42afcf6c4 100644 --- a/crates/gitbutler-core/src/ops/oplog.rs +++ b/crates/gitbutler-core/src/ops/oplog.rs @@ -1,8 +1,9 @@ -use anyhow::{anyhow, Context}; +use anyhow::anyhow; use git2::{FileMode, Oid}; use itertools::Itertools; use std::collections::HashMap; use std::str::FromStr; +use std::time::Duration; use std::{fs, path::PathBuf}; use anyhow::Result; @@ -573,17 +574,14 @@ impl Oplog for Project { fn should_auto_snapshot(&self) -> Result { let oplog_state = OplogHandle::new(&self.gb_dir()); - let last_snapshot_time = oplog_state.get_modified_at().unwrap_or_default(); - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .context("failed to get time since epoch")?; - if now - last_snapshot_time < Duration::from_secs(300) { - return Ok(false); - } else { + let last_snapshot_time = oplog_state.get_modified_at()?; + if last_snapshot_time.elapsed()? > Duration::from_secs(300) { let changed_lines = lines_since_snapshot(self)?; if changed_lines > self.snapshot_lines_threshold() { return Ok(true); } + } else { + return Ok(false); } Ok(false) } diff --git a/crates/gitbutler-core/src/ops/state.rs b/crates/gitbutler-core/src/ops/state.rs index f1775d71c..1f8c16caf 100644 --- a/crates/gitbutler-core/src/ops/state.rs +++ b/crates/gitbutler-core/src/ops/state.rs @@ -1,23 +1,48 @@ -use anyhow::{Context, Result}; +use anyhow::Result; use std::{ fs::File, io::Read, path::{Path, PathBuf}, - time::Duration, + time::SystemTime, }; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; use super::OPLOG_FILE_NAME; +/// SystemTime used to be serialized as a u64 of seconds, but is now a propper SystemTime struct. +/// This function will handle the old format gracefully. +fn unfailing_system_time_deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + Ok(SystemTime::deserialize(deserializer).unwrap_or(SystemTime::UNIX_EPOCH)) +} + +fn unix_epoch() -> SystemTime { + SystemTime::UNIX_EPOCH +} + /// This tracks the head of the oplog, persisted in operations-log.toml. -#[derive(Serialize, Deserialize, Debug, Default)] +#[derive(Serialize, Deserialize, Debug)] pub struct Oplog { /// This is the sha of the last oplog commit pub head_sha: Option, /// The time when the last snapshot was created. Seconds since Epoch - #[serde(default)] - pub modified_at: u64, + #[serde( + deserialize_with = "unfailing_system_time_deserialize", + default = "unix_epoch" + )] + pub modified_at: SystemTime, +} + +impl Default for Oplog { + fn default() -> Self { + Self { + head_sha: None, + modified_at: SystemTime::UNIX_EPOCH, + } + } } pub struct OplogHandle { @@ -53,9 +78,9 @@ impl OplogHandle { /// Gets the time when the last snapshot was created. /// /// Errors if the file cannot be read or written. - pub fn get_modified_at(&self) -> anyhow::Result { + pub fn get_modified_at(&self) -> anyhow::Result { let oplog = self.read_file()?; - Ok(Duration::from_secs(oplog.modified_at)) + Ok(oplog.modified_at) } /// Reads and parses the state file. @@ -73,15 +98,14 @@ impl OplogHandle { path: self.file_path.clone(), source: e, })?; + Ok(oplog) } fn write_file(&self, oplog: Oplog) -> anyhow::Result<()> { let mut oplog = oplog; - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .context("failed to get time since epoch")?; - oplog.modified_at = now.as_secs(); + let now = std::time::SystemTime::now(); + oplog.modified_at = now; write(self.file_path.as_path(), &oplog) } }