diff --git a/Cargo.lock b/Cargo.lock index b1fc10d8397..07f9e2a4e63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -390,7 +390,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -740,7 +740,7 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ "glib-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -1936,7 +1936,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -1953,7 +1953,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -1967,7 +1967,7 @@ dependencies = [ "gobject-sys", "libc", "pkg-config", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -1979,7 +1979,7 @@ dependencies = [ "gdk-sys", "glib-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", "x11", ] @@ -2071,7 +2071,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", "winapi", ] @@ -3224,7 +3224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -3254,7 +3254,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -3306,7 +3306,7 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -4814,7 +4814,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -6638,15 +6638,15 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.2.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ "cfg-expr 0.15.8", - "heck 0.5.0", + "heck 0.4.1", "pkg-config", "toml 0.8.14", - "version-compare 0.2.0", + "version-compare 0.1.1", ] [[package]] @@ -7556,9 +7556,9 @@ checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" [[package]] name = "version-compare" -version = "0.2.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" [[package]] name = "version_check" @@ -7765,7 +7765,7 @@ dependencies = [ "pango-sys", "pkg-config", "soup2-sys", - "system-deps 6.2.2", + "system-deps 6.2.0", ] [[package]] @@ -7970,9 +7970,9 @@ checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" [[package]] name = "windows-result" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" dependencies = [ "windows-targets 0.52.5", ] @@ -8073,9 +8073,9 @@ checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" [[package]] name = "windows-version" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6998aa457c9ba8ff2fb9f13e9d2a930dabcea28f1d0ab94d687d8b3654844515" +checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" dependencies = [ "windows-targets 0.52.5", ] @@ -8391,12 +8391,12 @@ dependencies = [ [[package]] name = "xdg-home" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" dependencies = [ "libc", - "windows-sys 0.52.0", + "winapi", ] [[package]] diff --git a/crates/gitbutler-tauri/src/logs.rs b/crates/gitbutler-tauri/src/logs.rs index 0e47bf2ab4e..25e81a52962 100644 --- a/crates/gitbutler-tauri/src/logs.rs +++ b/crates/gitbutler-tauri/src/logs.rs @@ -1,7 +1,7 @@ +use std::path::Path; use std::{fs, net::Ipv4Addr, time::Duration}; - use tauri::{AppHandle, Manager}; -use tracing::{metadata::LevelFilter, subscriber::set_global_default}; +use tracing::{instrument, metadata::LevelFilter, subscriber::set_global_default}; use tracing_appender::rolling::{RollingFileAppender, Rotation}; use tracing_subscriber::{fmt::format::FmtSpan, layer::SubscriberExt, Layer}; @@ -12,13 +12,22 @@ pub fn init(app_handle: &AppHandle) { .expect("failed to get logs dir"); fs::create_dir_all(&logs_dir).expect("failed to create logs dir"); + let log_prefix = "GitButler"; + let log_suffix = "log"; + let max_log_files = 14; + remove_old_logs(&logs_dir).ok(); let file_appender = RollingFileAppender::builder() .rotation(Rotation::DAILY) - .max_log_files(14) - .filename_prefix("GitButler.log") + .max_log_files(max_log_files) + .filename_prefix(log_prefix) + .filename_suffix(log_suffix) .build(&logs_dir) .expect("initializing rolling file appender failed"); let (file_writer, guard) = tracing_appender::non_blocking(file_appender); + // As the file-writer only checks `max_log_files` on file rotation, it bascially never happens. + // Run it now. + prune_old_logs(&logs_dir, Some(log_prefix), Some(log_suffix), max_log_files).ok(); + app_handle.manage(guard); // keep the guard alive for the lifetime of the app let format_for_humans = tracing_subscriber::fmt::format() @@ -81,3 +90,96 @@ fn get_server_addr(app_handle: &AppHandle) -> (Ipv4Addr, u16) { }; (Ipv4Addr::LOCALHOST, port) } + +/// Originally based on https://github.com/tokio-rs/tracing/blob/44861cad7a821f08b3c13aba14bb8ddf562b7053/tracing-appender/src/rolling.rs#L571 +#[instrument(err(Debug))] +fn prune_old_logs( + log_directory: &Path, + log_filename_prefix: Option<&str>, + log_filename_suffix: Option<&str>, + max_files: usize, +) -> anyhow::Result<()> { + let mut files: Vec<_> = { + let dir = fs::read_dir(log_directory)?; + dir.filter_map(|entry| { + let entry = entry.ok()?; + let metadata = entry.metadata().ok()?; + + // the appender only creates files, not directories or symlinks, + // so we should never delete a dir or symlink. + if !metadata.is_file() { + return None; + } + + let filename = entry.file_name(); + let filename = filename.to_str()?; + if let Some(prefix) = log_filename_prefix { + if !filename.starts_with(prefix) { + return None; + } + } + + if let Some(suffix) = log_filename_suffix { + if !filename.ends_with(suffix) { + return None; + } + } + + let created = metadata.created().ok()?; + Some((entry, created)) + }) + .collect() + }; + + if files.len() < max_files { + return Ok(()); + } + + // sort the files by their creation timestamps. + files.sort_by_key(|(_, created_at)| *created_at); + + // delete files, so that (n-1) files remain, because we will create another log file + for (file, _) in files.iter().take(files.len() - (max_files - 1)) { + if let Err(err) = fs::remove_file(file.path()) { + tracing::warn!( + "Failed to remove extra log file {}: {}", + file.path().display(), + err, + ); + } + } + + Ok(()) +} + +#[instrument(err(Debug))] +fn remove_old_logs(log_directory: &Path) -> anyhow::Result<()> { + let dir = fs::read_dir(log_directory)?; + let old_log_files = dir.filter_map(|entry| { + let entry = entry.ok()?; + let metadata = entry.metadata().ok()?; + + if !metadata.is_file() { + return None; + } + + let filename = entry.file_name(); + let filename = filename.to_str()?; + if !filename.starts_with("GitButler.log") { + return None; + } + + Some(entry.path()) + }); + for file_path in old_log_files { + if let Err(err) = fs::remove_file(&file_path) { + tracing::warn!( + "Failed to remove old log file {}: {}", + file_path.display(), + err, + ); + } + } + + Ok(()) +}