Mercurial > hg
comparison rust/chg/src/locator.rs @ 44681:00ac60658654
rust-chg: collect server flags from command arguments
This is the reimplementation of testsensitiveflag() and setcmdserverargs()
of chg.c.
Differential Revision: https://phab.mercurial-scm.org/D8380
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 07 Oct 2018 16:46:30 +0900 |
parents | 97e6d435ff7e |
children | 9ce613d648de |
comparison
equal
deleted
inserted
replaced
44680:43513444bb88 | 44681:00ac60658654 |
---|---|
28 | 28 |
29 /// Helper to connect to and spawn a server process. | 29 /// Helper to connect to and spawn a server process. |
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, |
36 base_sock_path: PathBuf, | 37 base_sock_path: PathBuf, |
37 timeout: Duration, | 38 timeout: Duration, |
43 /// If no `$CHGSOCKNAME` is specified, the socket directory will be | 44 /// If no `$CHGSOCKNAME` is specified, the socket directory will be |
44 /// created as necessary. | 45 /// created as necessary. |
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(), |
51 base_sock_path: prepare_server_socket_path()?, | 53 base_sock_path: prepare_server_socket_path()?, |
52 timeout: default_timeout(), | 54 timeout: default_timeout(), |
58 let src = self.base_sock_path.as_os_str().as_bytes(); | 60 let src = self.base_sock_path.as_os_str().as_bytes(); |
59 let mut buf = Vec::with_capacity(src.len() + 6); // "{src}.{pid}".len() | 61 let mut buf = Vec::with_capacity(src.len() + 6); // "{src}.{pid}".len() |
60 buf.extend_from_slice(src); | 62 buf.extend_from_slice(src); |
61 buf.extend_from_slice(format!(".{}", self.process_id).as_bytes()); | 63 buf.extend_from_slice(format!(".{}", self.process_id).as_bytes()); |
62 OsString::from_vec(buf).into() | 64 OsString::from_vec(buf).into() |
65 } | |
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(); | |
63 } | 74 } |
64 | 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. |
107 .arg("chgunix") | 118 .arg("chgunix") |
108 .arg("--address") | 119 .arg("--address") |
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()) |
115 .env("CHGINTERNALMARK", "") | 127 .env("CHGINTERNALMARK", "") |
116 .spawn_async() | 128 .spawn_async() |
273 unsupported.join(", ") | 285 unsupported.join(", ") |
274 ); | 286 ); |
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 } |