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