Show More
@@ -28,44 +28,41 b' pub async fn attach_io(' | |||||
28 | stdout: &impl AsRawFd, |
|
28 | stdout: &impl AsRawFd, | |
29 | stderr: &impl AsRawFd, |
|
29 | stderr: &impl AsRawFd, | |
30 | ) -> io::Result<()> { |
|
30 | ) -> io::Result<()> { | |
31 | // TODO: unindent |
|
31 | proto.send_command("attachio").await?; | |
32 | { |
|
32 | loop { | |
33 | proto.send_command("attachio").await?; |
|
33 | match proto.fetch_response().await? { | |
34 | loop { |
|
34 | ChannelMessage::Data(b'r', data) => { | |
35 | match proto.fetch_response().await? { |
|
35 | let fd_cnt = message::parse_result_code(data)?; | |
36 | ChannelMessage::Data(b'r', data) => { |
|
36 | if fd_cnt == 3 { | |
37 | let fd_cnt = message::parse_result_code(data)?; |
|
37 | return Ok(()); | |
38 |
|
|
38 | } else { | |
39 | return Ok(()); |
|
|||
40 | } else { |
|
|||
41 | return Err(io::Error::new( |
|
|||
42 | io::ErrorKind::InvalidData, |
|
|||
43 | "unexpected attachio result", |
|
|||
44 | )); |
|
|||
45 | } |
|
|||
46 | } |
|
|||
47 | ChannelMessage::Data(..) => { |
|
|||
48 | // just ignore data sent to uninteresting (optional) channel |
|
|||
49 | } |
|
|||
50 | ChannelMessage::InputRequest(1) => { |
|
|||
51 | // this may fail with EWOULDBLOCK in theory, but the |
|
|||
52 | // payload is quite small, and the send buffer should |
|
|||
53 | // be empty so the operation will complete immediately |
|
|||
54 | let sock_fd = proto.as_raw_fd(); |
|
|||
55 | let ifd = stdin.as_raw_fd(); |
|
|||
56 | let ofd = stdout.as_raw_fd(); |
|
|||
57 | let efd = stderr.as_raw_fd(); |
|
|||
58 | procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; |
|
|||
59 | } |
|
|||
60 | ChannelMessage::InputRequest(..) |
|
|||
61 | | ChannelMessage::LineRequest(..) |
|
|||
62 | | ChannelMessage::SystemRequest(..) => { |
|
|||
63 | return Err(io::Error::new( |
|
39 | return Err(io::Error::new( | |
64 | io::ErrorKind::InvalidData, |
|
40 | io::ErrorKind::InvalidData, | |
65 |
"un |
|
41 | "unexpected attachio result", | |
66 | )); |
|
42 | )); | |
67 | } |
|
43 | } | |
68 | } |
|
44 | } | |
|
45 | ChannelMessage::Data(..) => { | |||
|
46 | // just ignore data sent to uninteresting (optional) channel | |||
|
47 | } | |||
|
48 | ChannelMessage::InputRequest(1) => { | |||
|
49 | // this may fail with EWOULDBLOCK in theory, but the | |||
|
50 | // payload is quite small, and the send buffer should | |||
|
51 | // be empty so the operation will complete immediately | |||
|
52 | let sock_fd = proto.as_raw_fd(); | |||
|
53 | let ifd = stdin.as_raw_fd(); | |||
|
54 | let ofd = stdout.as_raw_fd(); | |||
|
55 | let efd = stderr.as_raw_fd(); | |||
|
56 | procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; | |||
|
57 | } | |||
|
58 | ChannelMessage::InputRequest(..) | |||
|
59 | | ChannelMessage::LineRequest(..) | |||
|
60 | | ChannelMessage::SystemRequest(..) => { | |||
|
61 | return Err(io::Error::new( | |||
|
62 | io::ErrorKind::InvalidData, | |||
|
63 | "unsupported request while attaching io", | |||
|
64 | )); | |||
|
65 | } | |||
69 | } |
|
66 | } | |
70 | } |
|
67 | } | |
71 | } |
|
68 | } |
@@ -88,22 +88,17 b' impl Locator {' | |||||
88 | } |
|
88 | } | |
89 | } |
|
89 | } | |
90 |
|
90 | |||
91 | // TODO: unindent |
|
91 | let msg = format!( | |
92 | { |
|
92 | concat!( | |
93 | { |
|
93 | "too many redirections.\n", | |
94 | let msg = format!( |
|
94 | "Please make sure {:?} is not a wrapper which ", | |
95 | concat!( |
|
95 | "changes sensitive environment variables ", | |
96 | "too many redirections.\n", |
|
96 | "before executing hg. If you have to use a ", | |
97 | "Please make sure {:?} is not a wrapper which ", |
|
97 | "wrapper, wrap chg instead of hg.", | |
98 | "changes sensitive environment variables ", |
|
98 | ), | |
99 | "before executing hg. If you have to use a ", |
|
99 | self.hg_command | |
100 | "wrapper, wrap chg instead of hg.", |
|
100 | ); | |
101 | ), |
|
101 | Err(io::Error::new(io::ErrorKind::Other, msg)) | |
102 | self.hg_command |
|
|||
103 | ); |
|
|||
104 | Err(io::Error::new(io::ErrorKind::Other, msg)) |
|
|||
105 | } |
|
|||
106 | } |
|
|||
107 | } |
|
102 | } | |
108 |
|
103 | |||
109 | /// Runs instructions received from the server. |
|
104 | /// Runs instructions received from the server. | |
@@ -157,38 +152,33 b' impl Locator {' | |||||
157 | .unwrap_or(&self.base_sock_path) |
|
152 | .unwrap_or(&self.base_sock_path) | |
158 | .clone(); |
|
153 | .clone(); | |
159 | debug!("try connect to {}", sock_path.display()); |
|
154 | debug!("try connect to {}", sock_path.display()); | |
160 | // TODO: unindent |
|
155 | let mut client = match ChgClient::connect(sock_path).await { | |
161 | { |
|
156 | Ok(client) => client, | |
162 | { |
|
157 | Err(_) => { | |
163 | let mut client = match ChgClient::connect(sock_path).await { |
|
158 | // Prevent us from being re-connected to the outdated | |
164 | Ok(client) => client, |
|
159 | // master server: We were told by the server to redirect | |
165 | Err(_) => { |
|
160 | // to redirect_sock_path, which didn't work. We do not | |
166 | // Prevent us from being re-connected to the outdated |
|
161 | // want to connect to the same master server again | |
167 | // master server: We were told by the server to redirect |
|
162 | // because it would probably tell us the same thing. | |
168 | // to redirect_sock_path, which didn't work. We do not |
|
163 | if self.redirect_sock_path.is_some() { | |
169 | // want to connect to the same master server again |
|
164 | fs::remove_file(&self.base_sock_path).unwrap_or(()); | |
170 | // because it would probably tell us the same thing. |
|
165 | // may race | |
171 | if self.redirect_sock_path.is_some() { |
|
|||
172 | fs::remove_file(&self.base_sock_path).unwrap_or(()); |
|
|||
173 | // may race |
|
|||
174 | } |
|
|||
175 | self.spawn_connect().await? |
|
|||
176 | } |
|
|||
177 | }; |
|
|||
178 | check_server_capabilities(client.server_spec())?; |
|
|||
179 | // It's purely optional, and the server might not support this command. |
|
|||
180 | if client.server_spec().capabilities.contains("setprocname") { |
|
|||
181 | client |
|
|||
182 | .set_process_name(format!("chg[worker/{}]", self.process_id)) |
|
|||
183 | .await?; |
|
|||
184 | } |
|
166 | } | |
185 | client.set_current_dir(&self.current_dir).await?; |
|
167 | self.spawn_connect().await? | |
186 | client |
|
|||
187 | .set_env_vars_os(self.env_vars.iter().cloned()) |
|
|||
188 | .await?; |
|
|||
189 | Ok(client) |
|
|||
190 | } |
|
168 | } | |
|
169 | }; | |||
|
170 | check_server_capabilities(client.server_spec())?; | |||
|
171 | // It's purely optional, and the server might not support this command. | |||
|
172 | if client.server_spec().capabilities.contains("setprocname") { | |||
|
173 | client | |||
|
174 | .set_process_name(format!("chg[worker/{}]", self.process_id)) | |||
|
175 | .await?; | |||
191 | } |
|
176 | } | |
|
177 | client.set_current_dir(&self.current_dir).await?; | |||
|
178 | client | |||
|
179 | .set_env_vars_os(self.env_vars.iter().cloned()) | |||
|
180 | .await?; | |||
|
181 | Ok(client) | |||
192 | } |
|
182 | } | |
193 |
|
183 | |||
194 | /// Spawns new server process and connects to it. |
|
184 | /// Spawns new server process and connects to it. | |
@@ -214,18 +204,13 b' impl Locator {' | |||||
214 | .env("CHGINTERNALMARK", "") |
|
204 | .env("CHGINTERNALMARK", "") | |
215 | .spawn()?; |
|
205 | .spawn()?; | |
216 | let client = self.connect_spawned(server, &sock_path).await?; |
|
206 | let client = self.connect_spawned(server, &sock_path).await?; | |
217 | // TODO: unindent |
|
207 | debug!( | |
218 | { |
|
208 | "rename {} to {}", | |
219 | { |
|
209 | sock_path.display(), | |
220 | debug!( |
|
210 | self.base_sock_path.display() | |
221 | "rename {} to {}", |
|
211 | ); | |
222 | sock_path.display(), |
|
212 | fs::rename(&sock_path, &self.base_sock_path)?; | |
223 | self.base_sock_path.display() |
|
213 | Ok(client) | |
224 | ); |
|
|||
225 | fs::rename(&sock_path, &self.base_sock_path)?; |
|
|||
226 | Ok(client) |
|
|||
227 | } |
|
|||
228 | } |
|
|||
229 | } |
|
214 | } | |
230 |
|
215 | |||
231 | /// Tries to connect to the just spawned server repeatedly until timeout |
|
216 | /// Tries to connect to the just spawned server repeatedly until timeout |
@@ -67,16 +67,11 b' impl SystemHandler for ChgUiHandler {' | |||||
67 |
|
67 | |||
68 | async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> { |
|
68 | async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> { | |
69 | let status = new_shell_command(&spec).spawn()?.await?; |
|
69 | let status = new_shell_command(&spec).spawn()?.await?; | |
70 | // TODO: unindent |
|
70 | let code = status | |
71 | { |
|
71 | .code() | |
72 | { |
|
72 | .or_else(|| status.signal().map(|n| -n)) | |
73 | let code = status |
|
73 | .expect("either exit code or signal should be set"); | |
74 |
|
|
74 | Ok(code) | |
75 | .or_else(|| status.signal().map(|n| -n)) |
|
|||
76 | .expect("either exit code or signal should be set"); |
|
|||
77 | Ok(code) |
|
|||
78 | } |
|
|||
79 | } |
|
|||
80 | } |
|
75 | } | |
81 | } |
|
76 | } | |
82 |
|
77 |
General Comments 0
You need to be logged in to leave comments.
Login now