From 789557e8fc502eba4db5ab3374b3a66d27f64596 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Thu, 5 Sep 2024 09:41:17 +0100 Subject: [PATCH] feat: optionally specify max commits between dev and main The default is 25. Closes kemitix/git-next#121 --- crates/cli/README.md | 5 +- crates/cli/src/repo/tests/given.rs | 17 +++ crates/core/src/config/commit_count.rs | 4 + crates/core/src/config/common.rs | 1 + crates/core/src/config/forge_config.rs | 7 + crates/core/src/config/forge_details.rs | 23 ++-- crates/core/src/config/mod.rs | 2 + crates/core/src/config/tests.rs | 127 +++++++++++++++--- crates/core/src/git/repo_details.rs | 8 +- crates/core/src/git/repository/factory.rs | 5 +- crates/core/src/git/repository/mod.rs | 7 +- crates/core/src/git/repository/open/mod.rs | 18 ++- crates/core/src/git/repository/open/oreal.rs | 27 ++-- crates/core/src/git/repository/open/otest.rs | 5 +- .../git/repository/open/tests/commit_log.rs | 9 +- .../git/repository/open/tests/forge_config.rs | 54 +++++++- .../git/repository/open/tests/read_file.rs | 6 +- crates/core/src/git/repository/test.rs | 4 +- crates/core/src/git/tests.rs | 26 +++- crates/core/src/git/validation/tests.rs | 18 ++- crates/forge-forgejo/src/tests.rs | 17 +++ crates/forge-github/src/tests/mod.rs | 17 +++ 22 files changed, 337 insertions(+), 70 deletions(-) create mode 100644 crates/core/src/config/commit_count.rs diff --git a/crates/cli/README.md b/crates/cli/README.md index a3e06e4..d0a04db 100644 --- a/crates/cli/README.md +++ b/crates/cli/README.md @@ -198,13 +198,14 @@ forge_type = "GitHub" hostname = "github.com" user = "username" token = "api-key" +max_dev_commits = 25 ``` - **forge_type** - one of: `ForgeJo` or `GitHub` - **hostname** - the hostname for the forge. - **user** - the user to authenticate as -- **token** - application token for the user. See below for the permissions - required for on each forge. +- **token** - application token for the user. See [Forges](#forges) below for the permissions required for each forge. +- **max_dev_commits** - [optional] the maximum number of commits allowed between `dev` and `main`. Defaults to 25. Generally, the `user` will need to be able to push to `main` and to _force-push_ to `next`. diff --git a/crates/cli/src/repo/tests/given.rs b/crates/cli/src/repo/tests/given.rs index c0a6b91..5fbab55 100644 --- a/crates/cli/src/repo/tests/given.rs +++ b/crates/cli/src/repo/tests/given.rs @@ -69,6 +69,22 @@ pub fn a_name() -> String { generate(5) } +pub fn maybe_a_number() -> Option { + use rand::Rng; + let mut rng = rand::thread_rng(); + if Rng::gen_ratio(&mut rng, 1, 2) { + Some(a_number()) + } else { + None + } +} + +pub fn a_number() -> u32 { + use rand::Rng; + let mut rng = rand::thread_rng(); + rng.gen_range(0..100) +} + pub fn a_webhook_id() -> WebhookId { WebhookId::new(a_name()) } @@ -89,6 +105,7 @@ pub fn a_forge_config() -> ForgeConfig { a_name(), a_name(), a_name(), + maybe_a_number(), BTreeMap::default(), // no repos ) } diff --git a/crates/core/src/config/commit_count.rs b/crates/core/src/config/commit_count.rs new file mode 100644 index 0000000..ef3e0d9 --- /dev/null +++ b/crates/core/src/config/commit_count.rs @@ -0,0 +1,4 @@ +// +use crate::newtype; + +newtype!(CommitCount, u32, Default, "A number of commits"); diff --git a/crates/core/src/config/common.rs b/crates/core/src/config/common.rs index 74c7242..3b37951 100644 --- a/crates/core/src/config/common.rs +++ b/crates/core/src/config/common.rs @@ -11,6 +11,7 @@ pub fn forge_details(n: u32, forge_type: ForgeType) -> ForgeDetails { hostname(n), user(n), api_token(n), + None, ) } diff --git a/crates/core/src/config/forge_config.rs b/crates/core/src/config/forge_config.rs index 832b0d1..7116be3 100644 --- a/crates/core/src/config/forge_config.rs +++ b/crates/core/src/config/forge_config.rs @@ -2,6 +2,8 @@ use std::collections::BTreeMap; use crate::config::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User}; +use super::CommitCount; + /// Defines a Forge to connect to /// Maps from `git-next-server.toml` at `forge.{forge}` #[derive( @@ -22,6 +24,7 @@ pub struct ForgeConfig { hostname: String, user: String, token: String, + max_dev_commits: Option, repos: BTreeMap, } impl ForgeConfig { @@ -41,6 +44,10 @@ impl ForgeConfig { ApiToken::new(self.token.clone().into()) } + pub(crate) fn max_dev_commits(&self) -> Option { + self.max_dev_commits.map(CommitCount::from) + } + pub fn repos(&self) -> impl Iterator { self.repos .iter() diff --git a/crates/core/src/config/forge_details.rs b/crates/core/src/config/forge_details.rs index b05ef6d..3dda4e8 100644 --- a/crates/core/src/config/forge_details.rs +++ b/crates/core/src/config/forge_details.rs @@ -1,5 +1,7 @@ use crate::config::{ApiToken, ForgeAlias, ForgeConfig, ForgeType, Hostname, User}; +use super::CommitCount; + /// The derived information about a Forge, used to create interactions with it #[derive(Clone, Default, Debug, derive_more::Constructor, derive_with::With)] pub struct ForgeDetails { @@ -8,8 +10,7 @@ pub struct ForgeDetails { hostname: Hostname, user: User, token: ApiToken, - // API Token - // Private SSH Key Path + max_dev_commits: Option, } impl ForgeDetails { #[must_use] @@ -35,15 +36,21 @@ impl ForgeDetails { pub const fn token(&self) -> &ApiToken { &self.token } + + #[must_use] + pub const fn max_dev_commits(&self) -> Option<&CommitCount> { + self.max_dev_commits.as_ref() + } } impl From<(&ForgeAlias, &ForgeConfig)> for ForgeDetails { - fn from(forge: (&ForgeAlias, &ForgeConfig)) -> Self { + fn from((forge_alias, forge_config): (&ForgeAlias, &ForgeConfig)) -> Self { Self { - forge_alias: forge.0.clone(), - forge_type: forge.1.forge_type(), - hostname: forge.1.hostname(), - user: forge.1.user(), - token: forge.1.token(), + forge_alias: forge_alias.clone(), + forge_type: forge_config.forge_type(), + hostname: forge_config.hostname(), + user: forge_config.user(), + token: forge_config.token(), + max_dev_commits: forge_config.max_dev_commits(), } } } diff --git a/crates/core/src/config/mod.rs b/crates/core/src/config/mod.rs index 4f1e479..9f6c82b 100644 --- a/crates/core/src/config/mod.rs +++ b/crates/core/src/config/mod.rs @@ -1,6 +1,7 @@ // mod api_token; mod branch_name; +mod commit_count; pub mod common; mod forge_alias; mod forge_config; @@ -26,6 +27,7 @@ mod tests; pub use api_token::ApiToken; pub use branch_name::BranchName; +pub use commit_count::CommitCount; pub use forge_alias::ForgeAlias; #[allow(clippy::module_name_repetitions)] pub use forge_config::ForgeConfig; diff --git a/crates/core/src/config/tests.rs b/crates/core/src/config/tests.rs index 3f34607..3765004 100644 --- a/crates/core/src/config/tests.rs +++ b/crates/core/src/config/tests.rs @@ -149,6 +149,8 @@ mod repo_config { } } mod forge_config { + use given::maybe_a_number; + use super::*; #[test] @@ -166,7 +168,7 @@ mod forge_config { let mut repos = BTreeMap::new(); repos.insert(red_name.clone(), red.clone()); repos.insert(blue_name.clone(), blue.clone()); - let fc = ForgeConfig::new(forge_type, hostname, user, token, repos); + let fc = ForgeConfig::new(forge_type, hostname, user, token, maybe_a_number(), repos); let returned_repos = fc.repos().collect::>(); @@ -186,7 +188,7 @@ mod forge_config { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname, user, token, repos); + let fc = ForgeConfig::new(forge_type, hostname, user, token, maybe_a_number(), repos); assert_eq!(fc.forge_type(), ForgeType::MockForge); } @@ -197,7 +199,14 @@ mod forge_config { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname.clone(), user, token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname.clone(), + user, + token, + maybe_a_number(), + repos, + ); assert_eq!(fc.hostname(), Hostname::new(hostname)); } @@ -208,7 +217,14 @@ mod forge_config { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname, user.clone(), token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user.clone(), + token, + maybe_a_number(), + repos, + ); assert_eq!(fc.user(), User::new(user)); } @@ -219,7 +235,14 @@ mod forge_config { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname, user, token.clone(), repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user, + token.clone(), + maybe_a_number(), + repos, + ); assert_eq!(fc.token().expose_secret(), token.as_str()); } @@ -237,7 +260,7 @@ mod forge_config { let mut repos = BTreeMap::new(); repos.insert(red_name.clone(), red.clone()); repos.insert(blue_name, blue); - let fc = ForgeConfig::new(forge_type, hostname, user, token, repos); + let fc = ForgeConfig::new(forge_type, hostname, user, token, maybe_a_number(), repos); let returned_repo = fc.get_repo(red_name.as_str()); @@ -255,8 +278,14 @@ mod forge_details { let user = User::new(given::a_name()); let token = ApiToken::new(given::a_name().into()); let forge_alias = ForgeAlias::new(given::a_name()); - let forge_details = - ForgeDetails::new(forge_alias.clone(), forge_type, hostname, user, token); + let forge_details = ForgeDetails::new( + forge_alias.clone(), + forge_type, + hostname, + user, + token, + given::maybe_a_number().map(CommitCount::from), + ); let result = forge_details.forge_alias(); @@ -269,7 +298,14 @@ mod forge_details { let user = User::new(given::a_name()); let token = ApiToken::new(given::a_name().into()); let forge_name = ForgeAlias::new(given::a_name()); - let forge_details = ForgeDetails::new(forge_name, forge_type, hostname, user, token); + let forge_details = ForgeDetails::new( + forge_name, + forge_type, + hostname, + user, + token, + given::maybe_a_number().map(CommitCount::from), + ); let result = forge_details.forge_type(); @@ -282,8 +318,14 @@ mod forge_details { let user = User::new(given::a_name()); let token = ApiToken::new(given::a_name().into()); let forge_name = ForgeAlias::new(given::a_name()); - let forge_details = - ForgeDetails::new(forge_name, forge_type, hostname.clone(), user, token); + let forge_details = ForgeDetails::new( + forge_name, + forge_type, + hostname.clone(), + user, + token, + given::maybe_a_number().map(CommitCount::from), + ); let result = forge_details.hostname(); @@ -296,8 +338,14 @@ mod forge_details { let user = User::new(given::a_name()); let token = ApiToken::new(given::a_name().into()); let forge_name = ForgeAlias::new(given::a_name()); - let forge_details = - ForgeDetails::new(forge_name, forge_type, hostname, user.clone(), token); + let forge_details = ForgeDetails::new( + forge_name, + forge_type, + hostname, + user.clone(), + token, + given::maybe_a_number().map(CommitCount::from), + ); let result = forge_details.user(); @@ -310,8 +358,14 @@ mod forge_details { let user = User::new(given::a_name()); let token = ApiToken::new(given::a_name().into()); let forge_name = ForgeAlias::new(given::a_name()); - let forge_details = - ForgeDetails::new(forge_name, forge_type, hostname, user, token.clone()); + let forge_details = ForgeDetails::new( + forge_name, + forge_type, + hostname, + user, + token.clone(), + given::maybe_a_number().map(CommitCount::from), + ); let result = forge_details.token(); @@ -325,7 +379,14 @@ mod forge_details { let user = User::new(given::a_name()); let token = ApiToken::new(given::a_name().into()); let forge_name = ForgeAlias::new(given::a_name()); - let forge_details = ForgeDetails::new(forge_name, forge_type, hostname, user, token); + let forge_details = ForgeDetails::new( + forge_name, + forge_type, + hostname, + user, + token, + given::maybe_a_number().map(CommitCount::from), + ); let result = forge_details.with_hostname(other_hostname.clone()); @@ -340,12 +401,14 @@ mod forge_details { let user = User::new(user_value.clone()); let token_value = given::a_name(); let token = ApiToken::new(token_value.clone().into()); + let max_dev_commits = given::maybe_a_number(); let forge_alias = ForgeAlias::new(given::a_name()); let forge_config = ForgeConfig::new( forge_type, hostname_value, user_value, token_value, + max_dev_commits, BTreeMap::new(), ); @@ -355,6 +418,12 @@ mod forge_details { assert_eq!(forge_details.hostname(), &hostname); assert_eq!(forge_details.user(), &user); assert_eq!(forge_details.token().expose_secret(), token.expose_secret()); + assert_eq!( + forge_details + .max_dev_commits() + .map(|commit_count| commit_count.clone().peel()), + max_dev_commits + ); } } mod forge_name { @@ -450,6 +519,7 @@ mod server { use super::*; #[test] + // TODO: use rstest to make sure we test all combinations fn load_should_parse_app_config() -> TestResult { let app_config = given::an_app_config(); let fs = kxio::fs::temp()?; @@ -492,6 +562,12 @@ mod server { let forge_hostname = forge_default.hostname(); let forge_user = forge_default.user(); let forge_token = forge_default.token().expose_secret().to_string(); + let optional_max_dev_commits = forge_default + .max_dev_commits() + .map(CommitCount::peel) + .map_or_else(String::new, |max_dev_commits| { + format!("max_dev_commits = {max_dev_commits}") + }); let mut repos: Vec = vec![]; for (repo_alias, server_repo_config) in forge_default.repos() { let repo_path = server_repo_config.repo(); @@ -542,6 +618,7 @@ forge_type = "{forge_type}" hostname = "{forge_hostname}" user = "{forge_user}" token = "{forge_token}" +{optional_max_dev_commits} [forge.{forge_alias}.repos] {repos} @@ -726,6 +803,23 @@ mod given { } generate(5) } + + pub fn a_number() -> u32 { + use rand::Rng; + let mut rng = rand::thread_rng(); + rng.gen_range(0..100) + } + + pub fn maybe_a_number() -> Option { + use rand::Rng; + let mut rng = rand::thread_rng(); + if Rng::gen_ratio(&mut rng, 1, 2) { + Some(a_number()) + } else { + None + } + } + pub fn an_app_config() -> AppConfig { AppConfig::new( a_listen(), @@ -785,6 +879,7 @@ mod given { a_name(), // hostname a_name(), // user a_name(), // token + maybe_a_number(), some_server_repo_configs(), ) } diff --git a/crates/core/src/git/repo_details.rs b/crates/core/src/git/repo_details.rs index fc39711..ba100ff 100644 --- a/crates/core/src/git/repo_details.rs +++ b/crates/core/src/git/repo_details.rs @@ -49,6 +49,7 @@ impl RepoDetails { forge_config.hostname(), forge_config.user(), forge_config.token(), + forge_config.max_dev_commits(), ), } } @@ -94,12 +95,7 @@ impl RepoDetails { |> GitDir::pathbuf |> gix::ThreadSafeRepository::open }?; - let repo = pike! { - gix_repo - |> RwLock::new - |> Arc::new - |> RealOpenRepository::new - }; + let repo = RealOpenRepository::new(Arc::new(RwLock::new(gix_repo)), self.forge.clone()); Ok(repo) } diff --git a/crates/core/src/git/repository/factory.rs b/crates/core/src/git/repository/factory.rs index 6ad30c5..31f6edb 100644 --- a/crates/core/src/git/repository/factory.rs +++ b/crates/core/src/git/repository/factory.rs @@ -66,7 +66,10 @@ impl RepositoryFactory for RealRepositoryFactory { )? .fetch_only(gix::progress::Discard, &AtomicBool::new(false))?; tracing::info!("created"); - let repo = RealOpenRepository::new(Arc::new(RwLock::new(gix_repo.into()))); + let repo = RealOpenRepository::new( + Arc::new(RwLock::new(gix_repo.into())), + repo_details.forge.clone(), + ); Ok(Box::new(repo)) } diff --git a/crates/core/src/git/repository/mod.rs b/crates/core/src/git/repository/mod.rs index a9ae6de..fd038f2 100644 --- a/crates/core/src/git/repository/mod.rs +++ b/crates/core/src/git/repository/mod.rs @@ -31,8 +31,11 @@ pub enum Repository { } #[cfg(test)] -pub(crate) const fn test(fs: kxio::fs::FileSystem) -> TestRepository { - TestRepository::new(fs, vec![], vec![]) +pub(crate) const fn test( + fs: kxio::fs::FileSystem, + forge_details: crate::ForgeDetails, +) -> TestRepository { + TestRepository::new(fs, vec![], vec![], forge_details) } /// Opens a repository, cloning if necessary diff --git a/crates/core/src/git/repository/open/mod.rs b/crates/core/src/git/repository/open/mod.rs index 74f25b0..df06d81 100644 --- a/crates/core/src/git/repository/open/mod.rs +++ b/crates/core/src/git/repository/open/mod.rs @@ -37,10 +37,11 @@ pub enum OpenRepository { } #[cfg(not(tarpaulin_include))] -pub fn real(gix_repo: gix::Repository) -> OpenRepository { - OpenRepository::Real(oreal::RealOpenRepository::new(Arc::new(RwLock::new( - gix_repo.into(), - )))) +pub fn real(gix_repo: gix::Repository, forge_details: crate::ForgeDetails) -> OpenRepository { + OpenRepository::Real(oreal::RealOpenRepository::new( + Arc::new(RwLock::new(gix_repo.into())), + forge_details, + )) } #[cfg(not(tarpaulin_include))] // don't test mocks @@ -49,8 +50,15 @@ pub(crate) fn test( fs: &kxio::fs::FileSystem, on_fetch: Vec, on_push: Vec, + forge_details: crate::ForgeDetails, ) -> OpenRepository { - OpenRepository::Test(TestOpenRepository::new(gitdir, fs, on_fetch, on_push)) + OpenRepository::Test(TestOpenRepository::new( + gitdir, + fs, + on_fetch, + on_push, + forge_details, + )) } #[allow(clippy::module_name_repetitions)] diff --git a/crates/core/src/git/repository/open/oreal.rs b/crates/core/src/git/repository/open/oreal.rs index 77b000d..58414bf 100644 --- a/crates/core/src/git/repository/open/oreal.rs +++ b/crates/core/src/git/repository/open/oreal.rs @@ -1,7 +1,7 @@ // use crate::{ git::{self, repository::OpenRepositoryLike}, - BranchName, Hostname, RemoteUrl, RepoPath, + BranchName, ForgeDetails, Hostname, RemoteUrl, RepoPath, }; use derive_more::Constructor; @@ -16,11 +16,14 @@ use std::{ }; #[derive(Clone, Debug, Constructor)] -pub struct RealOpenRepository(Arc>); +pub struct RealOpenRepository { + inner: Arc>, + forge_details: ForgeDetails, +} impl super::OpenRepositoryLike for RealOpenRepository { fn remote_branches(&self) -> git::push::Result> { let refs = self - .0 + .inner .read() .map_err(|_| git::push::Error::Lock) .and_then(|repo| { @@ -44,7 +47,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { #[tracing::instrument] fn find_default_remote(&self, direction: git::repository::Direction) -> Option { - let Ok(repository) = self.0.read() else { + let Ok(repository) = self.inner.read() else { #[cfg(not(tarpaulin_include))] // don't test mutex lock failure tracing::debug!("no repository"); return None; @@ -66,7 +69,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { fn fetch(&self) -> Result<(), git::fetch::Error> { use std::sync::atomic::AtomicBool; - let Ok(repository) = self.0.read() else { + let Ok(repository) = self.inner.read() else { #[cfg(not(tarpaulin_include))] // don't test mutex lock failure return Err(git::fetch::Error::Lock); }; @@ -117,7 +120,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { ) .into(); let git_dir = self - .0 + .inner .read() .map_err(|_| git::push::Error::Lock) .map(|r| r.git_dir().to_path_buf())?; @@ -140,8 +143,14 @@ impl super::OpenRepositoryLike for RealOpenRepository { branch_name: &BranchName, find_commits: &[git::Commit], ) -> Result, git::commit::log::Error> { - let limit = if find_commits.is_empty() { 1 } else { 25 }; - self.0 + let limit: usize = if find_commits.is_empty() { + 1 + } else { + self.forge_details + .max_dev_commits() + .map_or(25, |commit_count| commit_count.clone().peel() as usize) + }; + self.inner .read() .map_err(|_| git::commit::log::Error::Lock) .map(|repo| { @@ -196,7 +205,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { #[tracing::instrument(skip_all, fields(%branch_name, ?file_name))] fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result { - self.0 + self.inner .read() .map_err(|_| git::file::Error::Lock) .and_then(|repo| { diff --git a/crates/core/src/git/repository/open/otest.rs b/crates/core/src/git/repository/open/otest.rs index f36c3f9..dd4ac19 100644 --- a/crates/core/src/git/repository/open/otest.rs +++ b/crates/core/src/git/repository/open/otest.rs @@ -4,7 +4,7 @@ use crate::{ self, repository::open::{OpenRepositoryLike, RealOpenRepository}, }, - BranchName, GitDir, RemoteUrl, RepoBranches, + BranchName, ForgeDetails, GitDir, RemoteUrl, RepoBranches, }; use derive_more::Constructor; @@ -155,6 +155,7 @@ impl TestOpenRepository { fs: &kxio::fs::FileSystem, on_fetch: Vec, on_push: Vec, + forge_details: ForgeDetails, ) -> Self { let pathbuf = fs.base().join(gitdir.to_path_buf()); #[allow(clippy::expect_used)] @@ -165,7 +166,7 @@ impl TestOpenRepository { fetch_counter: Arc::new(RwLock::new(0)), on_push, push_counter: Arc::new(RwLock::new(0)), - real: RealOpenRepository::new(Arc::new(RwLock::new(gix.into()))), + real: RealOpenRepository::new(Arc::new(RwLock::new(gix.into())), forge_details), } } diff --git a/crates/core/src/git/repository/open/tests/commit_log.rs b/crates/core/src/git/repository/open/tests/commit_log.rs index b1f9bc5..38a7653 100644 --- a/crates/core/src/git/repository/open/tests/commit_log.rs +++ b/crates/core/src/git/repository/open/tests/commit_log.rs @@ -6,7 +6,8 @@ use super::*; fn should_return_single_item_in_commit_log_when_not_searching() -> TestResult { let_assert!(Ok(fs) = kxio::fs::temp()); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let test_repository = git::repository::test(fs.clone(), forge_details); let_assert!(Ok(open_repository) = test_repository.open(&gitdir)); let repo_config = &given::a_repo_config(); let branches = repo_config.branches(); @@ -23,7 +24,8 @@ fn should_return_capacity_25_in_commit_log_when_searching_for_garbage() -> TestR let_assert!(Ok(fs) = kxio::fs::temp()); let branch_name = given::a_branch_name(); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let test_repository = git::repository::test(fs.clone(), forge_details); let_assert!(Ok(open_repository) = test_repository.open(&gitdir)); for _ in [0; 25] { then::create_a_commit_on_branch(&fs, &gitdir, &branch_name)?; @@ -39,7 +41,8 @@ fn should_return_5_in_commit_log_when_searching_for_5th_item() -> TestResult { let_assert!(Ok(fs) = kxio::fs::temp(), "create temp directory"); let branch_name = given::a_branch_name(); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let test_repository = git::repository::test(fs.clone(), forge_details); let_assert!( Ok(open_repository) = test_repository.open(&gitdir), "open repository" diff --git a/crates/core/src/git/repository/open/tests/forge_config.rs b/crates/core/src/git/repository/open/tests/forge_config.rs index c433920..7c980f7 100644 --- a/crates/core/src/git/repository/open/tests/forge_config.rs +++ b/crates/core/src/git/repository/open/tests/forge_config.rs @@ -14,7 +14,14 @@ fn should_return_repos() { let mut repos = BTreeMap::new(); repos.insert(red_name.clone(), red.clone()); repos.insert(blue_name.clone(), blue.clone()); - let fc = ForgeConfig::new(forge_type, hostname, user, token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user, + token, + given::maybe_a_number(), + repos, + ); let returned_repos = fc.repos().collect::>(); @@ -35,7 +42,14 @@ fn should_return_forge_type() { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname, user, token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user, + token, + given::maybe_a_number(), + repos, + ); assert_eq!(fc.forge_type(), ForgeType::MockForge); } @@ -47,7 +61,14 @@ fn should_return_hostname() { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname.clone(), user, token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname.clone(), + user, + token, + given::maybe_a_number(), + repos, + ); assert_eq!(fc.hostname(), Hostname::new(hostname)); } @@ -59,7 +80,14 @@ fn should_return_user() { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname, user.clone(), token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user.clone(), + token, + given::maybe_a_number(), + repos, + ); assert_eq!(fc.user(), User::new(user)); } @@ -71,7 +99,14 @@ fn should_return_token() { let user = given::a_name(); let token = given::a_name(); let repos = BTreeMap::new(); - let fc = ForgeConfig::new(forge_type, hostname, user, token.clone(), repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user, + token.clone(), + given::maybe_a_number(), + repos, + ); assert_eq!(fc.token().expose_secret(), token.as_str()); } @@ -90,7 +125,14 @@ fn should_return_repo() { let mut repos = BTreeMap::new(); repos.insert(red_name.clone(), red.clone()); repos.insert(blue_name, blue); - let fc = ForgeConfig::new(forge_type, hostname, user, token, repos); + let fc = ForgeConfig::new( + forge_type, + hostname, + user, + token, + given::maybe_a_number(), + repos, + ); let returned_repo = fc.get_repo(red_name.as_str()); diff --git a/crates/core/src/git/repository/open/tests/read_file.rs b/crates/core/src/git/repository/open/tests/read_file.rs index 375ac29..8c7f944 100644 --- a/crates/core/src/git/repository/open/tests/read_file.rs +++ b/crates/core/src/git/repository/open/tests/read_file.rs @@ -9,8 +9,9 @@ fn should_return_file() -> TestResult { let file_name = given::a_pathbuf(); let contents = given::a_name(); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); + let forge_details = given::forge_details(); - let test_repository = git::repository::test(fs.clone()); + let test_repository = git::repository::test(fs.clone(), forge_details); let_assert!(Ok(open_repository) = test_repository.open(&gitdir)); then::commit_named_file_to_branch( &file_name, @@ -33,7 +34,8 @@ fn should_return_file() -> TestResult { fn should_error_on_missing_file() -> TestResult { let_assert!(Ok(fs) = kxio::fs::temp()); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let test_repository = git::repository::test(fs.clone(), forge_details); let_assert!(Ok(open_repository) = test_repository.open(&gitdir)); let repo_config = &given::a_repo_config(); let branches = repo_config.branches(); diff --git a/crates/core/src/git/repository/test.rs b/crates/core/src/git/repository/test.rs index 53e1ae5..44af530 100644 --- a/crates/core/src/git/repository/test.rs +++ b/crates/core/src/git/repository/test.rs @@ -13,7 +13,7 @@ use crate::{ }, RepoDetails, }, - GitDir, + ForgeDetails, GitDir, }; #[allow(clippy::module_name_repetitions)] @@ -22,6 +22,7 @@ pub struct TestRepository { fs: kxio::fs::FileSystem, on_fetch: Vec, on_push: Vec, + forge_details: ForgeDetails, } impl TestRepository { pub fn on_fetch(&mut self, on_fetch: OnFetch) { @@ -39,6 +40,7 @@ impl RepositoryLike for TestRepository { &self.fs, self.on_fetch.clone(), self.on_push.clone(), + self.forge_details.clone(), )) } diff --git a/crates/core/src/git/tests.rs b/crates/core/src/git/tests.rs index 3d17bda..1530ba9 100644 --- a/crates/core/src/git/tests.rs +++ b/crates/core/src/git/tests.rs @@ -172,6 +172,7 @@ mod repo_details { "host".to_string(), "user".to_string(), "token".to_string(), + given::maybe_a_number(), // max dev commits BTreeMap::new(), ), GitDir::new(PathBuf::default().join("foo"), StoragePathType::Internal), @@ -184,6 +185,8 @@ mod repo_details { } } pub mod given { + use crate::ForgeDetails; + use super::*; pub fn repo_branches() -> RepoBranches { @@ -219,6 +222,22 @@ pub mod given { generate(5) } + pub fn maybe_a_number() -> Option { + use rand::Rng; + let mut rng = rand::thread_rng(); + if Rng::gen_ratio(&mut rng, 1, 2) { + Some(a_number()) + } else { + None + } + } + + pub fn a_number() -> u32 { + use rand::Rng; + let mut rng = rand::thread_rng(); + rng.gen_range(0..100) + } + pub fn a_branch_name() -> BranchName { BranchName::new(a_name()) } @@ -235,10 +254,15 @@ pub mod given { format!("hostname-{}", a_name()), format!("user-{}", a_name()), format!("token-{}", a_name()), - BTreeMap::default(), // no repos + given::maybe_a_number(), // max dev commits + BTreeMap::default(), // no repos ) } + pub fn forge_details() -> ForgeDetails { + (&a_forge_alias(), &a_forge_config()).into() + } + pub fn a_server_repo_config() -> ServerRepoConfig { let main = a_branch_name().peel(); let next = a_branch_name().peel(); diff --git a/crates/core/src/git/validation/tests.rs b/crates/core/src/git/validation/tests.rs index 7b17545..12d5fac 100644 --- a/crates/core/src/git/validation/tests.rs +++ b/crates/core/src/git/validation/tests.rs @@ -207,7 +207,8 @@ mod positions { //given let fs = given::a_filesystem(); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let mut test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let mut test_repository = git::repository::test(fs.clone(), forge_details); let repo_config = given::a_repo_config(); test_repository.on_fetch(OnFetch::new( repo_config.branches().clone(), @@ -257,7 +258,8 @@ mod positions { //given let_assert!(Ok(fs) = kxio::fs::temp(), "temp fs"); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let mut test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let mut test_repository = git::repository::test(fs.clone(), forge_details); let repo_config = given::a_repo_config(); test_repository.on_fetch(OnFetch::new( repo_config.branches().clone(), @@ -343,7 +345,8 @@ mod positions { //given let_assert!(Ok(fs) = kxio::fs::temp(), "temp fs"); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let mut test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let mut test_repository = git::repository::test(fs.clone(), forge_details); let repo_config = given::a_repo_config(); test_repository.on_fetch(OnFetch::new( repo_config.branches().clone(), @@ -416,7 +419,8 @@ mod positions { //given let_assert!(Ok(fs) = kxio::fs::temp(), "temp fs"); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let mut test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let mut test_repository = git::repository::test(fs.clone(), forge_details); let repo_config = given::a_repo_config(); test_repository.on_fetch(OnFetch::new( repo_config.branches().clone(), @@ -501,7 +505,8 @@ mod positions { //given let_assert!(Ok(fs) = kxio::fs::temp(), "temp fs"); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let mut test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let mut test_repository = git::repository::test(fs.clone(), forge_details); let repo_config = given::a_repo_config(); test_repository.on_fetch(OnFetch::new( repo_config.branches().clone(), @@ -598,7 +603,8 @@ mod positions { //given let_assert!(Ok(fs) = kxio::fs::temp(), "temp fs"); let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let mut test_repository = git::repository::test(fs.clone()); + let forge_details = given::forge_details(); + let mut test_repository = git::repository::test(fs.clone(), forge_details); let repo_config = given::a_repo_config(); test_repository.on_fetch(OnFetch::new( repo_config.branches().clone(), diff --git a/crates/forge-forgejo/src/tests.rs b/crates/forge-forgejo/src/tests.rs index adbd9d2..46f852a 100644 --- a/crates/forge-forgejo/src/tests.rs +++ b/crates/forge-forgejo/src/tests.rs @@ -691,6 +691,22 @@ mod forgejo { generate(5) } + pub fn maybe_a_number() -> Option { + use rand::Rng; + let mut rng = rand::thread_rng(); + if Rng::gen_ratio(&mut rng, 1, 2) { + Some(a_number()) + } else { + None + } + } + + pub fn a_number() -> u32 { + use rand::Rng; + let mut rng = rand::thread_rng(); + rng.gen_range(0..100) + } + pub fn a_webhook_id() -> WebhookId { WebhookId::new(a_name()) } @@ -711,6 +727,7 @@ mod forgejo { a_name(), a_name(), a_name(), + maybe_a_number(), BTreeMap::default(), // no repos ) } diff --git a/crates/forge-github/src/tests/mod.rs b/crates/forge-github/src/tests/mod.rs index a240a45..99cf0d4 100644 --- a/crates/forge-github/src/tests/mod.rs +++ b/crates/forge-github/src/tests/mod.rs @@ -600,6 +600,7 @@ mod github { a_name(), a_name(), a_name(), + maybe_a_number(), BTreeMap::default(), ), GitDir::new(PathBuf::default(), StoragePathType::External), @@ -641,6 +642,22 @@ mod github { generate(5) } + pub fn maybe_a_number() -> Option { + use rand::Rng; + let mut rng = rand::thread_rng(); + if Rng::gen_ratio(&mut rng, 1, 2) { + Some(a_number()) + } else { + None + } + } + + pub fn a_number() -> u32 { + use rand::Rng; + let mut rng = rand::thread_rng(); + rng.gen_range(0..100) + } + pub fn a_webhook_id() -> WebhookId { WebhookId::new(given::a_name()) }