Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 31 additions & 37 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,34 @@ Versioning with Cargo's pre-1.0 compatibility rules.

## [Unreleased]

### Added

- A compiled, executed `Command` documentation example. The crate previously had
only `compile_fail` boundary pins, so no usage example was ever type-checked.
- `clippy::undocumented_unsafe_blocks` is denied, making CONTRIBUTING's
"every `unsafe` block carries a specific safety justification" rule
machine-checked instead of a convention.
- A `_typos.toml` so the spell-check gate has a checked-in configuration
matching the sibling repositories.

### Changed

- Strengthened process creation with private running/suspended typestates,
unified handle-transfer ownership, and value-based pseudoconsole storage.
- Aligned ConPTY startup with Microsoft Terminal by setting
`STARTF_USESTDHANDLES` while keeping all ordinary standard handles null.
- Require `SuspendedChild::resume` to observe the expected suspend count of
exactly one; externally changed counts now fail and roll back the process.
## [0.1.0] - 2026-08-03

### Fixed

- Prevented ConPTY children from reading or writing the parent's redirected
standard streams instead of the pseudoconsole channels.
- Always join both output reader threads when output capture encounters a
reader error or panic.
- The release-artifact checksum helper no longer relies on `LowerHex` being
implemented for the digest output, so it builds against both `sha2` 0.10 and
0.11. The bump itself stays deferred because `sha2` 0.11 requires Rust 1.85,
above this crate's 1.75 minimum.

## [0.1.0] - 2026-08-02
Initial release.

### Added

- Reusable Command and borrowed per-spawn capabilities.
- Transactional process creation with automatic rollback.
- Reusable `Command` and borrowed per-spawn capabilities.
- Transactional process creation with automatic rollback, built on private
running/suspended typestates that make a mismatched internal transition
unrepresentable.
- Explicit handle lists, high-level handle arguments and environment values,
alternate parents, ordered Jobs, typed mitigation policies, and ConPTY.
- Owned standard streams, cached exit status, concurrent output draining, and
SuspendedChild type-state transitions with pre-resume process and primary
thread inspection.
- README-backed crate documentation and packaged lifecycle examples and ADRs.
Pseudoconsole creation sets `STARTF_USESTDHANDLES` with all three standard
handles null, matching Microsoft Terminal's `ConptyConnection.cpp`, so a
hosted child cannot fall back to standard handles the parent redirected.
- Owned standard streams, cached exit status, and concurrent output draining.
Both reader threads are joined even when one reader fails or panics.
- `SuspendedChild` type-state transitions with pre-resume process and primary
thread inspection. `resume` requires the primary thread's previous suspend
count to be exactly one; externally changed counts fail and roll back.
- Crate documentation backed by `docs/crate.md`, with the README compiled and
executed as a doctest so its example cannot drift from the API.
- Packaged lifecycle examples and ADRs.
- Rust 1.75, cross-architecture, public API, coverage, mutation, supply-chain,
license, package, and CodeQL gates.
license, spelling, package, and CodeQL gates.
`clippy::undocumented_unsafe_blocks` is denied, making CONTRIBUTING's
"every `unsafe` block carries a specific safety justification" rule
machine-checked instead of a convention.

### Removed

Expand All @@ -57,5 +41,15 @@ Versioning with Cargo's pre-1.0 compatibility rules.
I/O or the argument/environment protocol, with inheritable duplicates limited
to the spawn transaction.

### Known limitations

- Windows retains a process-wide reverse inheritance race: unrelated
broad-inheritance spawns can receive a short-lived inheritable duplicate.
Avoid concurrent broad inheritance when transferred handles are sensitive.
See [ADR 0005](docs/adr/0005-handle-transfer-and-reverse-race.md).
- The `sha2` bump to 0.11 stays deferred because it requires Rust 1.85, above
this crate's 1.75 minimum. The release-artifact checksum helper builds
against both 0.10 and 0.11.

[Unreleased]: https://github.com/P4suta/windows-spawn/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/P4suta/windows-spawn/releases/tag/v0.1.0
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ Use `std::process::Command` for portable child processes. Use this crate for
The crate requires Windows 10 version 1809 or later and Rust 1.75 or later.
Non-Windows targets expose no public API.

This project is not affiliated with Microsoft or the `windows-rs` project. The
`windows-` prefix describes the target platform, not the publisher.

## Installation

`windows-spawn` 0.1.0 is not published yet, so registry installation is not
available. This repository is self-contained: it neither requires nor checks
out a downstream terminal crate. A downstream that validates the unpublished
version may temporarily supply its own local Cargo path override; that
bootstrap belongs to the downstream repository and is removed after 0.1.0 is
published.
```console
cargo add windows-spawn
```

## Minimal example

```rust,no_run
```rust
use windows_spawn::{Command, DropPolicy, SpawnOptions};

let mut command = Command::new(r"C:\Windows\System32\cmd.exe");
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
#![doc = include_str!("../docs/crate.md")]
#![deny(unsafe_code)]

// The rendered crate documentation comes from `docs/crate.md`, so the README
// would otherwise ship to crates.io without ever being compiled. Including it
// under `cfg(doctest)` type-checks and runs its examples without adding a
// second copy of the front page to the rendered docs.
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
mod readme_examples {}

#[cfg(windows)]
mod child;
#[cfg(windows)]
Expand Down