Refactor PostClone sections
Added a new Mode to handle an error last screen instead of complete. This avoids running commands with unexpected arguments
This commit is contained in:
parent
dd03962c84
commit
2a5167bf52
7 changed files with 49 additions and 30 deletions
|
|
@ -83,5 +83,12 @@
|
||||||
"<Ctrl-c>": "Quit", // Yet another way to quit
|
"<Ctrl-c>": "Quit", // Yet another way to quit
|
||||||
"<Ctrl-z>": "Suspend" // Suspend the application
|
"<Ctrl-z>": "Suspend" // Suspend the application
|
||||||
},
|
},
|
||||||
|
"Failed": {
|
||||||
|
"<Enter>": "Quit",
|
||||||
|
"<q>": "Quit", // Quit the application
|
||||||
|
"<Ctrl-d>": "Quit", // Another way to quit
|
||||||
|
"<Ctrl-c>": "Quit", // Yet another way to quit
|
||||||
|
"<Ctrl-z>": "Suspend" // Suspend the application
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
44
src/app.rs
44
src/app.rs
|
|
@ -84,6 +84,7 @@ pub enum Mode {
|
||||||
SelectParts,
|
SelectParts,
|
||||||
PostClone,
|
PostClone,
|
||||||
Done,
|
Done,
|
||||||
|
Failed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -140,6 +141,7 @@ impl App {
|
||||||
(Mode::SelectParts, Mode::Confirm) => Mode::PostClone,
|
(Mode::SelectParts, Mode::Confirm) => Mode::PostClone,
|
||||||
(_, Mode::PostClone) => Mode::Done,
|
(_, Mode::PostClone) => Mode::Done,
|
||||||
(_, Mode::Done) => Mode::Done,
|
(_, Mode::Done) => Mode::Done,
|
||||||
|
(_, Mode::Failed) => Mode::Failed,
|
||||||
// Invalid states
|
// Invalid states
|
||||||
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
||||||
};
|
};
|
||||||
|
|
@ -326,6 +328,7 @@ impl App {
|
||||||
self.selections[1] = two;
|
self.selections[1] = two;
|
||||||
}
|
}
|
||||||
Action::SetMode(new_mode) => {
|
Action::SetMode(new_mode) => {
|
||||||
|
info!("Setting mode to {new_mode:?}");
|
||||||
self.cur_mode = new_mode;
|
self.cur_mode = new_mode;
|
||||||
match new_mode {
|
match new_mode {
|
||||||
Mode::ScanDisks => {
|
Mode::ScanDisks => {
|
||||||
|
|
@ -364,7 +367,6 @@ impl App {
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
Mode::PostClone => {
|
Mode::PostClone => {
|
||||||
// TODO: FIXME
|
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
self.action_tx.send(Action::DisplayPopup(
|
||||||
popup::Type::Info,
|
popup::Type::Info,
|
||||||
String::from("Updating boot configuration"),
|
String::from("Updating boot configuration"),
|
||||||
|
|
@ -374,7 +376,14 @@ impl App {
|
||||||
let system32 = if cfg!(windows) {
|
let system32 = if cfg!(windows) {
|
||||||
match env::var("SYSTEMROOT") {
|
match env::var("SYSTEMROOT") {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(_) => panic!("Failed to find SYSTEMROOT"),
|
Err(_) => {
|
||||||
|
self.action_tx.send(Action::DisplayPopup(
|
||||||
|
popup::Type::Error,
|
||||||
|
String::from("ERROR\n\n\nFailed to find SYSTEMROOT"),
|
||||||
|
))?;
|
||||||
|
self.action_tx.send(Action::SetMode(Mode::Failed))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String::from(".")
|
String::from(".")
|
||||||
|
|
@ -385,29 +394,20 @@ impl App {
|
||||||
if let Some(disk_index) = self.disk_index_dest {
|
if let Some(disk_index) = self.disk_index_dest {
|
||||||
if let Some(disk) = disk_list.get(disk_index) {
|
if let Some(disk) = disk_list.get(disk_index) {
|
||||||
let table_type = self.table_type.clone().unwrap();
|
let table_type = self.table_type.clone().unwrap();
|
||||||
let letter_boot: String;
|
let letter_boot =
|
||||||
let letter_os: String;
|
disk.get_part_letter(self.part_index_boot.unwrap());
|
||||||
if let Some(part) =
|
let letter_os =
|
||||||
disk.parts.get(self.part_index_boot.unwrap())
|
disk.get_part_letter(self.part_index_os.unwrap());
|
||||||
{
|
|
||||||
letter_boot = if part.letter.is_empty() {
|
// Safety check
|
||||||
String::from("??")
|
if letter_boot.is_empty() || letter_os.is_empty() {
|
||||||
} else {
|
|
||||||
part.letter.clone()
|
|
||||||
};
|
|
||||||
letter_os = if part.letter.is_empty() {
|
|
||||||
String::from("??")
|
|
||||||
} else {
|
|
||||||
part.letter.clone()
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
self.action_tx.send(Action::DisplayPopup(
|
||||||
popup::Type::Error,
|
popup::Type::Error,
|
||||||
String::from(
|
String::from(
|
||||||
"Failed to get drive letters for destination",
|
"ERROR\n\n\nFailed to get drive letters for the destination",
|
||||||
),
|
),
|
||||||
))?;
|
))?;
|
||||||
self.action_tx.send(Action::SetMode(Mode::Done))?;
|
self.action_tx.send(Action::SetMode(Mode::Failed))?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -443,10 +443,10 @@ impl App {
|
||||||
// Lock in safe mode
|
// Lock in safe mode
|
||||||
let bcd_path = match table_type {
|
let bcd_path = match table_type {
|
||||||
PartitionTableType::Guid => {
|
PartitionTableType::Guid => {
|
||||||
format!("{letter_boot}\\EFI\\Microsoft\\Boot\\BCD")
|
format!("{letter_boot}:\\EFI\\Microsoft\\Boot\\BCD")
|
||||||
}
|
}
|
||||||
PartitionTableType::Legacy => {
|
PartitionTableType::Legacy => {
|
||||||
format!("{letter_boot}\\Boot\\BCD")
|
format!("{letter_boot}:\\Boot\\BCD")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.action_tx.send(Action::Command(
|
self.action_tx.send(Action::Command(
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ impl Component for Footer {
|
||||||
Mode::Confirm => {
|
Mode::Confirm => {
|
||||||
String::from("(Enter) to confirm / (b) to go back / (q) to quit")
|
String::from("(Enter) to confirm / (b) to go back / (q) to quit")
|
||||||
}
|
}
|
||||||
Mode::Done => String::from("(Enter) or (q) to quit"),
|
Mode::Done | Mode::Failed => String::from("(Enter) or (q) to quit"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ impl Left {
|
||||||
|
|
||||||
impl Component for Left {
|
impl Component for Left {
|
||||||
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
||||||
// TODO
|
|
||||||
let _ = key; // to appease clippy
|
let _ = key; // to appease clippy
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +248,7 @@ impl Component for Left {
|
||||||
(Mode::SelectTableType, Mode::Confirm) => {
|
(Mode::SelectTableType, Mode::Confirm) => {
|
||||||
self.title_text = String::from("Confirm Selections (Again)")
|
self.title_text = String::from("Confirm Selections (Again)")
|
||||||
}
|
}
|
||||||
(_, Mode::Done) => self.title_text = String::from("Done"),
|
(_, Mode::Done | Mode::Failed) => self.title_text = String::from("Done"),
|
||||||
// Invalid states
|
// Invalid states
|
||||||
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
(_, Mode::Confirm) => panic!("This shouldn't happen."),
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +273,12 @@ impl Component for Left {
|
||||||
|
|
||||||
// Body
|
// Body
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone | Mode::Done => {
|
Mode::ScanDisks
|
||||||
|
| Mode::PreClone
|
||||||
|
| Mode::Clone
|
||||||
|
| Mode::PostClone
|
||||||
|
| Mode::Done
|
||||||
|
| Mode::Failed => {
|
||||||
// Leave blank
|
// Leave blank
|
||||||
let paragraph = Paragraph::new(String::new()).block(
|
let paragraph = Paragraph::new(String::new()).block(
|
||||||
Block::default()
|
Block::default()
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ impl Right {
|
||||||
|
|
||||||
impl Component for Right {
|
impl Component for Right {
|
||||||
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
||||||
// TODO ??
|
|
||||||
let _ = key; // to appease clippy
|
let _ = key; // to appease clippy
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,19 @@ impl Disk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_part_letter(&self, part_index: usize) -> String {
|
||||||
|
// Used to get Boot and OS letters
|
||||||
|
if let Some(part) = self.parts.get(part_index) {
|
||||||
|
part.letter.clone()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_parts(&self) -> Vec<Partition> {
|
pub fn get_parts(&self) -> Vec<Partition> {
|
||||||
self.parts.clone()
|
self.parts.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_parts(&self) -> usize {
|
pub fn num_parts(&self) -> usize {
|
||||||
self.parts.len()
|
self.parts.len()
|
||||||
}
|
}
|
||||||
|
|
@ -223,6 +233,7 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
||||||
id: 1,
|
id: 1,
|
||||||
fs_type: String::from("FAT32"),
|
fs_type: String::from("FAT32"),
|
||||||
label: String::from("ESP"),
|
label: String::from("ESP"),
|
||||||
|
letter: String::from("S"),
|
||||||
part_type: String::from("EFI"),
|
part_type: String::from("EFI"),
|
||||||
size: 272_629_760,
|
size: 272_629_760,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -237,6 +248,7 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
||||||
id: 4,
|
id: 4,
|
||||||
fs_type: String::from("NTFS"),
|
fs_type: String::from("NTFS"),
|
||||||
label: String::from("Win10"),
|
label: String::from("Win10"),
|
||||||
|
letter: String::from("W"),
|
||||||
part_type: String::from("MS Basic Data"),
|
part_type: String::from("MS Basic Data"),
|
||||||
size: 824_340_119_552,
|
size: 824_340_119_552,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -287,8 +287,6 @@ pub fn parse_disk_numbers(contents: &str) -> Vec<&str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_partition_details(parts: &mut Vec<Partition>, contents: &str) {
|
pub fn parse_partition_details(parts: &mut Vec<Partition>, contents: &str) {
|
||||||
// TODO: Update multiple fields at once?
|
|
||||||
// https://stackoverflow.com/a/52905826
|
|
||||||
static RE_PAR: Lazy<Regex> = Lazy::new(|| {
|
static RE_PAR: Lazy<Regex> = Lazy::new(|| {
|
||||||
Regex::new(
|
Regex::new(
|
||||||
r"Partition (\d+)\r?\nType\s*: (\S+)(\r?\n.*){5}\s*(Volume.*\r?\n.*\r?\n|There is no volume)(.*)",
|
r"Partition (\d+)\r?\nType\s*: (\S+)(\r?\n.*){5}\s*(Volume.*\r?\n.*\r?\n|There is no volume)(.*)",
|
||||||
|
|
@ -324,7 +322,6 @@ pub fn parse_partition_details(parts: &mut Vec<Partition>, contents: &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh_disk_info(disk: &Disk) {
|
pub fn refresh_disk_info(disk: &Disk) {
|
||||||
// TODO: Needs refactor - assuming add_ functions are replaced with get_ variants
|
|
||||||
info!("Refresh disk info");
|
info!("Refresh disk info");
|
||||||
let mut disk = get_disk_details(disk.id, disk.size, None);
|
let mut disk = get_disk_details(disk.id, disk.size, None);
|
||||||
disk.parts = get_partition_details(disk.id, None, None);
|
disk.parts = get_partition_details(disk.id, None, None);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue