diff --git a/config.example.toml b/config.example.toml index 3ae12fda..a9a37548 100644 --- a/config.example.toml +++ b/config.example.toml @@ -25,6 +25,9 @@ # Arguments to pass Git when pulling Repositories #git_arguments = "--rebase --autostash" +# Arguments to pass tmux when pulling Repositories +#tmux_arguments = "-S /var/tmux.sock" + # Arguments to pass yay when updating packages #yay_arguments = "--nodevel" diff --git a/src/config.rs b/src/config.rs index 32634cbd..0fbe06ff 100644 --- a/src/config.rs +++ b/src/config.rs @@ -57,6 +57,7 @@ pub struct ConfigFile { remote_topgrades: Option>, ssh_arguments: Option, git_arguments: Option, + tmux_arguments: Option, set_title: Option, assume_yes: Option, yay_arguments: Option, @@ -289,6 +290,11 @@ impl Config { &self.config_file.git_arguments } + /// Extra Tmux arguments + pub fn tmux_arguments(&self) -> &Option { + &self.config_file.tmux_arguments + } + /// Prompt for a key before exiting pub fn keep_at_end(&self) -> bool { self.opt.keep_at_end || env::var("TOPGRADE_KEEP_END").is_ok() diff --git a/src/main.rs b/src/main.rs index 3c464ea8..66473497 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,7 @@ fn run() -> Result<(), Error> { if config.run_in_tmux() && env::var("TOPGRADE_INSIDE_TMUX").is_err() { #[cfg(unix)] { - tmux::run_in_tmux(); + tmux::run_in_tmux(config.tmux_arguments()); } } @@ -142,6 +142,7 @@ fn run() -> Result<(), Error> { remote_topgrade, config.ssh_arguments(), config.run_in_tmux(), + config.tmux_arguments(), ) }, config.no_retry(), diff --git a/src/steps/generic.rs b/src/steps/generic.rs index 2e25d780..3efce51a 100644 --- a/src/steps/generic.rs +++ b/src/steps/generic.rs @@ -149,13 +149,14 @@ pub fn run_remote_topgrade( hostname: &str, ssh_arguments: &Option, run_in_tmux: bool, + _tmux_arguments: &Option, ) -> Result<(), Error> { let ssh = utils::require("ssh")?; if run_in_tmux && !run_type.dry() { #[cfg(unix)] { - crate::tmux::run_remote_topgrade(hostname, &ssh)?; + crate::tmux::run_remote_topgrade(hostname, &ssh, _tmux_arguments)?; Err(ErrorKind::SkipStep.into()) } diff --git a/src/steps/tmux.rs b/src/steps/tmux.rs index 83976f01..90206b3f 100644 --- a/src/steps/tmux.rs +++ b/src/steps/tmux.rs @@ -7,7 +7,7 @@ use failure::ResultExt; use std::env; use std::io; use std::os::unix::process::CommandExt; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{exit, Command}; pub fn run_tpm(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { @@ -21,39 +21,61 @@ pub fn run_tpm(base_dirs: &BaseDirs, run_type: RunType) -> Result<(), Error> { run_type.execute(&tpm).arg("all").check_run() } -fn has_session(tmux: &Path, session_name: &str) -> Result { - Ok(Command::new(tmux) - .args(&["has-session", "-t", session_name]) - .env_remove("TMUX") - .output()? - .status - .success()) +struct Tmux { + tmux: PathBuf, + args: Option>, } -fn new_session(tmux: &Path, session_name: &str) -> Result { - Ok(Command::new(tmux) - .args(&["new-session", "-d", "-s", session_name, "-n", "dummy"]) - .env_remove("TMUX") - .spawn()? - .wait()? - .success()) +impl Tmux { + fn new(args: &Option) -> Self { + Self { + tmux: which("tmux").expect("Could not find tmux"), + args: args + .as_ref() + .map(|args| args.split_whitespace().map(String::from).collect()), + } + } + + fn build(&self) -> Command { + let mut command = Command::new(&self.tmux); + if let Some(args) = self.args.as_ref() { + command.args(args).env_remove("TMUX"); + } + command + } + + fn has_session(&self, session_name: &str) -> Result { + Ok(self + .build() + .args(&["has-session", "-t", session_name]) + .output()? + .status + .success()) + } + + fn new_session(&self, session_name: &str) -> Result { + Ok(self + .build() + .args(&["new-session", "-d", "-s", session_name, "-n", "dummy"]) + .spawn()? + .wait()? + .success()) + } + + fn run_in_session(&self, command: &str) -> Result<(), Error> { + self.build() + .args(&["new-window", "-a", "-t", "topgrade:1", command]) + .spawn() + .context(ErrorKind::ProcessExecution)? + .wait() + .context(ErrorKind::ProcessExecution)? + .check()?; + + Ok(()) + } } -fn run_in_session(tmux: &Path, command: &str) -> Result<(), Error> { - Command::new(tmux) - .args(&["new-window", "-a", "-t", "topgrade:1", command]) - .env_remove("TMUX") - .spawn() - .context(ErrorKind::ProcessExecution)? - .wait() - .context(ErrorKind::ProcessExecution)? - .check()?; - - Ok(()) -} - -pub fn run_in_tmux() -> ! { - let tmux = which("tmux").expect("Could not find tmux"); +pub fn run_in_tmux(args: &Option) -> ! { let command = { let mut command = vec![ String::from("env"), @@ -64,18 +86,20 @@ pub fn run_in_tmux() -> ! { command.join(" ") }; - if !has_session(&tmux, "topgrade").expect("Error launching tmux") { - new_session(&tmux, "topgrade").expect("Error launching tmux"); + let tmux = Tmux::new(args); + + if !tmux.has_session("topgrade").expect("Error launching tmux") { + tmux.new_session("topgrade").expect("Error launching tmux"); } - run_in_session(&tmux, &command).expect("Error launching tmux"); - Command::new(&tmux) + tmux.run_in_session(&command).expect("Error launching tmux"); + tmux.build() .args(&["kill-window", "-t", "topgrade:dummy"]) .output() .unwrap(); if env::var("TMUX").is_err() { - let err = Command::new(tmux).args(&["attach", "-t", "topgrade"]).exec(); + let err = tmux.build().args(&["attach", "-t", "topgrade"]).exec(); panic!("{:?}", err); } else { println!("Topgrade launched in a new tmux session"); @@ -83,13 +107,14 @@ pub fn run_in_tmux() -> ! { } } -pub fn run_remote_topgrade(hostname: &str, ssh: &Path) -> Result<(), Error> { +pub fn run_remote_topgrade(hostname: &str, ssh: &Path, tmux_args: &Option) -> Result<(), Error> { let command = format!( "{ssh} -t {hostname} env TOPGRADE_PREFIX={hostname} TOPGRADE_KEEP_END=1 topgrade", ssh = ssh.display(), hostname = hostname ); - Command::new(which("tmux").unwrap()) + Tmux::new(tmux_args) + .build() .args(&["new-window", "-a", "-t", "topgrade:1", &command]) .env_remove("TMUX") .spawn()