-
Notifications
You must be signed in to change notification settings - Fork 127
[Next] Configurable Btrfs subvol names #480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 17 commits
4d528da
85efc0b
6cf8745
bd54ed4
f3e3bc8
52b7cf4
9cc883b
0ebe92a
4e13156
69b8468
04bfffd
dd769f5
d7b5070
0e71046
7f55d83
aaccff3
a1f3892
44edb09
7528ba9
deb0ecb
6a0240f
216393b
59339bb
b32ac4e
4b5cf13
01f0445
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,6 +53,9 @@ public class Main : GLib.Object{ | |
| public bool include_btrfs_home_for_backup = false; | ||
| public bool include_btrfs_home_for_restore = false; | ||
| public static bool btrfs_version__can_recursive_delete = false; | ||
|
|
||
| public string root_subvolume_name = "@"; | ||
| public string home_subvolume_name = "@home"; | ||
|
|
||
| public bool stop_cron_emails = true; | ||
|
|
||
|
|
@@ -289,6 +292,23 @@ public class Main : GLib.Object{ | |
| this.app_conf_path_old = "/etc/timeshift.json"; | ||
| this.app_conf_path_default = GLib.Path.build_path (GLib.Path.DIR_SEPARATOR_S, Constants.SYSCONFDIR, "timeshift", "default.json"); | ||
| //sys_root and sys_home will be initialized by update_partition_list() | ||
|
|
||
| // Detect subvolume names based on distro id. | ||
| // Only has effect when timeshift is opened the first time, | ||
| // otherwise the setting is overwritten by loading the config. | ||
| if (this.current_distro.dist_id.down() == "fedora") { | ||
| this.root_subvolume_name = "root"; | ||
| this.home_subvolume_name = "home"; | ||
| } | ||
| else if (this.current_distro.dist_id.down() == "debian") { | ||
| this.root_subvolume_name = "@rootfs"; | ||
| this.home_subvolume_name = ""; | ||
| this.include_btrfs_home_for_backup = false; | ||
| } | ||
| else { //if (this.current_distro.dist_id.down() == "ubuntu") | ||
| this.root_subvolume_name = "@"; | ||
| this.home_subvolume_name = "@home"; | ||
| } | ||
|
|
||
| // check if running locally ------------------------ | ||
|
|
||
|
|
@@ -488,9 +508,9 @@ public class Main : GLib.Object{ | |
|
|
||
| log_debug("check_btrfs_layout_system()"); | ||
|
|
||
| bool supported = sys_subvolumes.has_key("@"); | ||
| bool supported = sys_subvolumes.has_key(root_subvolume_name); | ||
| if (include_btrfs_home_for_backup){ | ||
| supported = supported && sys_subvolumes.has_key("@home"); | ||
| supported = supported && sys_subvolumes.has_key(home_subvolume_name); | ||
| } | ||
|
|
||
| if (!supported){ | ||
|
|
@@ -521,18 +541,18 @@ public class Main : GLib.Object{ | |
|
|
||
| if (dev_home != dev_root){ | ||
|
|
||
| supported = supported && check_btrfs_volume(dev_root, "@", unlock); | ||
| supported = supported && check_btrfs_volume(dev_root, root_subvolume_name, unlock); | ||
|
|
||
| if (include_btrfs_home_for_backup){ | ||
| supported = supported && check_btrfs_volume(dev_home, "@home", unlock); | ||
| supported = supported && check_btrfs_volume(dev_home, home_subvolume_name, unlock); | ||
| } | ||
| } | ||
| else{ | ||
| if (include_btrfs_home_for_backup){ | ||
| supported = supported && check_btrfs_volume(dev_root, "@,@home", unlock); | ||
| } | ||
| else{ | ||
| supported = supported && check_btrfs_volume(dev_root, "@", unlock); | ||
| supported = supported && check_btrfs_volume(dev_root, root_subvolume_name, unlock); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1720,9 +1740,9 @@ public class Main : GLib.Object{ | |
|
|
||
| log_msg(_("Creating new backup...") + "(BTRFS)"); | ||
|
|
||
| log_msg(_("Saving to device") + ": %s".printf(repo.device.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths["@"])); | ||
| log_msg(_("Saving to device") + ": %s".printf(repo.device.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths[root_subvolume_name])); | ||
| if ((repo.device_home != null) && (repo.device_home.uuid != repo.device.uuid)){ | ||
| log_msg(_("Saving to device") + ": %s".printf(repo.device_home.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths["@home"])); | ||
| log_msg(_("Saving to device") + ": %s".printf(repo.device_home.device) + ", " + _("mounted at path") + ": %s".printf(repo.mount_paths[home_subvolume_name])); | ||
| } | ||
|
|
||
| // take new backup --------------------------------- | ||
|
|
@@ -1739,11 +1759,11 @@ public class Main : GLib.Object{ | |
|
|
||
| // create subvolume snapshots | ||
|
|
||
| var subvol_names = new string[] { "@" }; | ||
| var subvol_names = new string[] { root_subvolume_name }; | ||
|
|
||
| if (include_btrfs_home_for_backup){ | ||
|
|
||
| subvol_names = new string[] { "@","@home" }; | ||
| subvol_names = new string[] { root_subvolume_name,home_subvolume_name }; | ||
| } | ||
|
|
||
| foreach(var subvol_name in subvol_names){ | ||
|
|
@@ -1786,7 +1806,7 @@ public class Main : GLib.Object{ | |
|
|
||
| //log_msg(_("Writing control file...")); | ||
|
|
||
| snapshot_path = path_combine(repo.mount_paths["@"], "timeshift-btrfs/snapshots/%s".printf(snapshot_name)); | ||
| snapshot_path = path_combine(repo.mount_paths[root_subvolume_name], "timeshift-btrfs/snapshots/%s".printf(snapshot_name)); | ||
|
|
||
| string initial_tags = (tag == "ondemand") ? "" : tag; | ||
|
|
||
|
|
@@ -2344,11 +2364,11 @@ public class Main : GLib.Object{ | |
| // final check - check if target root device is mounted | ||
|
|
||
| if (btrfs_mode){ | ||
| if (repo.mount_paths["@"].length == 0){ | ||
| if (repo.mount_paths[root_subvolume_name].length == 0){ | ||
| log_error(_("BTRFS device is not mounted") + ": @"); | ||
| return false; | ||
| } | ||
| if (include_btrfs_home_for_restore && (repo.mount_paths["@home"].length == 0)){ | ||
| if (include_btrfs_home_for_restore && (repo.mount_paths[home_subvolume_name].length == 0)){ | ||
| log_error(_("BTRFS device is not mounted") + ": @home"); | ||
| return false; | ||
| } | ||
|
|
@@ -2430,7 +2450,7 @@ public class Main : GLib.Object{ | |
|
|
||
| if (!App.snapshot_to_restore.subvolumes.has_key(entry.subvolume_name())){ continue; } | ||
|
|
||
| if ((entry.subvolume_name() == "@home") && !include_btrfs_home_for_restore){ continue; } | ||
| if ((entry.subvolume_name() == home_subvolume_name) && !include_btrfs_home_for_restore){ continue; } | ||
| } | ||
|
|
||
| string dev_name = entry.device.full_name_with_parent; | ||
|
|
@@ -2466,7 +2486,7 @@ public class Main : GLib.Object{ | |
|
|
||
| if (!App.snapshot_to_restore.subvolumes.has_key(entry.subvolume_name())){ continue; } | ||
|
|
||
| if ((entry.subvolume_name() == "@home") && !include_btrfs_home_for_restore){ continue; } | ||
| if ((entry.subvolume_name() == home_subvolume_name) && !include_btrfs_home_for_restore){ continue; } | ||
| } | ||
|
|
||
| string dev_name = entry.device.full_name_with_parent; | ||
|
|
@@ -3166,7 +3186,7 @@ public class Main : GLib.Object{ | |
|
|
||
| foreach(var subvol in snapshot_to_restore.subvolumes.values){ | ||
|
|
||
| if ((subvol.name == "@home") && !include_btrfs_home_for_restore){ continue; } | ||
| if ((subvol.name == home_subvolume_name) && !include_btrfs_home_for_restore){ continue; } | ||
|
|
||
| subvol.restore(); | ||
| } | ||
|
|
@@ -3230,12 +3250,12 @@ public class Main : GLib.Object{ | |
|
|
||
| if (found){ | ||
| //delete system subvolumes | ||
| if (sys_subvolumes.has_key("@") && snapshot_to_restore.subvolumes.has_key("@")){ | ||
| sys_subvolumes["@"].remove(); | ||
| if (sys_subvolumes.has_key(root_subvolume_name) && snapshot_to_restore.subvolumes.has_key(root_subvolume_name)){ | ||
| sys_subvolumes[root_subvolume_name].remove(); | ||
| log_msg(_("Deleted subvolume") + ": @"); | ||
| } | ||
| if (include_btrfs_home_for_restore && sys_subvolumes.has_key("@home") && snapshot_to_restore.subvolumes.has_key("@home")){ | ||
| sys_subvolumes["@home"].remove(); | ||
| if (include_btrfs_home_for_restore && sys_subvolumes.has_key(home_subvolume_name) && snapshot_to_restore.subvolumes.has_key(home_subvolume_name)){ | ||
| sys_subvolumes[home_subvolume_name].remove(); | ||
| log_msg(_("Deleted subvolume") + ": @home"); | ||
| } | ||
|
|
||
|
|
@@ -3263,9 +3283,9 @@ public class Main : GLib.Object{ | |
|
|
||
| var subvol_list = new Gee.ArrayList<Subvolume>(); | ||
|
|
||
| var subvol_names = new string[] { "@" }; | ||
| var subvol_names = new string[] { root_subvolume_name }; | ||
| if (include_btrfs_home_for_restore){ | ||
| subvol_names = new string[] { "@","@home" }; | ||
| subvol_names = new string[] { root_subvolume_name,home_subvolume_name }; | ||
| } | ||
|
|
||
| foreach(string subvol_name in subvol_names){ | ||
|
|
@@ -3294,7 +3314,7 @@ public class Main : GLib.Object{ | |
| return false; | ||
| } | ||
| else{ | ||
| var subvol_dev = (subvol_name == "@") ? repo.device : repo.device_home; | ||
| var subvol_dev = (subvol_name == root_subvolume_name) ? repo.device : repo.device_home; | ||
| subvol_list.add(new Subvolume(subvol_name, dst_path, subvol_dev.uuid, repo)); | ||
|
|
||
| log_msg(_("Moved system subvolume to snapshot directory") + ": %s".printf(subvol_name)); | ||
|
|
@@ -3308,11 +3328,11 @@ public class Main : GLib.Object{ | |
| else{ | ||
| // write control file ----------- | ||
|
|
||
| snapshot_path = path_combine(repo.mount_paths["@"], "timeshift-btrfs/snapshots/%s".printf(snapshot_name)); | ||
| snapshot_path = path_combine(repo.mount_paths[root_subvolume_name], "timeshift-btrfs/snapshots/%s".printf(snapshot_name)); | ||
|
|
||
| var snap = Snapshot.write_control_file( | ||
| snapshot_path, dt_created, repo.device.uuid, | ||
| LinuxDistro.get_dist_info(path_combine(snapshot_path,"@")).full_name(), | ||
| LinuxDistro.get_dist_info(path_combine(snapshot_path,root_subvolume_name)).full_name(), | ||
| "ondemand", "", 0, true, false, repo); | ||
|
|
||
| snap.description = "Before restoring '%s'".printf(snapshot_to_restore.date_formatted); | ||
|
|
@@ -3357,6 +3377,9 @@ public class Main : GLib.Object{ | |
| config.set_string_member("parent_device_uuid", backup_parent_uuid); | ||
| } | ||
|
|
||
| config.set_string_member("root_subvolume_name", root_subvolume_name); | ||
| config.set_string_member("home_subvolume_name", home_subvolume_name); | ||
|
|
||
| config.set_string_member("do_first_run", false.to_string()); | ||
| config.set_string_member("btrfs_mode", btrfs_mode.to_string()); | ||
| config.set_string_member("include_btrfs_home_for_backup", include_btrfs_home_for_backup.to_string()); | ||
|
|
@@ -3476,6 +3499,9 @@ public class Main : GLib.Object{ | |
| if (cmd_btrfs_mode != null){ | ||
| btrfs_mode = cmd_btrfs_mode; //override | ||
| } | ||
|
|
||
| root_subvolume_name = json_get_string(config,"root_subvolume_name", root_subvolume_name); | ||
| home_subvolume_name = json_get_string(config,"home_subvolume_name", home_subvolume_name); | ||
|
|
||
| backup_uuid = json_get_string(config,"backup_device_uuid", backup_uuid); | ||
| backup_parent_uuid = json_get_string(config,"parent_device_uuid", backup_parent_uuid); | ||
|
|
@@ -3544,7 +3570,7 @@ public class Main : GLib.Object{ | |
|
|
||
| // load some defaults for first-run based on user's system type | ||
|
|
||
| bool supported = sys_subvolumes.has_key("@") && cmd_exists("btrfs"); // && sys_subvolumes.has_key("@home") | ||
| bool supported = sys_subvolumes.has_key(root_subvolume_name) && cmd_exists("btrfs"); // && sys_subvolumes.has_key(home_subvolume_name) | ||
| if (supported || (cmd_btrfs_mode == true)){ | ||
| log_msg(_("Selected default snapshot type") + ": %s".printf("BTRFS")); | ||
| btrfs_mode = true; | ||
|
|
@@ -3959,8 +3985,8 @@ public class Main : GLib.Object{ | |
| update_partitions(); | ||
|
|
||
| // In BTRFS mode, select the system disk if system disk is BTRFS | ||
| if (btrfs_mode && sys_subvolumes.has_key("@")){ | ||
| var subvol_root = sys_subvolumes["@"]; | ||
| if (btrfs_mode && sys_subvolumes.has_key(root_subvolume_name)){ | ||
| var subvol_root = sys_subvolumes[root_subvolume_name]; | ||
| repo = new SnapshotRepo.from_device(subvol_root.get_device(), parent_win, btrfs_mode); | ||
| return; | ||
| } | ||
|
|
@@ -3983,7 +4009,7 @@ public class Main : GLib.Object{ | |
| if (dev.has_children()) { return false; } | ||
|
|
||
| if (btrfs_mode && ((dev.fstype == "btrfs")||(dev.fstype == "luks"))){ | ||
| if (check_btrfs_volume(dev, "@", unlock)){ | ||
| if (check_btrfs_volume(dev, root_subvolume_name, unlock)){ | ||
| return true; | ||
| } | ||
| } | ||
|
|
@@ -4109,16 +4135,20 @@ public class Main : GLib.Object{ | |
| } | ||
|
|
||
| public bool query_subvolume_ids(){ | ||
| bool ok = query_subvolume_id("@"); | ||
| bool ok = query_subvolume_id(root_subvolume_name); | ||
| if ((repo.device_home != null) && (repo.device.uuid != repo.device_home.uuid)){ | ||
| ok = ok && query_subvolume_id("@home"); | ||
| ok = ok && query_subvolume_id(home_subvolume_name); | ||
| } | ||
| return ok; | ||
| } | ||
|
|
||
| public bool query_subvolume_id(string subvol_name){ | ||
|
|
||
| log_debug("query_subvolume_id():%s".printf(subvol_name)); | ||
|
|
||
| // Early out when configured subvolume name != actual. | ||
| if(sys_subvolumes[root_subvolume_name] == null || sys_subvolumes[home_subvolume_name] == null) | ||
| return false; | ||
|
|
||
| string cmd = ""; | ||
| string std_out; | ||
|
|
@@ -4149,14 +4179,14 @@ public class Main : GLib.Object{ | |
|
|
||
| Subvolume subvol = null; | ||
|
|
||
| if ((sys_subvolumes.size > 0) && line.has_suffix(sys_subvolumes["@"].path.replace(repo.mount_paths["@"] + "/"," "))){ | ||
| subvol = sys_subvolumes["@"]; | ||
| if ((sys_subvolumes.size > 0) && line.has_suffix(sys_subvolumes[root_subvolume_name].path.replace(repo.mount_paths[root_subvolume_name] + "/"," "))){ | ||
| subvol = sys_subvolumes[root_subvolume_name]; | ||
| } | ||
| else if ((sys_subvolumes.size > 0) | ||
| && sys_subvolumes.has_key("@home") | ||
| && line.has_suffix(sys_subvolumes["@home"].path.replace(repo.mount_paths["@home"] + "/"," "))){ | ||
| && sys_subvolumes.has_key(home_subvolume_name) | ||
| && line.has_suffix(sys_subvolumes[home_subvolume_name].path.replace(repo.mount_paths[home_subvolume_name] + "/"," "))){ | ||
|
|
||
fused0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| subvol = sys_subvolumes["@home"]; | ||
| subvol = sys_subvolumes[home_subvolume_name]; | ||
| } | ||
| else { | ||
| foreach(var bak in repo.snapshots){ | ||
|
|
@@ -4178,9 +4208,9 @@ public class Main : GLib.Object{ | |
| } | ||
|
|
||
| public bool query_subvolume_quotas(){ | ||
| bool ok = query_subvolume_quota("@"); | ||
| bool ok = query_subvolume_quota(root_subvolume_name); | ||
| if (repo.device.uuid != repo.device_home.uuid){ | ||
| ok = ok && query_subvolume_quota("@home"); | ||
| ok = ok && query_subvolume_quota(home_subvolume_name); | ||
| } | ||
| return ok; | ||
| } | ||
|
|
@@ -4241,15 +4271,15 @@ public class Main : GLib.Object{ | |
|
|
||
| Subvolume subvol = null; | ||
|
|
||
| if ((sys_subvolumes.size > 0) && (sys_subvolumes["@"].id == subvol_id)){ | ||
| if ((sys_subvolumes.size > 0) && (sys_subvolumes[root_subvolume_name].id == subvol_id)){ | ||
|
|
||
| subvol = sys_subvolumes["@"]; | ||
| subvol = sys_subvolumes[root_subvolume_name]; | ||
| } | ||
| else if ((sys_subvolumes.size > 0) | ||
| && sys_subvolumes.has_key("@home") | ||
| && (sys_subvolumes["@home"].id == subvol_id)){ | ||
| && sys_subvolumes.has_key(home_subvolume_name) | ||
| && (sys_subvolumes[home_subvolume_name].id == subvol_id)){ | ||
|
|
||
| subvol = sys_subvolumes["@home"]; | ||
| subvol = sys_subvolumes[home_subvolume_name]; | ||
|
Comment on lines
+4288
to
+4291
|
||
| } | ||
| else { | ||
| foreach(var bak in repo.snapshots){ | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -228,7 +228,7 @@ public class Snapshot : GLib.Object{ | |||||
| live = json_get_bool(config,"live",false); | ||||||
| string type = config.get_string_member_with_default("type", "rsync"); | ||||||
|
|
||||||
| string extension = (type == "btrfs") ? "@" : "localhost"; | ||||||
| string extension = (type == "btrfs") ? App.root_subvolume_name : "localhost"; | ||||||
| distro = LinuxDistro.get_dist_info(path_combine(path, extension)); | ||||||
|
|
||||||
| //log_debug("repo.mount_path: %s".printf(repo.mount_path)); | ||||||
|
|
@@ -239,7 +239,7 @@ public class Snapshot : GLib.Object{ | |||||
|
|
||||||
| foreach(string subvol_name in subvols.get_members()){ | ||||||
|
|
||||||
| if ((subvol_name != "@")&&(subvol_name != "@home")){ continue; } | ||||||
| if ((subvol_name != App.root_subvolume_name)&&(subvol_name != App.home_subvolume_name)){ continue; } | ||||||
|
||||||
| if ((subvol_name != App.root_subvolume_name)&&(subvol_name != App.home_subvolume_name)){ continue; } | |
| if ((subvol_name != App.root_subvolume_name) && ((App.home_subvolume_name == "") || (subvol_name != App.home_subvolume_name))) { continue; } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -193,31 +193,31 @@ public class SnapshotRepo : GLib.Object{ | |||||
| } | ||||||
|
|
||||||
| // rsync | ||||||
| mount_paths["@"] = ""; | ||||||
| mount_paths["@home"] = ""; | ||||||
| mount_paths[App.root_subvolume_name] = ""; | ||||||
| mount_paths[App.home_subvolume_name] = ""; | ||||||
|
|
||||||
| if (btrfs_mode){ | ||||||
|
|
||||||
| mount_paths["@"] = mount_path; | ||||||
| mount_paths["@home"] = mount_path; //default | ||||||
| mount_paths[App.root_subvolume_name] = mount_path; | ||||||
| mount_paths[App.home_subvolume_name] = mount_path; //default | ||||||
| device_home = device; //default | ||||||
|
|
||||||
| // mount @home if on different disk ------- | ||||||
|
|
||||||
| var repo_subvolumes = Subvolume.detect_subvolumes_for_system_by_path(path_combine(mount_path,"@"), this, parent_window); | ||||||
| var repo_subvolumes = Subvolume.detect_subvolumes_for_system_by_path(path_combine(mount_path,App.root_subvolume_name), this, parent_window); | ||||||
|
|
||||||
| if (repo_subvolumes.has_key("@home")){ | ||||||
| if (repo_subvolumes.has_key(App.home_subvolume_name)){ | ||||||
|
||||||
| if (repo_subvolumes.has_key(App.home_subvolume_name)){ | |
| if ((App.home_subvolume_name != "") && repo_subvolumes.has_key(App.home_subvolume_name)){ |
Uh oh!
There was an error while loading. Please reload this page.