gix_filter/driver/process/
mod.rs

1use std::collections::HashSet;
2
3use gix_packetline::blocking_io::{StreamingPeekableIter, WithSidebands, Writer};
4
5/// A set of capabilities that have been negotiated between client and server.
6pub type Capabilities = HashSet<String>;
7
8/// A handle to a client that allows communicating to a long-running process.
9pub struct Client {
10    /// The child process we are communicating with.
11    child: std::process::Child,
12    /// The names of the obtained capabilities after the handshake.
13    capabilities: Capabilities,
14    /// The negotiated version of the protocol.
15    version: usize,
16    /// A way to send packet-line encoded information to the process.
17    input: Writer<std::process::ChildStdin>,
18    /// A way to read information sent to us by the process.
19    out: StreamingPeekableIter<std::process::ChildStdout>,
20}
21
22/// A handle to facilitate typical server interactions that include the handshake and command-invocations.
23pub struct Server {
24    /// The names of the capabilities we can expect the client to use.
25    capabilities: Capabilities,
26    /// The negotiated version of the protocol, it's the highest supported one.
27    version: usize,
28    /// A way to receive information from the client.
29    input: StreamingPeekableIter<std::io::StdinLock<'static>>,
30    /// A way to send information to the client.
31    out: Writer<std::io::StdoutLock<'static>>,
32}
33
34/// The return status of an [invoked command][Client::invoke()].
35#[derive(Debug, Clone)]
36pub enum Status {
37    /// No new status was set, and nothing was sent, so instead we are to assume the previous status is still in effect.
38    Previous,
39    /// Something was sent, but we couldn't identify it as status.
40    Unset,
41    /// Assume the given named status.
42    Named(String),
43}
44
45/// Initialization
46impl Status {
47    /// Create a new instance that represents a successful operation.
48    pub fn success() -> Self {
49        Status::Named("success".into())
50    }
51
52    /// Create a new instance that represents a delayed operation.
53    pub fn delayed() -> Self {
54        Status::Named("delayed".into())
55    }
56
57    /// Create a status that indicates to the client that the command that caused it will not be run anymore throughout the lifetime
58    /// of the process. However, other commands may still run.
59    pub fn abort() -> Self {
60        Status::Named("abort".into())
61    }
62
63    /// Create a status that makes the client send a kill signal.
64    pub fn exit() -> Self {
65        Status::Named("send-term-signal".into())
66    }
67
68    /// Create a new instance that represents an error with the given `message`.
69    pub fn error(message: impl Into<String>) -> Self {
70        Status::Named(message.into())
71    }
72}
73
74/// Access
75impl Status {
76    /// Note that this is assumed true even if no new status is set, hence we assume that upon error, the caller will not continue
77    /// interacting with the process.
78    pub fn is_success(&self) -> bool {
79        match self {
80            Status::Previous => true,
81            Status::Unset => false,
82            Status::Named(n) => n == "success",
83        }
84    }
85
86    /// Returns true if this is an `abort` status.
87    pub fn is_abort(&self) -> bool {
88        self.message() == Some("abort")
89    }
90
91    /// Return true if the status is explicitly set to indicated delayed output processing
92    pub fn is_delayed(&self) -> bool {
93        match self {
94            Status::Previous | Status::Unset => false,
95            Status::Named(n) => n == "delayed",
96        }
97    }
98
99    /// Return the status message if present.
100    pub fn message(&self) -> Option<&str> {
101        match self {
102            Status::Previous | Status::Unset => None,
103            Status::Named(msg) => msg.as_str().into(),
104        }
105    }
106}
107
108///
109pub mod client;
110
111///
112pub mod server;
113
114type PacketlineReader<'a, T = std::process::ChildStdout> =
115    WithSidebands<'a, T, fn(bool, &[u8]) -> gix_packetline::read::ProgressAction>;