Remove calls to exit() and replace them with error propagation up to main()

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2019-10-19 08:54:57 +02:00
parent eb8912ffe6
commit 2811ad3d4d
2 changed files with 65 additions and 86 deletions

View file

@ -41,6 +41,5 @@ extern crate libimaginitcmd;
fn main() -> Result<()> { fn main() -> Result<()> {
libimaginitcmd::imag_init(); libimaginitcmd::imag_init()
Ok(())
} }

View file

@ -35,7 +35,8 @@
)] )]
extern crate clap; extern crate clap;
extern crate failure; #[macro_use] extern crate failure;
#[cfg(test)] #[cfg(test)]
extern crate toml; extern crate toml;
@ -50,12 +51,14 @@ use std::path::PathBuf;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use libimagerror::exit::ExitUnwrap; use failure::Fallible as Result;
use libimagerror::io::ToExitCode; use failure::ResultExt;
use failure::Error;
use failure::err_msg;
use libimagrt::runtime::Runtime; use libimagrt::runtime::Runtime;
use libimagrt::application::ImagApplication; use libimagrt::application::ImagApplication;
use failure::Fallible as Result;
use clap::App; use clap::App;
const CONFIGURATION_STR : &str = include_str!("../imagrc.toml"); const CONFIGURATION_STR : &str = include_str!("../imagrc.toml");
@ -100,7 +103,7 @@ impl ImagApplication for ImagInit {
} }
} }
pub fn imag_init() { pub fn imag_init() -> Result<()> {
let version = make_imag_version!(); let version = make_imag_version!();
let app = ui::build_ui(Runtime::get_default_cli_builder( let app = ui::build_ui(Runtime::get_default_cli_builder(
"imag-init", "imag-init",
@ -109,35 +112,27 @@ pub fn imag_init() {
let matches = app.get_matches(); let matches = app.get_matches();
let mut out = ::std::io::stdout(); let mut out = ::std::io::stdout();
let path = matches let path = if let Some(p) = matches.value_of("path") {
.value_of("path") PathBuf::from(String::from(p))
.map(String::from) } else {
.map(PathBuf::from)
.unwrap_or_else(|| {
::std::env::var("HOME") ::std::env::var("HOME")
.map_err(Error::from)
.map(PathBuf::from) .map(PathBuf::from)
.map(|mut p| { p.push(".imag"); p }) .map(|mut p| { p.push(".imag"); p })
.map(|path| if path.exists() { .and_then(|path| if path.exists() {
writeln!(out, "Path '{:?}' already exists!", path) Err(format_err!("Cannot continue: Path '{}' already exists", path.display()))
.to_exit_code()
.unwrap_or_exit();
writeln!(out, "Cannot continue.")
.to_exit_code()
.unwrap_or_exit();
::std::process::exit(1)
} else { } else {
path Ok(path)
}) })
.expect("Failed to retrieve/build path for imag directory.") .map_err(|_| err_msg("Failed to retrieve/build path for imag directory."))?
}); };
{ {
let mut store_path = path.clone(); let mut store_path = path.clone();
store_path.push("store"); store_path.push("store");
println!("Creating {}", store_path.display()); println!("Creating {}", store_path.display());
::std::fs::create_dir_all(store_path) ::std::fs::create_dir_all(store_path).context("Failed to create directory")?;
.expect("Failed to create directory");
} }
let config_path = { let config_path = {
@ -146,11 +141,12 @@ pub fn imag_init() {
config_path config_path
}; };
OpenOptions::new() let _ = OpenOptions::new()
.write(true) .write(true)
.create(true) .create(true)
.open(config_path) .open(config_path)
.map(|mut f| { .map_err(Error::from)
.and_then(|mut f| {
let content = if matches.is_present("devel") { let content = if matches.is_present("devel") {
get_config_devel() get_config_devel()
} else { } else {
@ -158,33 +154,34 @@ pub fn imag_init() {
}; };
f.write_all(content.as_bytes()) f.write_all(content.as_bytes())
.expect("Failed to write complete config to file"); .context("Failed to write complete config to file")
.map_err(Error::from)
}) })
.expect("Failed to open new configuration file"); .context("Failed to open new configuration file")?;
if find_command("git").is_some() && !matches.is_present("nogit") { if find_command("git").is_some() && !matches.is_present("nogit") {
// we initialize a git repository // we initialize a git repository
writeln!(out, "Going to initialize a git repository in the imag directory...") writeln!(out, "Going to initialize a git repository in the imag directory...")?;
.to_exit_code()
.unwrap_or_exit();
let gitignore_path = { let gitignore_path = {
let mut gitignore_path = path.clone(); let mut gitignore_path = path.clone();
gitignore_path.push(".gitignore"); gitignore_path.push(".gitignore");
gitignore_path.to_str().map(String::from).expect("Cannot convert path to string") gitignore_path.to_str().map(String::from)
}; }.ok_or_else(|| err_msg("Cannot convert path to string"))?;
OpenOptions::new() let _ = OpenOptions::new()
.write(true) .write(true)
.create(true) .create(true)
.open(gitignore_path.clone()) .open(gitignore_path.clone())
.map(|mut f| { .map_err(Error::from)
.and_then(|mut f| {
f.write_all(GITIGNORE_STR.as_bytes()) f.write_all(GITIGNORE_STR.as_bytes())
.expect("Failed to write complete gitignore to file"); .context("Failed to write complete gitignore to file")
.map_err(Error::from)
}) })
.expect("Failed to open new configuration file"); .context("Failed to open new configuration file")?;
let path_str = path.to_str().map(String::from).expect("Cannot convert path to string"); let path_str = path.to_str().map(String::from).ok_or_else(|| err_msg("Cannot convert path to string"))?;
let worktree = format!("--work-tree={}", path_str); let worktree = format!("--work-tree={}", path_str);
let gitdir = format!("--git-dir={}/.git", path_str); let gitdir = format!("--git-dir={}/.git", path_str);
@ -192,20 +189,16 @@ pub fn imag_init() {
let output = Command::new("git") let output = Command::new("git")
.args(&[&worktree, &gitdir, "--no-pager", "init"]) .args(&[&worktree, &gitdir, "--no-pager", "init"])
.output() .output()
.expect("Calling 'git init' failed"); .context("Calling 'git init' failed")?;
if output.status.success() { if output.status.success() {
writeln!(out, "{}", String::from_utf8(output.stdout).expect("No UTF-8 output")) writeln!(out, "{}", String::from_utf8(output.stdout).expect("No UTF-8 output"))?;
.to_exit_code() writeln!(out, "'git {} {} --no-pager init' succeeded", worktree, gitdir)?;
.unwrap_or_exit();
writeln!(out, "'git {} {} --no-pager init' succeeded", worktree, gitdir)
.to_exit_code()
.unwrap_or_exit();
} else { } else {
writeln!(out, "{}", String::from_utf8(output.stderr).expect("No UTF-8 output")) writeln!(out, "{}", String::from_utf8(output.stderr).expect("No UTF-8 output"))?;
.to_exit_code() if !output.status.success() {
.unwrap_or_exit(); return Err(err_msg("Failed to execute git command"));
::std::process::exit(output.status.code().unwrap_or(1)); }
} }
} }
@ -213,19 +206,16 @@ pub fn imag_init() {
let output = Command::new("git") let output = Command::new("git")
.args(&[&worktree, &gitdir, "--no-pager", "add", &gitignore_path]) .args(&[&worktree, &gitdir, "--no-pager", "add", &gitignore_path])
.output() .output()
.expect("Calling 'git add' failed"); .context("Calling 'git add' failed")?;
if output.status.success() { if output.status.success() {
writeln!(out, "{}", String::from_utf8(output.stdout).expect("No UTF-8 output")) writeln!(out, "{}", String::from_utf8(output.stdout).expect("No UTF-8 output"))?;
.to_exit_code() writeln!(out, "'git {} {} --no-pager add {}' succeeded", worktree, gitdir, gitignore_path)?;
.unwrap_or_exit();
writeln!(out, "'git {} {} --no-pager add {}' succeeded", worktree, gitdir, gitignore_path)
.to_exit_code()
.unwrap_or_exit();
} else { } else {
writeln!(out, "{}", String::from_utf8(output.stderr).expect("No UTF-8 output")) writeln!(out, "{}", String::from_utf8(output.stderr).expect("No UTF-8 output"))?;
.to_exit_code() if !output.status.success() {
.unwrap_or_exit(); return Err(err_msg("Failed to execute git command"));
::std::process::exit(output.status.code().unwrap_or(1)); }
} }
} }
@ -233,34 +223,24 @@ pub fn imag_init() {
let output = Command::new("git") let output = Command::new("git")
.args(&[&worktree, &gitdir, "--no-pager", "commit", &gitignore_path, "-m", "'Initial import'"]) .args(&[&worktree, &gitdir, "--no-pager", "commit", &gitignore_path, "-m", "'Initial import'"])
.output() .output()
.expect("Calling 'git commit' failed"); .context("Calling 'git commit' failed")?;
if output.status.success() { if output.status.success() {
writeln!(out, "{}", String::from_utf8(output.stdout).expect("No UTF-8 output")) writeln!(out, "{}", String::from_utf8(output.stdout).expect("No UTF-8 output"))?;
.to_exit_code() writeln!(out, "'git {} {} --no-pager commit {} -m 'Initial import'' succeeded", worktree, gitdir, gitignore_path)?;
.unwrap_or_exit();
writeln!(out, "'git {} {} --no-pager commit {} -m 'Initial import'' succeeded", worktree, gitdir, gitignore_path)
.to_exit_code()
.unwrap_or_exit();
} else { } else {
writeln!(out, "{}", String::from_utf8(output.stderr).expect("No UTF-8 output")) writeln!(out, "{}", String::from_utf8(output.stderr).expect("No UTF-8 output"))?;
.to_exit_code() if !output.status.success() {
.unwrap_or_exit(); return Err(err_msg("Failed to execute git command"));
::std::process::exit(output.status.code().unwrap_or(1)); }
} }
} }
writeln!(out, "git stuff finished!") writeln!(out, "git stuff finished!")?;
.to_exit_code()
.unwrap_or_exit();
} else { } else {
writeln!(out, "No git repository will be initialized") writeln!(out, "No git repository will be initialized")?;
.to_exit_code()
.unwrap_or_exit();
} }
writeln!(out, "Ready. Have fun with imag!") writeln!(out, "Ready. Have fun with imag!").map_err(Error::from)
.to_exit_code()
.unwrap_or_exit();
} }
fn get_config() -> String { fn get_config() -> String {