Refactored to add command and diskpart script support
Replaced previous background task setup to ensure tasks are run sequentially and not in parallel
This commit is contained in:
parent
c9884d5b6d
commit
61e539e071
6 changed files with 178 additions and 92 deletions
|
|
@ -37,7 +37,7 @@ pub enum Action {
|
||||||
Select(Option<usize>, Option<usize>), // indicies for (source, dest) or (boot, os)
|
Select(Option<usize>, Option<usize>), // indicies for (source, dest) or (boot, os)
|
||||||
SelectDriver(Driver),
|
SelectDriver(Driver),
|
||||||
SelectTableType(PartitionTableType),
|
SelectTableType(PartitionTableType),
|
||||||
UpdateDestDisk,
|
UpdateDestDisk(usize), // (disk_index)
|
||||||
UpdateDiskList(Vec<Disk>),
|
UpdateDiskList(Vec<Disk>),
|
||||||
// Screens
|
// Screens
|
||||||
DismissPopup,
|
DismissPopup,
|
||||||
|
|
|
||||||
255
src/app.rs
255
src/app.rs
|
|
@ -14,9 +14,11 @@
|
||||||
// along with Deja-vu. If not, see <https://www.gnu.org/licenses/>.
|
// along with Deja-vu. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::VecDeque,
|
||||||
env,
|
env,
|
||||||
iter::zip,
|
iter::zip,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
process::{Command, Stdio},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
thread::{self, sleep, JoinHandle},
|
thread::{self, sleep, JoinHandle},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
|
@ -40,12 +42,131 @@ use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
system::{
|
system::{
|
||||||
disk::{get_disks, refresh_disk_info, Disk, PartitionTableType},
|
disk::{get_disks, refresh_disk_info, Disk, PartitionTableType},
|
||||||
diskpart::build_dest_format_script,
|
diskpart::{build_dest_format_script, run_script_raw},
|
||||||
drivers::{self, Driver},
|
drivers::{self, Driver},
|
||||||
},
|
},
|
||||||
tui::{Event, Tui},
|
tui::{Event, Tui},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Tasks {
|
||||||
|
action_tx: mpsc::UnboundedSender<Action>,
|
||||||
|
disk_list: Arc<Mutex<Vec<Disk>>>,
|
||||||
|
handle: Option<JoinHandle<()>>,
|
||||||
|
task_list: VecDeque<Action>,
|
||||||
|
task_rx: mpsc::UnboundedReceiver<Action>,
|
||||||
|
task_tx: mpsc::UnboundedSender<Action>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tasks {
|
||||||
|
pub fn add(&mut self, task: Action) {
|
||||||
|
self.task_list.push_back(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn idle(&self) -> bool {
|
||||||
|
self.handle.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll(&mut self) -> Result<()> {
|
||||||
|
debug!("Polling tasks {:?} // {:?}", &self.handle, &self.task_list);
|
||||||
|
|
||||||
|
// Forward any errors (actions) to main app
|
||||||
|
if let Ok(action) = self.task_rx.try_recv() {
|
||||||
|
let result = self.action_tx.send(action.clone());
|
||||||
|
if result.is_err() {
|
||||||
|
panic!("Failed to send Action: {action:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check status of current task (if one is running).
|
||||||
|
// NOTE: Action::NextScreen is sent once all tasks are complete
|
||||||
|
if let Some(handle) = self.handle.take() {
|
||||||
|
if handle.is_finished() {
|
||||||
|
if self.task_list.is_empty() {
|
||||||
|
// No tasks remain
|
||||||
|
self.task_tx.send(Action::NextScreen)?;
|
||||||
|
} else {
|
||||||
|
// Start next task
|
||||||
|
self.start()?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Task not complete, return handle
|
||||||
|
self.handle = Some(handle);
|
||||||
|
}
|
||||||
|
} else if !self.task_list.is_empty() {
|
||||||
|
// No current task but one is available
|
||||||
|
self.start()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(&mut self) -> Result<()> {
|
||||||
|
if let Some(task) = self.task_list.pop_front() {
|
||||||
|
info!("Starting task: {task:?}");
|
||||||
|
let task_str = format!("{task:?}");
|
||||||
|
let task_tx = self.task_tx.clone();
|
||||||
|
match task {
|
||||||
|
Action::Command(ref cmd_path, ref cmd_args) => {
|
||||||
|
let cmd_path = cmd_path.clone();
|
||||||
|
let cmd_args = cmd_args.clone();
|
||||||
|
if cfg!(windows) {
|
||||||
|
self.handle = Some(thread::spawn(move || {
|
||||||
|
let output = Command::new(cmd_path)
|
||||||
|
.args(cmd_args)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.output();
|
||||||
|
if output.is_err() {
|
||||||
|
if let Err(_) = task_tx
|
||||||
|
.send(Action::Error(String::from("Failed to run command")))
|
||||||
|
{
|
||||||
|
panic!("Failed to send Action: {task_str:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
// Simulate task if not running under Windows
|
||||||
|
self.handle = Some(thread::spawn(|| sleep(Duration::from_secs(1))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Action::Diskpart(ref script) => {
|
||||||
|
if cfg!(windows) {
|
||||||
|
let script = String::from(script);
|
||||||
|
self.handle = Some(thread::spawn(move || {
|
||||||
|
let output = run_script_raw(script.as_str());
|
||||||
|
if !output.status.success() {
|
||||||
|
if let Err(_) = task_tx.send(Action::Error(String::from(
|
||||||
|
"Diskpart script returned an error",
|
||||||
|
))) {
|
||||||
|
panic!("Failed to send Action: {task_str:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
// Simulate task if not running under Windows
|
||||||
|
self.handle = Some(thread::spawn(|| sleep(Duration::from_secs(1))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Action::ScanDisks => {
|
||||||
|
let disk_list_arc = self.disk_list.clone();
|
||||||
|
self.handle = Some(thread::spawn(move || {
|
||||||
|
let mut disks = disk_list_arc.lock().unwrap();
|
||||||
|
*disks = get_disks();
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
Action::UpdateDestDisk(index) => {
|
||||||
|
let disk_list_arc = self.disk_list.clone();
|
||||||
|
self.handle = Some(thread::spawn(move || {
|
||||||
|
let mut disks = disk_list_arc.lock().unwrap();
|
||||||
|
refresh_disk_info(&mut disks[index]);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
// TUI
|
// TUI
|
||||||
action_rx: mpsc::UnboundedReceiver<Action>,
|
action_rx: mpsc::UnboundedReceiver<Action>,
|
||||||
|
|
@ -68,7 +189,7 @@ pub struct App {
|
||||||
prev_mode: Mode,
|
prev_mode: Mode,
|
||||||
selections: Vec<Option<usize>>,
|
selections: Vec<Option<usize>>,
|
||||||
table_type: Option<PartitionTableType>,
|
table_type: Option<PartitionTableType>,
|
||||||
task_handles: Vec<JoinHandle<()>>,
|
tasks: Tasks,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
|
@ -81,6 +202,7 @@ pub enum Mode {
|
||||||
Confirm,
|
Confirm,
|
||||||
PreClone,
|
PreClone,
|
||||||
Clone,
|
Clone,
|
||||||
|
UpdateDestDisk,
|
||||||
SelectParts,
|
SelectParts,
|
||||||
PostClone,
|
PostClone,
|
||||||
Done,
|
Done,
|
||||||
|
|
@ -90,6 +212,17 @@ pub enum Mode {
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
|
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
|
||||||
let (action_tx, action_rx) = mpsc::unbounded_channel();
|
let (action_tx, action_rx) = mpsc::unbounded_channel();
|
||||||
|
let (task_tx, task_rx) = mpsc::unbounded_channel();
|
||||||
|
let disk_list = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
let mut tasks = Tasks {
|
||||||
|
action_tx: action_tx.clone(),
|
||||||
|
disk_list: disk_list.clone(),
|
||||||
|
handle: None,
|
||||||
|
task_list: VecDeque::new(),
|
||||||
|
task_rx,
|
||||||
|
task_tx,
|
||||||
|
};
|
||||||
|
tasks.add(Action::ScanDisks);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
// TUI
|
// TUI
|
||||||
action_rx,
|
action_rx,
|
||||||
|
|
@ -112,14 +245,14 @@ impl App {
|
||||||
cur_mode: Mode::ScanDisks,
|
cur_mode: Mode::ScanDisks,
|
||||||
disk_index_dest: None,
|
disk_index_dest: None,
|
||||||
disk_index_source: None,
|
disk_index_source: None,
|
||||||
disk_list: Arc::new(Mutex::new(Vec::new())),
|
disk_list,
|
||||||
driver: None,
|
driver: None,
|
||||||
part_index_boot: None,
|
part_index_boot: None,
|
||||||
part_index_os: None,
|
part_index_os: None,
|
||||||
prev_mode: Mode::ScanDisks,
|
prev_mode: Mode::ScanDisks,
|
||||||
selections: vec![None, None],
|
selections: vec![None, None],
|
||||||
table_type: None,
|
table_type: None,
|
||||||
task_handles: Vec::new(),
|
tasks,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +270,8 @@ impl App {
|
||||||
(Mode::SelectDisks, Mode::Confirm) => Mode::SelectTableType,
|
(Mode::SelectDisks, Mode::Confirm) => Mode::SelectTableType,
|
||||||
(Mode::SelectTableType, Mode::Confirm) => Mode::PreClone,
|
(Mode::SelectTableType, Mode::Confirm) => Mode::PreClone,
|
||||||
(_, Mode::PreClone) => Mode::Clone,
|
(_, Mode::PreClone) => Mode::Clone,
|
||||||
(_, Mode::Clone) => Mode::SelectParts,
|
(_, Mode::Clone) => Mode::UpdateDestDisk,
|
||||||
|
(_, Mode::UpdateDestDisk) => Mode::SelectParts,
|
||||||
(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,
|
||||||
|
|
@ -163,8 +297,6 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&mut self) -> Result<()> {
|
pub async fn run(&mut self) -> Result<()> {
|
||||||
let disk_list_arc = Arc::clone(&self.disk_list);
|
|
||||||
self.task_handles.push(lazy_get_disks(disk_list_arc));
|
|
||||||
let mut tui = Tui::new()?
|
let mut tui = Tui::new()?
|
||||||
// .mouse(true) // uncomment this line to enable mouse support
|
// .mouse(true) // uncomment this line to enable mouse support
|
||||||
.tick_rate(self.tick_rate)
|
.tick_rate(self.tick_rate)
|
||||||
|
|
@ -255,21 +387,13 @@ impl App {
|
||||||
Action::Tick => {
|
Action::Tick => {
|
||||||
self.last_tick_key_events.drain(..);
|
self.last_tick_key_events.drain(..);
|
||||||
match self.cur_mode {
|
match self.cur_mode {
|
||||||
Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone => {
|
Mode::ScanDisks
|
||||||
|
| Mode::PreClone
|
||||||
|
| Mode::Clone
|
||||||
|
| Mode::UpdateDestDisk
|
||||||
|
| Mode::PostClone => {
|
||||||
// Check background task
|
// Check background task
|
||||||
if let Ok(_) = &self.disk_list.try_lock() {
|
self.tasks.poll()?; // Once all are complete Action::NextScreen is sent
|
||||||
if self.task_handles.is_empty() {
|
|
||||||
// All tasks complete
|
|
||||||
self.action_tx.send(Action::NextScreen)?;
|
|
||||||
} else {
|
|
||||||
// Tasks remain, check if current is complete
|
|
||||||
if let Some(handle) = self.task_handles.first() {
|
|
||||||
if handle.is_finished() {
|
|
||||||
self.task_handles.remove(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -279,10 +403,13 @@ impl App {
|
||||||
Action::Resume => self.should_suspend = false,
|
Action::Resume => self.should_suspend = false,
|
||||||
Action::ClearScreen => tui.terminal.clear()?,
|
Action::ClearScreen => tui.terminal.clear()?,
|
||||||
Action::Command(ref cmd_path, ref cmd_args) => self
|
Action::Command(ref cmd_path, ref cmd_args) => self
|
||||||
.task_handles
|
.tasks
|
||||||
.push(lazy_command(&cmd_path, cmd_args.clone())),
|
.add(Action::Command(cmd_path.clone(), cmd_args.clone())),
|
||||||
Action::Diskpart(ref script) => {
|
Action::Diskpart(ref script) => self.tasks.add(Action::Diskpart(script.clone())),
|
||||||
self.task_handles.push(lazy_diskpart(&script.to_owned()))
|
Action::Error(ref msg) => {
|
||||||
|
self.action_tx
|
||||||
|
.send(Action::DisplayPopup(popup::Type::Error, msg.clone()))?;
|
||||||
|
self.action_tx.send(Action::SetMode(Mode::Failed))?;
|
||||||
}
|
}
|
||||||
Action::InstallDriver => {
|
Action::InstallDriver => {
|
||||||
self.action_tx.send(Action::SetMode(Mode::InstallDrivers))?
|
self.action_tx.send(Action::SetMode(Mode::InstallDrivers))?
|
||||||
|
|
@ -307,11 +434,7 @@ impl App {
|
||||||
self.action_tx.send(Action::SetMode(mode))?;
|
self.action_tx.send(Action::SetMode(mode))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::ScanDisks => {
|
Action::ScanDisks => self.action_tx.send(Action::SetMode(Mode::ScanDisks))?,
|
||||||
let disk_list_arc = Arc::clone(&self.disk_list);
|
|
||||||
self.task_handles.push(lazy_get_disks(disk_list_arc));
|
|
||||||
self.action_tx.send(Action::SetMode(Mode::ScanDisks))?;
|
|
||||||
}
|
|
||||||
Action::Select(one, two) => {
|
Action::Select(one, two) => {
|
||||||
match self.cur_mode {
|
match self.cur_mode {
|
||||||
Mode::SelectDisks => {
|
Mode::SelectDisks => {
|
||||||
|
|
@ -333,6 +456,9 @@ impl App {
|
||||||
match new_mode {
|
match new_mode {
|
||||||
Mode::ScanDisks => {
|
Mode::ScanDisks => {
|
||||||
self.prev_mode = self.cur_mode;
|
self.prev_mode = self.cur_mode;
|
||||||
|
if self.tasks.idle() {
|
||||||
|
self.tasks.add(Action::ScanDisks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Mode::SelectDisks | Mode::SelectParts => {
|
Mode::SelectDisks | Mode::SelectParts => {
|
||||||
let disk_list = self.disk_list.lock().unwrap();
|
let disk_list = self.disk_list.lock().unwrap();
|
||||||
|
|
@ -365,7 +491,11 @@ impl App {
|
||||||
self.config.clone_app_path.clone(),
|
self.config.clone_app_path.clone(),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
))?;
|
))?;
|
||||||
self.action_tx.send(Action::UpdateDestDisk)?;
|
}
|
||||||
|
Mode::UpdateDestDisk => {
|
||||||
|
if let Some(dest_index) = self.disk_index_dest {
|
||||||
|
self.action_tx.send(Action::UpdateDestDisk(dest_index))?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Mode::PostClone => {
|
Mode::PostClone => {
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
self.action_tx.send(Action::DisplayPopup(
|
||||||
|
|
@ -378,11 +508,9 @@ impl App {
|
||||||
match env::var("SYSTEMROOT") {
|
match env::var("SYSTEMROOT") {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
self.action_tx.send(Action::Error(String::from(
|
||||||
popup::Type::Error,
|
"ERROR\n\n\nFailed to find SYSTEMROOT",
|
||||||
String::from("ERROR\n\n\nFailed to find SYSTEMROOT"),
|
)))?;
|
||||||
))?;
|
|
||||||
self.action_tx.send(Action::SetMode(Mode::Failed))?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -402,13 +530,9 @@ impl App {
|
||||||
|
|
||||||
// Safety check
|
// Safety check
|
||||||
if letter_boot.is_empty() || letter_os.is_empty() {
|
if letter_boot.is_empty() || letter_os.is_empty() {
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
self.action_tx.send(Action::Error(String::from(
|
||||||
popup::Type::Error,
|
"ERROR\n\n\nFailed to get drive letters for the destination",
|
||||||
String::from(
|
)))?;
|
||||||
"ERROR\n\n\nFailed to get drive letters for the destination",
|
|
||||||
),
|
|
||||||
))?;
|
|
||||||
self.action_tx.send(Action::SetMode(Mode::Failed))?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -489,13 +613,7 @@ impl App {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::UpdateDestDisk => {
|
Action::UpdateDestDisk(index) => self.tasks.add(Action::UpdateDestDisk(index)),
|
||||||
let disk_list_arc = Arc::clone(&self.disk_list);
|
|
||||||
if let Some(dest_index) = self.disk_index_dest {
|
|
||||||
self.task_handles
|
|
||||||
.push(lazy_update_dest_disk(disk_list_arc, dest_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
for component in self.components.iter_mut() {
|
for component in self.components.iter_mut() {
|
||||||
|
|
@ -587,40 +705,3 @@ fn get_chunks(r: Rect) -> Vec<Rect> {
|
||||||
// Done
|
// Done
|
||||||
chunks
|
chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lazy_command(cmd_path: &PathBuf, cmd_args: Vec<String>) -> JoinHandle<()> {
|
|
||||||
info!("Running Command: {cmd_path:?} {cmd_args:?}");
|
|
||||||
if cfg!(windows) {
|
|
||||||
// TODO: FIXME
|
|
||||||
thread::spawn(|| sleep(Duration::from_secs(1)))
|
|
||||||
} else {
|
|
||||||
thread::spawn(|| sleep(Duration::from_secs(1)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lazy_diskpart(script: &str) -> JoinHandle<()> {
|
|
||||||
if cfg!(windows) {
|
|
||||||
// TODO: FIXME
|
|
||||||
thread::spawn(|| sleep(Duration::from_secs(1)))
|
|
||||||
} else {
|
|
||||||
info!("Running (lazy) Diskpart: {:?}", &script);
|
|
||||||
thread::spawn(|| sleep(Duration::from_secs(1)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lazy_get_disks(disk_list_arc: Arc<Mutex<Vec<Disk>>>) -> JoinHandle<()> {
|
|
||||||
thread::spawn(move || {
|
|
||||||
let mut disks = disk_list_arc.lock().unwrap();
|
|
||||||
*disks = get_disks();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lazy_update_dest_disk(
|
|
||||||
disk_list_arc: Arc<Mutex<Vec<Disk>>>,
|
|
||||||
dest_index: usize,
|
|
||||||
) -> JoinHandle<()> {
|
|
||||||
thread::spawn(move || {
|
|
||||||
let mut disks = disk_list_arc.lock().unwrap();
|
|
||||||
refresh_disk_info(&mut disks[dest_index]);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,11 @@ impl Component for Footer {
|
||||||
Action::SetMode(new_mode) => {
|
Action::SetMode(new_mode) => {
|
||||||
self.footer_text = match new_mode {
|
self.footer_text = match new_mode {
|
||||||
Mode::ScanDisks => String::from("(q) to quit"),
|
Mode::ScanDisks => String::from("(q) to quit"),
|
||||||
Mode::PreClone | Mode::Clone | Mode::PostClone | Mode::SelectParts => {
|
Mode::PreClone
|
||||||
|
| Mode::Clone
|
||||||
|
| Mode::UpdateDestDisk
|
||||||
|
| Mode::SelectParts
|
||||||
|
| Mode::PostClone => {
|
||||||
String::from("(Enter) to select / (s) to start over / (q) to quit")
|
String::from("(Enter) to select / (s) to start over / (q) to quit")
|
||||||
}
|
}
|
||||||
Mode::SelectDisks => String::from(
|
Mode::SelectDisks => String::from(
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,7 @@ impl Component for Left {
|
||||||
self.selections[1] = None;
|
self.selections[1] = None;
|
||||||
self.title_text = String::from("Select Partition Table Type");
|
self.title_text = String::from("Select Partition Table Type");
|
||||||
}
|
}
|
||||||
(_, Mode::PreClone | Mode::Clone | Mode::PostClone) => {
|
(_, Mode::PreClone | Mode::Clone | Mode::UpdateDestDisk | Mode::PostClone) => {
|
||||||
self.title_text = String::from("Processing");
|
self.title_text = String::from("Processing");
|
||||||
}
|
}
|
||||||
(_, Mode::SelectParts) => {
|
(_, Mode::SelectParts) => {
|
||||||
|
|
@ -276,6 +276,7 @@ impl Component for Left {
|
||||||
Mode::ScanDisks
|
Mode::ScanDisks
|
||||||
| Mode::PreClone
|
| Mode::PreClone
|
||||||
| Mode::Clone
|
| Mode::Clone
|
||||||
|
| Mode::UpdateDestDisk
|
||||||
| Mode::PostClone
|
| Mode::PostClone
|
||||||
| Mode::Done
|
| Mode::Done
|
||||||
| Mode::Failed => {
|
| Mode::Failed => {
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ impl Component for Right {
|
||||||
.areas(area);
|
.areas(area);
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
let title_text = String::from("Info?");
|
let title_text = String::from("Info");
|
||||||
let title = Paragraph::new(Line::from(title_text).centered())
|
let title = Paragraph::new(Line::from(title_text).centered())
|
||||||
.block(Block::default().borders(Borders::NONE));
|
.block(Block::default().borders(Borders::NONE));
|
||||||
frame.render_widget(title, title_area);
|
frame.render_widget(title, title_area);
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,7 @@ pub fn run_script_raw(script: &str) -> Output {
|
||||||
.args(["/s", format!("{}", script_path.display()).as_str()])
|
.args(["/s", format!("{}", script_path.display()).as_str()])
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.output()
|
.output()
|
||||||
.expect("Failed to execute command");
|
.expect("Failed to execute Diskpart script");
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue