// This file is part of Deja-Vu.
//
// Deja-Vu is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Deja-Vu is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Deja-Vu. If not, see .
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)]
use std::{
collections::VecDeque,
fmt,
path::PathBuf,
process::{Command, Stdio},
sync::{Arc, Mutex},
thread::{self, JoinHandle, sleep},
time::Duration,
};
use color_eyre::Result;
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc;
use tracing::info;
use crate::{
action::Action,
components::popup,
system::{disk, diskpart},
};
#[derive(Clone, Debug)]
pub enum TaskResult {
Error(String),
Output(String, String, bool), // stdout, stderr, success
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum TaskType {
CommandNoWait(PathBuf, Vec), // (command, args)
CommandWait(PathBuf, Vec), // (command, args)
Diskpart(String), // (script_as_string)
ScanDisks,
Sleep,
TestPaths(Vec),
UpdateDestDisk(usize), // (disk_index)
UpdateDiskList,
}
impl fmt::Display for TaskType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TaskType::CommandNoWait(cmd_path, _) | TaskType::CommandWait(cmd_path, _) => {
write!(
f,
"Command(\"{}\")",
cmd_path.file_name().unwrap().to_string_lossy()
)
}
TaskType::Diskpart(_) => {
write!(f, "Diskpart")
}
TaskType::ScanDisks => write!(f, "ScanDisks"),
TaskType::Sleep => write!(f, "Sleep"),
TaskType::TestPaths(_) => write!(f, "TestPaths"),
TaskType::UpdateDestDisk(_) => write!(f, "UpdateDestDisk"),
TaskType::UpdateDiskList => write!(f, "UpdateDiskList"),
}
}
}
#[derive(Debug)]
pub struct Task {
pub handle: Option>,
pub result: Option,
pub task_type: TaskType,
}
impl Task {
#[must_use]
pub fn new(task_type: TaskType) -> Task {
Task {
handle: None,
result: None,
task_type,
}
}
}
#[derive(Debug)]
pub struct Tasks {
action_tx: mpsc::UnboundedSender,
disk_list: Arc>>,
cur_handle: Option>,
cur_task: Option,
task_list: VecDeque,
task_rx: mpsc::UnboundedReceiver,
task_tx: mpsc::UnboundedSender,
}
impl Tasks {
pub fn new(
action_tx: mpsc::UnboundedSender,
disk_list_arc: Arc>>,
) -> Self {
let (task_tx, task_rx) = mpsc::unbounded_channel();
Tasks {
action_tx,
disk_list: disk_list_arc,
cur_handle: None,
cur_task: None,
task_list: VecDeque::new(),
task_rx,
task_tx,
}
}
pub fn add(&mut self, task_type: TaskType) {
info!("Adding task: {:?}", &task_type);
self.task_list.push_back(Task::new(task_type));
}
#[must_use]
pub fn idle(&self) -> bool {
self.cur_handle.is_none()
}
pub fn poll(&mut self) -> Result