author | Yuya Nishihara <yuya@tcha.org> |
Fri, 10 Apr 2020 21:38:08 +0900 | |
changeset 44689 | 6bef9d43cc55 |
parent 44688 | 1f5ab1a9363d |
child 44693 | 61fda2dbc522 |
permissions | -rw-r--r-- |
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}; |
44688
1f5ab1a9363d
rust-chg: upgrade to 2018 edition and remove useless extern crates
Yuya Nishihara <yuya@tcha.org>
parents:
44684
diff
changeset
|
9 |
use log::debug; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
10 |
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
|
11 |
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
|
12 |
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
|
13 |
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
|
14 |
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
|
15 |
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
|
16 |
use std::path::{Path, PathBuf}; |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
17 |
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
|
18 |
use std::time::Duration; |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
19 |
use tokio::prelude::*; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
20 |
use tokio_hglib::UnixClient; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
21 |
use tokio_process::{Child, CommandExt}; |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
22 |
use tokio_timer; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
23 |
|
44689
6bef9d43cc55
rust-chg: use "crate::" to import local modules
Yuya Nishihara <yuya@tcha.org>
parents:
44688
diff
changeset
|
24 |
use crate::clientext::ChgClientExt; |
6bef9d43cc55
rust-chg: use "crate::" to import local modules
Yuya Nishihara <yuya@tcha.org>
parents:
44688
diff
changeset
|
25 |
use crate::message::{Instruction, ServerSpec}; |
6bef9d43cc55
rust-chg: use "crate::" to import local modules
Yuya Nishihara <yuya@tcha.org>
parents:
44688
diff
changeset
|
26 |
use crate::procutil; |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
27 |
|
44683
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
28 |
const REQUIRED_SERVER_CAPABILITIES: &[&str] = &[ |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
29 |
"attachio", |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
30 |
"chdir", |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
31 |
"runcommand", |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
32 |
"setenv", |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
33 |
"setumask2", |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
34 |
"validate", |
065048e66f32
rust-chg: send client side umask to server
Yuya Nishihara <yuya@tcha.org>
parents:
44682
diff
changeset
|
35 |
]; |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
36 |
|
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
37 |
/// 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
|
38 |
#[derive(Clone, Debug)] |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
39 |
pub struct Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
40 |
hg_command: OsString, |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
41 |
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
|
42 |
current_dir: PathBuf, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
43 |
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
|
44 |
process_id: u32, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
45 |
base_sock_path: PathBuf, |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
46 |
redirect_sock_path: Option<PathBuf>, |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
47 |
timeout: Duration, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
48 |
} |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
49 |
|
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
50 |
impl Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
51 |
/// 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
|
52 |
/// |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
53 |
/// 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
|
54 |
/// created as necessary. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
55 |
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
|
56 |
Ok(Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
57 |
hg_command: default_hg_command(), |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
58 |
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
|
59 |
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
|
60 |
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
|
61 |
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
|
62 |
base_sock_path: prepare_server_socket_path()?, |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
63 |
redirect_sock_path: None, |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
64 |
timeout: default_timeout(), |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
65 |
}) |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
66 |
} |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
67 |
|
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
68 |
/// 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
|
69 |
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
|
70 |
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
|
71 |
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
|
72 |
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
|
73 |
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
|
74 |
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
|
75 |
} |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
76 |
|
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
77 |
/// 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
|
78 |
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
|
79 |
where |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
80 |
I: IntoIterator<Item = P>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
81 |
P: AsRef<OsStr>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
82 |
{ |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
83 |
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
|
84 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
85 |
|
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
86 |
/// Connects to the server. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
87 |
/// |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
88 |
/// 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
|
89 |
pub fn connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> { |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
90 |
future::loop_fn((self, 0), |(loc, cnt)| { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
91 |
if cnt < 10 { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
92 |
let fut = loc |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
93 |
.try_connect() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
94 |
.and_then(|(loc, client)| { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
95 |
client |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
96 |
.validate(&loc.hg_early_args) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
97 |
.map(|(client, instructions)| (loc, client, instructions)) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
98 |
}) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
99 |
.and_then(move |(loc, client, instructions)| { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
100 |
loc.run_instructions(client, instructions, cnt) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
101 |
}); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
102 |
Either::A(fut) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
103 |
} else { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
104 |
let msg = format!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
105 |
concat!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
106 |
"too many redirections.\n", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
107 |
"Please make sure {:?} is not a wrapper which ", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
108 |
"changes sensitive environment variables ", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
109 |
"before executing hg. If you have to use a ", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
110 |
"wrapper, wrap chg instead of hg.", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
111 |
), |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
112 |
loc.hg_command |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
113 |
); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
114 |
Either::B(future::err(io::Error::new(io::ErrorKind::Other, msg))) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
115 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
116 |
}) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
117 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
118 |
|
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
119 |
/// Runs instructions received from the server. |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
120 |
fn run_instructions( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
121 |
mut self, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
122 |
client: UnixClient, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
123 |
instructions: Vec<Instruction>, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
124 |
cnt: usize, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
125 |
) -> io::Result<Loop<(Self, UnixClient), (Self, usize)>> { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
126 |
let mut reconnect = false; |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
127 |
for inst in instructions { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
128 |
debug!("instruction: {:?}", inst); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
129 |
match inst { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
130 |
Instruction::Exit(_) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
131 |
// Just returns the current connection to run the |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
132 |
// unparsable command and report the error |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
133 |
return Ok(Loop::Break((self, client))); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
134 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
135 |
Instruction::Reconnect => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
136 |
reconnect = true; |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
137 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
138 |
Instruction::Redirect(path) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
139 |
if path.parent() != self.base_sock_path.parent() { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
140 |
let msg = format!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
141 |
"insecure redirect instruction from server: {}", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
142 |
path.display() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
143 |
); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
144 |
return Err(io::Error::new(io::ErrorKind::InvalidData, msg)); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
145 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
146 |
self.redirect_sock_path = Some(path); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
147 |
reconnect = true; |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
148 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
149 |
Instruction::Unlink(path) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
150 |
if path.parent() != self.base_sock_path.parent() { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
151 |
let msg = format!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
152 |
"insecure unlink instruction from server: {}", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
153 |
path.display() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
154 |
); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
155 |
return Err(io::Error::new(io::ErrorKind::InvalidData, msg)); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
156 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
157 |
fs::remove_file(path).unwrap_or(()); // may race |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
158 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
159 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
160 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
161 |
|
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
162 |
if reconnect { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
163 |
Ok(Loop::Continue((self, cnt + 1))) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
164 |
} else { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
165 |
Ok(Loop::Break((self, client))) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
166 |
} |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
167 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
168 |
|
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
169 |
/// 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
|
170 |
fn try_connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> { |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
171 |
let sock_path = self |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
172 |
.redirect_sock_path |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
173 |
.as_ref() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
174 |
.unwrap_or(&self.base_sock_path) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
175 |
.clone(); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
176 |
debug!("try connect to {}", sock_path.display()); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
177 |
UnixClient::connect(sock_path) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
178 |
.then(|res| { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
179 |
match res { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
180 |
Ok(client) => Either::A(future::ok((self, client))), |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
181 |
Err(_) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
182 |
// Prevent us from being re-connected to the outdated |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
183 |
// master server: We were told by the server to redirect |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
184 |
// to redirect_sock_path, which didn't work. We do not |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
185 |
// want to connect to the same master server again |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
186 |
// because it would probably tell us the same thing. |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
187 |
if self.redirect_sock_path.is_some() { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
188 |
fs::remove_file(&self.base_sock_path).unwrap_or(()); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
189 |
// may race |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
190 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
191 |
Either::B(self.spawn_connect()) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
192 |
} |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
193 |
} |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
194 |
}) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
195 |
.and_then(|(loc, client)| { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
196 |
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
|
197 |
Ok((loc, client)) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
198 |
}) |
44673
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
199 |
.and_then(|(loc, client)| { |
44684
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
200 |
// It's purely optional, and the server might not support this command. |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
201 |
if client.server_spec().capabilities.contains("setprocname") { |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
202 |
let fut = client |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
203 |
.set_process_name(format!("chg[worker/{}]", loc.process_id)) |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
204 |
.map(|client| (loc, client)); |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
205 |
Either::A(fut) |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
206 |
} else { |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
207 |
Either::B(future::ok((loc, client))) |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
208 |
} |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
209 |
}) |
80d6e3415636
rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents:
44683
diff
changeset
|
210 |
.and_then(|(loc, client)| { |
44673
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
211 |
client |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
212 |
.set_current_dir(&loc.current_dir) |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
213 |
.map(|client| (loc, client)) |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
214 |
}) |
44675
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
215 |
.and_then(|(loc, client)| { |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
216 |
client |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
217 |
.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
|
218 |
.map(|client| (loc, client)) |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
219 |
}) |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
220 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
221 |
|
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
222 |
/// 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
|
223 |
/// |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
224 |
/// 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
|
225 |
/// 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
|
226 |
/// repository. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
227 |
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
|
228 |
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
|
229 |
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
|
230 |
Command::new(&self.hg_command) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
231 |
.arg("serve") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
232 |
.arg("--cmdserver") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
233 |
.arg("chgunix") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
234 |
.arg("--address") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
235 |
.arg(&sock_path) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
236 |
.arg("--daemon-postexec") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
237 |
.arg("chdir:/") |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
238 |
.args(&self.hg_early_args) |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
239 |
.current_dir(&self.current_dir) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
240 |
.env_clear() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
241 |
.envs(self.env_vars.iter().cloned()) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
242 |
.env("CHGINTERNALMARK", "") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
243 |
.spawn_async() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
244 |
.into_future() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
245 |
.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
|
246 |
.and_then(|(loc, client, sock_path)| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
247 |
debug!( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
248 |
"rename {} to {}", |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
249 |
sock_path.display(), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
250 |
loc.base_sock_path.display() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
251 |
); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
252 |
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
|
253 |
Ok((loc, client)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
254 |
}) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
255 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
256 |
|
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
257 |
/// 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
|
258 |
/// exceeded. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
259 |
fn connect_spawned( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
260 |
self, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
261 |
server: Child, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
262 |
sock_path: PathBuf, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
263 |
) -> 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
|
264 |
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
|
265 |
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
|
266 |
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
|
267 |
match res { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
268 |
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
|
269 |
Err(_) => { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
270 |
// try again with slight delay |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
271 |
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
|
272 |
.map(|()| Loop::Continue(sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
273 |
.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
|
274 |
Either::B(fut) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
275 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
276 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
277 |
}) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
278 |
}); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
279 |
|
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
280 |
// 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
|
281 |
connect |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
282 |
.select2(server) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
283 |
.map_err(|res| res.split().0) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
284 |
.timeout(self.timeout) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
285 |
.map_err(|err| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
286 |
err.into_inner().unwrap_or_else(|| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
287 |
io::Error::new( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
288 |
io::ErrorKind::TimedOut, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
289 |
"timed out while connecting to server", |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
290 |
) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
291 |
}) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
292 |
}) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
293 |
.and_then(|res| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
294 |
match res { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
295 |
Either::A(((client, sock_path), server)) => { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
296 |
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
|
297 |
Ok((self, client, sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
298 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
299 |
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
|
300 |
io::ErrorKind::Other, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
301 |
format!("server exited too early: {}", st), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
302 |
)), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
303 |
} |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
304 |
}) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
305 |
} |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
306 |
} |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
307 |
|
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
308 |
/// 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
|
309 |
/// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
310 |
/// 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
|
311 |
/// as necessary. |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
312 |
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
|
313 |
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
|
314 |
Ok(PathBuf::from(s)) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
315 |
} else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
316 |
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
|
317 |
create_secure_dir(&path)?; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
318 |
path.push("server"); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
319 |
Ok(path) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
320 |
} |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
321 |
} |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
322 |
|
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
323 |
/// 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
|
324 |
/// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
325 |
/// 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
|
326 |
/// 2. `$TMPDIR/chg$UID` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
327 |
/// 3. `/tmp/chg$UID` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
328 |
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
|
329 |
// 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
|
330 |
// 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
|
331 |
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
|
332 |
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
|
333 |
path.push("chg"); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
334 |
path |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
335 |
} else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
336 |
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
|
337 |
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
|
338 |
path |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
339 |
} |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
340 |
} |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
341 |
|
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
342 |
/// 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
|
343 |
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
|
344 |
// 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
|
345 |
env::var_os("CHGHG") |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
346 |
.or(env::var_os("HG")) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
347 |
.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
|
348 |
} |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
349 |
|
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
350 |
fn default_timeout() -> Duration { |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
351 |
let secs = env::var("CHGTIMEOUT") |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
352 |
.ok() |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
353 |
.and_then(|s| s.parse().ok()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
354 |
.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
|
355 |
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
|
356 |
} |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
357 |
|
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
358 |
/// 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
|
359 |
/// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
360 |
/// 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
|
361 |
fn create_secure_dir<P>(path: P) -> io::Result<()> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
362 |
where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
363 |
P: AsRef<Path>, |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
364 |
{ |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
365 |
DirBuilder::new() |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
366 |
.mode(0o700) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
367 |
.create(path.as_ref()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
368 |
.or_else(|err| { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
369 |
if err.kind() == io::ErrorKind::AlreadyExists { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
370 |
check_secure_dir(path).map(|_| ()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
371 |
} else { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
372 |
Err(err) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
373 |
} |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
374 |
}) |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
375 |
} |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
376 |
|
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
377 |
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
|
378 |
where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
379 |
P: AsRef<Path>, |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
380 |
{ |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
381 |
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
|
382 |
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
|
383 |
Ok(path) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
384 |
} else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
385 |
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
|
386 |
} |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
387 |
} |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
388 |
|
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
389 |
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
|
390 |
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
|
391 |
.iter() |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
392 |
.cloned() |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
393 |
.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
|
394 |
.collect(); |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
395 |
if unsupported.is_empty() { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
396 |
Ok(()) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
397 |
} else { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
398 |
let msg = format!( |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
399 |
"insufficient server capabilities: {}", |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
400 |
unsupported.join(", ") |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
401 |
); |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
402 |
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
|
403 |
} |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
404 |
} |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
405 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
406 |
/// 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
|
407 |
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
|
408 |
where |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
409 |
I: IntoIterator<Item = P>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
410 |
P: AsRef<OsStr>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
411 |
{ |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
412 |
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
|
413 |
let mut early_args = Vec::new(); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
414 |
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
|
415 |
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
|
416 |
if argb == b"--" { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
417 |
break; |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
418 |
} else if argb.starts_with(b"--") { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
419 |
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
|
420 |
match split.next().unwrap() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
421 |
b"traceback" => { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
422 |
if split.next().is_none() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
423 |
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
|
424 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
425 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
426 |
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
|
427 |
if split.next().is_some() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
428 |
// --<flag>=<val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
429 |
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
|
430 |
} else { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
431 |
// --<flag> <val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
432 |
args_iter.next().map(|val| { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
433 |
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
|
434 |
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
|
435 |
}); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
436 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
437 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
438 |
_ => {} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
439 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
440 |
} 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
|
441 |
if argb.len() > 2 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
442 |
// -R<val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
443 |
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
|
444 |
} else { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
445 |
// -R <val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
446 |
args_iter.next().map(|val| { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
447 |
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
|
448 |
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
|
449 |
}); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
450 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
451 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
452 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
453 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
454 |
early_args |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
455 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
456 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
457 |
#[cfg(test)] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
458 |
mod tests { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
459 |
use super::*; |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
460 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
461 |
#[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
462 |
fn collect_early_args_some() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
463 |
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
|
464 |
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
|
465 |
assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
466 |
collect_early_args(&["log", "-Ra", "foo"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
467 |
os_string_vec_from(&[b"-Ra"]) |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
468 |
); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
469 |
assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
470 |
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
|
471 |
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
|
472 |
); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
473 |
assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
474 |
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
|
475 |
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
|
476 |
); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
477 |
assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
478 |
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
|
479 |
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
|
480 |
); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
481 |
assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
482 |
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
|
483 |
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
|
484 |
); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
485 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
486 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
487 |
#[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
488 |
fn collect_early_args_orphaned() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
489 |
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
|
490 |
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
|
491 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
492 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
493 |
#[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
494 |
fn collect_early_args_unwanted_value() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
495 |
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
|
496 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
497 |
|
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
498 |
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
|
499 |
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
|
500 |
} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
501 |
} |