From d3d3462b5ee45f62ddd9eef89736681c610acc10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=E1=BB=A9c=20To=C3=A0n?= <33489972+ndtoan96@users.noreply.github.com> Date: Sat, 30 Sep 2023 14:36:58 +0700 Subject: [PATCH 1/2] fix: Windows build and add github action (#228) --- .github/workflows/rust.yml | 25 +++++++++++++++++++++++++ app/src/manager/folder.rs | 11 +++++++++-- core/src/manager/finder.rs | 21 ++++++--------------- shared/src/fs.rs | 1 + 4 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 00000000..617841b2 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,25 @@ +name: Rust + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/app/src/manager/folder.rs b/app/src/manager/folder.rs index 31b633cd..6f018c2e 100644 --- a/app/src/manager/folder.rs +++ b/app/src/manager/folder.rs @@ -65,12 +65,19 @@ impl<'a> Folder<'a> { let v = self.is_find.then_some(()).and_then(|_| { let finder = self.cx.manager.active().finder()?; - let (head, body, tail) = finder.explode(short.name)?; + #[cfg(target_os = "windows")] + let (head, body, tail) = finder.explode(short.name.to_string_lossy().as_bytes())?; + + #[cfg(not(target_os = "windows"))] + let (head, body, tail) = { + use std::os::unix::ffi::OsStrExt; + finder.explode(short.name.as_bytes())? + }; // TODO: to be configured by THEME? let style = Style::new().fg(Color::Rgb(255, 255, 50)).add_modifier(Modifier::ITALIC); Some(vec![ - Span::raw(short.prefix.join(head.as_ref()).display().to_string()), + Span::raw(short.prefix.join(head).display().to_string()), Span::styled(body, style), Span::raw(tail), ]) diff --git a/core/src/manager/finder.rs b/core/src/manager/finder.rs index e6a7cea1..414de6b2 100644 --- a/core/src/manager/finder.rs +++ b/core/src/manager/finder.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::BTreeMap, ffi::OsStr}; +use std::{collections::BTreeMap, ffi::OsStr}; use anyhow::Result; use regex::bytes::Regex; @@ -111,21 +111,12 @@ impl Finder { /// Explode the name into three parts: head, body, tail. #[inline] - pub fn explode<'a>(&self, name: &'a OsStr) -> Option<(Cow<'a, str>, Cow<'a, str>, Cow<'a, str>)> { - #[cfg(target_os = "windows")] - let b = { name.to_string_lossy().as_bytes() }; - - #[cfg(not(target_os = "windows"))] - let b = { - use std::os::unix::ffi::OsStrExt; - name.as_bytes() - }; - - let range = self.query.find(b).map(|m| m.range())?; + pub fn explode(&self, name: &[u8]) -> Option<(String, String, String)> { + let range = self.query.find(name).map(|m| m.range())?; Some(( - String::from_utf8_lossy(&b[..range.start]), - String::from_utf8_lossy(&b[range.start..range.end]), - String::from_utf8_lossy(&b[range.end..]), + String::from_utf8_lossy(&name[..range.start]).to_string(), + String::from_utf8_lossy(&name[range.start..range.end]).to_string(), + String::from_utf8_lossy(&name[range.end..]).to_string(), )) } } diff --git a/shared/src/fs.rs b/shared/src/fs.rs index 04801be6..66b260f3 100644 --- a/shared/src/fs.rs +++ b/shared/src/fs.rs @@ -172,6 +172,7 @@ pub fn max_common_root(files: &[impl AsRef]) -> PathBuf { root } +#[cfg(not(target_os = "windows"))] #[test] fn test_max_common_root() { assert_eq!(max_common_root(&[] as &[PathBuf]).as_os_str(), ""); From 5584ba48442c780d5a2b2c49419b19ee746c0b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sat, 30 Sep 2023 20:43:47 +0800 Subject: [PATCH 2/2] fix: set stdio to null when `orphan` is true (#229) --- core/src/external/shell.rs | 65 +++++++++++++++++-------------- core/src/tasks/workers/process.rs | 24 ++++++++---- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/core/src/external/shell.rs b/core/src/external/shell.rs index 2ca8f185..4285c7a7 100644 --- a/core/src/external/shell.rs +++ b/core/src/external/shell.rs @@ -15,37 +15,44 @@ impl ShellOpt { self.piped = true; self } + + #[inline] + fn stdio(&self) -> Stdio { + if self.orphan { + Stdio::null() + } else if self.piped { + Stdio::piped() + } else { + Stdio::inherit() + } + } } pub fn shell(opt: ShellOpt) -> Result { - #[cfg(not(target_os = "windows"))] - { - Ok( - Command::new("sh") - .arg("-c") - .arg(opt.cmd) - .arg("") // $0 is the command name - .args(opt.args) - .stdin(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) - .stdout(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) - .stderr(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) - .kill_on_drop(!opt.orphan) - .spawn()?, - ) - } + #[cfg(unix)] + return Ok( + Command::new("sh") + .arg("-c") + .stdin(opt.stdio()) + .stdout(opt.stdio()) + .stderr(opt.stdio()) + .arg(opt.cmd) + .arg("") // $0 is the command name + .args(opt.args) + .kill_on_drop(!opt.orphan) + .spawn()?, + ); - #[cfg(target_os = "windows")] - { - Ok( - Command::new("cmd") - .arg("/C") - .arg(opt.cmd) - .args(opt.args) - .stdin(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) - .stdout(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) - .stderr(if opt.piped { Stdio::piped() } else { Stdio::inherit() }) - .kill_on_drop(true) - .spawn()?, - ) - } + #[cfg(windows)] + return Ok( + Command::new("cmd") + .stdin(opt.stdio()) + .stdout(opt.stdio()) + .stderr(opt.stdio()) + .arg("/C") + .arg(opt.cmd) + .args(opt.args) + .kill_on_drop(true) + .spawn()?, + ); } diff --git a/core/src/tasks/workers/process.rs b/core/src/tasks/workers/process.rs index 6bed7b44..b45c86f7 100644 --- a/core/src/tasks/workers/process.rs +++ b/core/src/tasks/workers/process.rs @@ -2,7 +2,6 @@ use std::{ffi::OsString, mem}; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}}; -use tracing::trace; use crate::{emit, external::{self, ShellOpt}, tasks::TaskOp, BLOCKER}; @@ -41,26 +40,37 @@ impl Process { fn done(&self, id: usize) -> Result<()> { Ok(self.sch.send(TaskOp::Done(id))?) } pub(crate) async fn open(&self, mut task: ProcessOpOpen) -> Result<()> { + let opt = ShellOpt::from(&mut task); if task.block { let _guard = BLOCKER.acquire().await.unwrap(); emit!(Stop(true)).await; - match external::shell(ShellOpt::from(&mut task)) { + match external::shell(opt) { Ok(mut child) => { child.wait().await.ok(); + self.done(task.id)?; } Err(e) => { - trace!("Failed to spawn process: {e}"); + self.sch.send(TaskOp::New(task.id, 0))?; + self.log(task.id, format!("Failed to spawn process: {e}"))?; } } - emit!(Stop(false)).await; + return Ok(emit!(Stop(false)).await); + } - self.sch.send(TaskOp::Adv(task.id, 1, 0))?; - return self.done(task.id); + if task.orphan { + match external::shell(opt) { + Ok(_) => self.done(task.id)?, + Err(e) => { + self.sch.send(TaskOp::New(task.id, 0))?; + self.log(task.id, format!("Failed to spawn process: {e}"))?; + } + } + return Ok(()); } self.sch.send(TaskOp::New(task.id, 0))?; - let mut child = external::shell(ShellOpt::from(&mut task).with_piped())?; + let mut child = external::shell(opt.with_piped())?; let mut stdout = BufReader::new(child.stdout.take().unwrap()).lines(); let mut stderr = BufReader::new(child.stderr.take().unwrap()).lines();