Added initial git and storage engine

This commit is contained in:
2022-10-25 22:00:46 +02:00
parent 1be156d911
commit dce155979e
16 changed files with 931 additions and 12 deletions

View File

@@ -6,3 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
octopush_infra = { path = "../octopush_infra" }
octopush_core = { path = "../octopush_core" }
clap = { version = "4.0.18" }
eyre = { workspace = true }

View File

@@ -0,0 +1,33 @@
use clap::{Arg, ArgAction, ArgMatches, Command};
use octopush_infra::service_register::ServiceRegister;
pub fn execute_cmd() -> Command {
Command::new("execute")
.about("execute a certain action")
.arg(
Arg::new("action")
.long("action")
.short('a')
.action(ArgAction::Set)
.help("action path to your local octopush.yaml file")
.long_help("action path to your local octopush.yaml file")
.required(true),
)
}
pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
let action = args
.get_one::<String>("action")
.ok_or(eyre::anyhow!("--action is required"))?;
let service_register = ServiceRegister::new();
service_register
.git_provider
.clone_from_url("https://git.front.kjuulh.io/kjuulh/cuddle".to_string())
.await?;
service_register.cleanup().await?;
Ok(())
}

View File

@@ -0,0 +1 @@
pub mod execute;

View File

@@ -1,14 +1,38 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
mod commands;
use clap::Command;
const VERSION: &str = "1.0.0";
#[derive(Debug)]
pub struct OctopushCli {
cmd: clap::Command,
}
#[cfg(test)]
mod tests {
use super::*;
impl OctopushCli {
pub fn new() -> Self {
let cmd = Command::new("octopush")
.version(VERSION)
.author("Kasper J. Hermansen <contact@kjuulh.io>")
.about("Your cute action executor")
.propagate_version(true)
.subcommand_required(true)
.subcommand(commands::execute::execute_cmd());
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
Self { cmd }
}
pub async fn execute(self) -> eyre::Result<()> {
let matches = self.cmd.get_matches();
match matches.subcommand() {
Some(("execute", execute_sub)) => {
commands::execute::execute_subcommand(execute_sub).await?;
}
Some(_) => return Err(eyre::anyhow!("unknown subcommand, please see --help")),
None => return Err(eyre::anyhow!("no subcommand specified")),
}
Ok(())
}
}

View File

@@ -0,0 +1,14 @@
[package]
name = "octopush_core"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
async-trait = { workspace = true }
eyre = { workspace = true }
tokio = { workspace = true }
rand = "0.8.5"
hex = "0.4.3"
git2 = "0.15.0"

View File

@@ -0,0 +1,25 @@
use crate::storage::DynStorageEngine;
use super::GitProvider;
pub struct GitHubGitProvider {
storage_engine: DynStorageEngine,
}
impl GitHubGitProvider {
pub fn new(storage_engine: DynStorageEngine) -> Self {
Self { storage_engine }
}
}
#[async_trait::async_trait]
impl GitProvider for GitHubGitProvider {
async fn clone_from_url(&self, url: String) -> eyre::Result<()> {
let dir = self.storage_engine.allocate_dir().await?;
tokio::task::spawn_blocking(move || git2::Repository::clone(url.as_str(), dir.path()))
.await??;
Ok(())
}
}

View File

@@ -0,0 +1,9 @@
use std::sync::Arc;
pub mod github;
#[async_trait::async_trait]
pub trait GitProvider {
async fn clone_from_url(&self, url: String) -> eyre::Result<()>;
}
pub type DynGitProvider = Arc<dyn GitProvider + Send + Sync>;

View File

@@ -0,0 +1,2 @@
pub mod git;
pub mod storage;

View File

@@ -0,0 +1,51 @@
use std::path::PathBuf;
use rand::distributions::{DistString, Standard};
use super::StorageEngine;
pub struct LocalStorageEngine {
root: PathBuf,
}
impl LocalStorageEngine {
pub fn new(root: PathBuf) -> Self {
Self { root }
}
}
#[async_trait::async_trait]
impl StorageEngine for LocalStorageEngine {
async fn allocate_dir(&self) -> eyre::Result<super::TemporaryDir> {
let subdir_name = Standard.sample_string(&mut rand::thread_rng(), 2);
let mut path = self.root.clone();
path.push(hex::encode(subdir_name));
Ok(super::TemporaryDir::new(path))
}
async fn cleanup(&self) -> eyre::Result<()> {
tokio::fs::remove_dir_all(self.root.clone()).await?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use crate::storage::StorageEngine;
use super::LocalStorageEngine;
#[tokio::test]
async fn create_local_storage_engine_and_allocate() {
let local_storage = LocalStorageEngine::new(PathBuf::new());
let dir = local_storage.allocate_dir().await.expect("to allocate dir");
assert_eq!(dir.path().to_string_lossy().len(), 16);
assert_eq!(dir.path().to_string_lossy().is_empty(), false);
}
}

View File

@@ -0,0 +1,31 @@
pub mod local;
use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait;
#[async_trait]
pub trait StorageEngine {
async fn allocate_dir(&self) -> eyre::Result<TemporaryDir>;
async fn cleanup(&self) -> eyre::Result<()>;
}
pub type DynStorageEngine = Arc<dyn StorageEngine + Send + Sync>;
pub struct TemporaryDir {
path: PathBuf,
}
impl TemporaryDir {
pub fn new(path: PathBuf) -> Self {
Self { path }
}
pub fn path(&self) -> PathBuf {
self.path.clone()
}
pub fn cleanup(self) -> eyre::Result<()> {
Ok(())
}
}

View File

@@ -0,0 +1,11 @@
[package]
name = "octopush_infra"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
octopush_core = { path = "../octopush_core" }
eyre = { workspace = true }

View File

@@ -0,0 +1,16 @@
pub mod service_register;
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

View File

@@ -0,0 +1,27 @@
use std::sync::Arc;
use octopush_core::{
git::{github::GitHubGitProvider, DynGitProvider},
storage::{local::LocalStorageEngine, DynStorageEngine},
};
pub struct ServiceRegister {
pub storage_engine: DynStorageEngine,
pub git_provider: DynGitProvider,
}
impl ServiceRegister {
pub fn new() -> Self {
let storage_engine = Arc::new(LocalStorageEngine::new("/tmp/octopush".into()));
let git_provider = Arc::new(GitHubGitProvider::new(storage_engine.clone()));
Self {
storage_engine,
git_provider,
}
}
pub async fn cleanup(self) -> eyre::Result<()> {
self.storage_engine.cleanup().await
}
}