annotate rust/chg/src/locator.rs @ 44737:e9e44e61042b

rust-chg: upgrade to futures-0.3 based libraries And do some trivial fixes: - BytesMut::put_u32_be() -> put_u32() - tokio_process -> tokio::process, CommandExt -> Command, spawn_async() -> spawn(), stdin() -> stdin - tokio_timer::sleep() -> tokio::time::delay_for() Differential Revision: https://phab.mercurial-scm.org/D8441
author Yuya Nishihara <yuya@tcha.org>
date Fri, 10 Apr 2020 21:54:03 +0900
parents 61fda2dbc522
children a347a329e48d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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};
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};
44737
e9e44e61042b rust-chg: upgrade to futures-0.3 based libraries
Yuya Nishihara <yuya@tcha.org>
parents: 44693
diff changeset
17 use std::process;
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::*;
44737
e9e44e61042b rust-chg: upgrade to futures-0.3 based libraries
Yuya Nishihara <yuya@tcha.org>
parents: 44693
diff changeset
20 use tokio::process::{Child, Command};
e9e44e61042b rust-chg: upgrade to futures-0.3 based libraries
Yuya Nishihara <yuya@tcha.org>
parents: 44693
diff changeset
21 use tokio::time;
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
22 use tokio_hglib::UnixClient;
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.
44693
61fda2dbc522 rust-chg: leverage impl trait at argument position
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
78 pub fn set_early_args(&mut self, args: impl IntoIterator<Item = impl AsRef<OsStr>>) {
44681
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
79 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
80 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
81
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
82 /// Connects to the server.
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
83 ///
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
84 /// 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
85 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
86 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
87 if cnt < 10 {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
88 let fut = loc
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
89 .try_connect()
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
90 .and_then(|(loc, client)| {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
91 client
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
92 .validate(&loc.hg_early_args)
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
93 .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
94 })
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
95 .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
96 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
97 });
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
98 Either::A(fut)
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
99 } else {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
100 let msg = format!(
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
101 concat!(
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
102 "too many redirections.\n",
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
103 "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
104 "changes sensitive environment variables ",
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
105 "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
106 "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
107 ),
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
108 loc.hg_command
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 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
111 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
112 })
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
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
115 /// 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
116 fn run_instructions(
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
117 mut self,
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
118 client: UnixClient,
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
119 instructions: Vec<Instruction>,
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
120 cnt: usize,
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
121 ) -> 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
122 let mut reconnect = false;
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
123 for inst in instructions {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
124 debug!("instruction: {:?}", inst);
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
125 match inst {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
126 Instruction::Exit(_) => {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
127 // 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
128 // 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
129 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
130 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
131 Instruction::Reconnect => {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
132 reconnect = true;
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
133 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
134 Instruction::Redirect(path) => {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
135 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
136 let msg = format!(
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
137 "insecure redirect instruction from server: {}",
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
138 path.display()
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
139 );
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
140 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
141 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
142 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
143 reconnect = true;
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
144 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
145 Instruction::Unlink(path) => {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
146 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
147 let msg = format!(
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
148 "insecure unlink instruction from server: {}",
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
149 path.display()
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
150 );
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
151 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
152 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
153 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
154 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
155 }
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
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
158 if reconnect {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
159 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
160 } else {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
161 Ok(Loop::Break((self, client)))
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
162 }
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
163 }
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
164
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
165 /// 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
166 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
167 let sock_path = self
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
168 .redirect_sock_path
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
169 .as_ref()
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
170 .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
171 .clone();
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
172 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
173 UnixClient::connect(sock_path)
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
174 .then(|res| {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
175 match res {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
176 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
177 Err(_) => {
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
178 // 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
179 // 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
180 // 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
181 // 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
182 // 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
183 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
184 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
185 // may race
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
186 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
187 Either::B(self.spawn_connect())
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
188 }
9ce613d648de rust-chg: add config validation and process returned instructions
Yuya Nishihara <yuya@tcha.org>
parents: 44681
diff changeset
189 }
44672
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
190 })
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
191 .and_then(|(loc, client)| {
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
192 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
193 Ok((loc, client))
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
194 })
44673
0a2516efc463 rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents: 44672
diff changeset
195 .and_then(|(loc, client)| {
44684
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
196 // 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
197 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
198 let fut = client
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
199 .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
200 .map(|client| (loc, client));
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
201 Either::A(fut)
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
202 } else {
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
203 Either::B(future::ok((loc, client)))
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
204 }
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
205 })
80d6e3415636 rust-chg: update name of the server process
Yuya Nishihara <yuya@tcha.org>
parents: 44683
diff changeset
206 .and_then(|(loc, client)| {
44673
0a2516efc463 rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents: 44672
diff changeset
207 client
0a2516efc463 rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents: 44672
diff changeset
208 .set_current_dir(&loc.current_dir)
0a2516efc463 rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents: 44672
diff changeset
209 .map(|client| (loc, client))
0a2516efc463 rust-chg: move set_current_dir() to Locator
Yuya Nishihara <yuya@tcha.org>
parents: 44672
diff changeset
210 })
44675
97e6d435ff7e rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents: 44673
diff changeset
211 .and_then(|(loc, client)| {
97e6d435ff7e rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents: 44673
diff changeset
212 client
97e6d435ff7e rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents: 44673
diff changeset
213 .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
214 .map(|client| (loc, client))
97e6d435ff7e rust-chg: send client-side environment variables to server
Yuya Nishihara <yuya@tcha.org>
parents: 44673
diff changeset
215 })
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
216 }
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
217
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
218 /// 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
219 ///
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
220 /// 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
221 /// 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
222 /// repository.
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
223 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
224 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
225 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
226 Command::new(&self.hg_command)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
227 .arg("serve")
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
228 .arg("--cmdserver")
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
229 .arg("chgunix")
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
230 .arg("--address")
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
231 .arg(&sock_path)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
232 .arg("--daemon-postexec")
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
233 .arg("chdir:/")
44681
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
234 .args(&self.hg_early_args)
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
235 .current_dir(&self.current_dir)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
236 .env_clear()
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
237 .envs(self.env_vars.iter().cloned())
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
238 .env("CHGINTERNALMARK", "")
44737
e9e44e61042b rust-chg: upgrade to futures-0.3 based libraries
Yuya Nishihara <yuya@tcha.org>
parents: 44693
diff changeset
239 .spawn()
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
240 .into_future()
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
241 .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
242 .and_then(|(loc, client, sock_path)| {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
243 debug!(
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
244 "rename {} to {}",
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
245 sock_path.display(),
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
246 loc.base_sock_path.display()
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
247 );
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
248 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
249 Ok((loc, client))
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
250 })
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
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
253 /// 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
254 /// exceeded.
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
255 fn connect_spawned(
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
256 self,
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
257 server: Child,
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
258 sock_path: PathBuf,
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
259 ) -> 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
260 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
261 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
262 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
263 match res {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
264 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
265 Err(_) => {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
266 // try again with slight delay
44737
e9e44e61042b rust-chg: upgrade to futures-0.3 based libraries
Yuya Nishihara <yuya@tcha.org>
parents: 44693
diff changeset
267 let fut = time::delay_for(Duration::from_millis(10))
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
268 .map(|()| Loop::Continue(sock_path))
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
269 .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
270 Either::B(fut)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
271 }
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
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
276 // 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
277 connect
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
278 .select2(server)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
279 .map_err(|res| res.split().0)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
280 .timeout(self.timeout)
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
281 .map_err(|err| {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
282 err.into_inner().unwrap_or_else(|| {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
283 io::Error::new(
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
284 io::ErrorKind::TimedOut,
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
285 "timed out while connecting to server",
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 })
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
288 })
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
289 .and_then(|res| {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
290 match res {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
291 Either::A(((client, sock_path), server)) => {
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
292 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
293 Ok((self, client, sock_path))
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
294 }
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
295 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
296 io::ErrorKind::Other,
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
297 format!("server exited too early: {}", st),
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 }
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
300 })
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
301 }
40289
7d3285f799cc rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
302 }
7d3285f799cc rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
303
39976
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
304 /// 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
305 ///
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
306 /// 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
307 /// as necessary.
44671
bb936e25a84a rust-chg: spawn server process if not running
Yuya Nishihara <yuya@tcha.org>
parents: 44668
diff changeset
308 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
309 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
310 Ok(PathBuf::from(s))
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
311 } else {
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
312 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
313 create_secure_dir(&path)?;
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
314 path.push("server");
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
315 Ok(path)
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
316 }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
317 }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
318
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
319 /// 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
320 ///
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
321 /// 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
322 /// 2. `$TMPDIR/chg$UID`
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
323 /// 3. `/tmp/chg$UID`
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
324 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
325 // 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
326 // 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
327 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
328 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
329 path.push("chg");
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
330 path
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
331 } else {
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
332 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
333 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
334 path
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
335 }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
336 }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
337
40289
7d3285f799cc rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
338 /// 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
339 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
340 // 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
341 env::var_os("CHGHG")
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
342 .or(env::var_os("HG"))
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
343 .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
344 }
7d3285f799cc rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
345
7d3285f799cc rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
346 fn default_timeout() -> Duration {
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
347 let secs = env::var("CHGTIMEOUT")
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
348 .ok()
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
349 .and_then(|s| s.parse().ok())
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
350 .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
351 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
352 }
7d3285f799cc rust-chg: add struct holding information needed to spawn server process
Yuya Nishihara <yuya@tcha.org>
parents: 39976
diff changeset
353
39976
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
354 /// 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
355 ///
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
356 /// If the directory already exists, tests its permission.
44693
61fda2dbc522 rust-chg: leverage impl trait at argument position
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
357 fn create_secure_dir(path: impl AsRef<Path>) -> io::Result<()> {
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
358 DirBuilder::new()
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
359 .mode(0o700)
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
360 .create(path.as_ref())
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
361 .or_else(|err| {
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
362 if err.kind() == io::ErrorKind::AlreadyExists {
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
363 check_secure_dir(path).map(|_| ())
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
364 } else {
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
365 Err(err)
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
366 }
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
367 })
39976
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
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
370 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
371 where
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40289
diff changeset
372 P: AsRef<Path>,
39976
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
373 {
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
374 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
375 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
376 Ok(path)
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
377 } else {
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
378 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
379 }
44840bcc411a rust-chg: port basic socket path handling from cHg of C
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
380 }
44672
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
381
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
382 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
383 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
384 .iter()
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
385 .cloned()
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
386 .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
387 .collect();
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
388 if unsupported.is_empty() {
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
389 Ok(())
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
390 } else {
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
391 let msg = format!(
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
392 "insufficient server capabilities: {}",
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
393 unsupported.join(", ")
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
394 );
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
395 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
396 }
7bf45ed9e25e rust-chg: abort if server doesn't have required capabilities
Yuya Nishihara <yuya@tcha.org>
parents: 44671
diff changeset
397 }
44681
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
398
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
399 /// Collects arguments which need to be passed to the server at start.
44693
61fda2dbc522 rust-chg: leverage impl trait at argument position
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
400 pub fn collect_early_args(args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> Vec<OsString> {
44681
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
401 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
402 let mut early_args = Vec::new();
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
403 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
404 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
405 if argb == b"--" {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
406 break;
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
407 } else if argb.starts_with(b"--") {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
408 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
409 match split.next().unwrap() {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
410 b"traceback" => {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
411 if split.next().is_none() {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
412 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
413 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
414 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
415 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
416 if split.next().is_some() {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
417 // --<flag>=<val>
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
418 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
419 } else {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
420 // --<flag> <val>
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
421 args_iter.next().map(|val| {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
422 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
423 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
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 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
427 _ => {}
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
428 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
429 } 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
430 if argb.len() > 2 {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
431 // -R<val>
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
432 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
433 } else {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
434 // -R <val>
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
435 args_iter.next().map(|val| {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
436 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
437 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
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 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
441 }
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 early_args
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
444 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
445
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
446 #[cfg(test)]
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
447 mod tests {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
448 use super::*;
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 #[test]
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
451 fn collect_early_args_some() {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
452 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
453 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
454 assert_eq!(
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
455 collect_early_args(&["log", "-Ra", "foo"]),
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
456 os_string_vec_from(&[b"-Ra"])
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
457 );
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
458 assert_eq!(
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
459 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
460 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
461 );
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
462 assert_eq!(
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
463 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
464 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
465 );
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
466 assert_eq!(
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
467 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
468 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
469 );
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
470 assert_eq!(
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
471 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
472 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
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
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
476 #[test]
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
477 fn collect_early_args_orphaned() {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
478 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
479 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
480 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
481
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
482 #[test]
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
483 fn collect_early_args_unwanted_value() {
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
484 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
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 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
488 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
489 }
00ac60658654 rust-chg: collect server flags from command arguments
Yuya Nishihara <yuya@tcha.org>
parents: 44675
diff changeset
490 }