protofetch 0.1.20

A source dependency management tool for Protobuf.
Documentation
use std::{
    error::Error,
    path::{Path, PathBuf},
    sync::Arc,
};

use crate::{
    cli::command_handlers::{do_clean, do_fetch, do_init, do_lock, do_migrate},
    engine::ParallelConfig,
    git::cache::ProtofetchGitCache,
};

mod builder;

pub use builder::ProtofetchBuilder;

pub struct Protofetch {
    cache: Arc<ProtofetchGitCache>,
    root: PathBuf,
    module_file_name: PathBuf,
    lock_file_name: PathBuf,
    output_directory_name: Option<PathBuf>,
    parallel: ParallelConfig,
}

#[allow(dead_code)]
fn _assert_protofetch_auto_traits() {
    fn assert<T: Send + Sync + std::panic::UnwindSafe + std::panic::RefUnwindSafe>() {}
    assert::<Protofetch>();
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum LockMode {
    /// Verify that the lock file is up to date. This mode should be normally used on CI.
    Locked,
    /// Update the lock file if necessary.
    Update,
    /// Recreate the lock file from scratch.
    Recreate,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum LockUpdateMode {
    /// Verify that the lock file is up to date.
    Verify,
    /// Reconcile the lock file with the current module descriptor, updating it if necessary.
    Reconcile,
    /// Reconcile the lock file and update the selected dependencies, keeping other locked entries pinned.
    ReconcileAndUpdate(Vec<DependencyUpdate>),
    /// Recreate the lock file from scratch, updating all dependencies.
    Full,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum DependencyUpdate {
    Latest { name: String },
    Precise { name: String, commit_hash: String },
}

impl From<LockMode> for LockUpdateMode {
    fn from(lock_mode: LockMode) -> Self {
        match lock_mode {
            LockMode::Locked => LockUpdateMode::Verify,
            LockMode::Update => LockUpdateMode::Reconcile,
            LockMode::Recreate => LockUpdateMode::Full,
        }
    }
}

impl Protofetch {
    pub fn builder() -> ProtofetchBuilder {
        ProtofetchBuilder::default()
    }

    /// Creates an initial protofetch setup
    pub fn init(&self, name: Option<String>) -> Result<(), Box<dyn Error>> {
        do_init(&self.root, name, &self.module_file_name)
    }

    /// Fetches dependencies defined in the toml configuration file
    pub fn fetch(&self, lock_mode: LockMode) -> Result<(), Box<dyn Error>> {
        do_fetch(
            lock_mode,
            self.cache.clone(),
            &self.root,
            &self.module_file_name,
            &self.lock_file_name,
            self.output_directory_name.as_deref(),
            self.parallel,
        )
    }

    /// Creates, updates or verifies a lock file based on the toml configuration file.
    #[deprecated(note = "use Protofetch::update instead")]
    pub fn lock(&self, lock_mode: LockMode) -> Result<(), Box<dyn Error>> {
        self.update(lock_mode.into())
    }

    /// Creates, updates or verifies a lock file based on the toml configuration file.
    pub fn update(&self, lock_update_mode: LockUpdateMode) -> Result<(), Box<dyn Error>> {
        do_lock(
            lock_update_mode,
            self.cache.clone(),
            &self.root,
            &self.module_file_name,
            &self.lock_file_name,
            self.parallel,
        )?;
        Ok(())
    }

    /// Migrates a protodep.toml file to the protofetch format
    pub fn migrate(
        &self,
        name: Option<String>,
        source_directory_path: impl AsRef<Path>,
    ) -> Result<(), Box<dyn Error>> {
        do_migrate(
            &self.root,
            name,
            &self.module_file_name,
            source_directory_path.as_ref(),
        )
    }

    /// Delete generated proto sources and the lock file
    pub fn clean(&self) -> Result<(), Box<dyn Error>> {
        do_clean(
            &self.root,
            &self.module_file_name,
            &self.lock_file_name,
            self.output_directory_name.as_deref(),
        )
    }

    pub fn clear_cache(&self) -> Result<(), Box<dyn Error>> {
        self.cache.clear()?;
        Ok(())
    }
}