diff --git a/Cargo.lock b/Cargo.lock index 85bb670..d331023 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -344,7 +344,36 @@ dependencies = [ "chrono", "clap", "conventional_commit_parser", + "cuddle-please-commands", "cuddle-please-frontend", + "cuddle-please-misc", + "dotenv", + "git-cliff-core", + "lazy_static", + "parse-changelog", + "pretty_assertions", + "regex", + "reqwest", + "semver", + "serde", + "serde_yaml", + "tempdir", + "tracing", + "tracing-subscriber", + "tracing-test", + "url", +] + +[[package]] +name = "cuddle-please-commands" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "clap", + "conventional_commit_parser", + "cuddle-please-frontend", + "cuddle-please-misc", "dotenv", "git-cliff-core", "lazy_static", @@ -379,6 +408,31 @@ dependencies = [ "tracing-test", ] +[[package]] +name = "cuddle-please-misc" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "clap", + "conventional_commit_parser", + "dotenv", + "git-cliff-core", + "lazy_static", + "parse-changelog", + "pretty_assertions", + "regex", + "reqwest", + "semver", + "serde", + "serde_yaml", + "tempdir", + "tracing", + "tracing-subscriber", + "tracing-test", + "url", +] + [[package]] name = "deunicode" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index b0915df..beb8a5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,12 @@ [workspace] -members = ["crates/cuddle-please", "crates/cuddle-please-frontend"] +members = ["crates/cuddle-please", "crates/cuddle-please-frontend", "crates/cuddle-please-commands", "crates/cuddle-please-misc"] resolver = "2" [workspace.dependencies] cuddle-please = { path = "crates/cuddle-please" } cuddle-please-frontend = { path = "crates/cuddle-please-frontend" } +cuddle-please-commands = { path = "crates/cuddle-please-commands" } +cuddle-please-misc = { path = "crates/cuddle-please-misc" } anyhow = { version = "1.0.71" } tracing = { version = "0.1", features = ["log"] } diff --git a/crates/cuddle-please-commands/Cargo.toml b/crates/cuddle-please-commands/Cargo.toml new file mode 100644 index 0000000..967af68 --- /dev/null +++ b/crates/cuddle-please-commands/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "cuddle-please-commands" +version = "0.1.0" +edition = "2021" + + +[dependencies] +cuddle-please-frontend.workspace = true +cuddle-please-misc.workspace = true + +anyhow.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +clap.workspace = true +dotenv.workspace = true +serde_yaml.workspace = true +serde.workspace = true +reqwest = { workspace = true, features = ["blocking", "json"] } +url.workspace = true +semver.workspace = true +conventional_commit_parser.workspace = true +tempdir.workspace = true +git-cliff-core.workspace = true +regex.workspace = true +chrono.workspace = true +lazy_static.workspace = true +parse-changelog.workspace = true + +[dev-dependencies] +tracing-test = { workspace = true, features = ["no-env-filter"] } +pretty_assertions.workspace = true diff --git a/crates/cuddle-please-commands/src/command.rs b/crates/cuddle-please-commands/src/command.rs new file mode 100644 index 0000000..a42cac3 --- /dev/null +++ b/crates/cuddle-please-commands/src/command.rs @@ -0,0 +1,396 @@ +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, DynUi, + GiteaClient, GlobalArgs, NextVersion, StdinFn, VcsClient, +}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +pub struct Command { + #[command(flatten)] + global: GlobalArgs, + + #[command(flatten)] + config: ConfigArgs, + + #[command(subcommand)] + commands: Option, + + #[clap(skip)] + ui: DynUi, + + #[clap(skip)] + stdin: StdinFn, +} + +impl Default for Command { + fn default() -> Self { + Self::new() + } +} + +impl Command { + pub fn new() -> Self { + let args = std::env::args(); + + Self::new_from_args_with_stdin(Some(ConsoleUi::default()), args, || { + let mut input = String::new(); + std::io::stdin().read_to_string(&mut input)?; + Ok(input) + }) + } + + pub fn new_from_args(ui: Option, i: I) -> Self + where + I: IntoIterator, + T: Into + Clone, + UIF: Into, + { + let mut s = Self::parse_from(i); + + if let Some(ui) = ui { + s.ui = ui.into(); + } + + s + } + + pub fn new_from_args_with_stdin(ui: Option, i: I, input: F) -> Self + where + I: IntoIterator, + T: Into + Clone, + F: Fn() -> anyhow::Result + Send + Sync + 'static, + UIF: Into, + { + let mut s = Self::parse_from(i); + + if let Some(ui) = ui { + s.ui = ui.into(); + } + s.stdin = Some(Arc::new(Mutex::new(input))); + + s + } + + pub fn execute(self, current_dir: Option<&Path>) -> anyhow::Result<()> { + // 0. Get config + let mut builder = &mut PleaseConfigBuilder::new(); + + if self.global.config_stdin { + if let Some(stdin_fn) = self.stdin.clone() { + let output = (stdin_fn.lock().unwrap().deref())(); + builder = builder.with_stdin(output?); + } + } + // 1. Parse the current directory + let current_dir = get_current_path(current_dir, self.config.source.clone())?; + let config = builder + .with_config_file(¤t_dir) + .with_execution_env(std::env::vars()) + .with_cli(self.config.clone()) + .build()?; + + 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 + } + } + }; + } + + Some(Commands::Config { command }) => match command { + ConfigCommand::List { .. } => { + tracing::debug!("running command: config list"); + + self.ui.write_str_ln("cuddle-config"); + } + }, + Some(Commands::Gitea { command }) => { + let git_url = url::Url::parse(config.get_api_url())?; + + let mut url = String::new(); + url.push_str(git_url.scheme()); + url.push_str("://"); + url.push_str(&git_url.host().unwrap().to_string()); + if let Some(port) = git_url.port() { + url.push_str(format!(":{port}").as_str()); + } + + let client = GiteaClient::new(url, self.global.token); + match command { + GiteaCommand::Connect {} => { + client.connect(config.get_owner(), config.get_repository())?; + self.ui.write_str_ln("connected succesfully go gitea"); + } + GiteaCommand::Tags { command } => match command { + Some(GiteaTagsCommand::MostSignificant {}) => { + let tags = + client.get_tags(config.get_owner(), config.get_repository())?; + + match get_most_significant_version(tags.iter().collect()) { + Some(tag) => { + self.ui.write_str_ln(&format!( + "found most significant tags: {}", + tag.name + )); + } + None => { + self.ui.write_str_ln("found no tags with versioning schema"); + } + } + } + None => { + let tags = + client.get_tags(config.get_owner(), config.get_repository())?; + self.ui.write_str_ln("got tags from gitea"); + for tag in tags { + self.ui.write_str_ln(&format!("- {}", tag.name)) + } + } + }, + GiteaCommand::SinceCommit { sha, branch } => { + let commits = client.get_commits_since( + config.get_owner(), + config.get_repository(), + Some(sha), + branch, + )?; + self.ui.write_str_ln("got commits from gitea"); + for commit in commits { + self.ui.write_str_ln(&format!("- {}", commit.get_title())) + } + } + GiteaCommand::CheckPr {} => { + let pr = + client.get_pull_request(config.get_owner(), config.get_repository())?; + + match pr { + Some(index) => { + self.ui.write_str_ln(&format!( + "found cuddle-please (index={}) pr from gitea", + index + )); + } + None => { + self.ui.write_str_ln("found no cuddle-please pr from gitea"); + } + } + } + } + } + Some(Commands::Doctor {}) => { + match std::process::Command::new("git").arg("-v").output() { + Ok(o) => { + let stdout = std::str::from_utf8(&o.stdout).unwrap_or(""); + self.ui.write_str_ln(&format!("OK: {}", stdout)); + } + Err(e) => { + self.ui + .write_str_ln(&format!("WARNING: git is not installed: {}", e)); + } + } + } + None => {} + } + + Ok(()) + } + + fn get_git(&self, current_dir: &Path) -> anyhow::Result { + 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(), + ) + } +} + +#[derive(Debug, Clone, Subcommand)] +pub enum Commands { + /// Config is mostly used for debugging the final config output + Release {}, + + #[command(hide = true)] + Config { + #[command(subcommand)] + command: ConfigCommand, + }, + + #[command(hide = true)] + Gitea { + #[command(subcommand)] + command: GiteaCommand, + }, + /// Helps you identify missing things from your execution environment for cuddle-please to function as intended + Doctor {}, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum ConfigCommand { + /// List will list the final configuration + List {}, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum GiteaCommand { + Connect {}, + Tags { + #[command(subcommand)] + command: Option, + }, + SinceCommit { + #[arg(long)] + sha: String, + + #[arg(long)] + branch: String, + }, + CheckPr {}, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum GiteaTagsCommand { + MostSignificant {}, +} + +fn get_current_path( + optional_current_dir: Option<&Path>, + optional_source_path: Option, +) -> anyhow::Result { + let path = optional_source_path + .or_else(|| optional_current_dir.map(|p| p.to_path_buf())) // fall back on current env from environment + .filter(|v| v.to_string_lossy() != "") // make sure we don't get empty values + //.and_then(|p| p.canonicalize().ok()) // Make sure we get the absolute path + //.context("could not find current dir, pass --source as a replacement")?; + .unwrap_or(PathBuf::from(".")); + + if !path.exists() { + anyhow::bail!("path doesn't exist {}", path.display()); + } + + Ok(path) +} diff --git a/crates/cuddle-please-commands/src/lib.rs b/crates/cuddle-please-commands/src/lib.rs new file mode 100644 index 0000000..bf9b2db --- /dev/null +++ b/crates/cuddle-please-commands/src/lib.rs @@ -0,0 +1,3 @@ +mod command; + +pub use command::Command as PleaseCommand; diff --git a/crates/cuddle-please-misc/Cargo.toml b/crates/cuddle-please-misc/Cargo.toml new file mode 100644 index 0000000..2ed5cca --- /dev/null +++ b/crates/cuddle-please-misc/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "cuddle-please-misc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +clap.workspace = true +dotenv.workspace = true +serde_yaml.workspace = true +serde.workspace = true +reqwest = { workspace = true, features = ["blocking", "json"] } +url.workspace = true +semver.workspace = true +conventional_commit_parser.workspace = true +tempdir.workspace = true +git-cliff-core.workspace = true +regex.workspace = true +chrono.workspace = true +lazy_static.workspace = true +parse-changelog.workspace = true + +[dev-dependencies] +tracing-test = { workspace = true, features = ["no-env-filter"] } +pretty_assertions.workspace = true diff --git a/crates/cuddle-please-misc/src/args.rs b/crates/cuddle-please-misc/src/args.rs new file mode 100644 index 0000000..de50609 --- /dev/null +++ b/crates/cuddle-please-misc/src/args.rs @@ -0,0 +1,38 @@ +use std::sync::{Arc, Mutex}; + +use clap::Args; + +pub type StdinFn = Option anyhow::Result + Send + Sync + 'static>>>; + +#[derive(Args)] +pub struct GlobalArgs { + /// token is the personal access token from gitea. + #[arg( + env = "CUDDLE_PLEASE_TOKEN", + long, + long_help = "token is the personal access token from gitea. It requires at least repository write access, it isn't required by default, but for most usecases the flow will fail without it", + global = true, + help_heading = "Global" + )] + pub token: Option, + + /// whether to run in dry run mode (i.e. no pushes or releases) + #[arg(long, global = true, help_heading = "Global")] + pub dry_run: bool, + + /// Inject configuration from stdin + #[arg( + env = "CUDDLE_PLEASE_CONFIG_STDIN", + long, + global = true, + help_heading = "Global", + long_help = "inject via stdin +cat < anyhow::Result + Send + Sync + 'static>>>; - -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -pub struct Command { - #[command(flatten)] - global: GlobalArgs, - - #[command(flatten)] - config: ConfigArgs, - - #[command(subcommand)] - commands: Option, - - #[clap(skip)] - ui: DynUi, - - #[clap(skip)] - stdin: StdinFn, -} - -#[derive(Args)] -struct GlobalArgs { - /// token is the personal access token from gitea. - #[arg( - env = "CUDDLE_PLEASE_TOKEN", - long, - long_help = "token is the personal access token from gitea. It requires at least repository write access, it isn't required by default, but for most usecases the flow will fail without it", - global = true, - help_heading = "Global" - )] - token: Option, - - /// whether to run in dry run mode (i.e. no pushes or releases) - #[arg(long, global = true, help_heading = "Global")] - dry_run: bool, - - /// Inject configuration from stdin - #[arg( - env = "CUDDLE_PLEASE_CONFIG_STDIN", - long, - global = true, - help_heading = "Global", - long_help = "inject via stdin -cat < Self { - Self::new() - } -} - -impl Command { - pub fn new() -> Self { - let args = std::env::args(); - - Self::new_from_args_with_stdin(Some(ConsoleUi::default()), args, || { - let mut input = String::new(); - std::io::stdin().read_to_string(&mut input)?; - Ok(input) - }) - } - - pub fn new_from_args(ui: Option, i: I) -> Self - where - I: IntoIterator, - T: Into + Clone, - UIF: Into, - { - let mut s = Self::parse_from(i); - - if let Some(ui) = ui { - s.ui = ui.into(); - } - - s - } - - pub fn new_from_args_with_stdin(ui: Option, i: I, input: F) -> Self - where - I: IntoIterator, - T: Into + Clone, - F: Fn() -> anyhow::Result + Send + Sync + 'static, - UIF: Into, - { - let mut s = Self::parse_from(i); - - if let Some(ui) = ui { - s.ui = ui.into(); - } - s.stdin = Some(Arc::new(Mutex::new(input))); - - s - } - - pub fn execute(self, current_dir: Option<&Path>) -> anyhow::Result<()> { - // 0. Get config - let mut builder = &mut PleaseConfigBuilder::new(); - - if self.global.config_stdin { - if let Some(stdin_fn) = self.stdin.clone() { - let output = (stdin_fn.lock().unwrap().deref())(); - builder = builder.with_stdin(output?); - } - } - // 1. Parse the current directory - let current_dir = get_current_path(current_dir, self.config.source.clone())?; - let config = builder - .with_config_file(¤t_dir) - .with_execution_env(std::env::vars()) - .with_cli(self.config.clone()) - .build()?; - - 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 = - cliff::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 - } - } - }; - } - - Some(Commands::Config { command }) => match command { - ConfigCommand::List { .. } => { - tracing::debug!("running command: config list"); - - self.ui.write_str_ln("cuddle-config"); - } - }, - Some(Commands::Gitea { command }) => { - let git_url = url::Url::parse(config.get_api_url())?; - - let mut url = String::new(); - url.push_str(git_url.scheme()); - url.push_str("://"); - url.push_str(&git_url.host().unwrap().to_string()); - if let Some(port) = git_url.port() { - url.push_str(format!(":{port}").as_str()); - } - - let client = GiteaClient::new(url, self.global.token); - match command { - GiteaCommand::Connect {} => { - client.connect(config.get_owner(), config.get_repository())?; - self.ui.write_str_ln("connected succesfully go gitea"); - } - GiteaCommand::Tags { command } => match command { - Some(GiteaTagsCommand::MostSignificant {}) => { - let tags = - client.get_tags(config.get_owner(), config.get_repository())?; - - match get_most_significant_version(tags.iter().collect()) { - Some(tag) => { - self.ui.write_str_ln(&format!( - "found most significant tags: {}", - tag.name - )); - } - None => { - self.ui.write_str_ln("found no tags with versioning schema"); - } - } - } - None => { - let tags = - client.get_tags(config.get_owner(), config.get_repository())?; - self.ui.write_str_ln("got tags from gitea"); - for tag in tags { - self.ui.write_str_ln(&format!("- {}", tag.name)) - } - } - }, - GiteaCommand::SinceCommit { sha, branch } => { - let commits = client.get_commits_since( - config.get_owner(), - config.get_repository(), - Some(sha), - branch, - )?; - self.ui.write_str_ln("got commits from gitea"); - for commit in commits { - self.ui.write_str_ln(&format!("- {}", commit.get_title())) - } - } - GiteaCommand::CheckPr {} => { - let pr = - client.get_pull_request(config.get_owner(), config.get_repository())?; - - match pr { - Some(index) => { - self.ui.write_str_ln(&format!( - "found cuddle-please (index={}) pr from gitea", - index - )); - } - None => { - self.ui.write_str_ln("found no cuddle-please pr from gitea"); - } - } - } - } - } - Some(Commands::Doctor {}) => { - match std::process::Command::new("git").arg("-v").output() { - Ok(o) => { - let stdout = std::str::from_utf8(&o.stdout).unwrap_or(""); - self.ui.write_str_ln(&format!("OK: {}", stdout)); - } - Err(e) => { - self.ui - .write_str_ln(&format!("WARNING: git is not installed: {}", e)); - } - } - } - None => {} - } - - Ok(()) - } - - fn get_git(&self, current_dir: &Path) -> anyhow::Result { - 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(), - ) - } -} - -#[derive(Debug, Clone, Subcommand)] -enum Commands { - /// Config is mostly used for debugging the final config output - Release {}, - - #[command(hide = true)] - Config { - #[command(subcommand)] - command: ConfigCommand, - }, - - #[command(hide = true)] - Gitea { - #[command(subcommand)] - command: GiteaCommand, - }, - /// Helps you identify missing things from your execution environment for cuddle-please to function as intended - Doctor {}, -} - -#[derive(Subcommand, Debug, Clone)] -enum ConfigCommand { - /// List will list the final configuration - List {}, -} - -#[derive(Subcommand, Debug, Clone)] -enum GiteaCommand { - Connect {}, - Tags { - #[command(subcommand)] - command: Option, - }, - SinceCommit { - #[arg(long)] - sha: String, - - #[arg(long)] - branch: String, - }, - CheckPr {}, -} - -#[derive(Subcommand, Debug, Clone)] -enum GiteaTagsCommand { - MostSignificant {}, -} - -fn get_current_path( - optional_current_dir: Option<&Path>, - optional_source_path: Option, -) -> anyhow::Result { - let path = optional_source_path - .or_else(|| optional_current_dir.map(|p| p.to_path_buf())) // fall back on current env from environment - .filter(|v| v.to_string_lossy() != "") // make sure we don't get empty values - //.and_then(|p| p.canonicalize().ok()) // Make sure we get the absolute path - //.context("could not find current dir, pass --source as a replacement")?; - .unwrap_or(PathBuf::from(".")); - - if !path.exists() { - anyhow::bail!("path doesn't exist {}", path.display()); - } - - Ok(path) -} diff --git a/crates/cuddle-please/src/lib.rs b/crates/cuddle-please/src/lib.rs deleted file mode 100644 index 0d35dfa..0000000 --- a/crates/cuddle-please/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod cliff; -pub mod command; -pub mod git_client; -pub mod gitea_client; -pub mod ui; -pub mod versioning; diff --git a/crates/cuddle-please/src/main.rs b/crates/cuddle-please/src/main.rs index 5f20b40..5f3e099 100644 --- a/crates/cuddle-please/src/main.rs +++ b/crates/cuddle-please/src/main.rs @@ -1,11 +1,4 @@ -pub mod cliff; -pub mod command; -pub mod git_client; -pub mod gitea_client; -pub mod ui; -pub mod versioning; - -use command::Command; +use cuddle_please_commands::PleaseCommand; fn main() -> anyhow::Result<()> { dotenv::dotenv().ok(); @@ -14,7 +7,7 @@ fn main() -> anyhow::Result<()> { let current_dir = std::env::current_dir().ok(); let current_dir = current_dir.as_deref(); - Command::new().execute(current_dir)?; + PleaseCommand::new().execute(current_dir)?; Ok(()) } diff --git a/crates/cuddle-please/tests/common/mod.rs b/crates/cuddle-please/tests/common/mod.rs index d66e3f6..68db3ac 100644 --- a/crates/cuddle-please/tests/common/mod.rs +++ b/crates/cuddle-please/tests/common/mod.rs @@ -1,4 +1,4 @@ -use cuddle_please::ui::{DynUi, Ui}; +use cuddle_please_misc::{DynUi, Ui}; use std::{ io::Write, diff --git a/crates/cuddle-please/tests/config.rs b/crates/cuddle-please/tests/config.rs index 6057eb1..238d237 100644 --- a/crates/cuddle-please/tests/config.rs +++ b/crates/cuddle-please/tests/config.rs @@ -1,7 +1,7 @@ pub mod common; use common::BufferUi; -use cuddle_please::command::Command; +use cuddle_please_commands::PleaseCommand; use tracing_test::traced_test; use crate::common::{assert_output, get_test_data_path}; @@ -17,7 +17,7 @@ fn test_config_from_current_dir() { let ui = &BufferUi::default(); let current_dir = get_test_data_path("cuddle-embed"); - Command::new_from_args(Some(ui), args) + PleaseCommand::new_from_args(Some(ui), args) .execute(Some(¤t_dir)) .unwrap(); @@ -33,7 +33,7 @@ fn test_config_from_source_dir() { args.push("--source"); args.push(current_dir.to_str().unwrap()); - Command::new_from_args(Some(ui), args) + PleaseCommand::new_from_args(Some(ui), args) .execute(None) .unwrap(); @@ -55,7 +55,7 @@ settings: "#; args.push("--config-stdin"); - Command::new_from_args_with_stdin(Some(ui), args, || Ok(config.into())) + PleaseCommand::new_from_args_with_stdin(Some(ui), args, || Ok(config.into())) .execute(None) .unwrap(); assert_output(ui, "cuddle-config\n", ""); @@ -67,7 +67,7 @@ fn test_config_fails_when_not_path_is_set() { let args = get_base_args(); let ui = &BufferUi::default(); - let res = Command::new_from_args(Some(ui), args).execute(None); + let res = PleaseCommand::new_from_args(Some(ui), args).execute(None); assert!(res.is_err()) } diff --git a/crates/cuddle-please/tests/git.rs b/crates/cuddle-please/tests/git.rs index a84bd83..f123965 100644 --- a/crates/cuddle-please/tests/git.rs +++ b/crates/cuddle-please/tests/git.rs @@ -1,6 +1,6 @@ use std::path::Path; -use cuddle_please::git_client::VcsClient; +use cuddle_please_misc::VcsClient; use pretty_assertions::assert_eq; use tracing_test::traced_test; diff --git a/crates/cuddle-please/tests/vcs.rs b/crates/cuddle-please/tests/vcs.rs index ca099a9..0575160 100644 --- a/crates/cuddle-please/tests/vcs.rs +++ b/crates/cuddle-please/tests/vcs.rs @@ -1,6 +1,6 @@ pub mod common; -use cuddle_please::git_client::VcsClient; +use cuddle_please_misc::VcsClient; use tracing_test::traced_test; use crate::common::get_test_data_path;