Adapt supervisor to process-wrap (#815)
This commit is contained in:
parent
a6e0b3f70a
commit
75b2c4b4ae
|
@ -564,6 +564,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
|
@ -673,30 +679,6 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "command-group"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"nix 0.26.4",
|
||||
"tokio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "command-group"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a68fa787550392a9d58f44c21a3022cfb3ea3e2458b7f85d3b399d0ceeccf409"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"nix 0.27.1",
|
||||
"tokio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.4.0"
|
||||
|
@ -1758,7 +1740,7 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap 2.1.0",
|
||||
"indexmap 2.2.6",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
|
@ -1874,7 +1856,7 @@ dependencies = [
|
|||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.10",
|
||||
"socket2 0.5.5",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
@ -1904,7 +1886,7 @@ dependencies = [
|
|||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.52.0",
|
||||
"windows-core 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1972,9 +1954,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.3",
|
||||
|
@ -2098,9 +2080,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.151"
|
||||
version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
|
@ -2351,6 +2333,18 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
|
@ -2758,6 +2752,20 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "process-wrap"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df785e1a8a4f462ab97abb49e1718d8ee173f4fc37c29dde7d0487b6538c3a82"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"indexmap 2.2.6",
|
||||
"nix 0.28.0",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"windows 0.56.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prodash"
|
||||
version = "26.2.2"
|
||||
|
@ -3456,9 +3464,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.35.1"
|
||||
version = "1.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
|
||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -3546,7 +3554,7 @@ version = "0.19.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap 2.1.0",
|
||||
"indexmap 2.2.6",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
@ -3557,7 +3565,7 @@ version = "0.21.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
|
||||
dependencies = [
|
||||
"indexmap 2.1.0",
|
||||
"indexmap 2.2.6",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
|
@ -3992,7 +4000,6 @@ dependencies = [
|
|||
"async-priority-channel",
|
||||
"async-recursion",
|
||||
"atomic-take",
|
||||
"command-group 5.0.1",
|
||||
"futures",
|
||||
"ignore-files",
|
||||
"miette",
|
||||
|
@ -4000,6 +4007,7 @@ dependencies = [
|
|||
"normalize-path",
|
||||
"notify",
|
||||
"once_cell",
|
||||
"process-wrap",
|
||||
"project-origins",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
|
@ -4022,7 +4030,6 @@ dependencies = [
|
|||
"clap_complete_nushell",
|
||||
"clap_mangen",
|
||||
"clearscreen",
|
||||
"command-group 2.1.0",
|
||||
"console-subscriber",
|
||||
"dirs 5.0.1",
|
||||
"embed-resource",
|
||||
|
@ -4135,9 +4142,9 @@ name = "watchexec-supervisor"
|
|||
version = "1.0.3"
|
||||
dependencies = [
|
||||
"boxcar",
|
||||
"command-group 5.0.1",
|
||||
"futures",
|
||||
"nix 0.27.1",
|
||||
"process-wrap",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"watchexec-events",
|
||||
|
@ -4217,7 +4224,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core 0.52.0",
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
|
||||
dependencies = [
|
||||
"windows-core 0.56.0",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4235,7 +4252,60 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4253,7 +4323,7 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4273,17 +4343,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
"windows_aarch64_gnullvm 0.52.5",
|
||||
"windows_aarch64_msvc 0.52.5",
|
||||
"windows_i686_gnu 0.52.5",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.5",
|
||||
"windows_x86_64_gnu 0.52.5",
|
||||
"windows_x86_64_gnullvm 0.52.5",
|
||||
"windows_x86_64_msvc 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4294,9 +4365,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
@ -4306,9 +4377,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -4318,9 +4389,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
@ -4330,9 +4407,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
@ -4342,9 +4419,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
@ -4354,9 +4431,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -4366,9 +4443,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
|
|
|
@ -42,10 +42,6 @@ tracing-test = "0.1"
|
|||
uuid = { workspace = true, features = [ "v4", "fast-rng" ] }
|
||||
rand = { workspace = true }
|
||||
|
||||
[dependencies.command-group]
|
||||
version = "2.1.0"
|
||||
features = ["with-tokio"]
|
||||
|
||||
[dependencies.clap]
|
||||
version = "4.4.7"
|
||||
features = ["cargo", "derive", "env", "wrap_help"]
|
||||
|
|
|
@ -232,10 +232,16 @@ pub fn make_config(args: &Args, state: &State) -> Result<Config> {
|
|||
|
||||
if let Some(ref workdir) = workdir.as_ref() {
|
||||
debug!(?workdir, "set command workdir");
|
||||
command.current_dir(workdir);
|
||||
command.command_mut().current_dir(workdir);
|
||||
}
|
||||
|
||||
emit_events_to_command(command, events, emit_file, emit_events_to, add_envs);
|
||||
emit_events_to_command(
|
||||
command.command_mut(),
|
||||
events,
|
||||
emit_file,
|
||||
emit_events_to,
|
||||
add_envs,
|
||||
);
|
||||
});
|
||||
|
||||
let show_events = || {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
## Next (YYYY-MM-DD)
|
||||
|
||||
- Deps: replace command-group with process-wrap (in supervisor, but has flow-on effects)
|
||||
|
||||
## v3.0.1 (2023-11-29)
|
||||
|
||||
- Deps: watchexec-events and watchexec-signals after major bump and yank
|
||||
|
|
|
@ -26,9 +26,9 @@ once_cell = "1.8.0"
|
|||
thiserror = "1.0.44"
|
||||
normalize-path = "0.2.0"
|
||||
|
||||
[dependencies.command-group]
|
||||
version = "5.0.1"
|
||||
features = ["with-tokio"]
|
||||
[dependencies.process-wrap]
|
||||
version = "8.0.0"
|
||||
features = ["tokio1"]
|
||||
|
||||
[dependencies.watchexec-events]
|
||||
version = "2.0.1"
|
||||
|
|
|
@ -68,7 +68,7 @@ async fn main() -> Result<()> {
|
|||
job.set_spawn_hook(|cmd, _| {
|
||||
use nix::sys::signal::{sigprocmask, SigSet, SigmaskHow, Signal};
|
||||
unsafe {
|
||||
cmd.pre_exec(|| {
|
||||
cmd.command_mut().pre_exec(|| {
|
||||
let mut newset = SigSet::empty();
|
||||
newset.add(Signal::SIGINT);
|
||||
sigprocmask(SigmaskHow::SIG_BLOCK, Some(&newset), None)?;
|
||||
|
|
|
@ -47,7 +47,7 @@ async fn main() -> Result<()> {
|
|||
job.set_spawn_hook(|cmd, _| {
|
||||
use nix::sys::signal::{sigprocmask, SigSet, SigmaskHow, Signal};
|
||||
unsafe {
|
||||
cmd.pre_exec(|| {
|
||||
cmd.command_mut().pre_exec(|| {
|
||||
let mut newset = SigSet::empty();
|
||||
newset.add(Signal::SIGINT);
|
||||
sigprocmask(SigmaskHow::SIG_BLOCK, Some(&newset), None)?;
|
||||
|
|
|
@ -140,7 +140,8 @@ impl Watchexec {
|
|||
let notify = Arc::new(Notify::new());
|
||||
let start_lock = notify.clone();
|
||||
|
||||
let (ev_s, ev_r) = priority::bounded(config.event_channel_size.try_into().unwrap_or(u64::MAX));
|
||||
let (ev_s, ev_r) =
|
||||
priority::bounded(config.event_channel_size.try_into().unwrap_or(u64::MAX));
|
||||
let event_input = ev_s.clone();
|
||||
|
||||
trace!("creating main task");
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
## Next (YYYY-MM-DD)
|
||||
|
||||
- Deps: replace command-group with process-wrap
|
||||
|
||||
## v1.0.3 (2023-12-19)
|
||||
|
||||
- Fix Start executing even when the job is running.
|
||||
|
|
|
@ -18,9 +18,9 @@ edition = "2021"
|
|||
futures = "0.3.29"
|
||||
tracing = "0.1.40"
|
||||
|
||||
[dependencies.command-group]
|
||||
version = "5.0.1"
|
||||
features = ["with-tokio"]
|
||||
[dependencies.process-wrap]
|
||||
version = "8.0.0"
|
||||
features = ["reset-sigmask", "tokio1"]
|
||||
|
||||
[dependencies.tokio]
|
||||
version = "1.33.0"
|
||||
|
|
|
@ -61,6 +61,14 @@ pub struct SpawnOptions {
|
|||
/// [Job Objects]: https://en.wikipedia.org/wiki/Object_Manager_(Windows)
|
||||
pub grouped: bool,
|
||||
|
||||
/// Run the program in a new session.
|
||||
///
|
||||
/// This will use Unix [sessions]. On Windows, this is not supported. This
|
||||
/// implies `grouped: true`.
|
||||
///
|
||||
/// [sessions]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html
|
||||
pub session: bool,
|
||||
|
||||
/// Reset the signal mask of the process before we spawn it.
|
||||
///
|
||||
/// By default, the signal mask of the process is inherited from the parent process. This means
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use std::fmt;
|
||||
|
||||
use process_wrap::tokio::{KillOnDrop, TokioCommandWrap};
|
||||
use tokio::process::Command as TokioCommand;
|
||||
use tracing::trace;
|
||||
|
||||
use super::{Command, Program};
|
||||
use super::{Command, Program, SpawnOptions};
|
||||
|
||||
impl Command {
|
||||
/// Obtain a [`tokio::process::Command`].
|
||||
pub fn to_spawnable(&self) -> TokioCommand {
|
||||
/// Obtain a [`process_wrap::tokio::TokioCommandWrap`].
|
||||
pub fn to_spawnable(&self) -> TokioCommandWrap {
|
||||
trace!(program=?self.program, "constructing command");
|
||||
|
||||
#[cfg_attr(not(unix), allow(unused_mut))]
|
||||
let mut cmd = match &self.program {
|
||||
let cmd = match &self.program {
|
||||
Program::Exec { prog, args, .. } => {
|
||||
let mut c = TokioCommand::new(prog);
|
||||
c.args(args);
|
||||
|
@ -56,19 +56,28 @@ impl Command {
|
|||
}
|
||||
};
|
||||
|
||||
let mut cmd = TokioCommandWrap::from(cmd);
|
||||
cmd.wrap(KillOnDrop);
|
||||
|
||||
match self.options {
|
||||
#[cfg(unix)]
|
||||
SpawnOptions { session: true, .. } => {
|
||||
cmd.wrap(process_wrap::tokio::ProcessSession);
|
||||
}
|
||||
#[cfg(unix)]
|
||||
SpawnOptions { grouped: true, .. } => {
|
||||
cmd.wrap(process_wrap::tokio::ProcessGroup::leader());
|
||||
}
|
||||
#[cfg(windows)]
|
||||
SpawnOptions { grouped: true, .. } | SpawnOptions { session: true, .. } => {
|
||||
cmd.wrap(process_wrap::tokio::JobObject);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
if self.options.reset_sigmask {
|
||||
use nix::sys::signal::{sigprocmask, SigSet, SigmaskHow};
|
||||
unsafe {
|
||||
cmd.pre_exec(|| {
|
||||
let mut oldset = SigSet::empty();
|
||||
let newset = SigSet::all();
|
||||
trace!(unblocking=?newset, "resetting process sigmask");
|
||||
sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&newset), Some(&mut oldset))?;
|
||||
trace!(?oldset, "sigmask reset");
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
cmd.wrap(process_wrap::tokio::ResetSigmask);
|
||||
}
|
||||
|
||||
cmd
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{future::Future, sync::Arc, time::Duration};
|
||||
|
||||
use tokio::process::Command as TokioCommand;
|
||||
use process_wrap::tokio::TokioCommandWrap;
|
||||
use watchexec_signals::Signal;
|
||||
|
||||
use crate::{command::Command, errors::SyncIoError, flag::Flag};
|
||||
|
@ -289,11 +289,11 @@ impl Job {
|
|||
/// Set the spawn hook.
|
||||
///
|
||||
/// The hook will be called once per process spawned, before the process is spawned. It's given
|
||||
/// a mutable reference to the [`tokio::process::Command`] and some context; it can modify the
|
||||
/// command as it sees fit.
|
||||
/// a mutable reference to the [`process_wrap::tokio::TokioCommandWrap`] and some context; it
|
||||
/// can modify or further [wrap](process_wrap) the command as it sees fit.
|
||||
pub fn set_spawn_hook(
|
||||
&self,
|
||||
fun: impl Fn(&mut TokioCommand, &JobTaskContext<'_>) + Send + Sync + 'static,
|
||||
fun: impl Fn(&mut TokioCommandWrap, &JobTaskContext<'_>) + Send + Sync + 'static,
|
||||
) -> Ticket {
|
||||
self.control(Control::SetSyncSpawnHook(Arc::new(fun)))
|
||||
}
|
||||
|
@ -301,8 +301,8 @@ impl Job {
|
|||
/// Set the spawn hook (async version).
|
||||
///
|
||||
/// The hook will be called once per process spawned, before the process is spawned. It's given
|
||||
/// a mutable reference to the [`tokio::process::Command`] and some context; it can modify the
|
||||
/// command as it sees fit.
|
||||
/// a mutable reference to the [`process_wrap::tokio::TokioCommandWrap`] and some context; it
|
||||
/// can modify or further [wrap](process_wrap) the command as it sees fit.
|
||||
///
|
||||
/// A gotcha when using this method is that the future returned by the function can live longer
|
||||
/// than the references it was given, so you can't bring the command or context into the async
|
||||
|
@ -313,7 +313,10 @@ impl Job {
|
|||
/// spawn hooks that can't be done in the simpler sync version.
|
||||
pub fn set_spawn_async_hook(
|
||||
&self,
|
||||
fun: impl (Fn(&mut TokioCommand, &JobTaskContext<'_>) -> Box<dyn Future<Output = ()> + Send + Sync>)
|
||||
fun: impl (Fn(
|
||||
&mut TokioCommandWrap,
|
||||
&JobTaskContext<'_>,
|
||||
) -> Box<dyn Future<Output = ()> + Send + Sync>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use std::{sync::Arc, time::Instant};
|
||||
|
||||
#[cfg(not(test))]
|
||||
use command_group::{tokio::ErasedChild, AsyncCommandGroup};
|
||||
use tokio::process::Command as TokioCommand;
|
||||
use process_wrap::tokio::{TokioChildWrapper, TokioCommandWrap};
|
||||
use tracing::trace;
|
||||
use watchexec_events::ProcessEnd;
|
||||
|
||||
|
@ -33,7 +31,7 @@ pub enum CommandState {
|
|||
|
||||
/// The child process.
|
||||
#[cfg(not(test))]
|
||||
child: ErasedChild,
|
||||
child: Box<dyn TokioChildWrapper>,
|
||||
|
||||
/// The time at which the process was spawned.
|
||||
started: Instant,
|
||||
|
@ -75,7 +73,7 @@ impl CommandState {
|
|||
pub(crate) fn spawn(
|
||||
&mut self,
|
||||
command: Arc<Command>,
|
||||
mut spawnable: TokioCommand,
|
||||
mut spawnable: TokioCommandWrap,
|
||||
) -> std::io::Result<bool> {
|
||||
if let Self::Running { .. } = self {
|
||||
trace!("command running, not spawning again");
|
||||
|
@ -88,11 +86,7 @@ impl CommandState {
|
|||
let child = super::TestChild::new(command)?;
|
||||
|
||||
#[cfg(not(test))]
|
||||
let child = if command.options.grouped {
|
||||
ErasedChild::Grouped(spawnable.group().kill_on_drop(true).spawn()?)
|
||||
} else {
|
||||
ErasedChild::Ungrouped(spawnable.kill_on_drop(true).spawn()?)
|
||||
};
|
||||
let child = spawnable.spawn()?;
|
||||
|
||||
*self = Self::Running {
|
||||
child,
|
||||
|
@ -136,7 +130,7 @@ impl CommandState {
|
|||
|
||||
pub(crate) async fn wait(&mut self) -> std::io::Result<bool> {
|
||||
if let Self::Running { child, started } = self {
|
||||
let end = child.wait().await?;
|
||||
let end = Box::into_pin(child.wait()).await?;
|
||||
*self = Self::Finished {
|
||||
status: end.into(),
|
||||
started: *started,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::{future::Future, mem::take, sync::Arc, time::Instant};
|
||||
|
||||
use tokio::{process::Command as TokioCommand, select, task::JoinHandle};
|
||||
use process_wrap::tokio::TokioCommandWrap;
|
||||
use tokio::{select, task::JoinHandle};
|
||||
use tracing::{instrument, trace, trace_span, Instrument};
|
||||
use watchexec_signals::Signal;
|
||||
|
||||
|
@ -156,9 +157,9 @@ pub fn start_job(command: Arc<Command>) -> (Job, JoinHandle<()>) {
|
|||
Control::Stop => {
|
||||
if let CommandState::Running { child, started, .. } = &mut command_state {
|
||||
trace!("stopping child");
|
||||
try_with_handler!(child.kill().await);
|
||||
try_with_handler!(Box::into_pin(child.kill()).await);
|
||||
trace!("waiting on child");
|
||||
let status = try_with_handler!(child.wait().await);
|
||||
let status = try_with_handler!(Box::into_pin(child.wait()).await);
|
||||
|
||||
trace!(?status, "got child end status");
|
||||
command_state = CommandState::Finished {
|
||||
|
@ -188,9 +189,9 @@ pub fn start_job(command: Arc<Command>) -> (Job, JoinHandle<()>) {
|
|||
Control::TryRestart => {
|
||||
if let CommandState::Running { child, started, .. } = &mut command_state {
|
||||
trace!("stopping child");
|
||||
try_with_handler!(child.kill().await);
|
||||
try_with_handler!(Box::into_pin(child.kill()).await);
|
||||
trace!("waiting on child");
|
||||
let status = try_with_handler!(child.wait().await);
|
||||
let status = try_with_handler!(Box::into_pin(child.wait()).await);
|
||||
|
||||
trace!(?status, "got child end status");
|
||||
command_state = CommandState::Finished {
|
||||
|
@ -238,9 +239,9 @@ pub fn start_job(command: Arc<Command>) -> (Job, JoinHandle<()>) {
|
|||
|
||||
if let CommandState::Running { child, started, .. } = &mut command_state {
|
||||
trace!("stopping child forcefully");
|
||||
try_with_handler!(child.kill().await);
|
||||
try_with_handler!(Box::into_pin(child.kill()).await);
|
||||
trace!("waiting on child");
|
||||
let status = try_with_handler!(child.wait().await);
|
||||
let status = try_with_handler!(Box::into_pin(child.wait()).await);
|
||||
|
||||
trace!(?status, "got child end status");
|
||||
command_state = CommandState::Finished {
|
||||
|
@ -411,15 +412,15 @@ pub type AsyncFunc = Box<
|
|||
>;
|
||||
|
||||
pub type SyncSpawnHook =
|
||||
Arc<dyn Fn(&mut TokioCommand, &JobTaskContext<'_>) + Send + Sync + 'static>;
|
||||
Arc<dyn Fn(&mut TokioCommandWrap, &JobTaskContext<'_>) + Send + Sync + 'static>;
|
||||
pub type AsyncSpawnHook = Arc<
|
||||
dyn (Fn(&mut TokioCommand, &JobTaskContext<'_>) -> Box<dyn Future<Output = ()> + Send + Sync>)
|
||||
dyn (Fn(&mut TokioCommandWrap, &JobTaskContext<'_>) -> Box<dyn Future<Output = ()> + Send + Sync>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
>;
|
||||
|
||||
sync_async_callbox!(SpawnHook, SyncSpawnHook, AsyncSpawnHook, (command: &mut TokioCommand, context: &JobTaskContext<'_>));
|
||||
sync_async_callbox!(SpawnHook, SyncSpawnHook, AsyncSpawnHook, (command: &mut TokioCommandWrap, context: &JobTaskContext<'_>));
|
||||
|
||||
pub type SyncErrorHandler = Arc<dyn Fn(SyncIoError) + Send + Sync + 'static>;
|
||||
pub type AsyncErrorHandler = Arc<
|
||||
|
@ -432,8 +433,8 @@ sync_async_callbox!(ErrorHandler, SyncErrorHandler, AsyncErrorHandler, (error: S
|
|||
#[instrument(level = "trace")]
|
||||
async fn signal_child(
|
||||
signal: Signal,
|
||||
#[cfg(not(test))] child: &mut Box<dyn process_wrap::tokio::TokioChildWrapper>,
|
||||
#[cfg(test)] child: &mut super::TestChild,
|
||||
#[cfg(not(test))] child: &mut command_group::tokio::ErasedChild,
|
||||
) -> std::io::Result<()> {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
|
@ -442,7 +443,7 @@ async fn signal_child(
|
|||
.or_else(|| Signal::Terminate.to_nix())
|
||||
.expect("UNWRAP: guaranteed for Signal::Terminate default");
|
||||
trace!(signal=?sig, "sending signal");
|
||||
child.signal(sig)?;
|
||||
child.signal(sig as _)?;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
|
|
@ -328,6 +328,7 @@ async fn start() {
|
|||
#[cfg(unix)]
|
||||
#[tokio::test]
|
||||
async fn signal_unix() {
|
||||
use nix::sys::signal::Signal;
|
||||
let (job, task) = start_job(working_command());
|
||||
|
||||
expect_state!(job, CommandState::Pending);
|
||||
|
@ -336,9 +337,9 @@ async fn signal_unix() {
|
|||
job.signal(watchexec_signals::Signal::User1).await;
|
||||
|
||||
let calls = get_child(&job).await.calls;
|
||||
assert!(calls
|
||||
.iter()
|
||||
.any(|(_, call)| matches!(call, TestChildCall::Signal(command_group::Signal::SIGUSR1))));
|
||||
assert!(calls.iter().any(
|
||||
|(_, call)| matches!(call, TestChildCall::Signal(sig) if *sig == Signal::SIGUSR1 as i32)
|
||||
));
|
||||
|
||||
task.abort();
|
||||
}
|
||||
|
@ -553,6 +554,7 @@ async fn graceful_stop_beyond_grace() {
|
|||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use nix::sys::signal::Signal;
|
||||
expect_state!(
|
||||
job,
|
||||
CommandState::Running { .. },
|
||||
|
@ -562,7 +564,7 @@ async fn graceful_stop_beyond_grace() {
|
|||
let calls = get_child(&job).await.calls;
|
||||
assert!(calls.iter().any(|(_, call)| matches!(
|
||||
call,
|
||||
TestChildCall::Signal(command_group::Signal::SIGUSR1)
|
||||
TestChildCall::Signal(sig) if *sig == Signal::SIGUSR1 as i32
|
||||
)));
|
||||
}
|
||||
|
||||
|
@ -596,6 +598,7 @@ async fn graceful_restart_beyond_grace() {
|
|||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use nix::sys::signal::Signal;
|
||||
expect_state!(
|
||||
job,
|
||||
CommandState::Running { .. },
|
||||
|
@ -605,7 +608,7 @@ async fn graceful_restart_beyond_grace() {
|
|||
let calls = get_child(&job).await.calls;
|
||||
assert!(calls.iter().any(|(_, call)| matches!(
|
||||
call,
|
||||
TestChildCall::Signal(command_group::Signal::SIGUSR1)
|
||||
TestChildCall::Signal(sig) if *sig == Signal::SIGUSR1 as i32
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::{
|
||||
future::Future,
|
||||
io::Result,
|
||||
path::Path,
|
||||
process::{ExitStatus, Output},
|
||||
|
@ -6,8 +7,6 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
use command_group::Signal;
|
||||
use tokio::{sync::Mutex, time::sleep};
|
||||
use watchexec_events::ProcessEnd;
|
||||
|
||||
|
@ -35,7 +34,7 @@ impl TestChild {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
grouped: command.options.grouped,
|
||||
grouped: command.options.grouped || command.options.session,
|
||||
command,
|
||||
calls: Arc::new(boxcar::Vec::new()),
|
||||
output: Arc::new(Mutex::new(None)),
|
||||
|
@ -52,7 +51,7 @@ pub enum TestChildCall {
|
|||
TryWait,
|
||||
Wait,
|
||||
#[cfg(unix)]
|
||||
Signal(Signal),
|
||||
Signal(i32),
|
||||
}
|
||||
|
||||
// Exact same signatures as ErasedChild
|
||||
|
@ -62,9 +61,9 @@ impl TestChild {
|
|||
None
|
||||
}
|
||||
|
||||
pub async fn kill(&mut self) -> Result<()> {
|
||||
pub fn kill(&mut self) -> Box<dyn Future<Output = Result<()>> + Send + '_> {
|
||||
self.calls.push(TestChildCall::Kill);
|
||||
Ok(())
|
||||
Box::new(async { Ok(()) })
|
||||
}
|
||||
|
||||
pub fn start_kill(&mut self) -> Result<()> {
|
||||
|
@ -96,54 +95,58 @@ impl TestChild {
|
|||
.and_then(|o| o.as_ref().map(|o| o.status)))
|
||||
}
|
||||
|
||||
pub async fn wait(&mut self) -> Result<ExitStatus> {
|
||||
pub fn wait(&mut self) -> Box<dyn Future<Output = Result<ExitStatus>> + Send + '_> {
|
||||
self.calls.push(TestChildCall::Wait);
|
||||
if let Program::Exec { prog, args } = &self.command.program {
|
||||
if prog == Path::new("sleep") {
|
||||
if let Some(time) = args
|
||||
.get(0)
|
||||
.and_then(|arg| arg.parse().ok())
|
||||
.map(Duration::from_millis)
|
||||
{
|
||||
if self.spawned.elapsed() < time {
|
||||
sleep(time - self.spawned.elapsed()).await;
|
||||
if let Ok(guard) = self.output.try_lock() {
|
||||
if let Some(output) = guard.as_ref() {
|
||||
return Ok(output.status);
|
||||
Box::new(async {
|
||||
if let Program::Exec { prog, args } = &self.command.program {
|
||||
if prog == Path::new("sleep") {
|
||||
if let Some(time) = args
|
||||
.get(0)
|
||||
.and_then(|arg| arg.parse().ok())
|
||||
.map(Duration::from_millis)
|
||||
{
|
||||
if self.spawned.elapsed() < time {
|
||||
sleep(time - self.spawned.elapsed()).await;
|
||||
if let Ok(guard) = self.output.try_lock() {
|
||||
if let Some(output) = guard.as_ref() {
|
||||
return Ok(output.status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(ProcessEnd::Success.into_exitstatus());
|
||||
return Ok(ProcessEnd::Success.into_exitstatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
eprintln!("[{:?}] child: output lock", Instant::now());
|
||||
let output = self.output.lock().await;
|
||||
if let Some(output) = output.as_ref() {
|
||||
return Ok(output.status);
|
||||
}
|
||||
eprintln!("[{:?}] child: output unlock", Instant::now());
|
||||
loop {
|
||||
eprintln!("[{:?}] child: output lock", Instant::now());
|
||||
let output = self.output.lock().await;
|
||||
if let Some(output) = output.as_ref() {
|
||||
return Ok(output.status);
|
||||
}
|
||||
eprintln!("[{:?}] child: output unlock", Instant::now());
|
||||
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_with_output(self) -> Result<Output> {
|
||||
loop {
|
||||
let mut output = self.output.lock().await;
|
||||
if let Some(output) = output.take() {
|
||||
return Ok(output);
|
||||
} else {
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn wait_with_output(self) -> Box<dyn Future<Output = Result<Output>> + Send> {
|
||||
Box::new(async move {
|
||||
loop {
|
||||
let mut output = self.output.lock().await;
|
||||
if let Some(output) = output.take() {
|
||||
return Ok(output);
|
||||
} else {
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn signal(&self, sig: Signal) -> Result<()> {
|
||||
pub fn signal(&self, sig: i32) -> Result<()> {
|
||||
self.calls.push(TestChildCall::Signal(sig));
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
use command_group::AsyncCommandGroup;
|
||||
use watchexec_supervisor::command::{Command, Program, Shell};
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn unix_shell_none() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Exec {
|
||||
prog: "echo".into(),
|
||||
args: vec!["hi".into()],
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Exec {
|
||||
prog: "echo".into(),
|
||||
args: vec!["hi".into()],
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
@ -21,16 +23,19 @@ async fn unix_shell_none() -> Result<(), std::io::Error> {
|
|||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn unix_shell_sh() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::new("sh"),
|
||||
command: "echo hi".into(),
|
||||
args: Vec::new(),
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::new("sh"),
|
||||
command: "echo hi".into(),
|
||||
args: Vec::new(),
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
@ -39,16 +44,19 @@ async fn unix_shell_sh() -> Result<(), std::io::Error> {
|
|||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn unix_shell_alternate() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::new("bash"),
|
||||
command: "echo".into(),
|
||||
args: vec!["--".into(), "hi".into()],
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::new("bash"),
|
||||
command: "echo".into(),
|
||||
args: vec!["--".into(), "hi".into()],
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
@ -57,19 +65,22 @@ async fn unix_shell_alternate() -> Result<(), std::io::Error> {
|
|||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn unix_shell_alternate_shopts() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell {
|
||||
options: vec!["-o".into(), "errexit".into()],
|
||||
..Shell::new("bash")
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell {
|
||||
options: vec!["-o".into(), "errexit".into()],
|
||||
..Shell::new("bash")
|
||||
},
|
||||
command: "echo hi".into(),
|
||||
args: Vec::new(),
|
||||
},
|
||||
command: "echo hi".into(),
|
||||
args: Vec::new(),
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
@ -78,15 +89,18 @@ async fn unix_shell_alternate_shopts() -> Result<(), std::io::Error> {
|
|||
#[tokio::test]
|
||||
#[cfg(windows)]
|
||||
async fn windows_shell_none() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Exec {
|
||||
prog: "echo".into(),
|
||||
args: vec!["hi".into()],
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Exec {
|
||||
prog: "echo".into(),
|
||||
args: vec!["hi".into()],
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
@ -95,16 +109,19 @@ async fn windows_shell_none() -> Result<(), std::io::Error> {
|
|||
#[tokio::test]
|
||||
#[cfg(windows)]
|
||||
async fn windows_shell_cmd() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::cmd(),
|
||||
args: Vec::new(),
|
||||
command: r#""echo" hi"#.into()
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::cmd(),
|
||||
args: Vec::new(),
|
||||
command: r#""echo" hi"#.into()
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
@ -113,16 +130,19 @@ async fn windows_shell_cmd() -> Result<(), std::io::Error> {
|
|||
#[tokio::test]
|
||||
#[cfg(windows)]
|
||||
async fn windows_shell_powershell() -> Result<(), std::io::Error> {
|
||||
assert!(Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::new("pwsh.exe"),
|
||||
args: Vec::new(),
|
||||
command: "echo hi".into()
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.group_status()
|
||||
assert!(Box::into_pin(
|
||||
Command {
|
||||
program: Program::Shell {
|
||||
shell: Shell::new("pwsh.exe"),
|
||||
args: Vec::new(),
|
||||
command: "echo hi".into()
|
||||
},
|
||||
options: Default::default()
|
||||
}
|
||||
.to_spawnable()
|
||||
.spawn()?
|
||||
.wait()
|
||||
)
|
||||
.await?
|
||||
.success());
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in New Issue