Added initial git and storage engine
This commit is contained in:
@@ -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 }
|
||||
|
33
crates/octopush_cli/src/commands/execute.rs
Normal file
33
crates/octopush_cli/src/commands/execute.rs
Normal 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(())
|
||||
}
|
1
crates/octopush_cli/src/commands/mod.rs
Normal file
1
crates/octopush_cli/src/commands/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod execute;
|
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
14
crates/octopush_core/Cargo.toml
Normal file
14
crates/octopush_core/Cargo.toml
Normal 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"
|
25
crates/octopush_core/src/git/github.rs
Normal file
25
crates/octopush_core/src/git/github.rs
Normal 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(())
|
||||
}
|
||||
}
|
9
crates/octopush_core/src/git/mod.rs
Normal file
9
crates/octopush_core/src/git/mod.rs
Normal 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>;
|
2
crates/octopush_core/src/lib.rs
Normal file
2
crates/octopush_core/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod git;
|
||||
pub mod storage;
|
51
crates/octopush_core/src/storage/local.rs
Normal file
51
crates/octopush_core/src/storage/local.rs
Normal 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);
|
||||
}
|
||||
}
|
31
crates/octopush_core/src/storage/mod.rs
Normal file
31
crates/octopush_core/src/storage/mod.rs
Normal 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(())
|
||||
}
|
||||
}
|
11
crates/octopush_infra/Cargo.toml
Normal file
11
crates/octopush_infra/Cargo.toml
Normal 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 }
|
16
crates/octopush_infra/src/lib.rs
Normal file
16
crates/octopush_infra/src/lib.rs
Normal 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);
|
||||
}
|
||||
}
|
27
crates/octopush_infra/src/service_register.rs
Normal file
27
crates/octopush_infra/src/service_register.rs
Normal 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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user