feat: handle Git errors
This commit is contained in:
parent
eb87453bd1
commit
b758042836
3 changed files with 61 additions and 32 deletions
|
@ -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<ParseError> for ServiceError {
|
||||
|
@ -127,6 +131,13 @@ impl From<ParseError> for ServiceError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<GitError> 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<V> = std::result::Result<V, ServiceError>;
|
||||
|
@ -167,6 +178,7 @@ impl ResponseError for ServiceError {
|
|||
|
||||
ServiceError::UnauthorizedOperation(_) => StatusCode::UNAUTHORIZED,
|
||||
ServiceError::BadRequest(_) => StatusCode::BAD_REQUEST,
|
||||
ServiceError::GitError(_) => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
54
src/page.rs
54
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<Repository> {
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -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<Self, ConfigError> {
|
||||
pub fn new() -> ServiceResult<Self> {
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue