Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
windows: Introduce new crate
Lorenz Leutgeb committed 2 months ago
commit b81ab621cf39376049162d110e63eecdf4810597
parent 50fb228ae4c0c8f68413dc7922a1e2a32ace5655
5 files changed +230 -6
modified Cargo.lock
@@ -3208,6 +3208,14 @@ dependencies = [
]

[[package]]
+
name = "radicle-windows"
+
version = "0.1.0"
+
dependencies = [
+
 "thiserror 2.0.17",
+
 "windows 0.62.2",
+
]
+

+
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4799,6 +4807,27 @@ dependencies = [
]

[[package]]
+
name = "windows"
+
version = "0.62.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
+
dependencies = [
+
 "windows-collections",
+
 "windows-core 0.62.2",
+
 "windows-future",
+
 "windows-numerics",
+
]
+

+
[[package]]
+
name = "windows-collections"
+
version = "0.3.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
+
dependencies = [
+
 "windows-core 0.62.2",
+
]
+

+
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4813,14 +4842,38 @@ version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
-
 "windows-implement",
-
 "windows-interface",
-
 "windows-result",
-
 "windows-strings",
+
 "windows-implement 0.58.0",
+
 "windows-interface 0.58.0",
+
 "windows-result 0.2.0",
+
 "windows-strings 0.1.0",
 "windows-targets 0.52.6",
]

[[package]]
+
name = "windows-core"
+
version = "0.62.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
+
dependencies = [
+
 "windows-implement 0.60.2",
+
 "windows-interface 0.59.3",
+
 "windows-link",
+
 "windows-result 0.4.1",
+
 "windows-strings 0.5.1",
+
]
+

+
[[package]]
+
name = "windows-future"
+
version = "0.3.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
+
dependencies = [
+
 "windows-core 0.62.2",
+
 "windows-link",
+
 "windows-threading",
+
]
+

+
[[package]]
name = "windows-implement"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4832,6 +4885,17 @@ dependencies = [
]

[[package]]
+
name = "windows-implement"
+
version = "0.60.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+
dependencies = [
+
 "proc-macro2",
+
 "quote",
+
 "syn 2.0.106",
+
]
+

+
[[package]]
name = "windows-interface"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4843,12 +4907,33 @@ dependencies = [
]

[[package]]
+
name = "windows-interface"
+
version = "0.59.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+
dependencies = [
+
 "proc-macro2",
+
 "quote",
+
 "syn 2.0.106",
+
]
+

+
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"

[[package]]
+
name = "windows-numerics"
+
version = "0.3.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
+
dependencies = [
+
 "windows-core 0.62.2",
+
 "windows-link",
+
]
+

+
[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4858,16 +4943,34 @@ dependencies = [
]

[[package]]
+
name = "windows-result"
+
version = "0.4.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+
dependencies = [
+
 "windows-link",
+
]
+

+
[[package]]
name = "windows-strings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
-
 "windows-result",
+
 "windows-result 0.2.0",
 "windows-targets 0.52.6",
]

[[package]]
+
name = "windows-strings"
+
version = "0.5.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+
dependencies = [
+
 "windows-link",
+
]
+

+
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4951,6 +5054,15 @@ dependencies = [
]

[[package]]
+
name = "windows-threading"
+
version = "0.2.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
+
dependencies = [
+
 "windows-link",
+
]
+

+
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5107,7 +5219,7 @@ dependencies = [
 "log",
 "rand 0.8.5",
 "sync-ptr",
-
 "windows",
+
 "windows 0.58.0",
]

[[package]]
modified Cargo.toml
@@ -59,6 +59,7 @@ radicle-signals = { version = "0.11", path = "crates/radicle-signals" }
radicle-ssh = { version = "0.10", path = "crates/radicle-ssh", default-features = false }
radicle-systemd = { version = "0.11", path = "crates/radicle-systemd" }
radicle-term = { version = "0.16", path = "crates/radicle-term" }
+
radicle-windows = { version = "0.1", path = "crates/radicle-windows" }
schemars = { version = "1.0.4", default-features = false }
serde = { version = "1.0", default-features = false }
serde_json = "1.0"
added crates/radicle-windows/Cargo.toml
@@ -0,0 +1,25 @@
+
[package]
+
name = "radicle-windows"
+
description = "Radicle integration with Windows"
+
homepage.workspace = true
+
repository.workspace = true
+
license.workspace = true
+
edition.workspace = true
+
version = "0.1.0"
+
rust-version.workspace = true
+

+
[target.'cfg(windows)'.dependencies]
+
thiserror = { workspace = true }
+

+
[target.'cfg(windows)'.dependencies.windows]
+
version = "0.62"
+
features = [
+
    "Win32_Foundation",
+
    "Win32_Security",
+
    "Win32_System_JobObjects",
+
    "Win32_System_Threading",
+
    "Win32_System_ProcessStatus",
+
]
+

+
[package.metadata.docs.rs]
+
default-target = "x86_64-pc-windows-msvc"
added crates/radicle-windows/src/jobs.rs
@@ -0,0 +1,82 @@
+
use std::io;
+
use std::os::windows::io::AsRawHandle as _;
+

+
use windows::{
+
    core::PCWSTR,
+
    Win32::{
+
        Foundation::{CloseHandle, HANDLE},
+
        System::JobObjects::{AssignProcessToJobObject, CreateJobObjectW, TerminateJobObject},
+
    },
+
};
+

+
use thiserror::Error;
+

+
#[derive(Error, Debug)]
+
#[non_exhaustive]
+
pub enum Error {
+
    #[error("Failed to create job: {0}")]
+
    Create(io::Error),
+
    #[error("Failed to assign job: {0}")]
+
    Assign(io::Error),
+
    #[error("Failed to terminate job: {0}")]
+
    Terminate(io::Error),
+
}
+

+
impl From<Error> for io::Error {
+
    fn from(value: Error) -> Self {
+
        use Error::*;
+
        match value {
+
            Create(error) | Assign(error) | Terminate(error) => error,
+
        }
+
    }
+
}
+

+
/// Wraps a handle to a job object.
+
/// See also <https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects>.
+
#[derive(Debug)]
+
#[repr(transparent)]
+
pub struct Job {
+
    handle: HANDLE,
+
}
+

+
unsafe impl Send for Job {}
+
unsafe impl Sync for Job {}
+

+
impl Job {
+
    /// Create a new, empty, job object.
+
    /// See also <https://learn.microsoft.com/windows/win32/api/jobapi2/nf-jobapi2-createjobobjectw>.
+
    pub fn new() -> Result<Self, Error> {
+
        unsafe { CreateJobObjectW(None, PCWSTR::null()) }
+
            .map_err(|e| Error::Create(e.into()))
+
            .map(|handle| Self { handle })
+
    }
+

+
    /// Assign a process to the job object.
+
    /// See also <https://docs.microsoft.com/windows/win32/api/jobapi2/nf-jobapi2-assignprocesstojobobject>.
+
    pub fn assign(&self, child: &std::process::Child) -> Result<(), Error> {
+
        let handle = child.as_raw_handle();
+
        unsafe { AssignProcessToJobObject(self.handle, HANDLE(handle)) }
+
            .map_err(|e| Error::Assign(e.into()))
+
    }
+

+
    /// Terminate a job object.
+
    /// See also <https://learn.microsoft.com/windows/win32/api/jobapi2/nf-jobapi2-terminatejobobject>.
+
    pub fn terminate(self, exit_code: u32) -> Result<(), Error> {
+
        unsafe { TerminateJobObject(self.handle, exit_code) }
+
            .map_err(|e| Error::Terminate(e.into()))
+
    }
+

+
    /// Convenience method to create a new job and assign a child process to it.
+
    /// See also [`Job::new`] and [`Job::assign`].
+
    pub fn for_child(child: &std::process::Child) -> Result<Self, Error> {
+
        let job = Self::new()?;
+
        job.assign(child)?;
+
        Ok(job)
+
    }
+
}
+

+
impl Drop for Job {
+
    fn drop(&mut self) {
+
        let _ = unsafe { CloseHandle(self.handle) };
+
    }
+
}
added crates/radicle-windows/src/lib.rs
@@ -0,0 +1,4 @@
+
//! Library for interaction with Windows, specialized for Radicle.
+

+
#[cfg(windows)]
+
pub mod jobs;