diff options
Diffstat (limited to 'src/forge')
| -rw-r--r-- | src/forge/gitlab/config.rs | 26 | ||||
| -rw-r--r-- | src/forge/gitlab/mod.rs | 73 | ||||
| -rw-r--r-- | src/forge/mod.rs | 48 |
3 files changed, 147 insertions, 0 deletions
diff --git a/src/forge/gitlab/config.rs b/src/forge/gitlab/config.rs new file mode 100644 index 0000000..37186e8 --- /dev/null +++ b/src/forge/gitlab/config.rs @@ -0,0 +1,26 @@ +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + +use crate::config::ForgeConfigTrait; + +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)] +pub struct Gitlab { + // pub url: url::Url, + pub host: String, + pub token: String, + pub directory: PathBuf, + #[serde(default = "default_tls")] + pub tls: bool, + #[serde(default)] + pub auto_create_branches: bool, +} + +const fn default_tls() -> bool { + true +} + +impl ForgeConfigTrait for Gitlab { + fn root(&self) -> &str { + self.directory.to_str().unwrap() + } +} diff --git a/src/forge/gitlab/mod.rs b/src/forge/gitlab/mod.rs new file mode 100644 index 0000000..a32c367 --- /dev/null +++ b/src/forge/gitlab/mod.rs @@ -0,0 +1,73 @@ +use anyhow::{bail, Context, Result}; +use gitlab::AsyncGitlab; + +use graphql_client::GraphQLQuery; +use tracing::{debug, trace}; + +pub mod config; + +#[derive(Clone, Debug)] +pub struct Gitlab { + client: AsyncGitlab, +} + +impl Gitlab { + pub async fn new(host: &str, token: &str, tls: bool) -> Result<Gitlab> { + let mut gitlab = gitlab::GitlabBuilder::new(host, token); + + if !tls { + gitlab.insecure(); + } + + let gitlab = gitlab.build_async().await?; + + Ok(Gitlab { client: gitlab }) + } + + pub async fn from_config(forge: &config::Gitlab) -> Result<Gitlab> { + Gitlab::new(&forge.host, &forge.token, forge.tls).await + } +} + +#[async_trait::async_trait] +impl super::ForgeTrait for Gitlab { + async fn projects(&self, scope: &str) -> Result<Vec<super::Project>> { + let query = Projects::build_query(projects::Variables { + scope: scope.to_owned(), + }); + debug!("query: {:#?}", query); + let res = self.client.graphql::<Projects>(&query).await?; + + let res = res + .projects + .unwrap() + .nodes + .unwrap() + .into_iter() + .filter(|x| x.is_some()) + .map(|x| x.unwrap().into()) + .collect(); + + Ok(res) + } +} + +#[derive(GraphQLQuery)] +#[graphql( + query_path = "graphql/projects_query.graphql", + schema_path = "graphql/schema.graphql", + response_derives = "Clone, Debug" +)] +pub struct Projects; + +impl Into<super::Project> for projects::ProjectsProjectsNodes { + fn into(self) -> super::Project { + super::Project { + id: self.id, + name: self.name, + path: self.full_path, + ssh_clone_url: self.ssh_url_to_repo, + http_clone_url: self.http_url_to_repo, + } + } +} diff --git a/src/forge/mod.rs b/src/forge/mod.rs new file mode 100644 index 0000000..3e94812 --- /dev/null +++ b/src/forge/mod.rs @@ -0,0 +1,48 @@ +use std::ops::Deref; + +use anyhow::{Result, bail}; +use serde::{Deserialize, Serialize}; + +use crate::config::ForgeConfig; + +pub mod gitlab; + +#[derive(Clone, Debug)] +pub enum Forge { + Gitlab(self::gitlab::Gitlab), +} + +impl Forge { + pub async fn new(config: &ForgeConfig) -> Result<Forge> { + match config { + ForgeConfig::Gitlab(config) => { + Ok(Forge::Gitlab(gitlab::Gitlab::from_config(config).await?)) + } + _ => bail!("wrong forge type found"), + } + } +} + +#[async_trait::async_trait] +pub trait ForgeTrait { + async fn projects(&self, scope: &str) -> Result<Vec<Project>>; +} + +impl Deref for Forge { + type Target = dyn ForgeTrait; + + fn deref(&self) -> &Self::Target { + match self { + Forge::Gitlab(forge) => forge, + } + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Project { + pub id: String, + pub name: String, + pub path: String, + pub ssh_clone_url: Option<String>, + pub http_clone_url: Option<String>, +} |
