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