mirror of
				https://github.com/edera-dev/krata.git
				synced 2025-11-03 07:19:37 +00:00 
			
		
		
		
	hypha: convert to using anyhow for error handling
This commit is contained in:
		@ -13,6 +13,7 @@ resolver = "2"
 | 
			
		||||
version = "0.0.1"
 | 
			
		||||
 | 
			
		||||
[workspace.dependencies]
 | 
			
		||||
anyhow = "1.0"
 | 
			
		||||
thiserror = "1.0"
 | 
			
		||||
log = "0.4.20"
 | 
			
		||||
libc = "0.2"
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ edition = "2021"
 | 
			
		||||
resolver = "2"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
anyhow = { workspace = true }
 | 
			
		||||
log = { workspace = true }
 | 
			
		||||
env_logger = { workspace = true }
 | 
			
		||||
zstd = { workspace = true }
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use hypha::container::init::ContainerInit;
 | 
			
		||||
use hypha::error::Result;
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
    env_logger::init();
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use clap::{Parser, Subcommand};
 | 
			
		||||
use hypha::ctl::Controller;
 | 
			
		||||
use hypha::error::{HyphaError, Result};
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
#[derive(Parser, Debug)]
 | 
			
		||||
@ -48,8 +48,7 @@ fn main() -> Result<()> {
 | 
			
		||||
 | 
			
		||||
    let args = ControllerArgs::parse();
 | 
			
		||||
    let store_path = if args.store == "auto" {
 | 
			
		||||
        default_store_path()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("unable to determine default store path"))
 | 
			
		||||
        default_store_path().ok_or_else(|| anyhow!("unable to determine default store path"))
 | 
			
		||||
    } else {
 | 
			
		||||
        Ok(PathBuf::from(args.store))
 | 
			
		||||
    }?;
 | 
			
		||||
@ -57,7 +56,7 @@ fn main() -> Result<()> {
 | 
			
		||||
    let store_path = store_path
 | 
			
		||||
        .to_str()
 | 
			
		||||
        .map(|x| x.to_string())
 | 
			
		||||
        .ok_or_else(|| HyphaError::new("unable to convert store path to string"))?;
 | 
			
		||||
        .ok_or_else(|| anyhow!("unable to convert store path to string"))?;
 | 
			
		||||
 | 
			
		||||
    let mut controller = Controller::new(store_path.clone())?;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use crate::error::{HyphaError, Result};
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use loopdev::{LoopControl, LoopDevice};
 | 
			
		||||
use xenclient::BlockDeviceRef;
 | 
			
		||||
 | 
			
		||||
@ -16,11 +16,9 @@ impl AutoLoop {
 | 
			
		||||
        device.with().read_only(true).attach(file)?;
 | 
			
		||||
        let path = device
 | 
			
		||||
            .path()
 | 
			
		||||
            .ok_or(HyphaError::new("unable to get loop device path"))?
 | 
			
		||||
            .ok_or(anyhow!("unable to get loop device path"))?
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or(HyphaError::new(
 | 
			
		||||
                "unable to convert loop device path to string",
 | 
			
		||||
            ))?
 | 
			
		||||
            .ok_or(anyhow!("unable to convert loop device path to string",))?
 | 
			
		||||
            .to_string();
 | 
			
		||||
        let major = device.major()?;
 | 
			
		||||
        let minor = device.minor()?;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
use crate::error::Result;
 | 
			
		||||
use crate::hypha_err;
 | 
			
		||||
use crate::shared::LaunchInfo;
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use log::trace;
 | 
			
		||||
use nix::libc::dup2;
 | 
			
		||||
use nix::unistd::execve;
 | 
			
		||||
@ -69,7 +68,9 @@ impl ContainerInit {
 | 
			
		||||
        if let Some(cfg) = config.config() {
 | 
			
		||||
            self.run(cfg, &launch)?;
 | 
			
		||||
        } else {
 | 
			
		||||
            return hypha_err!("unable to determine what to execute, image config doesn't tell us");
 | 
			
		||||
            return Err(anyhow!(
 | 
			
		||||
                "unable to determine what to execute, image config doesn't tell us"
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
use crate::error::Result;
 | 
			
		||||
use crate::image::ImageInfo;
 | 
			
		||||
use crate::shared::LaunchInfo;
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use backhand::{FilesystemWriter, NodeHeader};
 | 
			
		||||
use log::trace;
 | 
			
		||||
use std::fs;
 | 
			
		||||
 | 
			
		||||
@ -2,11 +2,11 @@ pub mod cfgblk;
 | 
			
		||||
 | 
			
		||||
use crate::autoloop::AutoLoop;
 | 
			
		||||
use crate::ctl::cfgblk::ConfigBlock;
 | 
			
		||||
use crate::error::{HyphaError, Result};
 | 
			
		||||
use crate::image::cache::ImageCache;
 | 
			
		||||
use crate::image::name::ImageName;
 | 
			
		||||
use crate::image::{ImageCompiler, ImageInfo};
 | 
			
		||||
use crate::shared::LaunchInfo;
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use loopdev::LoopControl;
 | 
			
		||||
use std::io::{Read, Write};
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
@ -82,16 +82,16 @@ impl Controller {
 | 
			
		||||
        let image_squashfs_path = image_info
 | 
			
		||||
            .image_squashfs
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("failed to convert image squashfs path to string"))?;
 | 
			
		||||
            .ok_or_else(|| anyhow!("failed to convert image squashfs path to string"))?;
 | 
			
		||||
 | 
			
		||||
        let cfgblk_dir_path = cfgblk
 | 
			
		||||
            .dir
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("failed to convert cfgblk directory path to string"))?;
 | 
			
		||||
            .ok_or_else(|| anyhow!("failed to convert cfgblk directory path to string"))?;
 | 
			
		||||
        let cfgblk_squashfs_path = cfgblk
 | 
			
		||||
            .file
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("failed to convert cfgblk squashfs path to string"))?;
 | 
			
		||||
            .ok_or_else(|| anyhow!("failed to convert cfgblk squashfs path to string"))?;
 | 
			
		||||
 | 
			
		||||
        let image_squashfs_loop = self.autoloop.loopify(image_squashfs_path)?;
 | 
			
		||||
        let cfgblk_squashfs_loop = self.autoloop.loopify(cfgblk_squashfs_path)?;
 | 
			
		||||
@ -149,17 +149,15 @@ impl Controller {
 | 
			
		||||
        let dom_path = store.get_domain_path(domid)?;
 | 
			
		||||
        let uuid = match store.read_string_optional(format!("{}/hypha/uuid", dom_path).as_str())? {
 | 
			
		||||
            None => {
 | 
			
		||||
                return Err(HyphaError::new(&format!(
 | 
			
		||||
                return Err(anyhow!(
 | 
			
		||||
                    "domain {} was not found or not created by hypha",
 | 
			
		||||
                    domid
 | 
			
		||||
                )))
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
            Some(value) => value,
 | 
			
		||||
        };
 | 
			
		||||
        if uuid.is_empty() {
 | 
			
		||||
            return Err(HyphaError::new(
 | 
			
		||||
                "unable to find hypha uuid based on the domain",
 | 
			
		||||
            ));
 | 
			
		||||
            return Err(anyhow!("unable to find hypha uuid based on the domain",));
 | 
			
		||||
        }
 | 
			
		||||
        let uuid = Uuid::parse_str(&uuid)?;
 | 
			
		||||
        let loops = store.read_string(format!("{}/hypha/loops", dom_path).as_str())?;
 | 
			
		||||
@ -235,8 +233,8 @@ impl Controller {
 | 
			
		||||
                None => continue,
 | 
			
		||||
                Some(value) => value,
 | 
			
		||||
            };
 | 
			
		||||
            let domid = u32::from_str(&domid_candidate)
 | 
			
		||||
                .map_err(|_| HyphaError::new("failed to parse domid"))?;
 | 
			
		||||
            let domid =
 | 
			
		||||
                u32::from_str(&domid_candidate).map_err(|_| anyhow!("failed to parse domid"))?;
 | 
			
		||||
            let uuid = Uuid::from_str(&uuid_string)?;
 | 
			
		||||
            let image = self
 | 
			
		||||
                .client
 | 
			
		||||
 | 
			
		||||
@ -1,141 +0,0 @@
 | 
			
		||||
use backhand::BackhandError;
 | 
			
		||||
use cli_tables::TableError;
 | 
			
		||||
use oci_spec::OciSpecError;
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use std::ffi::NulError;
 | 
			
		||||
use std::fmt::{Display, Formatter};
 | 
			
		||||
use std::num::ParseIntError;
 | 
			
		||||
use std::path::StripPrefixError;
 | 
			
		||||
use xenclient::XenClientError;
 | 
			
		||||
 | 
			
		||||
pub type Result<T> = std::result::Result<T, HyphaError>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct HyphaError {
 | 
			
		||||
    message: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl HyphaError {
 | 
			
		||||
    pub fn new(msg: &str) -> HyphaError {
 | 
			
		||||
        HyphaError {
 | 
			
		||||
            message: msg.to_string(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Display for HyphaError {
 | 
			
		||||
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        write!(f, "{}", self.message)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Error for HyphaError {
 | 
			
		||||
    fn description(&self) -> &str {
 | 
			
		||||
        &self.message
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! hypha_err {
 | 
			
		||||
    ($($arg:tt)*) => {{
 | 
			
		||||
        use $crate::error::HyphaError;
 | 
			
		||||
        let text = std::fmt::format(format_args!($($arg)*));
 | 
			
		||||
        Err(HyphaError::new(text.as_str()))
 | 
			
		||||
    }}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<std::io::Error> for HyphaError {
 | 
			
		||||
    fn from(value: std::io::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<XenClientError> for HyphaError {
 | 
			
		||||
    fn from(value: XenClientError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<walkdir::Error> for HyphaError {
 | 
			
		||||
    fn from(value: walkdir::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<StripPrefixError> for HyphaError {
 | 
			
		||||
    fn from(value: StripPrefixError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<BackhandError> for HyphaError {
 | 
			
		||||
    fn from(value: BackhandError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<serde_json::Error> for HyphaError {
 | 
			
		||||
    fn from(value: serde_json::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ureq::Error> for HyphaError {
 | 
			
		||||
    fn from(value: ureq::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<ParseIntError> for HyphaError {
 | 
			
		||||
    fn from(value: ParseIntError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<OciSpecError> for HyphaError {
 | 
			
		||||
    fn from(value: OciSpecError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<url::ParseError> for HyphaError {
 | 
			
		||||
    fn from(value: url::ParseError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<std::fmt::Error> for HyphaError {
 | 
			
		||||
    fn from(value: std::fmt::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<uuid::Error> for HyphaError {
 | 
			
		||||
    fn from(value: uuid::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<xenstore::error::Error> for HyphaError {
 | 
			
		||||
    fn from(value: xenstore::error::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<TableError> for HyphaError {
 | 
			
		||||
    fn from(value: TableError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<NulError> for HyphaError {
 | 
			
		||||
    fn from(value: NulError) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<nix::Error> for HyphaError {
 | 
			
		||||
    fn from(value: nix::Error) -> Self {
 | 
			
		||||
        HyphaError::new(value.to_string().as_str())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use crate::error::{HyphaError, Result};
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use oci_spec::image::{Arch, Descriptor, ImageIndex, ImageManifest, MediaType, Os, ToDockerV2S2};
 | 
			
		||||
use std::io::copy;
 | 
			
		||||
use std::io::{Read, Write};
 | 
			
		||||
@ -63,21 +63,21 @@ impl RegistryClient {
 | 
			
		||||
            MediaType::ImageIndex.to_docker_v2s2()?,
 | 
			
		||||
        );
 | 
			
		||||
        let response = self.call(self.agent.get(url.as_str()).set("Accept", &accept))?;
 | 
			
		||||
        let content_type = response.header("Content-Type").ok_or_else(|| {
 | 
			
		||||
            HyphaError::new("registry response did not have a Content-Type header")
 | 
			
		||||
        })?;
 | 
			
		||||
        let content_type = response
 | 
			
		||||
            .header("Content-Type")
 | 
			
		||||
            .ok_or_else(|| anyhow!("registry response did not have a Content-Type header"))?;
 | 
			
		||||
        if content_type == MediaType::ImageIndex.to_string()
 | 
			
		||||
            || content_type == MediaType::ImageIndex.to_docker_v2s2()?
 | 
			
		||||
        {
 | 
			
		||||
            let index = ImageIndex::from_reader(response.into_reader())?;
 | 
			
		||||
            let descriptor = self
 | 
			
		||||
                .pick_manifest(index)
 | 
			
		||||
                .ok_or_else(|| HyphaError::new("unable to pick manifest from index"))?;
 | 
			
		||||
                .ok_or_else(|| anyhow!("unable to pick manifest from index"))?;
 | 
			
		||||
            return self.get_manifest_with_digest(name, descriptor.digest());
 | 
			
		||||
        }
 | 
			
		||||
        let digest = response
 | 
			
		||||
            .header("Docker-Content-Digest")
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("fetching manifest did not yield a content digest"))?
 | 
			
		||||
            .ok_or_else(|| anyhow!("fetching manifest did not yield a content digest"))?
 | 
			
		||||
            .to_string();
 | 
			
		||||
        let manifest = ImageManifest::from_reader(response.into_reader())?;
 | 
			
		||||
        Ok((manifest, digest))
 | 
			
		||||
 | 
			
		||||
@ -2,10 +2,10 @@ pub mod cache;
 | 
			
		||||
pub mod fetch;
 | 
			
		||||
pub mod name;
 | 
			
		||||
 | 
			
		||||
use crate::error::{HyphaError, Result};
 | 
			
		||||
use crate::image::cache::ImageCache;
 | 
			
		||||
use crate::image::fetch::RegistryClient;
 | 
			
		||||
use crate::image::name::ImageName;
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use backhand::compression::Compressor;
 | 
			
		||||
use backhand::{FilesystemCompressor, FilesystemWriter, NodeHeader};
 | 
			
		||||
use flate2::read::GzDecoder;
 | 
			
		||||
@ -160,10 +160,10 @@ impl ImageCompiler<'_> {
 | 
			
		||||
                let mut entry = entry?;
 | 
			
		||||
                let path = entry.path()?;
 | 
			
		||||
                let Some(name) = path.file_name() else {
 | 
			
		||||
                    return Err(HyphaError::new("unable to get file name"));
 | 
			
		||||
                    return Err(anyhow!("unable to get file name"));
 | 
			
		||||
                };
 | 
			
		||||
                let Some(name) = name.to_str() else {
 | 
			
		||||
                    return Err(HyphaError::new("unable to get file name as string"));
 | 
			
		||||
                    return Err(anyhow!("unable to get file name as string"));
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                if name.starts_with(".wh.") {
 | 
			
		||||
@ -214,7 +214,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
                    } else if path.is_dir() {
 | 
			
		||||
                        fs::remove_dir_all(&path)?;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return Err(HyphaError::new("opaque whiteout entry did not exist"));
 | 
			
		||||
                        return Err(anyhow!("opaque whiteout entry did not exist"));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
@ -280,7 +280,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
    fn check_safe_path(&self, dst: &PathBuf, image_dir: &PathBuf) -> Result<()> {
 | 
			
		||||
        let resolved = path_clean::clean(dst);
 | 
			
		||||
        if !resolved.starts_with(image_dir) {
 | 
			
		||||
            return Err(HyphaError::new("layer attempts to work outside image dir"));
 | 
			
		||||
            return Err(anyhow!("layer attempts to work outside image dir"));
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -306,7 +306,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
            let mut file = File::create(&layer_path)?;
 | 
			
		||||
            let size = client.write_blob(&image.name, layer, &mut file)?;
 | 
			
		||||
            if layer.size() as u64 != size {
 | 
			
		||||
                return Err(HyphaError::new(
 | 
			
		||||
                return Err(anyhow!(
 | 
			
		||||
                    "downloaded layer size differs from size in manifest",
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
@ -323,11 +323,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
            MediaType::ImageLayer => LayerCompressionType::None,
 | 
			
		||||
            MediaType::ImageLayerGzip => LayerCompressionType::Gzip,
 | 
			
		||||
            MediaType::ImageLayerZstd => LayerCompressionType::Zstd,
 | 
			
		||||
            other => {
 | 
			
		||||
                return Err(HyphaError::new(
 | 
			
		||||
                    format!("found layer with unknown media type: {}", other).as_str(),
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
            other => return Err(anyhow!("found layer with unknown media type: {}", other)),
 | 
			
		||||
        };
 | 
			
		||||
        Ok(LayerFile {
 | 
			
		||||
            digest: layer.digest().clone(),
 | 
			
		||||
@ -346,7 +342,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
                .path()
 | 
			
		||||
                .strip_prefix(image_dir)?
 | 
			
		||||
                .to_str()
 | 
			
		||||
                .ok_or_else(|| HyphaError::new("failed to strip prefix of tmpdir"))?;
 | 
			
		||||
                .ok_or_else(|| anyhow!("failed to strip prefix of tmpdir"))?;
 | 
			
		||||
            let rel = format!("/{}", rel);
 | 
			
		||||
            trace!("ImageCompiler squash write {}", rel);
 | 
			
		||||
            let typ = entry.file_type();
 | 
			
		||||
@ -373,7 +369,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
                let symlink = fs::read_link(entry.path())?;
 | 
			
		||||
                let symlink = symlink
 | 
			
		||||
                    .to_str()
 | 
			
		||||
                    .ok_or_else(|| HyphaError::new("failed to read symlink"))?;
 | 
			
		||||
                    .ok_or_else(|| anyhow!("failed to read symlink"))?;
 | 
			
		||||
                writer.push_symlink(symlink, rel, header)?;
 | 
			
		||||
            } else if typ.is_dir() {
 | 
			
		||||
                writer.push_dir(rel, header)?;
 | 
			
		||||
@ -393,7 +389,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
                let device = metadata.dev();
 | 
			
		||||
                writer.push_char_device(device as u32, rel, header)?;
 | 
			
		||||
            } else {
 | 
			
		||||
                return Err(HyphaError::new("invalid file type"));
 | 
			
		||||
                return Err(anyhow!("invalid file type"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -401,7 +397,7 @@ impl ImageCompiler<'_> {
 | 
			
		||||
 | 
			
		||||
        let squash_file_path = squash_file
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("failed to convert squashfs string"))?;
 | 
			
		||||
            .ok_or_else(|| anyhow!("failed to convert squashfs string"))?;
 | 
			
		||||
 | 
			
		||||
        let mut file = File::create(squash_file)?;
 | 
			
		||||
        trace!("ImageCompiler squash generate: {}", squash_file_path);
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use crate::error::Result;
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use url::Url;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
pub mod autoloop;
 | 
			
		||||
pub mod container;
 | 
			
		||||
pub mod ctl;
 | 
			
		||||
pub mod error;
 | 
			
		||||
pub mod image;
 | 
			
		||||
mod shared;
 | 
			
		||||
pub mod shared;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user