diff --git a/Cargo.lock b/Cargo.lock index 5df071c..e56e97a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,7 +399,7 @@ dependencies = [ [[package]] name = "timetracking" -version = "1.5.20-alpha.0" +version = "1.5.20" dependencies = [ "anyhow", "bincode", diff --git a/Cargo.toml b/Cargo.toml index 59a0787..ebe0ea8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "timetracking" description = "Simple time tracker with simple data format" -version = "1.5.20-alpha.0" +version = "1.5.20" authors = ["hardliner66 "] edition = "2018" license-file = "LICENSE" diff --git a/src/main.rs b/src/main.rs index 113ab25..079f522 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use anyhow::{Context, Result}; use chrono::{prelude::*, serde::ts_seconds, Duration, NaiveDate, NaiveDateTime, NaiveTime}; use iif::iif; use serde::{Deserialize, Serialize}; -use std::io; +use std::{fs::File, io::{self, Write}}; use std::path::{Path, PathBuf}; use structopt::StructOpt; @@ -238,25 +238,41 @@ fn read_json_data>(path: P) -> Result> { Ok(serde_json::from_str(&data)?) } +fn write_with_flush, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { + let mut f = File::create(path)?; + f.write_all(contents.as_ref())?; + f.flush()?; + Ok(()) +} + #[cfg(feature = "binary")] -fn write_data>(path: P, data: &[TrackingEvent]) { +fn write_data>(path: P, data: &[TrackingEvent]) -> Result<()> { + let data = bincode::serialize(data).expect("could not serialize data"); - std::fs::write(path, data).expect("could not write data file"); + + let temp_path = path.as_ref().with_extension("bin.bak"); + + match write_with_flush(&temp_path, &data) { + Ok(_) => { + Ok(std::fs::rename(temp_path, path.as_ref())?) + } + Err(e) => Err(e.into()), + } } -fn write_json_data>(path: P, data: &[TrackingEvent], pretty: bool) { +fn write_json_data>(path: P, data: &[TrackingEvent], pretty: bool) -> Result<()> { let data = iif!( pretty, serde_json::to_string_pretty(data), serde_json::to_string(data) ) .expect("could not serialize data"); - std::fs::write(path, data).expect("could not write data file"); + Ok(write_with_flush(&path, &data)?) } #[cfg(not(feature = "binary"))] -fn write_data>(path: P, data: &[TrackingEvent]) { - write_json_data(path, data, false); +fn write_data>(path: P, data: &[TrackingEvent]) -> Result<()> { + write_json_data(path, data, false) } fn start_tracking( @@ -877,7 +893,7 @@ fn main() -> Result<()> { if readable { export_human_readable(expanded_path, &data); } else { - write_json_data(expanded_path, &data, pretty); + write_json_data(expanded_path, &data, pretty).expect("Could not write file"); } false } @@ -893,7 +909,7 @@ fn main() -> Result<()> { if data_changed { data.sort_by_key(|e| e.time(true)); data.dedup(); - write_data(expanded_path, &data); + write_data(expanded_path, &data).expect("Could not write file!"); } Ok(())