From aaff762ce2dc42e799176fff5d6effb8063fcb67 Mon Sep 17 00:00:00 2001 From: FrostBird347 <39435218+FrostBird347@users.noreply.github.com> Date: Wed, 27 May 2026 14:58:27 +0800 Subject: [PATCH 1/2] Keep local hardlinks Fixes issue #542 --- src/Utility/RsyncTask.vala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Utility/RsyncTask.vala b/src/Utility/RsyncTask.vala index 0019dda6..9fa730f5 100644 --- a/src/Utility/RsyncTask.vala +++ b/src/Utility/RsyncTask.vala @@ -216,6 +216,8 @@ public class RsyncTask : AsyncTask{ cmd += " --sparse"; + cmd += " --hard-links"; + //if (relative){ // cmd += " --relative"; //} From eec4b2c29036f5cd45ac82347998d5052a92ecd9 Mon Sep 17 00:00:00 2001 From: FrostBird347 <39435218+FrostBird347@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:53:17 +0800 Subject: [PATCH 2/2] Add additional rsync options --- files/timeshift.json | 2 ++ src/Core/Main.vala | 15 ++++++++++++++- src/Gtk/MiscBox.vala | 33 +++++++++++++++++++++++++++++++++ src/Utility/RsyncTask.vala | 11 +++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/files/timeshift.json b/files/timeshift.json index 4d5a6910..7da23b3f 100644 --- a/files/timeshift.json +++ b/files/timeshift.json @@ -17,6 +17,8 @@ "count_boot" : "5", "snapshot_size" : "0", "snapshot_count" : "0", + "rsync_no_inc" : "false", + "rsync_checksum" : "false", "exclude" : [ ], "exclude-apps" : [ diff --git a/src/Core/Main.vala b/src/Core/Main.vala index 52c4650e..fdb1dbe0 100644 --- a/src/Core/Main.vala +++ b/src/Core/Main.vala @@ -134,6 +134,8 @@ public class Main : GLib.Object{ public string date_format = "%Y-%m-%d %H:%M:%S"; public const string date_format_default = "%Y-%m-%d %H:%M:%S"; + public bool rsync_no_inc = false; + public bool rsync_checksum = false; public Gee.ArrayList delete_list; @@ -1665,6 +1667,9 @@ public class Main : GLib.Object{ task.rsync_log_file = log_file; task.prg_count_total = Main.first_snapshot_count; + task.no_inc = rsync_no_inc; + task.checksum = rsync_checksum; + task.relative = true; task.verbose = true; task.delete_extra = true; @@ -2568,7 +2573,11 @@ public class Main : GLib.Object{ if (dry_run){ sh += " --dry-run"; } - + + if (rsync_checksum) { + sh += " --checksum"; + } + sh += " --log-file=\"%s\"".printf(restore_log_file); sh += " --exclude-from=\"%s\"".printf(restore_exclude_file); @@ -3394,6 +3403,8 @@ public class Main : GLib.Object{ } config.set_string_member("date_format", date_format); + config.set_string_member("rsync_no_inc", rsync_no_inc.to_string()); + config.set_string_member("rsync_checksum", rsync_checksum.to_string()); Json.Array arr = new Json.Array(); foreach(string path in exclude_list_user){ @@ -3506,6 +3517,8 @@ public class Main : GLib.Object{ this.count_boot = json_get_int(config,"count_boot",count_boot); this.date_format = json_get_string(config, "date_format", date_format_default); + rsync_no_inc = json_get_bool(config, "rsync_no_inc", rsync_no_inc); + rsync_checksum = json_get_bool(config, "rsync_checksum", rsync_checksum); Main.first_snapshot_size = json_get_uint64(config,"snapshot_size", Main.first_snapshot_size); diff --git a/src/Gtk/MiscBox.vala b/src/Gtk/MiscBox.vala index b652324b..9dce8c0c 100644 --- a/src/Gtk/MiscBox.vala +++ b/src/Gtk/MiscBox.vala @@ -54,11 +54,44 @@ class MiscBox : Gtk.Box{ // ------------------------ init_date_format_option(vbox); + + init_rsync_options(vbox); refresh(); log_debug("MiscBox: MiscBox(): exit"); } + + private void init_rsync_options(Gtk.Box box){ + + log_debug("MiscBox: init_rsync_options()"); + + Gtk.Label label_rsync = add_label_header(box, _("Rsync Options"), false); + label_rsync.margin_top = 12; + label_rsync.margin_bottom = 6; + + //no_inc_recursive + + Gtk.CheckButton chk_rsync_no_inc = add_checkbox(this, _("Disable incremental recursion in rsync snapshots")); + chk_rsync_no_inc.set_tooltip_text(_("Ensures newly hardlinked files will always be linked with the previous snapshot correctly, at the cost of backups taking significantly longer to start and rsync using significantly more memory. Note that if this option is unchecked, the worst case scenario would only result in a few files being incorrectly marked as new.")); + + chk_rsync_no_inc.active = App.rsync_no_inc; + chk_rsync_no_inc.toggled.connect(()=>{ + App.rsync_no_inc = chk_rsync_no_inc.active; + }); + + //checksum + + Gtk.CheckButton chk_rsync_checksum = add_checkbox(this, _("Compare file checksums in rsync snapshots")); + chk_rsync_checksum.set_tooltip_text(_("Compare the contents of all files when creating or restoring snapshots. This can be helpful when you suspect file corruption has occured, but it comes at a massive cost of speed and thus should not be left enabled.")); + + chk_rsync_checksum.active = App.rsync_checksum; + chk_rsync_checksum.toggled.connect(()=>{ + App.rsync_checksum = chk_rsync_checksum.active; + }); + + log_debug("MiscBox: init_rsync_options(): exit"); + } private void init_date_format_option(Gtk.Box box){ diff --git a/src/Utility/RsyncTask.vala b/src/Utility/RsyncTask.vala index 9fa730f5..0d9e4158 100644 --- a/src/Utility/RsyncTask.vala +++ b/src/Utility/RsyncTask.vala @@ -51,6 +51,9 @@ public class RsyncTask : AsyncTask{ public bool delete_excluded = false; public bool relative = false; + public bool no_inc = false; + public bool checksum = false; + public string rsync_log_file = ""; public string exclude_from_file = ""; public string link_from_path = ""; @@ -218,6 +221,14 @@ public class RsyncTask : AsyncTask{ cmd += " --hard-links"; + if (no_inc) { + cmd += " --no-inc-recursive"; + } + + if (checksum) { + cmd += " --checksum"; + } + //if (relative){ // cmd += " --relative"; //}