Description: Default subvolume, blkid, btrfs-mode-switch, swapfile-detect
 .
 timeshift (23.07.1-1+mx23+2) mx; urgency=medium
 .
   [23.07.1-1+mx23+2]
   * Fix toggle switch between rsync and btrfs mode
   * Use check size of Gee.ArrayList
   * Use blkid for all partitions if lsblk fails to get uuid or fstype
   * Add /tmpdir/* to exclude list
   * Add /home/snapshot/* to exclude list
   * Add /swap/* to exclude list
   * Add swap files listed in fstab to exclude list
   [23.07.1-1+mx23+1]
   * Fix: Allows default btrfs subvolume to be different from the top subvolume.
   * Fix: Always mount the top btrfs subvolume.
   * Fix: Adjustment of the default subvolume after restore.
   * Fix: Use blkid if lsblk fails on luks devices with btrfs.
Author: fehlix <fehlix@mxlinux.org>

--- timeshift-23.07.1.orig/meson.build
+++ timeshift-23.07.1/meson.build
@@ -1,8 +1,15 @@
 project(
   'timeshift', 'vala', 'c',
-  version: '23.07.1',
+  version: configure_file(
+    command: [
+    'dpkg-parsechangelog', '-l',
+    meson.project_source_root() / 'debian/changelog',
+    '-SVersion'],
+    capture: true,
+    output: 'version',
+    ),
   license : 'GPL-2.0-or-later',
-  meson_version: '>= 0.54.0',
+  meson_version: '>= 1.0',
   default_options: ['c_std=c99', 'build.c_std=c99'])
 
 dependencies = [
--- timeshift-23.07.1.orig/src/Core/Main.vala
+++ timeshift-23.07.1/src/Core/Main.vala
@@ -554,6 +554,7 @@ public class Main : GLib.Object{
 		exclude_list_default.add("/media/*");
 		exclude_list_default.add("/mnt/*");
 		exclude_list_default.add("/tmp/*");
+		exclude_list_default.add("/tmpdir/*");
 		exclude_list_default.add("/run/*");
 		exclude_list_default.add("/var/run/*");
 		exclude_list_default.add("/var/lock/*");
@@ -573,10 +574,19 @@ public class Main : GLib.Object{
 		exclude_list_default.add("/var/log/timeshift/*");
 		exclude_list_default.add("/var/log/timeshift-btrfs/*");
 		exclude_list_default.add("/swapfile");
+		exclude_list_default.add("/swap/*");
 		exclude_list_default.add("/snap/*");
 
 		foreach(var entry in FsTabEntry.read_file("/etc/fstab")){
-
+			// detect swap files in fstab
+			if ( (entry.type == "swap") && (entry.device_string.has_prefix("/")) ){ 
+				if (entry.device_string.has_prefix("/dev/")){ continue; }
+				if (!file_exists(entry.device_string)){ continue; }
+				// exclude found swap file
+				exclude_list_default.add(entry.device_string);
+				continue;
+			}
+			
 			if (!entry.mount_point.has_prefix("/")){ continue; }
 
 			// ignore standard system folders
@@ -615,6 +625,7 @@ public class Main : GLib.Object{
 		exclude_list_default.add("/root/.gvfs");
 		exclude_list_default.add("/root/.local/share/[Tt]rash");
 
+		exclude_list_default.add("/home/snapshot/*");
 		exclude_list_default.add("/home/*/.thumbnails");
 		exclude_list_default.add("/home/*/.cache");
 		exclude_list_default.add("/home/*/.dbus");
@@ -4390,7 +4401,8 @@ public class Main : GLib.Object{
 				int retval3 = exec_sync(cmd3);
 				
 				if (retval3 != 0){
-					log_error("Failed to remove directory");
+					log_error(cmd3);
+					log_error("Failed to remove directory : '%s'".printf(escape_single_quote(mdir)));
 					log_msg("Ret=%d".printf(retval3));
 					//ignore
 				}
--- timeshift-23.07.1.orig/src/Core/Subvolume.vala
+++ timeshift-23.07.1/src/Core/Subvolume.vala
@@ -39,6 +39,7 @@ public class Subvolume : GLib.Object{
 	public int64 unshared_bytes = 0;
 
 	public string mount_path = "";
+	public string default_subvolid = "";
 
 	//parent
 	public SnapshotRepo? repo;
@@ -123,6 +124,8 @@ public class Subvolume : GLib.Object{
 	
 	public bool remove(){
 
+		string backup_mount_point =  App.mount_point_app + "/backup";
+
 		if (is_system_subvolume){
 			if (name == "@"){
 				path = path_combine(App.mount_point_app + "/backup", "@");
@@ -131,16 +134,38 @@ public class Subvolume : GLib.Object{
 				path = path_combine(App.mount_point_app + "/backup-home", "@home");
 			}
 		}
-		
 		string cmd = "";
 		string std_out, std_err, subpath;
 		int ret_val;
+		int status;
 
 		if (!dir_exists(path)){ return true; } // ok, item does not exist
 
-		log_msg("%s: %s (Id:%ld)".printf(_("Deleting subvolume"), name, id));
-
 		string options = App.use_option_raw ? "--commit-after" : "";
+
+		if (name == "@"){
+			// print_info();
+			cmd = "sh -c \"btrfs subvolume get-default %s | cut -d ' ' -f2\"".printf(backup_mount_point);
+			log_debug(cmd);
+			std_out = ""; std_err = ""; 
+			status = exec_sync(cmd, out std_out, out std_err);
+			default_subvolid = std_out.strip();
+			log_debug("Default subvolid : '%s'".printf(default_subvolid));
+			if (status != 0){
+				log_error(std_err);
+				log_error(_("btrfs returned an error") + ": %d".printf(status));
+				log_error(_("Failed to get default subvolume") + ": %s".printf(name));
+				return false;
+			}
+			if ((default_subvolid != "5") && ((default_subvolid == "%ld".printf(id)) || (id == -1 ))) {
+				cmd = "sh -c \"btrfs subvolume set-default 5 %s\"".printf(backup_mount_point);
+				log_debug(cmd);
+				std_out = ""; std_err = ""; 
+				status = exec_sync(cmd, out std_out, out std_err);
+			}
+		}
+
+		log_msg("%s: %s (Id:%ld)".printf(_("Deleting subvolume"), name, id));
 		
 		subpath = path_combine(path, name);
 		if (dir_exists(subpath)) { // there is a nested subvol to remove first
@@ -164,6 +189,21 @@ public class Subvolume : GLib.Object{
 			return false;
 		}
 
+		if ((name == "@") && (default_subvolid != "5")) {
+			cmd = "sh -c \"btrfs subvolume set-default $(btrfs subvolume list %s | grep -E '([[:space:]]|/)@$' | tail -1 | cut -d ' ' -f2) %s\"".printf(backup_mount_point, backup_mount_point);
+			log_debug("Reset default subvolume");
+			log_debug(cmd);
+			std_out = ""; std_err = ""; 
+			status = exec_sync(cmd, out std_out, out std_err);
+			
+			if (status != 0){
+				log_error(std_err);
+				log_error(_("btrfs returned an error") + ": %d".printf(status));
+				log_error(_("Failed to set default subvolume") + ": %s".printf(name));
+				return false;
+			}
+		
+		}
 		log_msg("%s: %s (Id:%ld)\n".printf(_("Deleted subvolume"), name, id));
 
 		if (App.btrfs_qgroups_enabled) {
@@ -189,6 +229,8 @@ public class Subvolume : GLib.Object{
 
 		if (is_system_subvolume) { return false; }
 
+		string backup_mount_point =  App.mount_point_app + "/backup";
+		
 		// restore snapshot subvolume by creating new subvolume snapshots ----------------------
 		
 		string src_path = path;
@@ -218,7 +260,62 @@ public class Subvolume : GLib.Object{
 		}
 
 		log_msg(_("Restored system subvolume") + ": %s".printf(name));
-		
+
+		if (name == "@"){
+
+			if (default_subvolid.length == 0) {
+				cmd = "sh -c \"btrfs subvolume get-default %s | cut -d ' ' -f2\"".printf(backup_mount_point);
+				log_debug("Get default subvolume Id");
+				log_debug(cmd);
+				std_out = ""; std_err = ""; 
+				status = exec_sync(cmd, out std_out, out std_err);
+				default_subvolid = std_out.strip();
+				
+				if (status != 0){
+					log_error(std_err);
+					log_error(_("btrfs returned an error") + ": %d".printf(status));
+					log_error(_("Failed to get default subvolume") + ": %s".printf(name));
+					return false;
+				}
+			}
+
+			if ( default_subvolid == "5"){
+				return true;
+			}
+			
+			cmd = "sh -c \"btrfs subvolume list %s | grep ' @$' | cut -d ' ' -f2\"".printf(backup_mount_point);
+			log_debug("Get default subvolume id");
+			log_debug(cmd);
+			std_out = ""; std_err = ""; 
+			status = exec_sync(cmd, out std_out, out std_err);
+			string new_subvolid = std_out.strip();
+			
+			if (status != 0){
+				log_error(std_err);
+				log_error(_("btrfs returned an error") + ": %d".printf(status));
+				log_error(_("Failed to restored subvolume id") + ": %s".printf(name));
+				return false;
+			}
+			
+			if (default_subvolid == new_subvolid) {
+				// default subvolid already set
+				return true;
+			}
+			cmd = "sh -c \"btrfs subvolume set-default %s %s\"".printf(new_subvolid, backup_mount_point);
+			log_debug("Set default subvolume id");
+			log_debug(cmd);
+			std_out = ""; std_err = ""; 
+			status = exec_sync(cmd, out std_out, out std_err);
+			
+			if (status != 0){
+				log_error(std_err);
+				log_error(_("btrfs returned an error") + ": %d".printf(status));
+				log_error(_("Failed to set default subvolume") + ": %s".printf(name));
+				return false;
+			}
+			
+		}
+
 		return true;
 	}
 }
--- timeshift-23.07.1.orig/src/Gtk/SnapshotBackendBox.vala
+++ timeshift-23.07.1/src/Gtk/SnapshotBackendBox.vala
@@ -114,7 +114,8 @@ class SnapshotBackendBox : Gtk.Box{
 
 	private bool check_for_btrfs_tools() {
         try {
-            const string args[] = {"lsblk", "-o", "FSTYPE", null};
+            //const string args[] = {"lsblk", "-o", "FSTYPE", null};
+            const string args[] = {"blkid", "-s", "TYPE", "-o", "value", null};
             var proc = new Subprocess.newv(
                 args,
                 SubprocessFlags.STDOUT_PIPE | SubprocessFlags.STDERR_SILENCE
--- timeshift-23.07.1.orig/src/Utility/Device.vala
+++ timeshift-23.07.1/src/Utility/Device.vala
@@ -452,6 +452,19 @@ public class Device : GLib.Object{
 					pi.fstype = (pi.fstype == "crypto_luks") ? "luks" : pi.fstype;
 					pi.fstype = (pi.fstype == "lvm2_member") ? "lvm2" : pi.fstype;
 
+					if ((pi.kname.length > 0) && (pi.uuid.length == 0)){
+						string kdev = "/dev/%s".printf(pi.kname);
+						if (file_exists(kdev)) { 
+	 						var klist = get_block_devices_using_blkid(kdev);
+							if (klist.size > 0 ) { 
+								Device kpi = klist[0];
+		 						pi.uuid = kpi.uuid;
+		 						pi.label = kpi.label;
+		 						pi.fstype = kpi.fstype;
+							}
+						}
+					}
+					
 					pi.size_bytes = int64.parse(match.fetch(++pos).strip());
 
 					var mp = match.fetch(++pos).strip();
@@ -714,12 +727,13 @@ public class Device : GLib.Object{
 		MatchInfo match;
 
 		cmd = "/sbin/blkid" + ((dev_name.length > 0) ? " " + dev_name: "");
+		cmd = "sh -c \"%s\"".printf(cmd);
 
 		if (LOG_DEBUG){
 			log_debug(cmd);
 		}
 		
-		ret_val = exec_script_sync(cmd, out std_out, out std_err);
+		ret_val = exec_sync(cmd, out std_out, out std_err);
 		if (ret_val != 0){
 			var msg = "blkid: " + _("Failed to get partition list");
 			msg += (dev_name.length > 0) ? ": " + dev_name : "";
@@ -1610,7 +1624,14 @@ public class Device : GLib.Object{
 			cmd = "mount -o %s \"%s\" \"%s\"".printf(mount_options, device, mount_point);
 		}
 		else{
-			cmd = "mount \"%s\" \"%s\"".printf(device, mount_point);
+			cmd = "blkid  -o value -s TYPE \"%s\"".printf(device);
+			int status = exec_sync(cmd, out std_out, out std_err);
+			if (status == 0 && std_out.strip() == "btrfs"){
+				cmd = "mount -o subvol=/ \"%s\" \"%s\"".printf(device, mount_point);
+			} 
+			else{
+				cmd = "mount \"%s\" \"%s\"".printf(device, mount_point);
+			}
 		}
 
 		ret_val = exec_sync(cmd, out std_out, out std_err);
