diff --git a/src/errors.rs b/src/errors.rs index 3c310da..e819c0c 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -25,6 +25,7 @@ use actix_web::{ }; use config::ConfigError as ConfigErrorInner; use derive_more::{Display, Error}; +use git2::Error as GitError; use serde::{Deserialize, Serialize}; use url::ParseError; @@ -118,6 +119,9 @@ pub enum ServiceError { #[display(fmt = "Configuration Error {}", _0)] ConfigError(ConfigError), + + #[display(fmt = "Git Error {}", _0)] + GitError(GitError), } impl From for ServiceError { @@ -127,6 +131,13 @@ impl From for ServiceError { } } +impl From for ServiceError { + #[cfg(not(tarpaulin_include))] + fn from(e: GitError) -> ServiceError { + ServiceError::GitError(e) + } +} + /// Generic result data structure #[cfg(not(tarpaulin_include))] pub type ServiceResult = std::result::Result; @@ -167,6 +178,7 @@ impl ResponseError for ServiceError { ServiceError::UnauthorizedOperation(_) => StatusCode::UNAUTHORIZED, ServiceError::BadRequest(_) => StatusCode::BAD_REQUEST, + ServiceError::GitError(_) => StatusCode::BAD_REQUEST, } } } diff --git a/src/page.rs b/src/page.rs index 65ecb91..7f3faa2 100644 --- a/src/page.rs +++ b/src/page.rs @@ -18,6 +18,8 @@ use git2::{build::CheckoutBuilder, BranchType, Direction, ObjectType, Repository use log::info; use serde::Deserialize; +use crate::errors::*; + #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct Page { pub secret: String, @@ -27,50 +29,50 @@ pub struct Page { } impl Page { - fn create_repo(&self) -> Repository { + fn create_repo(&self) -> ServiceResult { let repo = Repository::open(&self.path); if let Ok(repo) = repo { - return repo; + return Ok(repo); } else { info!("Cloning repository {} at {}", self.repo, self.path); - Repository::clone(&self.repo, &self.path).unwrap() + Repository::clone(&self.repo, &self.path)?; }; - let repo = Repository::open(&self.path).unwrap(); - self._fetch_upstream(&repo, &self.branch); - self.deploy_branch(&repo); - repo + let repo = Repository::open(&self.path)?; + self._fetch_upstream(&repo, &self.branch)?; + self.deploy_branch(&repo)?; + Ok(repo) } - pub fn deploy_branch(&self, repo: &Repository) { - let branch = repo - .find_branch(&format!("origin/{}", &self.branch), BranchType::Remote) - .unwrap(); + pub fn deploy_branch(&self, repo: &Repository) -> ServiceResult<()> { + let branch = repo.find_branch(&format!("origin/{}", &self.branch), BranchType::Remote)?; let mut checkout_options = CheckoutBuilder::new(); checkout_options.force(); - let tree = branch.get().peel(ObjectType::Tree).unwrap(); + let tree = branch.get().peel(ObjectType::Tree)?; - repo.checkout_tree(&tree, Some(&mut checkout_options)) - .unwrap(); - repo.set_head(branch.get().name().unwrap()).unwrap(); + repo.checkout_tree(&tree, Some(&mut checkout_options))?; + repo.set_head(branch.get().name().unwrap())?; info!("Deploying branch {}", self.branch); + Ok(()) } - fn _fetch_upstream(&self, repo: &Repository, branch: &str) { + fn _fetch_upstream(&self, repo: &Repository, branch: &str) -> ServiceResult<()> { let mut remote = repo.find_remote("origin").unwrap(); - remote.connect(Direction::Fetch).unwrap(); + remote.connect(Direction::Fetch)?; info!("Updating repository {}", self.repo); - remote.fetch(&[branch], None, None).unwrap(); - remote.disconnect().unwrap(); + remote.fetch(&[branch], None, None)?; + remote.disconnect()?; + Ok(()) } - pub fn update(&self) { - let repo = self.create_repo(); - self._fetch_upstream(&repo, &self.branch); - self.deploy_branch(&repo); + pub fn update(&self) -> ServiceResult<()> { + let repo = self.create_repo()?; + self._fetch_upstream(&repo, &self.branch)?; + self.deploy_branch(&repo)?; + Ok(()) } } @@ -105,9 +107,9 @@ mod tests { "repository doesn't exist yet" ); - let repo = page.create_repo(); + let repo = page.create_repo().unwrap(); assert!(!repo.is_bare(), "repository isn't bare"); - page.create_repo(); + page.create_repo().unwrap(); assert!( Repository::open(tmp_dir.as_path()).is_ok(), "repository exists yet" @@ -119,7 +121,7 @@ mod tests { &"origin/gh-pages" ); page.branch = "master".to_string(); - page.update(); + page.update().unwrap(); let master = page.get_tree(&repo); assert_eq!(master.name().unwrap().as_ref().unwrap(), &"origin/master"); } diff --git a/src/settings.rs b/src/settings.rs index 1d0a0e3..d93157d 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -17,11 +17,12 @@ use std::env; use std::path::Path; -use config::{Config, ConfigError, Environment, File}; +use config::{Config, Environment, File}; use log::warn; use serde::Deserialize; use url::Url; +use crate::errors::*; use crate::page::Page; #[derive(Debug, Clone, Deserialize)] @@ -47,7 +48,7 @@ pub struct Settings { #[cfg(not(tarpaulin_include))] impl Settings { - pub fn new() -> Result { + pub fn new() -> ServiceResult { let mut s = Config::builder(); const CURRENT_DIR: &str = "./config/default.toml"; @@ -99,12 +100,26 @@ impl Settings { if index2 == index { continue; } - if page.secret == page2.secret || page.repo == page2.repo || page.path == page2.path - { - panic!("duplicate page onfiguration {:?} and {:?}", page, page2); + if page.secret == page2.secret { + log::error!( + "{}", + ServiceError::SecretTaken(page.to_owned(), page2.to_owned()) + ); + } else if page.repo == page2.repo { + log::error!( + "{}", + ServiceError::DuplicateRepositoryURL(page.to_owned(), page2.to_owned(),) + ); + } else if page.path == page2.path { + log::error!( + "{}", + ServiceError::PathTaken(page.to_owned(), page2.to_owned()) + ); } } - page.update(); + if let Err(e) = page.update() { + log::error!("{e}"); + } } Ok(settings)