Show More
@@ -30,6 +30,7 b' const REQUIRED_SERVER_CAPABILITIES: &[&s' | |||
|
30 | 30 | #[derive(Clone, Debug)] |
|
31 | 31 | pub struct Locator { |
|
32 | 32 | hg_command: OsString, |
|
33 | hg_early_args: Vec<OsString>, | |
|
33 | 34 | current_dir: PathBuf, |
|
34 | 35 | env_vars: Vec<(OsString, OsString)>, |
|
35 | 36 | process_id: u32, |
@@ -45,6 +46,7 b' impl Locator {' | |||
|
45 | 46 | pub fn prepare_from_env() -> io::Result<Locator> { |
|
46 | 47 | Ok(Locator { |
|
47 | 48 | hg_command: default_hg_command(), |
|
49 | hg_early_args: Vec::new(), | |
|
48 | 50 | current_dir: env::current_dir()?, |
|
49 | 51 | env_vars: env::vars_os().collect(), |
|
50 | 52 | process_id: process::id(), |
@@ -62,6 +64,15 b' impl Locator {' | |||
|
62 | 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 | 76 | /// Connects to the server. |
|
66 | 77 | /// |
|
67 | 78 | /// The server process will be spawned if not running. |
@@ -109,6 +120,7 b' impl Locator {' | |||
|
109 | 120 | .arg(&sock_path) |
|
110 | 121 | .arg("--daemon-postexec") |
|
111 | 122 | .arg("chdir:/") |
|
123 | .args(&self.hg_early_args) | |
|
112 | 124 | .current_dir(&self.current_dir) |
|
113 | 125 | .env_clear() |
|
114 | 126 | .envs(self.env_vars.iter().cloned()) |
@@ -275,3 +287,100 b' fn check_server_capabilities(spec: &Serv' | |||
|
275 | 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 | 9 | extern crate tokio; |
|
10 | 10 | extern crate tokio_hglib; |
|
11 | 11 | |
|
12 | use chg::locator::Locator; | |
|
12 | use chg::locator::{self, Locator}; | |
|
13 | 13 | use chg::procutil; |
|
14 | 14 | use chg::{ChgClientExt, ChgUiHandler}; |
|
15 | 15 | use futures::sync::oneshot; |
@@ -73,7 +73,8 b' fn main() {' | |||
|
73 | 73 | } |
|
74 | 74 | |
|
75 | 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 | 78 | let handler = ChgUiHandler::new(); |
|
78 | 79 | let (result_tx, result_rx) = oneshot::channel(); |
|
79 | 80 | let fut = loc |
General Comments 0
You need to be logged in to leave comments.
Login now