Show More
@@ -30,6 +30,7 b' const REQUIRED_SERVER_CAPABILITIES: &[&s' | |||||
30 | #[derive(Clone, Debug)] |
|
30 | #[derive(Clone, Debug)] | |
31 | pub struct Locator { |
|
31 | pub struct Locator { | |
32 | hg_command: OsString, |
|
32 | hg_command: OsString, | |
|
33 | hg_early_args: Vec<OsString>, | |||
33 | current_dir: PathBuf, |
|
34 | current_dir: PathBuf, | |
34 | env_vars: Vec<(OsString, OsString)>, |
|
35 | env_vars: Vec<(OsString, OsString)>, | |
35 | process_id: u32, |
|
36 | process_id: u32, | |
@@ -45,6 +46,7 b' impl Locator {' | |||||
45 | pub fn prepare_from_env() -> io::Result<Locator> { |
|
46 | pub fn prepare_from_env() -> io::Result<Locator> { | |
46 | Ok(Locator { |
|
47 | Ok(Locator { | |
47 | hg_command: default_hg_command(), |
|
48 | hg_command: default_hg_command(), | |
|
49 | hg_early_args: Vec::new(), | |||
48 | current_dir: env::current_dir()?, |
|
50 | current_dir: env::current_dir()?, | |
49 | env_vars: env::vars_os().collect(), |
|
51 | env_vars: env::vars_os().collect(), | |
50 | process_id: process::id(), |
|
52 | process_id: process::id(), | |
@@ -62,6 +64,15 b' impl Locator {' | |||||
62 | OsString::from_vec(buf).into() |
|
64 | OsString::from_vec(buf).into() | |
63 | } |
|
65 | } | |
64 |
|
66 | |||
|
67 | /// Specifies the arguments to be passed to the server at start. | |||
|
68 | pub fn set_early_args<I, P>(&mut self, args: I) | |||
|
69 | where | |||
|
70 | I: IntoIterator<Item = P>, | |||
|
71 | P: AsRef<OsStr>, | |||
|
72 | { | |||
|
73 | self.hg_early_args = args.into_iter().map(|a| a.as_ref().to_owned()).collect(); | |||
|
74 | } | |||
|
75 | ||||
65 | /// Connects to the server. |
|
76 | /// Connects to the server. | |
66 | /// |
|
77 | /// | |
67 | /// The server process will be spawned if not running. |
|
78 | /// The server process will be spawned if not running. | |
@@ -109,6 +120,7 b' impl Locator {' | |||||
109 | .arg(&sock_path) |
|
120 | .arg(&sock_path) | |
110 | .arg("--daemon-postexec") |
|
121 | .arg("--daemon-postexec") | |
111 | .arg("chdir:/") |
|
122 | .arg("chdir:/") | |
|
123 | .args(&self.hg_early_args) | |||
112 | .current_dir(&self.current_dir) |
|
124 | .current_dir(&self.current_dir) | |
113 | .env_clear() |
|
125 | .env_clear() | |
114 | .envs(self.env_vars.iter().cloned()) |
|
126 | .envs(self.env_vars.iter().cloned()) | |
@@ -275,3 +287,100 b' fn check_server_capabilities(spec: &Serv' | |||||
275 | Err(io::Error::new(io::ErrorKind::Other, msg)) |
|
287 | Err(io::Error::new(io::ErrorKind::Other, msg)) | |
276 | } |
|
288 | } | |
277 | } |
|
289 | } | |
|
290 | ||||
|
291 | /// Collects arguments which need to be passed to the server at start. | |||
|
292 | pub fn collect_early_args<I, P>(args: I) -> Vec<OsString> | |||
|
293 | where | |||
|
294 | I: IntoIterator<Item = P>, | |||
|
295 | P: AsRef<OsStr>, | |||
|
296 | { | |||
|
297 | let mut args_iter = args.into_iter(); | |||
|
298 | let mut early_args = Vec::new(); | |||
|
299 | while let Some(arg) = args_iter.next() { | |||
|
300 | let argb = arg.as_ref().as_bytes(); | |||
|
301 | if argb == b"--" { | |||
|
302 | break; | |||
|
303 | } else if argb.starts_with(b"--") { | |||
|
304 | let mut split = argb[2..].splitn(2, |&c| c == b'='); | |||
|
305 | match split.next().unwrap() { | |||
|
306 | b"traceback" => { | |||
|
307 | if split.next().is_none() { | |||
|
308 | early_args.push(arg.as_ref().to_owned()); | |||
|
309 | } | |||
|
310 | } | |||
|
311 | b"config" | b"cwd" | b"repo" | b"repository" => { | |||
|
312 | if split.next().is_some() { | |||
|
313 | // --<flag>=<val> | |||
|
314 | early_args.push(arg.as_ref().to_owned()); | |||
|
315 | } else { | |||
|
316 | // --<flag> <val> | |||
|
317 | args_iter.next().map(|val| { | |||
|
318 | early_args.push(arg.as_ref().to_owned()); | |||
|
319 | early_args.push(val.as_ref().to_owned()); | |||
|
320 | }); | |||
|
321 | } | |||
|
322 | } | |||
|
323 | _ => {} | |||
|
324 | } | |||
|
325 | } else if argb.starts_with(b"-R") { | |||
|
326 | if argb.len() > 2 { | |||
|
327 | // -R<val> | |||
|
328 | early_args.push(arg.as_ref().to_owned()); | |||
|
329 | } else { | |||
|
330 | // -R <val> | |||
|
331 | args_iter.next().map(|val| { | |||
|
332 | early_args.push(arg.as_ref().to_owned()); | |||
|
333 | early_args.push(val.as_ref().to_owned()); | |||
|
334 | }); | |||
|
335 | } | |||
|
336 | } | |||
|
337 | } | |||
|
338 | ||||
|
339 | early_args | |||
|
340 | } | |||
|
341 | ||||
|
342 | #[cfg(test)] | |||
|
343 | mod tests { | |||
|
344 | use super::*; | |||
|
345 | ||||
|
346 | #[test] | |||
|
347 | fn collect_early_args_some() { | |||
|
348 | assert!(collect_early_args(&[] as &[&OsStr]).is_empty()); | |||
|
349 | assert!(collect_early_args(&["log"]).is_empty()); | |||
|
350 | assert_eq!( | |||
|
351 | collect_early_args(&["log", "-Ra", "foo"]), | |||
|
352 | os_string_vec_from(&[b"-Ra"]) | |||
|
353 | ); | |||
|
354 | assert_eq!( | |||
|
355 | collect_early_args(&["log", "-R", "repo", "", "--traceback", "a"]), | |||
|
356 | os_string_vec_from(&[b"-R", b"repo", b"--traceback"]) | |||
|
357 | ); | |||
|
358 | assert_eq!( | |||
|
359 | collect_early_args(&["log", "--config", "diff.git=1", "-q"]), | |||
|
360 | os_string_vec_from(&[b"--config", b"diff.git=1"]) | |||
|
361 | ); | |||
|
362 | assert_eq!( | |||
|
363 | collect_early_args(&["--cwd=..", "--repository", "r", "log"]), | |||
|
364 | os_string_vec_from(&[b"--cwd=..", b"--repository", b"r"]) | |||
|
365 | ); | |||
|
366 | assert_eq!( | |||
|
367 | collect_early_args(&["log", "--repo=r", "--repos", "a"]), | |||
|
368 | os_string_vec_from(&[b"--repo=r"]) | |||
|
369 | ); | |||
|
370 | } | |||
|
371 | ||||
|
372 | #[test] | |||
|
373 | fn collect_early_args_orphaned() { | |||
|
374 | assert!(collect_early_args(&["log", "-R"]).is_empty()); | |||
|
375 | assert!(collect_early_args(&["log", "--config"]).is_empty()); | |||
|
376 | } | |||
|
377 | ||||
|
378 | #[test] | |||
|
379 | fn collect_early_args_unwanted_value() { | |||
|
380 | assert!(collect_early_args(&["log", "--traceback="]).is_empty()); | |||
|
381 | } | |||
|
382 | ||||
|
383 | fn os_string_vec_from(v: &[&[u8]]) -> Vec<OsString> { | |||
|
384 | v.iter().map(|s| OsStr::from_bytes(s).to_owned()).collect() | |||
|
385 | } | |||
|
386 | } |
@@ -9,7 +9,7 b' extern crate log;' | |||||
9 | extern crate tokio; |
|
9 | extern crate tokio; | |
10 | extern crate tokio_hglib; |
|
10 | extern crate tokio_hglib; | |
11 |
|
11 | |||
12 | use chg::locator::Locator; |
|
12 | use chg::locator::{self, Locator}; | |
13 | use chg::procutil; |
|
13 | use chg::procutil; | |
14 | use chg::{ChgClientExt, ChgUiHandler}; |
|
14 | use chg::{ChgClientExt, ChgUiHandler}; | |
15 | use futures::sync::oneshot; |
|
15 | use futures::sync::oneshot; | |
@@ -73,7 +73,8 b' fn main() {' | |||||
73 | } |
|
73 | } | |
74 |
|
74 | |||
75 | fn run() -> io::Result<i32> { |
|
75 | fn run() -> io::Result<i32> { | |
76 | let loc = Locator::prepare_from_env()?; |
|
76 | let mut loc = Locator::prepare_from_env()?; | |
|
77 | loc.set_early_args(locator::collect_early_args(env::args_os().skip(1))); | |||
77 | let handler = ChgUiHandler::new(); |
|
78 | let handler = ChgUiHandler::new(); | |
78 | let (result_tx, result_rx) = oneshot::channel(); |
|
79 | let (result_tx, result_rx) = oneshot::channel(); | |
79 | let fut = loc |
|
80 | let fut = loc |
General Comments 0
You need to be logged in to leave comments.
Login now