feat: optionally specify max commits between dev and main
All checks were successful
Rust / build (push) Successful in 6m21s
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
Release Please / Release-plz (push) Successful in 2m9s
All checks were successful
Rust / build (push) Successful in 6m21s
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
Release Please / Release-plz (push) Successful in 2m9s
The default is 25. Closes kemitix/git-next#121
This commit is contained in:
parent
3672fd5d45
commit
e759e495fd
24 changed files with 351 additions and 85 deletions
|
@ -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`.
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
//
|
||||
use git_next_core::{
|
||||
git::{ForgeLike, RepoDetails},
|
||||
ForgeType,
|
||||
};
|
||||
use git_next_core::git::{ForgeLike, RepoDetails};
|
||||
|
||||
#[cfg(feature = "forgejo")]
|
||||
use git_next_forge_forgejo::ForgeJo;
|
||||
|
@ -19,9 +16,9 @@ impl Forge {
|
|||
pub fn create(repo_details: RepoDetails, net: Network) -> Box<dyn ForgeLike> {
|
||||
match repo_details.forge.forge_type() {
|
||||
#[cfg(feature = "forgejo")]
|
||||
ForgeType::ForgeJo => Box::new(ForgeJo::new(repo_details, net)),
|
||||
git_next_core::ForgeType::ForgeJo => Box::new(ForgeJo::new(repo_details, net)),
|
||||
#[cfg(feature = "github")]
|
||||
ForgeType::GitHub => Box::new(Github::new(repo_details, net)),
|
||||
git_next_core::ForgeType::GitHub => Box::new(Github::new(repo_details, net)),
|
||||
_ => {
|
||||
drop(repo_details);
|
||||
drop(net);
|
||||
|
|
|
@ -11,7 +11,7 @@ use git_next_core::{
|
|||
#[test]
|
||||
fn test_forgejo_name() {
|
||||
let net = Network::new_mock();
|
||||
let repo_details = given_repo_details(ForgeType::ForgeJo);
|
||||
let repo_details = given_repo_details(git_next_core::ForgeType::ForgeJo);
|
||||
let forge = Forge::create(repo_details, net);
|
||||
assert_eq!(forge.name(), "forgejo");
|
||||
}
|
||||
|
@ -20,20 +20,17 @@ fn test_forgejo_name() {
|
|||
#[test]
|
||||
fn test_github_name() {
|
||||
let net = Network::new_mock();
|
||||
let repo_details = given_repo_details(ForgeType::GitHub);
|
||||
let repo_details = given_repo_details(git_next_core::ForgeType::GitHub);
|
||||
let forge = Forge::create(repo_details, net);
|
||||
assert_eq!(forge.name(), "github");
|
||||
}
|
||||
|
||||
fn given_fs() -> kxio::fs::FileSystem {
|
||||
kxio::fs::temp().unwrap_or_else(|e| {
|
||||
#[allow(dead_code)]
|
||||
fn given_repo_details(forge_type: git_next_core::ForgeType) -> RepoDetails {
|
||||
let fs = kxio::fs::temp().unwrap_or_else(|e| {
|
||||
println!("{e}");
|
||||
panic!("fs")
|
||||
})
|
||||
}
|
||||
|
||||
fn given_repo_details(forge_type: ForgeType) -> RepoDetails {
|
||||
let fs = given_fs();
|
||||
});
|
||||
git::repo_details(
|
||||
1,
|
||||
git::Generation::default(),
|
||||
|
|
|
@ -69,6 +69,22 @@ pub fn a_name() -> String {
|
|||
generate(5)
|
||||
}
|
||||
|
||||
pub fn maybe_a_number() -> Option<u32> {
|
||||
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
|
||||
)
|
||||
}
|
||||
|
|
4
crates/core/src/config/commit_count.rs
Normal file
4
crates/core/src/config/commit_count.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
//
|
||||
use crate::newtype;
|
||||
|
||||
newtype!(CommitCount, u32, Default, "A number of commits");
|
|
@ -11,6 +11,7 @@ pub fn forge_details(n: u32, forge_type: ForgeType) -> ForgeDetails {
|
|||
hostname(n),
|
||||
user(n),
|
||||
api_token(n),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u32>,
|
||||
repos: BTreeMap<String, ServerRepoConfig>,
|
||||
}
|
||||
impl ForgeConfig {
|
||||
|
@ -41,6 +44,10 @@ impl ForgeConfig {
|
|||
ApiToken::new(self.token.clone().into())
|
||||
}
|
||||
|
||||
pub(crate) fn max_dev_commits(&self) -> Option<CommitCount> {
|
||||
self.max_dev_commits.map(CommitCount::from)
|
||||
}
|
||||
|
||||
pub fn repos(&self) -> impl Iterator<Item = (RepoAlias, &ServerRepoConfig)> {
|
||||
self.repos
|
||||
.iter()
|
||||
|
|
|
@ -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<CommitCount>,
|
||||
}
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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::<Vec<_>>();
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -492,6 +561,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<String> = vec![];
|
||||
for (repo_alias, server_repo_config) in forge_default.repos() {
|
||||
let repo_path = server_repo_config.repo();
|
||||
|
@ -542,6 +617,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 +802,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<u32> {
|
||||
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 +878,7 @@ mod given {
|
|||
a_name(), // hostname
|
||||
a_name(), // user
|
||||
a_name(), // token
|
||||
maybe_a_number(),
|
||||
some_server_repo_configs(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<otest::OnFetch>,
|
||||
on_push: Vec<otest::OnPush>,
|
||||
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)]
|
||||
|
|
|
@ -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<RwLock<gix::ThreadSafeRepository>>);
|
||||
pub struct RealOpenRepository {
|
||||
inner: Arc<RwLock<gix::ThreadSafeRepository>>,
|
||||
forge_details: ForgeDetails,
|
||||
}
|
||||
impl super::OpenRepositoryLike for RealOpenRepository {
|
||||
fn remote_branches(&self) -> git::push::Result<Vec<BranchName>> {
|
||||
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<RemoteUrl> {
|
||||
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<Vec<git::Commit>, 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<String> {
|
||||
self.0
|
||||
self.inner
|
||||
.read()
|
||||
.map_err(|_| git::file::Error::Lock)
|
||||
.and_then(|repo| {
|
||||
|
|
|
@ -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<OnFetch>,
|
||||
on_push: Vec<OnPush>,
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::CommitCount;
|
||||
|
||||
//
|
||||
use super::*;
|
||||
|
||||
|
@ -6,7 +8,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 +26,10 @@ 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().with_max_dev_commits(Some(CommitCount::from(25)));
|
||||
let_assert!(Some(max_dev_commits) = forge_details.max_dev_commits());
|
||||
assert!(**max_dev_commits >= 25);
|
||||
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 +45,10 @@ 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().with_max_dev_commits(Some(CommitCount::from(10)));
|
||||
let_assert!(Some(max_dev_commits) = forge_details.max_dev_commits());
|
||||
assert!(**max_dev_commits > 5);
|
||||
let test_repository = git::repository::test(fs.clone(), forge_details);
|
||||
let_assert!(
|
||||
Ok(open_repository) = test_repository.open(&gitdir),
|
||||
"open repository"
|
||||
|
|
|
@ -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::<Vec<_>>();
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<git::repository::open::otest::OnFetch>,
|
||||
on_push: Vec<git::repository::open::otest::OnPush>,
|
||||
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(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u32> {
|
||||
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(5..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();
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -691,6 +691,22 @@ mod forgejo {
|
|||
generate(5)
|
||||
}
|
||||
|
||||
pub fn maybe_a_number() -> Option<u32> {
|
||||
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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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<u32> {
|
||||
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())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue