genpac 0.1.0

Sandbox for Gentoo ebuild development using bubblewrap
// Copyright (C) 2023 Gokul Das B
// SPDX-License-Identifier: GPL-3.0-or-later
//! Main entry point: Genpac (Gentoo Packaging Environment)
//!
//! This module deals mainly with finding the configuration file, initiating cli processing,
//! starting the logger and dispatching work to appropriate submodules.

use anyhow::{Context, Result as AResult};
use clap::{Parser, Subcommand};
pub use common::*;
use global::GlobalsFinal;
use std::path::PathBuf;

mod bubblewrap;
mod common;
mod extract;
mod global;
#[cfg(feature = "remap")]
mod remap;
mod sandbox;
mod snapshot;

const CONFIGFILE: &str = "${XDG_CONFIG_HOME:-~/.config}/genpac/config.toml";

/// Subcommands and subcommand dispatcher
#[derive(Subcommand)]
pub enum SubCommands {
    #[cfg(feature = "remap")]
    Remap(remap::SubCmdArgs),

    #[command(alias = "sbox")]
    Sandbox(sandbox::SubCmdArgs),

    #[command(subcommand, alias = "snap")]
    Snapshot(snapshot::SubCmdArgs),

    Extract(extract::SubCmdArgs),
}

impl SubCommands {
    fn dispatch(self, globals: GlobalsFinal) -> AResult<()> {
        match self {
            #[cfg(feature = "remap")]
            Self::Remap(sc) => sc.handle(globals)?,
            Self::Sandbox(sc) => sc.handle(globals)?,
            Self::Snapshot(sc) => sc.handle(globals)?,
            Self::Extract(sc) => sc.handle(globals)?,
        }
        Ok(())
    }
}

fn main() -> AResult<()> {
    let cli = global::Cli::parse();
    let globals = cli.globals().init_logger()?;

    let cfg = shellexpand::env(CONFIGFILE).context("Cannot expand config file path")?;
    let cfg = shellexpand::tilde(&cfg);
    let cfg = PathBuf::from(cfg.as_ref());
    if !cfg.is_file() {
        let e = format!("Config file '{}' not found. Cannot proceed!", cfg.display());
        log::error!("{e}");
        anyhow::bail!(e);
    } else {
        log::debug!("Loading config from '{}'", cfg.display());
    }
    let cfg = std::fs::read_to_string(cfg).context("Unable to read config file")?;
    let globals = match globals.config(cfg) {
        Ok(x) => x,
        Err(e) => {
            log::error!("Unable to parse configuration file:");
            log::error!("{e}");
            anyhow::bail!(e);
        }
    };

    match cli.subcmd().dispatch(globals) {
        Ok(()) => Ok(()),
        Err(e) => {
            log::error!("Failed to execute subcommand:");
            log::error!("{e}");
            anyhow::bail!(e);
        }
    }
}