diff --git a/crates/cuddle-please-commands/src/command.rs b/crates/cuddle-please-commands/src/command.rs index 8f4231a..22303cd 100644 --- a/crates/cuddle-please-commands/src/command.rs +++ b/crates/cuddle-please-commands/src/command.rs @@ -1,19 +1,24 @@ use std::{ + env::current_dir, io::Read, ops::Deref, path::{Path, PathBuf}, + rc::Rc, sync::{Arc, Mutex}, }; use ::semver::Version; use anyhow::Context; use clap::{Parser, Subcommand}; -use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfigBuilder}; +use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfig, PleaseConfigBuilder}; use cuddle_please_misc::{ - changelog_parser, get_most_significant_version, ChangeLogBuilder, ConsoleUi, DynUi, - GiteaClient, GlobalArgs, NextVersion, StdinFn, VcsClient, + changelog_parser, get_most_significant_version, ChangeLogBuilder, ConsoleUi, + DynRemoteGitClient, DynUi, GiteaClient, GlobalArgs, LocalGitClient, NextVersion, + RemoteGitEngine, StdinFn, VcsClient, }; +use crate::release_command::ReleaseCommand; + #[derive(Parser)] #[command(author, version, about, long_about = None)] pub struct Command { @@ -84,124 +89,13 @@ impl Command { pub fn execute(self, current_dir: Option<&Path>) -> anyhow::Result<()> { let config = self.build_config(current_dir)?; + let git_client = self.get_git(config.get_source())?; + let gitea_client = self.get_gitea_client(); match &self.commands { Some(Commands::Release {}) => { - tracing::debug!("running bare command"); - // 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence - // 2a. if not existing use default. - // 2b. if not in a git repo abort. (unless --no-vcs is turned added) - let git_client = self.get_git(config.get_source())?; - - // 3. Create gitea client and do a health check - let gitea_client = self.get_gitea_client(); - gitea_client - .connect(config.get_owner(), config.get_repository()) - .context("failed to connect to gitea repository")?; - // 4. Fetch git tags for the current repository - let tags = gitea_client.get_tags(config.get_owner(), config.get_repository())?; - - let significant_tag = get_most_significant_version(tags.iter().collect()); - - // 5. Fetch git commits since last git tag - let commits = gitea_client.get_commits_since( - config.get_owner(), - config.get_repository(), - significant_tag.map(|st| st.commit.sha.clone()), - config.get_branch(), - )?; - - // 7. Create a versioning client - let current_version = significant_tag - .map(|st| Version::try_from(st).unwrap()) - .unwrap_or(Version::new(0, 1, 0)); - - // 8. Parse conventional commits and determine next version - - let commit_strs = commits - .iter() - .map(|c| c.commit.message.as_str()) - .collect::>(); - - if commit_strs.is_empty() { - tracing::info!("no commits to base release on"); - return Ok(()); - } - - let next_version = current_version.next(&commit_strs); - - // Compose changelog - let builder = ChangeLogBuilder::new(&commit_strs, next_version.to_string()).build(); - - let changelog_placement = config.get_source().join("CHANGELOG.md"); - - let changelog = match std::fs::read_to_string(&changelog_placement).ok() { - Some(existing_changelog) => builder.prepend(existing_changelog)?, - None => builder.generate()?, - }; - - let changelog_last_changes = changelog_parser::last_changes(&changelog)?; - - // 9b. check for release commit and release, if release exists continue - // 10b. create release - if let Some(first_commit) = commit_strs.first() { - if first_commit.contains("chore(release): ") { - if !self.global.dry_run { - gitea_client.create_release( - config.get_owner(), - config.get_repository(), - next_version.to_string(), - changelog_last_changes.unwrap(), - !next_version.pre.is_empty(), - )?; - } else { - tracing::debug!("creating release (dry_run)"); - } - - return Ok(()); - } - } - - // 9a. Create / Update Pr - // Create or update branch - git_client.checkout_branch()?; - - std::fs::write(changelog_placement, changelog.as_bytes())?; - - git_client.commit_and_push(next_version.to_string(), self.global.dry_run)?; - - let _pr_number = match gitea_client - .get_pull_request(config.get_owner(), config.get_repository())? - { - Some(existing_pr) => { - if !self.global.dry_run { - gitea_client.update_pull_request( - config.get_owner(), - config.get_repository(), - next_version.to_string(), - changelog_last_changes.unwrap(), - existing_pr, - )? - } else { - tracing::debug!("updating pull request (dry_run)"); - 1 - } - } - None => { - if !self.global.dry_run { - gitea_client.create_pull_request( - config.get_owner(), - config.get_repository(), - next_version.to_string(), - changelog, - config.get_branch(), - )? - } else { - tracing::debug!("creating pull request (dry_run)"); - 1 - } - } - }; + ReleaseCommand::new(config, git_client, gitea_client) + .execute(self.global.dry_run)?; } Some(Commands::Config { command }) => match command { @@ -222,7 +116,7 @@ impl Command { url.push_str(format!(":{port}").as_str()); } - let client = GiteaClient::new(url, self.global.token); + let client = GiteaClient::new(&url, self.global.token.as_ref().map(|t| t.as_str())); match command { GiteaCommand::Connect {} => { client.connect(config.get_owner(), config.get_repository())?; @@ -302,10 +196,7 @@ impl Command { Ok(()) } - fn build_config( - &self, - current_dir: Option<&Path>, - ) -> Result { + fn build_config(&self, current_dir: Option<&Path>) -> Result { let mut builder = &mut PleaseConfigBuilder::new(); if self.global.config_stdin { if let Some(stdin_fn) = self.stdin.clone() { @@ -316,6 +207,7 @@ impl Command { let current_dir = get_current_path(current_dir, self.config.source.clone())?; let config = builder .with_config_file(¤t_dir) + .with_source(¤t_dir) .with_execution_env(std::env::vars()) .with_cli(self.config.clone()) .build()?; @@ -323,14 +215,21 @@ impl Command { } fn get_git(&self, current_dir: &Path) -> anyhow::Result { - VcsClient::new_git(current_dir) + if self.global.no_vcs { + Ok(VcsClient::new_noop()) + } else { + VcsClient::new_git(current_dir) + } } - fn get_gitea_client(&self) -> GiteaClient { - GiteaClient::new( - self.config.api_url.clone().expect("api_url to be set"), - self.global.token.clone(), - ) + fn get_gitea_client(&self) -> DynRemoteGitClient { + match self.global.engine { + cuddle_please_misc::RemoteEngine::Local => Box::new(LocalGitClient::new()), + cuddle_please_misc::RemoteEngine::Gitea => Box::new(GiteaClient::new( + &self.config.api_url.clone().expect("api_url to be set"), + self.global.token.as_ref().map(|t| t.as_str()), + )), + } } } diff --git a/crates/cuddle-please-commands/src/lib.rs b/crates/cuddle-please-commands/src/lib.rs index bf9b2db..c7455ce 100644 --- a/crates/cuddle-please-commands/src/lib.rs +++ b/crates/cuddle-please-commands/src/lib.rs @@ -1,3 +1,4 @@ mod command; +mod release_command; pub use command::Command as PleaseCommand; diff --git a/crates/cuddle-please-commands/src/release_command.rs b/crates/cuddle-please-commands/src/release_command.rs new file mode 100644 index 0000000..8f7725f --- /dev/null +++ b/crates/cuddle-please-commands/src/release_command.rs @@ -0,0 +1,159 @@ +use cuddle_please_frontend::PleaseConfig; + +use std::{ + io::Read, + ops::Deref, + path::{Path, PathBuf}, + sync::{Arc, Mutex}, +}; + +use ::semver::Version; +use anyhow::Context; +use clap::{Parser, Subcommand}; +use cuddle_please_frontend::{gatheres::ConfigArgs, PleaseConfigBuilder}; +use cuddle_please_misc::{ + changelog_parser, get_most_significant_version, ChangeLogBuilder, ConsoleUi, + DynRemoteGitClient, DynUi, GiteaClient, GlobalArgs, NextVersion, StdinFn, VcsClient, +}; + +pub struct ReleaseCommand { + config: PleaseConfig, + git_client: VcsClient, + gitea_client: DynRemoteGitClient, +} + +impl ReleaseCommand { + pub fn new( + config: PleaseConfig, + git_client: VcsClient, + gitea_client: DynRemoteGitClient, + ) -> Self { + Self { + config, + git_client, + gitea_client, + } + } + + pub fn execute(&self, dry_run: bool) -> anyhow::Result<()> { + tracing::debug!("running bare command"); + let owner = self.config.get_owner(); + let repository = self.config.get_repository(); + let branch = self.config.get_branch(); + let source = self.config.get_source(); + + // 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence + // 2a. if not existing use default. + // 2b. if not in a git repo abort. (unless --no-vcs is turned added) + + // 3. Create gitea client and do a health check + self.gitea_client + .connect(owner, repository) + .context("failed to connect to gitea repository")?; + // 4. Fetch git tags for the current repository + let tags = self.gitea_client.get_tags(owner, repository)?; + + let significant_tag = get_most_significant_version(tags.iter().collect()); + + // 5. Fetch git commits since last git tag + let commits = self.gitea_client.get_commits_since( + owner, + repository, + significant_tag.map(|st| st.commit.sha.as_str()), + branch, + )?; + + // 7. Create a versioning client + let current_version = significant_tag + .map(|st| Version::try_from(st).unwrap()) + .unwrap_or(Version::new(0, 1, 0)); + + // 8. Parse conventional commits and determine next version + + let commit_strs = commits + .iter() + .map(|c| c.commit.message.as_str()) + .collect::>(); + + if commit_strs.is_empty() { + tracing::info!("no commits to base release on"); + return Ok(()); + } + + let next_version = current_version.next(&commit_strs); + + // Compose changelog + let builder = ChangeLogBuilder::new(&commit_strs, next_version.to_string()).build(); + + let changelog_placement = source.join("CHANGELOG.md"); + + let changelog = match std::fs::read_to_string(&changelog_placement).ok() { + Some(existing_changelog) => builder.prepend(existing_changelog)?, + None => builder.generate()?, + }; + + let changelog_last_changes = changelog_parser::last_changes(&changelog)?; + + // 9b. check for release commit and release, if release exists continue + // 10b. create release + if let Some(first_commit) = commit_strs.first() { + if first_commit.contains("chore(release): ") { + if !dry_run { + self.gitea_client.create_release( + owner, + repository, + &next_version.to_string(), + &changelog_last_changes.unwrap(), + !next_version.pre.is_empty(), + )?; + } else { + tracing::debug!("creating release (dry_run)"); + } + + return Ok(()); + } + } + + // 9a. Create / Update Pr + // Create or update branch + self.git_client.checkout_branch()?; + + std::fs::write(changelog_placement, changelog.as_bytes())?; + + self.git_client + .commit_and_push(next_version.to_string(), dry_run)?; + + let _pr_number = match self.gitea_client.get_pull_request(owner, repository)? { + Some(existing_pr) => { + if !dry_run { + self.gitea_client.update_pull_request( + owner, + repository, + &next_version.to_string(), + &changelog_last_changes.unwrap(), + existing_pr, + )? + } else { + tracing::debug!("updating pull request (dry_run)"); + 1 + } + } + None => { + if !dry_run { + self.gitea_client.create_pull_request( + owner, + repository, + &next_version.to_string(), + &changelog, + branch, + )? + } else { + tracing::debug!("creating pull request (dry_run)"); + 1 + } + } + }; + + Ok(()) + } +} diff --git a/crates/cuddle-please-frontend/src/gatheres/mod.rs b/crates/cuddle-please-frontend/src/gatheres/mod.rs index 0ec8679..5a88ec6 100644 --- a/crates/cuddle-please-frontend/src/gatheres/mod.rs +++ b/crates/cuddle-please-frontend/src/gatheres/mod.rs @@ -1,9 +1,11 @@ mod cli; mod config_file; mod execution_env; +mod source; mod stdin; pub use cli::ConfigArgs; pub(crate) use config_file::get_config_from_config_file; pub(crate) use execution_env::get_from_environment; +pub(crate) use source::get_source; pub(crate) use stdin::get_config_from_stdin; diff --git a/crates/cuddle-please-frontend/src/gatheres/source.rs b/crates/cuddle-please-frontend/src/gatheres/source.rs new file mode 100644 index 0000000..6b67d2a --- /dev/null +++ b/crates/cuddle-please-frontend/src/gatheres/source.rs @@ -0,0 +1,13 @@ +use std::path::Path; + +use crate::stage0_config; + +pub fn get_source(source: &Path) -> stage0_config::PleaseConfigBuilder { + stage0_config::PleaseConfigBuilder { + project: Some(stage0_config::PleaseProjectConfigBuilder { + source: Some(source.to_path_buf()), + ..Default::default() + }), + ..Default::default() + } +} diff --git a/crates/cuddle-please-frontend/src/lib.rs b/crates/cuddle-please-frontend/src/lib.rs index 2da616d..15a4854 100644 --- a/crates/cuddle-please-frontend/src/lib.rs +++ b/crates/cuddle-please-frontend/src/lib.rs @@ -48,6 +48,7 @@ pub struct PleaseConfigBuilder { execution_env: Option, cli: Option, config: Option, + source: Option, } impl PleaseConfigBuilder { @@ -80,8 +81,20 @@ impl PleaseConfigBuilder { self } + pub fn with_source(&mut self, source: &Path) -> &mut Self { + self.source = Some(gatheres::get_source(source)); + + self + } + pub fn build(&mut self) -> anyhow::Result { - let gathered = vec![&self.execution_env, &self.config, &self.stdin, &self.cli]; + let gathered = vec![ + &self.execution_env, + &self.source, + &self.config, + &self.stdin, + &self.cli, + ]; let final_config = gathered .into_iter() diff --git a/crates/cuddle-please-misc/src/args.rs b/crates/cuddle-please-misc/src/args.rs index de50609..b57c205 100644 --- a/crates/cuddle-please-misc/src/args.rs +++ b/crates/cuddle-please-misc/src/args.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use clap::Args; +use clap::{Args, ValueEnum}; pub type StdinFn = Option anyhow::Result + 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, } diff --git a/crates/cuddle-please-misc/src/gitea_client.rs b/crates/cuddle-please-misc/src/gitea_client.rs index 2003b72..4747198 100644 --- a/crates/cuddle-please-misc/src/gitea_client.rs +++ b/crates/cuddle-please-misc/src/gitea_client.rs @@ -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>; + + fn get_commits_since( + &self, + owner: &str, + repo: &str, + since_sha: Option<&str>, + branch: &str, + ) -> anyhow::Result>; + + fn get_pull_request(&self, owner: &str, repo: &str) -> anyhow::Result>; + + fn create_pull_request( + &self, + owner: &str, + repo: &str, + version: &str, + body: &str, + base: &str, + ) -> anyhow::Result; + + fn update_pull_request( + &self, + owner: &str, + repo: &str, + version: &str, + body: &str, + index: usize, + ) -> anyhow::Result; + + fn create_release( + &self, + owner: &str, + repo: &str, + version: &str, + body: &str, + prerelease: bool, + ) -> anyhow::Result; +} + +pub type DynRemoteGitClient = Box; + #[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, token: Option>) -> 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, repo: impl Into) -> anyhow::Result<()> { - let client = self.create_client()?; + fn get_commits_since_inner( + &self, + owner: &str, + repo: &str, + since_sha: Option<&str>, + branch: &str, + get_commits: F, + ) -> anyhow::Result> + where + F: Fn(&str, &str, &str, usize) -> anyhow::Result<(Vec, 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 = 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( + &self, + owner: &str, + repo: &str, + request_pull_request: F, + ) -> anyhow::Result> + where + F: Fn(&str, &str, usize) -> anyhow::Result<(Vec, 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, - repo: impl Into, - ) -> anyhow::Result> { + fn get_tags(&self, owner: &str, repo: &str) -> anyhow::Result> { 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, - repo: impl Into, - since_sha: Option>, - branch: impl Into, + owner: &str, + repo: &str, + since_sha: Option<&str>, + branch: &str, ) -> anyhow::Result> { let get_commits_since_page = |owner: &str, repo: &str, @@ -149,62 +271,7 @@ impl GiteaClient { Ok(commits) } - fn get_commits_since_inner( - &self, - owner: impl Into, - repo: impl Into, - since_sha: Option>, - branch: impl Into, - get_commits: F, - ) -> anyhow::Result> - where - F: Fn(&str, &str, &str, usize) -> anyhow::Result<(Vec, bool)>, - { - let mut commits = Vec::new(); - let mut page = 1; - - let owner: String = owner.into(); - let repo: String = repo.into(); - let since_sha: Option = 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, - repo: impl Into, - ) -> anyhow::Result> { + fn get_pull_request(&self, owner: &str, repo: &str) -> anyhow::Result> { let request_pull_request = |owner: &str, repo: &str, page: usize| -> anyhow::Result<(Vec, 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( + fn create_pull_request( &self, - owner: impl Into, - repo: impl Into, - request_pull_request: F, - ) -> anyhow::Result> - where - F: Fn(&str, &str, usize) -> anyhow::Result<(Vec, 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, - repo: impl Into, - version: impl Into, - body: impl Into, - base: impl Into, + owner: &str, + repo: &str, + version: &str, + body: &str, + base: &str, ) -> anyhow::Result { #[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, - repo: impl Into, - version: impl Into, - body: impl Into, + owner: &str, + repo: &str, + version: &str, + body: &str, index: usize, ) -> anyhow::Result { #[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, - repo: impl Into, - version: impl Into, - body: impl Into, + owner: &str, + repo: &str, + version: &str, + body: &str, prerelease: bool, ) -> anyhow::Result { #[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, bool)> { let commit_page = api_res.get(page - 1).unwrap(); diff --git a/crates/cuddle-please-misc/src/lib.rs b/crates/cuddle-please-misc/src/lib.rs index 3e6c582..a7a4fc6 100644 --- a/crates/cuddle-please-misc/src/lib.rs +++ b/crates/cuddle-please-misc/src/lib.rs @@ -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}; diff --git a/crates/cuddle-please-misc/src/local_git_client.rs b/crates/cuddle-please-misc/src/local_git_client.rs new file mode 100644 index 0000000..4509f30 --- /dev/null +++ b/crates/cuddle-please-misc/src/local_git_client.rs @@ -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> { + todo!() + } + + fn get_commits_since( + &self, + owner: &str, + repo: &str, + since_sha: Option<&str>, + branch: &str, + ) -> anyhow::Result> { + todo!() + } + + fn get_pull_request(&self, owner: &str, repo: &str) -> anyhow::Result> { + todo!() + } + + fn create_pull_request( + &self, + owner: &str, + repo: &str, + version: &str, + body: &str, + base: &str, + ) -> anyhow::Result { + todo!() + } + + fn update_pull_request( + &self, + owner: &str, + repo: &str, + version: &str, + body: &str, + index: usize, + ) -> anyhow::Result { + todo!() + } + + fn create_release( + &self, + owner: &str, + repo: &str, + version: &str, + body: &str, + prerelease: bool, + ) -> anyhow::Result { + todo!() + } +} diff --git a/crates/cuddle-please/tests/config.rs b/crates/cuddle-please/tests/config.rs index 238d237..288cb8a 100644 --- a/crates/cuddle-please/tests/config.rs +++ b/crates/cuddle-please/tests/config.rs @@ -7,7 +7,13 @@ use tracing_test::traced_test; use crate::common::{assert_output, get_test_data_path}; fn get_base_args<'a>() -> Vec<&'a str> { - vec!["cuddle-please", "config", "list"] + vec![ + "cuddle-please", + "config", + "list", + "--no-vcs", + "--engine=local", + ] } #[test]