refactor: move gitea out of the way

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2023-08-01 16:38:30 +02:00
parent 39db4b8d1c
commit e51454088e
11 changed files with 481 additions and 277 deletions

View File

@@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex};
use clap::Args;
use clap::{Args, ValueEnum};
pub type StdinFn = Option<Arc<Mutex<dyn Fn() -> anyhow::Result<String> + Send + Sync + 'static>>>;
@@ -35,4 +35,27 @@ EOF
config-stdin will consume stdin until the channel is closed via. EOF"
)]
pub config_stdin: bool,
#[arg(
env = "CUDDLE_PLEASE_NO_VCS",
long,
global = true,
help_heading = "Global"
)]
pub no_vcs: bool,
#[arg(
env = "CUDDLE_PLEASE_ENGINE",
long,
global = true,
help_heading = "Global",
default_value = "gitea"
)]
pub engine: RemoteEngine,
}
#[derive(ValueEnum, Clone, Debug)]
pub enum RemoteEngine {
Local,
Gitea,
}

View File

@@ -3,6 +3,51 @@ use reqwest::header::{HeaderMap, HeaderValue};
use semver::Version;
use serde::{Deserialize, Serialize};
pub trait RemoteGitEngine {
fn connect(&self, owner: &str, repo: &str) -> anyhow::Result<()>;
fn get_tags(&self, owner: &str, repo: &str) -> anyhow::Result<Vec<Tag>>;
fn get_commits_since(
&self,
owner: &str,
repo: &str,
since_sha: Option<&str>,
branch: &str,
) -> anyhow::Result<Vec<Commit>>;
fn get_pull_request(&self, owner: &str, repo: &str) -> anyhow::Result<Option<usize>>;
fn create_pull_request(
&self,
owner: &str,
repo: &str,
version: &str,
body: &str,
base: &str,
) -> anyhow::Result<usize>;
fn update_pull_request(
&self,
owner: &str,
repo: &str,
version: &str,
body: &str,
index: usize,
) -> anyhow::Result<usize>;
fn create_release(
&self,
owner: &str,
repo: &str,
version: &str,
body: &str,
prerelease: bool,
) -> anyhow::Result<Release>;
}
pub type DynRemoteGitClient = Box<dyn RemoteGitEngine>;
#[allow(dead_code)]
pub struct GiteaClient {
url: String,
@@ -13,7 +58,7 @@ pub struct GiteaClient {
const APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
impl GiteaClient {
pub fn new(url: impl Into<String>, token: Option<impl Into<String>>) -> Self {
pub fn new(url: &str, token: Option<&str>) -> Self {
Self {
url: url.into(),
token: token.map(|t| t.into()),
@@ -40,11 +85,92 @@ impl GiteaClient {
Ok(client)
}
pub fn connect(&self, owner: impl Into<String>, repo: impl Into<String>) -> anyhow::Result<()> {
let client = self.create_client()?;
fn get_commits_since_inner<F>(
&self,
owner: &str,
repo: &str,
since_sha: Option<&str>,
branch: &str,
get_commits: F,
) -> anyhow::Result<Vec<Commit>>
where
F: Fn(&str, &str, &str, usize) -> anyhow::Result<(Vec<Commit>, bool)>,
{
let mut commits = Vec::new();
let mut page = 1;
let owner = owner.into();
let repo = repo.into();
let owner: String = owner.into();
let repo: String = repo.into();
let since_sha: Option<String> = since_sha.map(|ss| ss.into());
let branch: String = branch.into();
let mut found_commit = false;
loop {
let (new_commits, has_more) = get_commits(&owner, &repo, &branch, page)?;
for commit in new_commits {
if let Some(since_sha) = &since_sha {
if commit.sha.contains(since_sha) {
found_commit = true;
} else if !found_commit {
commits.push(commit);
}
} else {
commits.push(commit);
}
}
if !has_more {
break;
}
page += 1;
}
if !found_commit && since_sha.is_some() {
return Err(anyhow::anyhow!(
"sha was not found in commit chain: {} on branch: {}",
since_sha.unwrap_or("".into()),
branch
));
}
Ok(commits)
}
fn get_pull_request_inner<F>(
&self,
owner: &str,
repo: &str,
request_pull_request: F,
) -> anyhow::Result<Option<usize>>
where
F: Fn(&str, &str, usize) -> anyhow::Result<(Vec<PullRequest>, bool)>,
{
let mut page = 1;
let owner: String = owner.into();
let repo: String = repo.into();
loop {
let (pull_requests, has_more) = request_pull_request(&owner, &repo, page)?;
for pull_request in pull_requests {
if pull_request.head.r#ref.contains("cuddle-please/release") {
return Ok(Some(pull_request.number));
}
}
if !has_more {
break;
}
page += 1;
}
Ok(None)
}
}
impl RemoteGitEngine for GiteaClient {
fn connect(&self, owner: &str, repo: &str) -> anyhow::Result<()> {
let client = self.create_client()?;
tracing::trace!(owner = &owner, repo = &repo, "gitea connect");
@@ -67,19 +193,15 @@ impl GiteaClient {
Ok(())
}
pub fn get_tags(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
) -> anyhow::Result<Vec<Tag>> {
fn get_tags(&self, owner: &str, repo: &str) -> anyhow::Result<Vec<Tag>> {
let client = self.create_client()?;
let request = client
.get(format!(
"{}/api/v1/repos/{}/{}/tags",
&self.url.trim_end_matches('/'),
owner.into(),
repo.into()
owner,
repo
))
.build()?;
@@ -93,12 +215,12 @@ impl GiteaClient {
Ok(tags)
}
pub fn get_commits_since(
fn get_commits_since(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
since_sha: Option<impl Into<String>>,
branch: impl Into<String>,
owner: &str,
repo: &str,
since_sha: Option<&str>,
branch: &str,
) -> anyhow::Result<Vec<Commit>> {
let get_commits_since_page = |owner: &str,
repo: &str,
@@ -149,62 +271,7 @@ impl GiteaClient {
Ok(commits)
}
fn get_commits_since_inner<F>(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
since_sha: Option<impl Into<String>>,
branch: impl Into<String>,
get_commits: F,
) -> anyhow::Result<Vec<Commit>>
where
F: Fn(&str, &str, &str, usize) -> anyhow::Result<(Vec<Commit>, bool)>,
{
let mut commits = Vec::new();
let mut page = 1;
let owner: String = owner.into();
let repo: String = repo.into();
let since_sha: Option<String> = since_sha.map(|ss| ss.into());
let branch: String = branch.into();
let mut found_commit = false;
loop {
let (new_commits, has_more) = get_commits(&owner, &repo, &branch, page)?;
for commit in new_commits {
if let Some(since_sha) = &since_sha {
if commit.sha.contains(since_sha) {
found_commit = true;
} else if !found_commit {
commits.push(commit);
}
} else {
commits.push(commit);
}
}
if !has_more {
break;
}
page += 1;
}
if !found_commit && since_sha.is_some() {
return Err(anyhow::anyhow!(
"sha was not found in commit chain: {} on branch: {}",
since_sha.unwrap_or("".into()),
branch
));
}
Ok(commits)
}
pub fn get_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
) -> anyhow::Result<Option<usize>> {
fn get_pull_request(&self, owner: &str, repo: &str) -> anyhow::Result<Option<usize>> {
let request_pull_request =
|owner: &str, repo: &str, page: usize| -> anyhow::Result<(Vec<PullRequest>, bool)> {
let client = self.create_client()?;
@@ -241,44 +308,13 @@ impl GiteaClient {
self.get_pull_request_inner(owner, repo, request_pull_request)
}
fn get_pull_request_inner<F>(
fn create_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
request_pull_request: F,
) -> anyhow::Result<Option<usize>>
where
F: Fn(&str, &str, usize) -> anyhow::Result<(Vec<PullRequest>, bool)>,
{
let mut page = 1;
let owner: String = owner.into();
let repo: String = repo.into();
loop {
let (pull_requests, has_more) = request_pull_request(&owner, &repo, page)?;
for pull_request in pull_requests {
if pull_request.head.r#ref.contains("cuddle-please/release") {
return Ok(Some(pull_request.number));
}
}
if !has_more {
break;
}
page += 1;
}
Ok(None)
}
pub fn create_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
version: impl Into<String>,
body: impl Into<String>,
base: impl Into<String>,
owner: &str,
repo: &str,
version: &str,
body: &str,
base: &str,
) -> anyhow::Result<usize> {
#[derive(Clone, Debug, Serialize, Deserialize)]
struct CreatePullRequestOption {
@@ -290,15 +326,9 @@ impl GiteaClient {
let client = self.create_client()?;
let owner = owner.into();
let repo = repo.into();
let version = version.into();
let body = body.into();
let base = base.into();
let request = CreatePullRequestOption {
base: base.clone(),
body: body.clone(),
base: base.into(),
body: body.into(),
head: "cuddle-please/release".into(),
title: format!("chore(release): {}", version),
};
@@ -329,12 +359,12 @@ impl GiteaClient {
Ok(commits.number)
}
pub fn update_pull_request(
fn update_pull_request(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
version: impl Into<String>,
body: impl Into<String>,
owner: &str,
repo: &str,
version: &str,
body: &str,
index: usize,
) -> anyhow::Result<usize> {
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -345,13 +375,8 @@ impl GiteaClient {
let client = self.create_client()?;
let owner = owner.into();
let repo = repo.into();
let version = version.into();
let body = body.into();
let request = CreatePullRequestOption {
body: body.clone(),
body: body.into(),
title: format!("chore(release): {}", version),
};
@@ -381,12 +406,12 @@ impl GiteaClient {
Ok(commits.number)
}
pub fn create_release(
fn create_release(
&self,
owner: impl Into<String>,
repo: impl Into<String>,
version: impl Into<String>,
body: impl Into<String>,
owner: &str,
repo: &str,
version: &str,
body: &str,
prerelease: bool,
) -> anyhow::Result<Release> {
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -401,17 +426,12 @@ impl GiteaClient {
let client = self.create_client()?;
let owner = owner.into();
let repo = repo.into();
let version = version.into();
let body = body.into();
let request = CreateReleaseOption {
body,
body: body.into(),
draft: false,
name: version.clone(),
name: version.into(),
prerelease,
tag_name: version.clone(),
tag_name: version.into(),
};
tracing::trace!(
@@ -563,7 +583,7 @@ mod test {
let commits = client.get_commits_since_inner(
"owner",
"repo",
Some(sha),
Some(&sha),
"some-branch",
|_, _, _, page| -> anyhow::Result<(Vec<Commit>, bool)> {
let commit_page = api_res.get(page - 1).unwrap();

View File

@@ -2,12 +2,14 @@ mod args;
mod cliff;
mod git_client;
mod gitea_client;
mod local_git_client;
mod ui;
mod versioning;
pub use args::{GlobalArgs, StdinFn};
pub use args::{GlobalArgs, RemoteEngine, StdinFn};
pub use cliff::{changelog_parser, ChangeLogBuilder};
pub use git_client::VcsClient;
pub use gitea_client::GiteaClient;
pub use gitea_client::{DynRemoteGitClient, GiteaClient, RemoteGitEngine};
pub use local_git_client::LocalGitClient;
pub use ui::{ConsoleUi, DynUi, Ui};
pub use versioning::{next_version::NextVersion, semver::get_most_significant_version};

View File

@@ -0,0 +1,66 @@
use crate::RemoteGitEngine;
pub struct LocalGitClient {}
impl LocalGitClient {
pub fn new() -> Self {
Self {}
}
}
impl RemoteGitEngine for LocalGitClient {
fn connect(&self, owner: &str, repo: &str) -> anyhow::Result<()> {
todo!()
}
fn get_tags(&self, owner: &str, repo: &str) -> anyhow::Result<Vec<crate::gitea_client::Tag>> {
todo!()
}
fn get_commits_since(
&self,
owner: &str,
repo: &str,
since_sha: Option<&str>,
branch: &str,
) -> anyhow::Result<Vec<crate::gitea_client::Commit>> {
todo!()
}
fn get_pull_request(&self, owner: &str, repo: &str) -> anyhow::Result<Option<usize>> {
todo!()
}
fn create_pull_request(
&self,
owner: &str,
repo: &str,
version: &str,
body: &str,
base: &str,
) -> anyhow::Result<usize> {
todo!()
}
fn update_pull_request(
&self,
owner: &str,
repo: &str,
version: &str,
body: &str,
index: usize,
) -> anyhow::Result<usize> {
todo!()
}
fn create_release(
&self,
owner: &str,
repo: &str,
version: &str,
body: &str,
prerelease: bool,
) -> anyhow::Result<crate::gitea_client::Release> {
todo!()
}
}