Skip to content

Commit e62c9ea

Browse files
fix: properly support quoted commands
1 parent 37de6c1 commit e62c9ea

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

winapps/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ thiserror = "2.0.9"
1515
enum_dispatch = "0.3.13"
1616
base64 = "0.22.1"
1717
regex = "1.11.2"
18+
shlex = "1.3.0"

winapps/src/command.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use crate::{Config, Error, IntoResult, Result, ensure};
1+
use crate::{Config, Error, IntoResult, Result, bail, ensure};
2+
use shlex::{split, try_join};
23
use std::{
34
fmt::{Display, Formatter},
5+
iter,
46
process::{Child, Command as StdCommand, Stdio},
57
str::FromStr,
68
};
@@ -27,23 +29,15 @@ impl FromStr for Command {
2729
fn from_str(command: &str) -> std::result::Result<Self, Self::Err> {
2830
ensure!(!command.is_empty(), Error::EmptyCommand);
2931

30-
let (exec, args) = if command.contains(" ") {
31-
let mut split = command.split(" ");
32-
33-
(
34-
split
35-
.next()
36-
.expect("There should always be at least one element in the split if the command contains a space")
37-
.to_string(),
38-
split.map(|s| s.to_string()).collect::<Vec<String>>(),
39-
)
40-
} else {
41-
(command.to_string(), Vec::new())
32+
let mut items = split(command).unwrap_or(Vec::new()).into_iter();
33+
34+
let Some(exec) = items.next() else {
35+
bail!("Commands should have an executable")
4236
};
4337

4438
Ok(Self {
4539
exec,
46-
args,
40+
args: items.collect(),
4741
error_message: String::from("Error running child command"),
4842
loud: false,
4943
})
@@ -61,7 +55,9 @@ impl Command {
6155
}
6256

6357
pub fn into_remote(mut self, config: &Config) -> Self {
64-
let prev = format!("{} {}", self.exec, self.args.join(" "));
58+
let prev =
59+
try_join(iter::once(self.exec.as_str()).chain(self.args.iter().map(|s| s.as_str())))
60+
.expect("Since this has been created by shlex::join, it should always be valid");
6561

6662
self.exec = "sshpass".to_string();
6763
self.clear_args()

0 commit comments

Comments
 (0)