mirror of
https://github.com/nukesor/pueue
synced 2024-07-22 02:34:22 +00:00
Better support for windows
This commit is contained in:
parent
e5eb58ec5f
commit
48cd7a3c7d
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -1082,7 +1082,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1208,15 +1207,6 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
|
@ -1500,7 +1490,6 @@ dependencies = [
|
|||
"checksum syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0"
|
||||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
|
|
|
@ -34,10 +34,8 @@ path = "shared/lib.rs"
|
|||
anyhow = "1"
|
||||
async-std = { version = "1", features = ["attributes", "unstable"] }
|
||||
dirs = "2"
|
||||
users = "^0.9"
|
||||
chrono = { version = "^0.4", features = ["serde"] }
|
||||
rand = "^0.7"
|
||||
nix = "0.16"
|
||||
strum = "0.17"
|
||||
strum_macros = "0.17"
|
||||
|
||||
|
@ -50,8 +48,12 @@ serde_derive = "^1.0"
|
|||
|
||||
log = "0.4"
|
||||
config = "^0.10"
|
||||
simplelog = "0.7"
|
||||
simplelog = { version = "0.7", default-features = false }
|
||||
structopt = "0.3"
|
||||
crossterm = "^0.15"
|
||||
comfy-table= "0.0.6"
|
||||
tempfile = "^3"
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
users = "^0.9"
|
||||
nix = "0.16"
|
||||
|
|
|
@ -8,9 +8,11 @@ use ::std::time::Duration;
|
|||
use ::anyhow::Result;
|
||||
use ::chrono::prelude::*;
|
||||
use ::log::{debug, error, info, warn};
|
||||
use ::nix::sys::signal;
|
||||
use ::nix::sys::signal::Signal;
|
||||
use ::nix::unistd::Pid;
|
||||
#[cfg(not(windows))]
|
||||
use ::nix::{
|
||||
sys::signal::{self, Signal},
|
||||
unistd::Pid,
|
||||
};
|
||||
|
||||
use ::pueue::log::*;
|
||||
use ::pueue::message::*;
|
||||
|
@ -119,8 +121,10 @@ impl TaskHandler {
|
|||
};
|
||||
|
||||
// Spawn the actual subprocess
|
||||
let spawn_result = Command::new("sh")
|
||||
.arg("-c")
|
||||
let spawn_result = Command::new(if cfg!(windows) { "cmd" } else { "sh" })
|
||||
// Windows: Tell cmd to output everything using unicode.
|
||||
.args(if cfg!(windows) { Some("/U") } else { None })
|
||||
.arg(if cfg!(windows) { "/C" } else { "-c" })
|
||||
.arg(&task.command)
|
||||
.current_dir(&task.path)
|
||||
.stdin(Stdio::piped())
|
||||
|
@ -258,6 +262,7 @@ impl TaskHandler {
|
|||
}
|
||||
|
||||
/// Send a signal to a unix process
|
||||
#[cfg(not(windows))]
|
||||
fn send_signal(&mut self, id: usize, signal: Signal) -> Result<bool, nix::Error> {
|
||||
if let Some(child) = self.children.get(&id) {
|
||||
debug!("Sending signal {} to {}", signal, id);
|
||||
|
@ -319,12 +324,19 @@ impl TaskHandler {
|
|||
return;
|
||||
}
|
||||
}
|
||||
match self.send_signal(id, Signal::SIGCONT) {
|
||||
Err(err) => warn!("Failed starting task {}: {:?}", id, err),
|
||||
Ok(success) => {
|
||||
if success {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
state.change_status(id, TaskStatus::Running);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
warn!("Failed starting task {}: not supported on windows.", id);
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
match self.send_signal(id, Signal::SIGCONT) {
|
||||
Err(err) => warn!("Failed starting task {}: {:?}", id, err),
|
||||
Ok(success) => {
|
||||
if success {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
state.change_status(id, TaskStatus::Running);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,12 +371,19 @@ impl TaskHandler {
|
|||
if !self.children.contains_key(&id) {
|
||||
return;
|
||||
}
|
||||
match self.send_signal(id, Signal::SIGSTOP) {
|
||||
Err(err) => info!("Failed pausing task {}: {:?}", id, err),
|
||||
Ok(success) => {
|
||||
if success {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
state.change_status(id, TaskStatus::Paused);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
info!("Failed pausing task {}: not supported on windows.", id);
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
match self.send_signal(id, Signal::SIGSTOP) {
|
||||
Err(err) => info!("Failed pausing task {}: {:?}", id, err),
|
||||
Ok(success) => {
|
||||
if success {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
state.change_status(id, TaskStatus::Paused);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use ::anyhow::Result;
|
||||
use ::byteorder::{LittleEndian, ReadBytesExt};
|
||||
use ::log::error;
|
||||
use ::std::borrow::Cow;
|
||||
use ::std::fs::{remove_file, File};
|
||||
use ::std::io::prelude::*;
|
||||
use ::std::path::{Path, PathBuf};
|
||||
|
@ -32,6 +34,30 @@ pub fn get_log_file_handles(task_id: usize, settings: &Settings) -> Result<(File
|
|||
Ok((stdout, stderr))
|
||||
}
|
||||
|
||||
fn command_data_to_text(mut data: &[u8]) -> Cow<str> {
|
||||
if cfg!(windows) {
|
||||
// On windows we run the command using "cmd" with a flag that makes it output Unicode (UTF16).
|
||||
|
||||
let is_odd = data.len() % 2 == 1;
|
||||
let mut buffer = Vec::with_capacity(data.len() / 2 + if is_odd { 1 } else { 0 });
|
||||
|
||||
type CmdUtf16Endian = LittleEndian;
|
||||
|
||||
while data.len() > 1 {
|
||||
buffer.push(data.read_u16::<CmdUtf16Endian>().unwrap());
|
||||
}
|
||||
if is_odd {
|
||||
let extra = [*data.last().unwrap(), 0];
|
||||
let mut extra = &extra as &[u8];
|
||||
buffer.push(extra.read_u16::<CmdUtf16Endian>().unwrap());
|
||||
}
|
||||
|
||||
Cow::from(String::from_utf16_lossy(&buffer))
|
||||
} else {
|
||||
String::from_utf8_lossy(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the content of temporary stdout and stderr files for a task
|
||||
pub fn read_log_files(task_id: usize, settings: &Settings) -> Result<(String, String)> {
|
||||
let (mut stdout_handle, mut stderr_handle) = get_log_file_handles(task_id, settings)?;
|
||||
|
@ -41,8 +67,8 @@ pub fn read_log_files(task_id: usize, settings: &Settings) -> Result<(String, St
|
|||
stdout_handle.read_to_end(&mut stdout_buffer)?;
|
||||
stderr_handle.read_to_end(&mut stderr_buffer)?;
|
||||
|
||||
let stdout = String::from_utf8_lossy(&stdout_buffer);
|
||||
let stderr = String::from_utf8_lossy(&stderr_buffer);
|
||||
let stdout = command_data_to_text(&stdout_buffer);
|
||||
let stderr = command_data_to_text(&stderr_buffer);
|
||||
|
||||
Ok((stdout.to_string(), stderr.to_string()))
|
||||
}
|
||||
|
|
|
@ -153,3 +153,32 @@ fn default_pueue_path() -> Result<String> {
|
|||
|v| Ok(v.to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn default_config_path() -> Result<PathBuf> {
|
||||
Ok(get_home_dir()?.join("pueue.yml"))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn get_config_paths() -> Result<Vec<PathBuf>> {
|
||||
Ok(vec![
|
||||
// Windows Terminal stores its config file in the "AppData/Local" directory.
|
||||
dirs::data_local_dir()
|
||||
.ok_or(anyhow!("Couldn't resolve app data directory"))?
|
||||
.join("pueue/pueue.yml"),
|
||||
default_config_path()?,
|
||||
Path::new("./pueue.yml").to_path_buf(),
|
||||
])
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn default_pueue_path() -> Result<String> {
|
||||
// Use local data directory since this data doesn't need to be synced.
|
||||
let path = dirs::data_local_dir()
|
||||
.ok_or(anyhow!("Couldn't resolve app data directory"))?
|
||||
.join("pueue");
|
||||
path.to_str().map_or_else(
|
||||
|| Err(anyhow!("Failed to parse log path (Weird characters?)")),
|
||||
|v| Ok(v.to_string()),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue