Mercurial > hg
annotate rust/chg/src/locator.rs @ 44682:9ce613d648de
rust-chg: add config validation and process returned instructions
This is the reimplementation of runinstructions() and main() in chg.c.
In Rust version, we only pass in early arguments to the server as the locator
doesn't know the full arguments. This should be fine since these arguments
are just passed in to _earlyparseopts() and _parseconfig(), which means the
server doesn't need full arguments.
Another difference is the handling of the "exit <code>" instruction. In Rust
version, we can simply reuse the connection instead of "exit(code)" as the
command error isn't displayed yet. That's because the client-side stdio is not
attached until the connection is validated. This behavior is cleaner than C,
but it also means that the early server exception wouldn't be propagated to
client because stderr isn't attached. So we might have to reconsider when to
attach/detach the server stdio.
Differential Revision: https://phab.mercurial-scm.org/D8381
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 07 Oct 2018 16:14:21 +0900 |
parents | 00ac60658654 |
children | 065048e66f32 |
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; |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
24 use super::message::{Instruction, 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 |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
27 const REQUIRED_SERVER_CAPABILITIES: &[&str] = |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
28 &["attachio", "chdir", "runcommand", "setenv", "validate"]; |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
29 |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
30 /// 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
|
31 #[derive(Clone, Debug)] |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
32 pub struct Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
33 hg_command: OsString, |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
34 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
|
35 current_dir: PathBuf, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
36 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
|
37 process_id: u32, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
38 base_sock_path: PathBuf, |
44682
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
39 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
|
40 timeout: Duration, |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
41 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
42 |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
43 impl Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
44 /// 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
|
45 /// |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
46 /// 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
|
47 /// created as necessary. |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
48 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
|
49 Ok(Locator { |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
50 hg_command: default_hg_command(), |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
51 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
|
52 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
|
53 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
|
54 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
|
55 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
|
56 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
|
57 timeout: default_timeout(), |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
58 }) |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
59 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
60 |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
61 /// 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
|
62 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
|
63 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
|
64 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
|
65 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
|
66 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
|
67 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
|
68 } |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
69 |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
70 /// 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
|
71 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
|
72 where |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
73 I: IntoIterator<Item = P>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
74 P: AsRef<OsStr>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
75 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
76 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
|
77 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
78 |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
79 /// Connects to the server. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
80 /// |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
81 /// 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
|
82 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
|
83 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
|
84 if cnt < 10 { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
85 let fut = loc |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
86 .try_connect() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
87 .and_then(|(loc, client)| { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
88 client |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
89 .validate(&loc.hg_early_args) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
90 .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
|
91 }) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
92 .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
|
93 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
|
94 }); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
95 Either::A(fut) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
96 } else { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
97 let msg = format!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
98 concat!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
99 "too many redirections.\n", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
100 "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
|
101 "changes sensitive environment variables ", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
102 "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
|
103 "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
|
104 ), |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
105 loc.hg_command |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
106 ); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
107 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
|
108 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
109 }) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
110 } |
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 /// 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
|
113 fn run_instructions( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
114 mut self, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
115 client: UnixClient, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
116 instructions: Vec<Instruction>, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
117 cnt: usize, |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
118 ) -> 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
|
119 let mut reconnect = false; |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
120 for inst in instructions { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
121 debug!("instruction: {:?}", inst); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
122 match inst { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
123 Instruction::Exit(_) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
124 // 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
|
125 // 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
|
126 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
|
127 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
128 Instruction::Reconnect => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
129 reconnect = true; |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
130 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
131 Instruction::Redirect(path) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
132 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
|
133 let msg = format!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
134 "insecure redirect instruction from server: {}", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
135 path.display() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
136 ); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
137 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
|
138 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
139 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
|
140 reconnect = true; |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
141 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
142 Instruction::Unlink(path) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
143 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
|
144 let msg = format!( |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
145 "insecure unlink instruction from server: {}", |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
146 path.display() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
147 ); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
148 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
|
149 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
150 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
|
151 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
152 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
153 } |
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 if reconnect { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
156 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
|
157 } else { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
158 Ok(Loop::Break((self, client))) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
159 } |
44671
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 /// 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
|
163 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
|
164 let sock_path = self |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
165 .redirect_sock_path |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
166 .as_ref() |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
167 .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
|
168 .clone(); |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
169 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
|
170 UnixClient::connect(sock_path) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
171 .then(|res| { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
172 match res { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
173 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
|
174 Err(_) => { |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
175 // 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
|
176 // 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
|
177 // 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
|
178 // 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
|
179 // 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
|
180 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
|
181 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
|
182 // may race |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
183 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
184 Either::B(self.spawn_connect()) |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
185 } |
9ce613d648de
rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents:
44681
diff
changeset
|
186 } |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
187 }) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
188 .and_then(|(loc, client)| { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
189 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
|
190 Ok((loc, client)) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
191 }) |
44673
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
192 .and_then(|(loc, client)| { |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
193 client |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
194 .set_current_dir(&loc.current_dir) |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
195 .map(|client| (loc, client)) |
0a2516efc463
rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents:
44672
diff
changeset
|
196 }) |
44675
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
197 .and_then(|(loc, client)| { |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
198 client |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
199 .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
|
200 .map(|client| (loc, client)) |
97e6d435ff7e
rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents:
44673
diff
changeset
|
201 }) |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
202 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
203 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
204 /// 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
|
205 /// |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
206 /// 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
|
207 /// 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
|
208 /// repository. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
209 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
|
210 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
|
211 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
|
212 Command::new(&self.hg_command) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
213 .arg("serve") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
214 .arg("--cmdserver") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
215 .arg("chgunix") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
216 .arg("--address") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
217 .arg(&sock_path) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
218 .arg("--daemon-postexec") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
219 .arg("chdir:/") |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
220 .args(&self.hg_early_args) |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
221 .current_dir(&self.current_dir) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
222 .env_clear() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
223 .envs(self.env_vars.iter().cloned()) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
224 .env("CHGINTERNALMARK", "") |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
225 .spawn_async() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
226 .into_future() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
227 .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
|
228 .and_then(|(loc, client, sock_path)| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
229 debug!( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
230 "rename {} to {}", |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
231 sock_path.display(), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
232 loc.base_sock_path.display() |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
233 ); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
234 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
|
235 Ok((loc, client)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
236 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
237 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
238 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
239 /// 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
|
240 /// exceeded. |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
241 fn connect_spawned( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
242 self, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
243 server: Child, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
244 sock_path: PathBuf, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
245 ) -> 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
|
246 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
|
247 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
|
248 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
|
249 match res { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
250 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
|
251 Err(_) => { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
252 // try again with slight delay |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
253 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
|
254 .map(|()| Loop::Continue(sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
255 .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
|
256 Either::B(fut) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
257 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
258 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
259 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
260 }); |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
261 |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
262 // 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
|
263 connect |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
264 .select2(server) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
265 .map_err(|res| res.split().0) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
266 .timeout(self.timeout) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
267 .map_err(|err| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
268 err.into_inner().unwrap_or_else(|| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
269 io::Error::new( |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
270 io::ErrorKind::TimedOut, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
271 "timed out while connecting to server", |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
272 ) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
273 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
274 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
275 .and_then(|res| { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
276 match res { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
277 Either::A(((client, sock_path), server)) => { |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
278 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
|
279 Ok((self, client, sock_path)) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
280 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
281 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
|
282 io::ErrorKind::Other, |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
283 format!("server exited too early: {}", st), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
284 )), |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
285 } |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
286 }) |
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
287 } |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
288 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
289 |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
290 /// 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
|
291 /// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
292 /// 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
|
293 /// as necessary. |
44671
bb936e25a84a
rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents:
44668
diff
changeset
|
294 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
|
295 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
|
296 Ok(PathBuf::from(s)) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
297 } else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
298 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
|
299 create_secure_dir(&path)?; |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
300 path.push("server"); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
301 Ok(path) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
302 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
303 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
304 |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
305 /// 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
|
306 /// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
307 /// 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
|
308 /// 2. `$TMPDIR/chg$UID` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
309 /// 3. `/tmp/chg$UID` |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
310 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
|
311 // 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
|
312 // 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
|
313 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
|
314 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
|
315 path.push("chg"); |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
316 path |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
317 } else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
318 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
|
319 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
|
320 path |
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 |
40289
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
324 /// 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
|
325 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
|
326 // 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
|
327 env::var_os("CHGHG") |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
328 .or(env::var_os("HG")) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
329 .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
|
330 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
331 |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
332 fn default_timeout() -> Duration { |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
333 let secs = env::var("CHGTIMEOUT") |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
334 .ok() |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
335 .and_then(|s| s.parse().ok()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
336 .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
|
337 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
|
338 } |
7d3285f799cc
rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents:
39976
diff
changeset
|
339 |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
340 /// 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
|
341 /// |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
342 /// 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
|
343 fn create_secure_dir<P>(path: P) -> io::Result<()> |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
344 where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
345 P: AsRef<Path>, |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
346 { |
43818
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
347 DirBuilder::new() |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
348 .mode(0o700) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
349 .create(path.as_ref()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
350 .or_else(|err| { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
351 if err.kind() == io::ErrorKind::AlreadyExists { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
352 check_secure_dir(path).map(|_| ()) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
353 } else { |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
354 Err(err) |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
355 } |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
356 }) |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
357 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
358 |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
359 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
|
360 where |
ce088b38f92b
rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40289
diff
changeset
|
361 P: AsRef<Path>, |
39976
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
362 { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
363 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
|
364 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
|
365 Ok(path) |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
366 } else { |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
367 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
|
368 } |
44840bcc411a
rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
369 } |
44672
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
370 |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
371 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
|
372 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
|
373 .iter() |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
374 .cloned() |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
375 .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
|
376 .collect(); |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
377 if unsupported.is_empty() { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
378 Ok(()) |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
379 } else { |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
380 let msg = format!( |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
381 "insufficient server capabilities: {}", |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
382 unsupported.join(", ") |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
383 ); |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
384 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
|
385 } |
7bf45ed9e25e
rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents:
44671
diff
changeset
|
386 } |
44681
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
387 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
388 /// 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
|
389 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
|
390 where |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
391 I: IntoIterator<Item = P>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
392 P: AsRef<OsStr>, |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
393 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
394 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
|
395 let mut early_args = Vec::new(); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
396 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
|
397 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
|
398 if argb == b"--" { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
399 break; |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
400 } else if argb.starts_with(b"--") { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
401 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
|
402 match split.next().unwrap() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
403 b"traceback" => { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
404 if split.next().is_none() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
405 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
|
406 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
407 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
408 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
|
409 if split.next().is_some() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
410 // --<flag>=<val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
411 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
|
412 } else { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
413 // --<flag> <val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
414 args_iter.next().map(|val| { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
415 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
|
416 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
|
417 }); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
418 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
419 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
420 _ => {} |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
421 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
422 } 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
|
423 if argb.len() > 2 { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
424 // -R<val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
425 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
|
426 } else { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
427 // -R <val> |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
428 args_iter.next().map(|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 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
|
431 }); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
432 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
433 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
434 } |
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 early_args |
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 #[cfg(test)] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
440 mod tests { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
441 use super::*; |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
442 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
443 #[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
444 fn collect_early_args_some() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
445 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
|
446 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
|
447 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
448 collect_early_args(&["log", "-Ra", "foo"]), |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
449 os_string_vec_from(&[b"-Ra"]) |
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 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
452 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
|
453 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
|
454 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
455 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
456 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
|
457 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
|
458 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
459 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
460 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
|
461 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
|
462 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
463 assert_eq!( |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
464 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
|
465 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
|
466 ); |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
467 } |
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 #[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
470 fn collect_early_args_orphaned() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
471 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
|
472 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
|
473 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
474 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
475 #[test] |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
476 fn collect_early_args_unwanted_value() { |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
477 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
|
478 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
479 |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
480 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
|
481 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
|
482 } |
00ac60658654
rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents:
44675
diff
changeset
|
483 } |