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:
2Shirt 2024-11-11 00:03:49 -08:00
parent dd03962c84
commit 2a5167bf52
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
7 changed files with 49 additions and 30 deletions

View file

@ -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
},
} }
} }

View file

@ -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(

View file

@ -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"),
} }
} }
_ => {} _ => {}

View file

@ -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()

View file

@ -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)
} }

View file

@ -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()

View file

@ -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);