From 1991a31f79fa7bb4f46d820e322cd049c50cc923 Mon Sep 17 00:00:00 2001 From: Roey Darwish Dror Date: Sun, 1 Mar 2020 21:56:29 +0200 Subject: [PATCH] Migrate away from failure --- Cargo.lock | 33 ++-------- Cargo.toml | 2 +- src/error.rs | 130 ------------------------------------- src/main.rs | 31 ++++----- src/process.rs | 32 +++------ src/storage/crypt.rs | 23 +++---- src/storage/filesystem.rs | 11 ++-- src/storage/loop_device.rs | 12 ++-- src/storage/mount_stack.rs | 9 ++- 9 files changed, 51 insertions(+), 232 deletions(-) delete mode 100644 src/error.rs diff --git a/Cargo.lock b/Cargo.lock index aec5bd4..0da9408 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,11 +12,11 @@ dependencies = [ name = "alma" version = "0.10.0" dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "byte-unit 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "dialoguer 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -35,6 +35,11 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atty" version = "0.2.13" @@ -178,18 +183,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -473,17 +466,6 @@ dependencies = [ "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "synstructure" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tempfile" version = "3.1.0" @@ -620,6 +602,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" @@ -636,7 +619,6 @@ dependencies = [ "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" @@ -671,7 +653,6 @@ dependencies = [ "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" "checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" diff --git a/Cargo.toml b/Cargo.toml index 6f2fcc2..f502906 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] which = "3.1.0" -failure = "0.1.5" +anyhow = "1.0" log = "0.4.6" structopt = "0.3.11" tempfile = "3.0.5" diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index eca29a1..0000000 --- a/src/error.rs +++ /dev/null @@ -1,130 +0,0 @@ -use failure::{Backtrace, Context, Fail}; -use std::fmt::{self, Display}; - -#[derive(Debug)] -pub struct Error { - inner: Context, -} - -#[derive(Clone, Eq, PartialEq, Debug, Fail)] -pub enum ErrorKind { - #[fail(display = "Error quering information about the block device")] - DeviceQuery, - - #[fail(display = "Invalid device name")] - InvalidDeviceName, - - #[fail(display = "The given block device is neither removable nor a loop device")] - DangerousDevice, - - #[fail(display = "Partition {} does not exist", _0)] - NoSuchPartition(u8), - - #[fail(display = "Could not find {}", _0)] - NoTool(&'static str), - - #[fail(display = "Error creating a temporary directory")] - TmpDirError, - - #[fail(display = "Partitioning error")] - Partitioning, - - #[fail(display = "Error formatting filesystems")] - Formatting, - - #[fail(display = "Error mounting filesystems")] - Mounting, - - #[fail(display = "Error creating the boot directory")] - CreateBoot, - - #[fail(display = "Pacstrap error")] - Pacstrap, - - #[fail(display = "fstab error")] - Fstab, - - #[fail(display = "Post installation configuration error")] - PostInstallation, - - #[fail(display = "Initramfs error")] - Initramfs, - - #[fail(display = "Bootloader error")] - Bootloader, - - #[fail(display = "Error caused by the interactive mode")] - Interactive, - - #[fail(display = "Failed umounting filesystems")] - UmountFailure, - - #[fail(display = "Error setting up an encrypted device")] - LuksSetup, - - #[fail(display = "Error opening the encrypted device")] - LuksOpen, - - #[fail(display = "Error closing the encrypted device")] - LuksClose, - - #[fail(display = "Error detecting whether the root partition is an encrypted device")] - LuksDetection, - - #[fail(display = "Error setting the locale")] - Locale, - - #[fail(display = "Failed launching Qemu")] - Qemu, - - #[fail(display = "Error loading preset \"{}\"", _0)] - Preset(String), - - #[fail(display = "Missing environment variables \"{:?}\"", _0)] - MissingEnvironmentVariables(Vec), - - #[fail(display = "Error executing preset script")] - PresetScript, - - #[fail(display = "Error creating the image")] - Image, - - #[fail(display = "Error setting up a loop device: {}", _0)] - Losetup(String), - - #[fail(display = "Error querying storage devices")] - StorageDevicesQuery, - - #[fail(display = "There are no removable devices")] - NoRemovableDevices, -} - -impl Fail for Error { - fn cause(&self) -> Option<&dyn Fail> { - self.inner.cause() - } - - fn backtrace(&self) -> Option<&Backtrace> { - self.inner.backtrace() - } -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&self.inner, f) - } -} - -impl From for Error { - fn from(kind: ErrorKind) -> Error { - Error { - inner: Context::new(kind), - } - } -} - -impl From> for Error { - fn from(inner: Context) -> Error { - Error { inner } - } -} diff --git a/src/main.rs b/src/main.rs index a01cdc7..1209ffc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ mod args; -mod error; mod initcpio; mod presets; mod process; @@ -7,14 +6,13 @@ mod storage; mod tool; use crate::args::*; -use crate::error::*; use crate::process::CommandExt; use crate::storage::*; use crate::tool::Tool; +use anyhow::{anyhow, Result}; use byte_unit::Byte; use console::style; use dialoguer::{theme::ColorfulTheme, Select}; -use failure::{Fail, ResultExt}; use log::{debug, error, info, log_enabled, Level, LevelFilter}; use pretty_env_logger; use std::collections::HashSet; @@ -41,7 +39,7 @@ fn mount<'a>( mount_path: &Path, boot_filesystem: &'a Filesystem, root_filesystem: &'a Filesystem, -) -> Result, Error> { +) -> Result> { let mut mount_stack = MountStack::new(); debug!( "Root partition: {}", @@ -49,18 +47,14 @@ fn mount<'a>( ); info!("Mounting filesystems to {}", mount_path.display()); - mount_stack - .mount(&root_filesystem, mount_path.into(), None) - .context(ErrorKind::Mounting)?; + mount_stack.mount(&root_filesystem, mount_path.into(), None)?; let boot_point = mount_path.join("boot"); if !boot_point.exists() { - fs::create_dir(&boot_point).context(ErrorKind::CreateBoot)?; + fs::create_dir(&boot_point)?; } - mount_stack - .mount(&boot_filesystem, boot_point, None) - .context(ErrorKind::Mounting)?; + mount_stack.mount(&boot_filesystem, boot_point, None)?; Ok(mount_stack) } @@ -73,7 +67,7 @@ fn fix_fstab(fstab: &str) -> String { .join("\n") } -fn create_image(path: &Path, size: Byte, overwrite: bool) -> Result { +fn create_image(path: &Path, size: Byte, overwrite: bool) -> Result { { let mut options = fs::OpenOptions::new(); @@ -83,20 +77,19 @@ fn create_image(path: &Path, size: Byte, overwrite: bool) -> Result Result { +fn select_block_device(allow_non_removable: bool) -> Result { let devices = get_storage_devices(allow_non_removable)?; if devices.is_empty() { - Err(ErrorKind::NoRemovableDevices)? + return Err(anyhow!("No removable devices")); } if allow_non_removable { @@ -119,7 +112,7 @@ fn select_block_device(allow_non_removable: bool) -> Result { } #[allow(clippy::cognitive_complexity)] -fn create(command: CreateCommand) -> Result<(), Error> { +fn create(command: CreateCommand) -> Result<()> { let presets = presets::Presets::load(&command.presets)?; let sgdisk = Tool::find("sgdisk")?; @@ -162,7 +155,7 @@ fn create(command: CreateCommand) -> Result<(), Error> { command.allow_non_removable, )?; - let mount_point = tempdir().context(ErrorKind::TmpDirError)?; + let mount_point = tempdir()?; let disk_path = storage_device.path(); info!("Partitioning the block device"); diff --git a/src/process.rs b/src/process.rs index 51eafd6..0696f6c 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,25 +1,15 @@ -use super::error::*; -use failure::{Fail, ResultExt}; +use anyhow::{Error, Result}; use log::error; -use std::process::{Command, ExitStatus}; +use std::process::Command; use std::str; -#[derive(Debug, Fail)] -enum ProcessError { - #[fail(display = "{}", _0)] - BadExitCode(ExitStatus), - - #[fail(display = "Process output isn't valid UTF-8")] - InvalidUtf8, -} - pub trait CommandExt { - fn run(&mut self, context: ErrorKind) -> Result<(), Error>; - fn run_text_output(&mut self, context: ErrorKind) -> Result; + fn run(&mut self, context: Error) -> Result<()>; + fn run_text_output(&mut self, context: Error) -> Result; } impl CommandExt for Command { - fn run(&mut self, context: ErrorKind) -> Result<(), Error> { + fn run(&mut self, context: Error) -> Result<(), Error> { let exit_status = self .spawn() .with_context(|_| context.clone())? @@ -27,25 +17,21 @@ impl CommandExt for Command { .with_context(|_| context.clone())?; if !exit_status.success() { - Err(ProcessError::BadExitCode(exit_status)).with_context(|_| context.clone())?; + Err(context)?; } Ok(()) } - fn run_text_output(&mut self, context: ErrorKind) -> Result { + fn run_text_output(&mut self, context: Error) -> Result { let output = self.output().with_context(|_| context.clone())?; if !output.status.success() { let error = str::from_utf8(&output.stderr).unwrap_or("[INVALID UTF8]"); error!("{}", error); - Err(ProcessError::BadExitCode(output.status)).with_context(|_| context.clone())?; + return Err(context); } - Ok(String::from( - str::from_utf8(&output.stdout) - .map_err(|_| ProcessError::InvalidUtf8) - .with_context(|_| context.clone())?, - )) + Ok(String::from(str::from_utf8(&output.stdout)?)) } } diff --git a/src/storage/crypt.rs b/src/storage/crypt.rs index d9e23e8..90ab26c 100644 --- a/src/storage/crypt.rs +++ b/src/storage/crypt.rs @@ -1,8 +1,7 @@ use super::markers::BlockDevice; -use crate::error::{Error, ErrorKind}; use crate::process::CommandExt; use crate::tool::Tool; -use failure::ResultExt; +use anyhow::{anyhow, Result}; use log::{debug, warn}; use std::fs; use std::io::Read; @@ -21,14 +20,14 @@ pub struct EncryptedDevice<'t, 'o> { } impl<'t, 'o> EncryptedDevice<'t, 'o> { - pub fn prepare(cryptsetup: &Tool, device: &dyn BlockDevice) -> Result<(), Error> { + pub fn prepare(cryptsetup: &Tool, device: &dyn BlockDevice) -> Result<()> { debug!("Preparing encrypted device in {}", device.path().display()); cryptsetup .execute() .arg("luksFormat") .arg("-q") .arg(device.path()) - .run(ErrorKind::LuksSetup)?; + .run(anyhow!("LUKS setup failed"))?; Ok(()) } @@ -37,7 +36,7 @@ impl<'t, 'o> EncryptedDevice<'t, 'o> { cryptsetup: &'t Tool, device: &'o dyn BlockDevice, name: String, - ) -> Result, Error> { + ) -> Result> { debug!( "Opening encrypted device {} as {}", device.path().display(), @@ -48,7 +47,7 @@ impl<'t, 'o> EncryptedDevice<'t, 'o> { .arg("open") .arg(device.path()) .arg(&name) - .run(ErrorKind::LuksOpen)?; + .run(anyhow!("Error opening LUKS"))?; let path = PathBuf::from("/dev/mapper").join(&name); Ok(Self { @@ -59,13 +58,13 @@ impl<'t, 'o> EncryptedDevice<'t, 'o> { }) } - fn _close(&mut self) -> Result<(), Error> { + fn _close(&mut self) -> Result<()> { debug!("Closing encrypted device {}", self.name); self.cryptsetup .execute() .arg("close") .arg(&self.name) - .run(ErrorKind::LuksClose)?; + .run(anyhow!("Error closing LUKS"))?; Ok(()) } @@ -85,16 +84,14 @@ impl<'t, 'o> BlockDevice for EncryptedDevice<'t, 'o> { } } -pub fn is_encrypted_device(device: &dyn BlockDevice) -> Result { +pub fn is_encrypted_device(device: &dyn BlockDevice) -> Result { let mut f = fs::OpenOptions::new() .read(true) .write(false) - .open(device.path()) - .context(ErrorKind::LuksDetection)?; + .open(device.path())?; let mut buffer = [0; 6]; - f.read_exact(&mut buffer) - .context(ErrorKind::LuksDetection)?; + f.read_exact(&mut buffer)?; Ok(buffer == LUKS_MAGIC_1 || buffer == LUKS_MAGIC_2) } diff --git a/src/storage/filesystem.rs b/src/storage/filesystem.rs index 2d8e03b..ff9606e 100644 --- a/src/storage/filesystem.rs +++ b/src/storage/filesystem.rs @@ -1,9 +1,6 @@ use super::markers::BlockDevice; -use crate::{ - error::{Error, ErrorKind}, - process::CommandExt, - tool::Tool, -}; +use crate::{process::CommandExt, tool::Tool}; +use anyhow::{anyhow, Result}; #[derive(Debug, Clone, Copy)] pub enum FilesystemType { @@ -31,14 +28,14 @@ impl<'a> Filesystem<'a> { block: &'a dyn BlockDevice, fs_type: FilesystemType, mkfs: &Tool, - ) -> Result { + ) -> Result { let mut command = mkfs.execute(); match fs_type { FilesystemType::Ext4 => command.arg("-F").arg(block.path()), FilesystemType::Vfat => command.arg("-F32").arg(block.path()), }; - command.run(ErrorKind::Formatting)?; + command.run(anyhow!("Error formatting the file systems"))?; Ok(Self { fs_type, block }) } diff --git a/src/storage/loop_device.rs b/src/storage/loop_device.rs index 7156ce0..5570bbe 100644 --- a/src/storage/loop_device.rs +++ b/src/storage/loop_device.rs @@ -1,6 +1,5 @@ -use crate::error::{Error, ErrorKind}; use crate::tool::Tool; -use failure::ResultExt; +use anyhow::{anyhow, Result}; use log::info; use std::path::{Path, PathBuf}; @@ -11,19 +10,16 @@ pub struct LoopDevice { } impl LoopDevice { - pub fn create(file: &Path) -> Result { + pub fn create(file: &Path) -> Result { let losetup = Tool::find("losetup")?; let output = losetup .execute() .args(&["--find", "-P", "--show"]) .arg(file) - .output() - .context(ErrorKind::Image)?; + .output()?; if !output.status.success() { - Err(ErrorKind::Losetup( - String::from_utf8(output.stderr).unwrap(), - ))? + return Err(anyhow!("{}", String::from_utf8(output.stderr).unwrap(),)); } let path = PathBuf::from(String::from_utf8(output.stdout).unwrap().trim()); diff --git a/src/storage/mount_stack.rs b/src/storage/mount_stack.rs index c77e0e2..653e0ac 100644 --- a/src/storage/mount_stack.rs +++ b/src/storage/mount_stack.rs @@ -1,6 +1,5 @@ use super::Filesystem; -use crate::error::{Error, ErrorKind}; -use failure::Fail; +use anyhow::Result; use log::{debug, warn}; use nix; use nix::mount::{mount, umount, MsFlags}; @@ -40,21 +39,21 @@ impl<'a> MountStack<'a> { Ok(()) } - fn _umount(&mut self) -> Result<(), Error> { + fn _umount(&mut self) -> Result<()> { let mut result = Ok(()); while let Some(target) = self.targets.pop() { debug!("Unmounting {}", target.display()); if let Err(e) = umount(&target) { warn!("Unable to umount {}: {}", target.display(), e); - result = Err(Error::from(e.context(ErrorKind::UmountFailure))); + result = Err(e.into()); }; } result } - pub fn umount(mut self) -> Result<(), Error> { + pub fn umount(mut self) -> Result<()> { self._umount() } }