Mercurial > hg
annotate 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 |
rev | line source |
---|---|
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
1 // Copyright 2011, 2018 Yuya Nishihara <yuya@tcha.org> |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
2 // |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
3 // This software may be used and distributed according to the terms of the |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
4 // GNU General Public License version 2 or any later version. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
5 |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
6 //! Utility for locating command-server process. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
7 |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
8 use futures::future::{self, Either, Loop}; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
9 use std::env; |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
10 use std::ffi::{OsStr, OsString}; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
11 use std::fs::{self, DirBuilder}; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
12 use std::io; |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
13 use std::os::unix::ffi::{OsStrExt, OsStringExt}; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
14 use std::os::unix::fs::{DirBuilderExt, MetadataExt}; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
15 use std::path::{Path, PathBuf}; |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
16 use std::process::{self, Command}; |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
17 use std::time::Duration; |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
18 use tokio::prelude::*; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
19 use tokio_hglib::UnixClient; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
20 use tokio_process::{Child, CommandExt}; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
21 use tokio_timer; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
22 |
44673
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
23 use super::clientext::ChgClientExt; |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
24 use super::message::ServerSpec; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
25 use super::procutil; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
26 |
44675
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
27 const REQUIRED_SERVER_CAPABILITIES: &[&str] = &["attachio", "chdir", "runcommand", "setenv"]; |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
28 |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
29 /// Helper to connect to and spawn a server process. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
30 #[derive(Clone, Debug)] |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
31 pub struct Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
32 hg_command: OsString, |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
33 hg_early_args: Vec<OsString>, |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
34 current_dir: PathBuf, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
35 env_vars: Vec<(OsString, OsString)>, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
36 process_id: u32, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
37 base_sock_path: PathBuf, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
38 timeout: Duration, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
39 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
40 |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
41 impl Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
42 /// Creates locator capturing the current process environment. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
43 /// |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
44 /// If no `$CHGSOCKNAME` is specified, the socket directory will be |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
45 /// created as necessary. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
46 pub fn prepare_from_env() -> io::Result<Locator> { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
47 Ok(Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
48 hg_command: default_hg_command(), |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
49 hg_early_args: Vec::new(), |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
50 current_dir: env::current_dir()?, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
51 env_vars: env::vars_os().collect(), |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
52 process_id: process::id(), |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
53 base_sock_path: prepare_server_socket_path()?, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
54 timeout: default_timeout(), |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
55 }) |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
56 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
57 |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
58 /// Temporary socket path for this client process. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
59 fn temp_sock_path(&self) -> PathBuf { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
60 let src = self.base_sock_path.as_os_str().as_bytes(); |
44668
c11d98cff883
rust-chg: add brief comment about initial capacity of temp_sock_path()
Yuya Nishihara <yuya@tcha.org>
parents:
43818
diff
changeset
|
61 let mut buf = Vec::with_capacity(src.len() + 6); // "{src}.{pid}".len() |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
62 buf.extend_from_slice(src); |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
63 buf.extend_from_slice(format!(".{}", self.process_id).as_bytes()); |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
64 OsString::from_vec(buf).into() |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
65 } |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
66 |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
67 /// Specifies the arguments to be passed to the server at start. |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
68 pub fn set_early_args<I, P>(&mut self, args: I) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
69 where |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
70 I: IntoIterator<Item = P>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
71 P: AsRef<OsStr>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
72 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
73 self.hg_early_args = args.into_iter().map(|a| a.as_ref().to_owned()).collect(); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
74 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
75 |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
76 /// Connects to the server. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
77 /// |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
78 /// The server process will be spawned if not running. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
79 pub fn connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
80 self.try_connect() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
81 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
82 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
83 /// Tries to connect to the existing server, or spawns new if not running. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
84 fn try_connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
85 debug!("try connect to {}", self.base_sock_path.display()); |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
86 UnixClient::connect(self.base_sock_path.clone()) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
87 .then(|res| match res { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
88 Ok(client) => Either::A(future::ok((self, client))), |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
89 Err(_) => Either::B(self.spawn_connect()), |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
90 }) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
91 .and_then(|(loc, client)| { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
92 check_server_capabilities(client.server_spec())?; |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
93 Ok((loc, client)) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
94 }) |
44673
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
95 .and_then(|(loc, client)| { |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
96 client |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
97 .set_current_dir(&loc.current_dir) |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
98 .map(|client| (loc, client)) |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
99 }) |
44675
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
100 .and_then(|(loc, client)| { |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
101 client |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
102 .set_env_vars_os(loc.env_vars.iter().cloned()) |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
103 .map(|client| (loc, client)) |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
104 }) |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
105 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
106 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
107 /// Spawns new server process and connects to it. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
108 /// |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
109 /// The server will be spawned at the current working directory, then |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
110 /// chdir to "/", so that the server will load configs from the target |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
111 /// repository. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
112 fn spawn_connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
113 let sock_path = self.temp_sock_path(); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
114 debug!("start cmdserver at {}", sock_path.display()); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
115 Command::new(&self.hg_command) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
116 .arg("serve") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
117 .arg("--cmdserver") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
118 .arg("chgunix") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
119 .arg("--address") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
120 .arg(&sock_path) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
121 .arg("--daemon-postexec") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
122 .arg("chdir:/") |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
123 .args(&self.hg_early_args) |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
124 .current_dir(&self.current_dir) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
125 .env_clear() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
126 .envs(self.env_vars.iter().cloned()) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
127 .env("CHGINTERNALMARK", "") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
128 .spawn_async() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
129 .into_future() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
130 .and_then(|server| self.connect_spawned(server, sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
131 .and_then(|(loc, client, sock_path)| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
132 debug!( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
133 "rename {} to {}", |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
134 sock_path.display(), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
135 loc.base_sock_path.display() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
136 ); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
137 fs::rename(&sock_path, &loc.base_sock_path)?; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
138 Ok((loc, client)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
139 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
140 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
141 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
142 /// Tries to connect to the just spawned server repeatedly until timeout |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
143 /// exceeded. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
144 fn connect_spawned( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
145 self, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
146 server: Child, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
147 sock_path: PathBuf, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
148 ) -> impl Future<Item = (Self, UnixClient, PathBuf), Error = io::Error> { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
149 debug!("try connect to {} repeatedly", sock_path.display()); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
150 let connect = future::loop_fn(sock_path, |sock_path| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
151 UnixClient::connect(sock_path.clone()).then(|res| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
152 match res { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
153 Ok(client) => Either::A(future::ok(Loop::Break((client, sock_path)))), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
154 Err(_) => { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
155 // try again with slight delay |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
156 let fut = tokio_timer::sleep(Duration::from_millis(10)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
157 .map(|()| Loop::Continue(sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
158 .map_err(|err| io::Error::new(io::ErrorKind::Other, err)); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
159 Either::B(fut) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
160 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
161 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
162 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
163 }); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
164 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
165 // waits for either connection established or server failed to start |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
166 connect |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
167 .select2(server) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
168 .map_err(|res| res.split().0) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
169 .timeout(self.timeout) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
170 .map_err(|err| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
171 err.into_inner().unwrap_or_else(|| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
172 io::Error::new( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
173 io::ErrorKind::TimedOut, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
174 "timed out while connecting to server", |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
175 ) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
176 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
177 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
178 .and_then(|res| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
179 match res { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
180 Either::A(((client, sock_path), server)) => { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
181 server.forget(); // continue to run in background |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
182 Ok((self, client, sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
183 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
184 Either::B((st, _)) => Err(io::Error::new( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
185 io::ErrorKind::Other, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
186 format!("server exited too early: {}", st), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
187 )), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
188 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
189 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
190 } |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
191 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
192 |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
193 /// Determines the server socket to connect to. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
194 /// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
195 /// If no `$CHGSOCKNAME` is specified, the socket directory will be created |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
196 /// as necessary. |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
197 fn prepare_server_socket_path() -> io::Result<PathBuf> { |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
198 if let Some(s) = env::var_os("CHGSOCKNAME") { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
199 Ok(PathBuf::from(s)) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
200 } else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
201 let mut path = default_server_socket_dir(); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
202 create_secure_dir(&path)?; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
203 path.push("server"); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
204 Ok(path) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
205 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
206 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
207 |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
208 /// Determines the default server socket path as follows. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
209 /// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
210 /// 1. `$XDG_RUNTIME_DIR/chg` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
211 /// 2. `$TMPDIR/chg$UID` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
212 /// 3. `/tmp/chg$UID` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
213 pub fn default_server_socket_dir() -> PathBuf { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
214 // XDG_RUNTIME_DIR should be ignored if it has an insufficient permission. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
215 // https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
216 if let Some(Ok(s)) = env::var_os("XDG_RUNTIME_DIR").map(check_secure_dir) { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
217 let mut path = PathBuf::from(s); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
218 path.push("chg"); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
219 path |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
220 } else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
221 let mut path = env::temp_dir(); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
222 path.push(format!("chg{}", procutil::get_effective_uid())); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
223 path |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
224 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
225 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
226 |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
227 /// Determines the default hg command. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
228 pub fn default_hg_command() -> OsString { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
229 // TODO: maybe allow embedding the path at compile time (or load from hgrc) |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
230 env::var_os("CHGHG") |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
231 .or(env::var_os("HG")) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
232 .unwrap_or(OsStr::new("hg").to_owned()) |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
233 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
234 |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
235 fn default_timeout() -> Duration { |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
236 let secs = env::var("CHGTIMEOUT") |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
237 .ok() |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
238 .and_then(|s| s.parse().ok()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
239 .unwrap_or(60); |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
240 Duration::from_secs(secs) |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
241 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
242 |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
243 /// Creates a directory which the other users cannot access to. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
244 /// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
245 /// If the directory already exists, tests its permission. |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
246 fn create_secure_dir<P>(path: P) -> io::Result<()> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
247 where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
248 P: AsRef<Path>, |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
249 { |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
250 DirBuilder::new() |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
251 .mode(0o700) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
252 .create(path.as_ref()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
253 .or_else(|err| { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
254 if err.kind() == io::ErrorKind::AlreadyExists { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
255 check_secure_dir(path).map(|_| ()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
256 } else { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
257 Err(err) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
258 } |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
259 }) |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
260 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
261 |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
262 fn check_secure_dir<P>(path: P) -> io::Result<P> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
263 where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
264 P: AsRef<Path>, |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
265 { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
266 let a = fs::symlink_metadata(path.as_ref())?; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
267 if a.is_dir() && a.uid() == procutil::get_effective_uid() && (a.mode() & 0o777) == 0o700 { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
268 Ok(path) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
269 } else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
270 Err(io::Error::new(io::ErrorKind::Other, "insecure directory")) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
271 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
272 } |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
273 |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
274 fn check_server_capabilities(spec: &ServerSpec) -> io::Result<()> { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
275 let unsupported: Vec<_> = REQUIRED_SERVER_CAPABILITIES |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
276 .iter() |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
277 .cloned() |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
278 .filter(|&s| !spec.capabilities.contains(s)) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
279 .collect(); |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
280 if unsupported.is_empty() { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
281 Ok(()) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
282 } else { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
283 let msg = format!( |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
284 "insufficient server capabilities: {}", |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
285 unsupported.join(", ") |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
286 ); |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
287 Err(io::Error::new(io::ErrorKind::Other, msg)) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
288 } |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
289 } |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
290 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
291 /// Collects arguments which need to be passed to the server at start. |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
292 pub fn collect_early_args<I, P>(args: I) -> Vec<OsString> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
293 where |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
294 I: IntoIterator<Item = P>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
295 P: AsRef<OsStr>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
296 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
297 let mut args_iter = args.into_iter(); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
298 let mut early_args = Vec::new(); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
299 while let Some(arg) = args_iter.next() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
300 let argb = arg.as_ref().as_bytes(); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
301 if argb == b"--" { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
302 break; |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
303 } else if argb.starts_with(b"--") { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
304 let mut split = argb[2..].splitn(2, |&c| c == b'='); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
305 match split.next().unwrap() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
306 b"traceback" => { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
307 if split.next().is_none() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
308 early_args.push(arg.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
309 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
310 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
311 b"config" | b"cwd" | b"repo" | b"repository" => { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
312 if split.next().is_some() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
313 // --<flag>=<val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
314 early_args.push(arg.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
315 } else { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
316 // --<flag> <val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
317 args_iter.next().map(|val| { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
318 early_args.push(arg.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
319 early_args.push(val.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
320 }); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
321 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
322 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
323 _ => {} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
324 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
325 } else if argb.starts_with(b"-R") { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
326 if argb.len() > 2 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
327 // -R<val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
328 early_args.push(arg.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
329 } else { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
330 // -R <val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
331 args_iter.next().map(|val| { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
332 early_args.push(arg.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
333 early_args.push(val.as_ref().to_owned()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
334 }); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
335 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
336 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
337 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
338 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
339 early_args |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
340 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
341 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
342 #[cfg(test)] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
343 mod tests { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
344 use super::*; |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
345 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
346 #[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
347 fn collect_early_args_some() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
348 assert!(collect_early_args(&[] as &[&OsStr]).is_empty()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
349 assert!(collect_early_args(&["log"]).is_empty()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
350 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
351 collect_early_args(&["log", "-Ra", "foo"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
352 os_string_vec_from(&[b"-Ra"]) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
353 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
354 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
355 collect_early_args(&["log", "-R", "repo", "", "--traceback", "a"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
356 os_string_vec_from(&[b"-R", b"repo", b"--traceback"]) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
357 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
358 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
359 collect_early_args(&["log", "--config", "diff.git=1", "-q"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
360 os_string_vec_from(&[b"--config", b"diff.git=1"]) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
361 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
362 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
363 collect_early_args(&["--cwd=..", "--repository", "r", "log"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
364 os_string_vec_from(&[b"--cwd=..", b"--repository", b"r"]) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
365 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
366 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
367 collect_early_args(&["log", "--repo=r", "--repos", "a"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
368 os_string_vec_from(&[b"--repo=r"]) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
369 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
370 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
371 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
372 #[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
373 fn collect_early_args_orphaned() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
374 assert!(collect_early_args(&["log", "-R"]).is_empty()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
375 assert!(collect_early_args(&["log", "--config"]).is_empty()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
376 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
377 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
378 #[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
379 fn collect_early_args_unwanted_value() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
380 assert!(collect_early_args(&["log", "--traceback="]).is_empty()); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
381 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
382 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
383 fn os_string_vec_from(v: &[&[u8]]) -> Vec<OsString> { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
384 v.iter().map(|s| OsStr::from_bytes(s).to_owned()).collect() |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
385 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
386 } |