refactor: merge config crate into core crate
This commit is contained in:
parent
48c968db2d
commit
ab728c7364
114 changed files with 739 additions and 866 deletions
|
@ -14,6 +14,7 @@ categories = { workspace = true }
|
||||||
[dependencies]
|
[dependencies]
|
||||||
git-next-core = { workspace = true }
|
git-next-core = { workspace = true }
|
||||||
git-next-server = { workspace = true }
|
git-next-server = { workspace = true }
|
||||||
|
git-next-git = { workspace = true }
|
||||||
|
|
||||||
# CLI parsing
|
# CLI parsing
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//
|
||||||
use kxio::fs::FileSystem;
|
use kxio::fs::FileSystem;
|
||||||
|
|
||||||
pub fn run(fs: FileSystem) {
|
pub fn run(fs: FileSystem) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//
|
||||||
mod init;
|
mod init;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -29,7 +30,7 @@ enum Server {
|
||||||
fn main() {
|
fn main() {
|
||||||
let fs = fs::new(PathBuf::default());
|
let fs = fs::new(PathBuf::default());
|
||||||
let net = Network::new_real();
|
let net = Network::new_real();
|
||||||
let repository_factory = git_next_server::repository_factory();
|
let repository_factory = git_next_git::repository::factory::real();
|
||||||
let commands = Commands::parse();
|
let commands = Commands::parse();
|
||||||
|
|
||||||
match commands.command {
|
match commands.command {
|
||||||
|
|
|
@ -4,7 +4,7 @@ version = { workspace = true }
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
description = "Base types for git-next, the trunk-based development manager"
|
description = "[deprecated crate] Base types for git-next, the trunk-based development manager"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["forgejo", "github"]
|
default = ["forgejo", "github"]
|
||||||
|
@ -12,39 +12,6 @@ forgejo = []
|
||||||
github = []
|
github = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# logging
|
|
||||||
tracing = { workspace = true }
|
|
||||||
|
|
||||||
# fs/network
|
|
||||||
kxio = { workspace = true }
|
|
||||||
|
|
||||||
# TOML parsing
|
|
||||||
serde = { workspace = true }
|
|
||||||
# serde_json = { workspace = true }
|
|
||||||
toml = { workspace = true }
|
|
||||||
|
|
||||||
# Secrets and Password
|
|
||||||
secrecy = { workspace = true }
|
|
||||||
|
|
||||||
# Git
|
|
||||||
gix = { workspace = true }
|
|
||||||
git-url-parse = { workspace = true }
|
|
||||||
|
|
||||||
# Webhooks
|
|
||||||
ulid = { workspace = true }
|
|
||||||
|
|
||||||
# boilerplate
|
|
||||||
derive_more = { workspace = true }
|
|
||||||
derive-with = { workspace = true }
|
|
||||||
thiserror = { workspace = true }
|
|
||||||
pike = { workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
# # Testing
|
|
||||||
assert2 = { workspace = true }
|
|
||||||
rand = { workspace = true }
|
|
||||||
pretty_assertions = { workspace = true }
|
|
||||||
test-log = { workspace = true }
|
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
nursery = { level = "warn", priority = -1 }
|
nursery = { level = "warn", priority = -1 }
|
||||||
|
|
|
@ -7,3 +7,5 @@ development workflows where each commit must pass CI before being included in
|
||||||
the main branch.
|
the main branch.
|
||||||
|
|
||||||
See [git-next](https://crates.io/crates/git-next) for more information.
|
See [git-next](https://crates.io/crates/git-next) for more information.
|
||||||
|
|
||||||
|
N.B. this crate has been merged into [git-next-core](https://crates.io/crates/git-next-core).
|
||||||
|
|
|
@ -1,50 +1,2 @@
|
||||||
//
|
// moved to crates/core/src/config/
|
||||||
mod api_token;
|
// moved newtype to crates/core/src/macros/
|
||||||
mod branch_name;
|
|
||||||
pub mod common;
|
|
||||||
mod forge_alias;
|
|
||||||
mod forge_config;
|
|
||||||
mod forge_details;
|
|
||||||
mod forge_type;
|
|
||||||
pub mod git_dir;
|
|
||||||
mod host_name;
|
|
||||||
mod newtype;
|
|
||||||
mod registered_webhook;
|
|
||||||
mod remote_url;
|
|
||||||
mod repo_alias;
|
|
||||||
mod repo_branches;
|
|
||||||
mod repo_config;
|
|
||||||
mod repo_config_source;
|
|
||||||
mod repo_path;
|
|
||||||
pub mod server;
|
|
||||||
mod server_repo_config;
|
|
||||||
mod user;
|
|
||||||
pub mod webhook;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
pub use api_token::ApiToken;
|
|
||||||
pub use branch_name::BranchName;
|
|
||||||
pub use forge_alias::ForgeAlias;
|
|
||||||
pub use forge_config::ForgeConfig;
|
|
||||||
pub use forge_details::ForgeDetails;
|
|
||||||
pub use forge_type::ForgeType;
|
|
||||||
pub use git_dir::GitDir;
|
|
||||||
pub use git_dir::StoragePathType;
|
|
||||||
pub use host_name::Hostname;
|
|
||||||
pub use registered_webhook::RegisteredWebhook;
|
|
||||||
pub use remote_url::RemoteUrl;
|
|
||||||
pub use repo_alias::RepoAlias;
|
|
||||||
pub use repo_branches::RepoBranches;
|
|
||||||
pub use repo_config::RepoConfig;
|
|
||||||
pub use repo_config_source::RepoConfigSource;
|
|
||||||
pub use repo_path::RepoPath;
|
|
||||||
pub use server_repo_config::ServerRepoConfig;
|
|
||||||
pub use user::User;
|
|
||||||
pub use webhook::auth::WebhookAuth;
|
|
||||||
pub use webhook::forge_notification::ForgeNotification;
|
|
||||||
pub use webhook::id::WebhookId;
|
|
||||||
|
|
||||||
// re-export
|
|
||||||
pub use pike::{pike, pike_opt, pike_res};
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
//
|
|
||||||
use crate as config;
|
|
||||||
|
|
||||||
#[derive(Debug, derive_more::Constructor)]
|
|
||||||
pub struct RegisteredWebhook {
|
|
||||||
id: config::WebhookId,
|
|
||||||
auth: config::WebhookAuth,
|
|
||||||
}
|
|
||||||
impl RegisteredWebhook {
|
|
||||||
pub const fn id(&self) -> &config::WebhookId {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
pub const fn auth(&self) -> &config::WebhookAuth {
|
|
||||||
&self.auth
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,6 +6,11 @@ license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
description = "core for git-next, the trunk-based development manager"
|
description = "core for git-next, the trunk-based development manager"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["forgejo", "github"]
|
||||||
|
forgejo = []
|
||||||
|
github = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# logging
|
# logging
|
||||||
console-subscriber = { workspace = true }
|
console-subscriber = { workspace = true }
|
||||||
|
@ -19,9 +24,31 @@ kxio = { workspace = true }
|
||||||
actix = { workspace = true }
|
actix = { workspace = true }
|
||||||
actix-rt = { workspace = true }
|
actix-rt = { workspace = true }
|
||||||
|
|
||||||
|
# TOML parsing
|
||||||
|
serde = { workspace = true }
|
||||||
|
toml = { workspace = true }
|
||||||
|
|
||||||
|
# Secrets and Password
|
||||||
|
secrecy = { workspace = true }
|
||||||
|
|
||||||
|
# Git
|
||||||
|
gix = { workspace = true }
|
||||||
|
git-url-parse = { workspace = true }
|
||||||
|
|
||||||
|
# Webhooks
|
||||||
|
ulid = { workspace = true }
|
||||||
|
|
||||||
|
# boilerplate
|
||||||
|
derive_more = { workspace = true }
|
||||||
|
derive-with = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
pike = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# Testing
|
# Testing
|
||||||
assert2 = { workspace = true }
|
assert2 = { workspace = true }
|
||||||
|
rand = { workspace = true }
|
||||||
|
test-log = { workspace = true }
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
nursery = { level = "warn", priority = -1 }
|
nursery = { level = "warn", priority = -1 }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{
|
use crate::config::{
|
||||||
ApiToken, BranchName, ForgeAlias, ForgeDetails, ForgeType, Hostname, RepoAlias, RepoBranches,
|
ApiToken, BranchName, ForgeAlias, ForgeDetails, ForgeType, Hostname, RepoAlias, RepoBranches,
|
||||||
RepoConfig, RepoConfigSource, RepoPath, User,
|
RepoConfig, RepoConfigSource, RepoPath, User,
|
||||||
};
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User};
|
use crate::config::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User};
|
||||||
|
|
||||||
/// Defines a Forge to connect to
|
/// Defines a Forge to connect to
|
||||||
/// Maps from `git-next-server.toml` at `forge.{forge}`
|
/// Maps from `git-next-server.toml` at `forge.{forge}`
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{ApiToken, ForgeAlias, ForgeConfig, ForgeType, Hostname, User};
|
use crate::config::{ApiToken, ForgeAlias, ForgeConfig, ForgeType, Hostname, User};
|
||||||
|
|
||||||
/// The derived information about a Forge, used to create interactions with it
|
/// The derived information about a Forge, used to create interactions with it
|
||||||
#[derive(Clone, Default, Debug, derive_more::Constructor, derive_with::With)]
|
#[derive(Clone, Default, Debug, derive_more::Constructor, derive_with::With)]
|
49
crates/core/src/config/mod.rs
Normal file
49
crates/core/src/config/mod.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
mod api_token;
|
||||||
|
mod branch_name;
|
||||||
|
pub mod common;
|
||||||
|
mod forge_alias;
|
||||||
|
mod forge_config;
|
||||||
|
mod forge_details;
|
||||||
|
mod forge_type;
|
||||||
|
pub mod git_dir;
|
||||||
|
mod host_name;
|
||||||
|
mod registered_webhook;
|
||||||
|
mod remote_url;
|
||||||
|
mod repo_alias;
|
||||||
|
mod repo_branches;
|
||||||
|
mod repo_config;
|
||||||
|
mod repo_config_source;
|
||||||
|
mod repo_path;
|
||||||
|
pub mod server;
|
||||||
|
mod server_repo_config;
|
||||||
|
mod user;
|
||||||
|
pub mod webhook;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
pub use api_token::ApiToken;
|
||||||
|
pub use branch_name::BranchName;
|
||||||
|
pub use forge_alias::ForgeAlias;
|
||||||
|
pub use forge_config::ForgeConfig;
|
||||||
|
pub use forge_details::ForgeDetails;
|
||||||
|
pub use forge_type::ForgeType;
|
||||||
|
pub use git_dir::GitDir;
|
||||||
|
pub use git_dir::StoragePathType;
|
||||||
|
pub use host_name::Hostname;
|
||||||
|
pub use registered_webhook::RegisteredWebhook;
|
||||||
|
pub use remote_url::RemoteUrl;
|
||||||
|
pub use repo_alias::RepoAlias;
|
||||||
|
pub use repo_branches::RepoBranches;
|
||||||
|
pub use repo_config::RepoConfig;
|
||||||
|
pub use repo_config_source::RepoConfigSource;
|
||||||
|
pub use repo_path::RepoPath;
|
||||||
|
pub use server_repo_config::ServerRepoConfig;
|
||||||
|
pub use user::User;
|
||||||
|
pub use webhook::auth::WebhookAuth;
|
||||||
|
pub use webhook::forge_notification::ForgeNotification;
|
||||||
|
pub use webhook::id::WebhookId;
|
||||||
|
|
||||||
|
// re-export
|
||||||
|
pub use pike::{pike, pike_opt, pike_res};
|
16
crates/core/src/config/registered_webhook.rs
Normal file
16
crates/core/src/config/registered_webhook.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
use crate::config::{WebhookAuth, WebhookId};
|
||||||
|
|
||||||
|
#[derive(Debug, derive_more::Constructor)]
|
||||||
|
pub struct RegisteredWebhook {
|
||||||
|
id: WebhookId,
|
||||||
|
auth: WebhookAuth,
|
||||||
|
}
|
||||||
|
impl RegisteredWebhook {
|
||||||
|
pub const fn id(&self) -> &WebhookId {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
pub const fn auth(&self) -> &WebhookAuth {
|
||||||
|
&self.auth
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::BranchName;
|
use crate::config::BranchName;
|
||||||
|
|
||||||
/// Mapped from `.git-next.toml` file at `branches`
|
/// Mapped from `.git-next.toml` file at `branches`
|
||||||
#[derive(
|
#[derive(
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::RepoBranches;
|
use crate::config::{RepoBranches, RepoConfigSource};
|
||||||
use crate::RepoConfigSource;
|
|
||||||
|
|
||||||
/// Mapped from `.git-next.toml` file in target repo
|
/// Mapped from `.git-next.toml` file in target repo
|
||||||
/// Is also derived from the optional parameters in `git-next-server.toml` at
|
/// Is also derived from the optional parameters in `git-next-server.toml` at
|
|
@ -11,7 +11,10 @@ use kxio::fs::FileSystem;
|
||||||
use secrecy::Secret;
|
use secrecy::Secret;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{newtype, ForgeAlias, ForgeConfig, RepoAlias};
|
use crate::{
|
||||||
|
config::{ForgeAlias, ForgeConfig, RepoAlias},
|
||||||
|
newtype,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
|
@ -1,6 +1,10 @@
|
||||||
|
//
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{BranchName, GitDir, RepoBranches, RepoConfig, RepoConfigSource, RepoPath};
|
use crate::config::{
|
||||||
|
git_dir::StoragePathType, BranchName, GitDir, RepoBranches, RepoConfig, RepoConfigSource,
|
||||||
|
RepoPath,
|
||||||
|
};
|
||||||
|
|
||||||
/// Defines a Repo within a ForgeConfig to be monitored by the server
|
/// Defines a Repo within a ForgeConfig to be monitored by the server
|
||||||
/// Maps from `git-next-server.toml` at `forge.{forge}.repos.{name}`
|
/// Maps from `git-next-server.toml` at `forge.{forge}.repos.{name}`
|
||||||
|
@ -38,7 +42,7 @@ impl ServerRepoConfig {
|
||||||
self.gitdir
|
self.gitdir
|
||||||
.clone()
|
.clone()
|
||||||
// Provenance is external as the gitdir is only used to specify non-internal paths
|
// Provenance is external as the gitdir is only used to specify non-internal paths
|
||||||
.map(|dir| GitDir::new(dir, crate::git_dir::StoragePathType::External))
|
.map(|dir| GitDir::new(dir, StoragePathType::External))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a RepoConfig from the server configuration if ALL THREE branches were provided
|
/// Returns a RepoConfig from the server configuration if ALL THREE branches were provided
|
|
@ -1,5 +1,7 @@
|
||||||
//
|
//
|
||||||
crate::newtype!(WebhookAuth: ulid::Ulid, derive_more::Display: r#"The unique token authorisation for the webhook.
|
use crate::newtype;
|
||||||
|
|
||||||
|
newtype!(WebhookAuth: ulid::Ulid, derive_more::Display: r#"The unique token authorisation for the webhook.
|
||||||
|
|
||||||
Each monitored repository has it's own unique token, and it is different each time `git-next` runs."#);
|
Each monitored repository has it's own unique token, and it is different each time `git-next` runs."#);
|
||||||
impl WebhookAuth {
|
impl WebhookAuth {
|
|
@ -1,21 +1,23 @@
|
||||||
//
|
//
|
||||||
use crate as config;
|
use crate::config::{ForgeAlias, RepoAlias};
|
||||||
|
|
||||||
|
use derive_more::Constructor;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// A notification receive from a Forge, typically via a Webhook.
|
/// A notification receive from a Forge, typically via a Webhook.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, derive_more::Constructor)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, derive_more::Constructor)]
|
||||||
pub struct ForgeNotification {
|
pub struct ForgeNotification {
|
||||||
forge_alias: config::ForgeAlias,
|
forge_alias: ForgeAlias,
|
||||||
repo_alias: config::RepoAlias,
|
repo_alias: RepoAlias,
|
||||||
headers: BTreeMap<String, String>,
|
headers: BTreeMap<String, String>,
|
||||||
body: Body,
|
body: Body,
|
||||||
}
|
}
|
||||||
impl ForgeNotification {
|
impl ForgeNotification {
|
||||||
pub const fn forge_alias(&self) -> &config::ForgeAlias {
|
pub const fn forge_alias(&self) -> &ForgeAlias {
|
||||||
&self.forge_alias
|
&self.forge_alias
|
||||||
}
|
}
|
||||||
pub const fn repo_alias(&self) -> &config::RepoAlias {
|
pub const fn repo_alias(&self) -> &RepoAlias {
|
||||||
&self.repo_alias
|
&self.repo_alias
|
||||||
}
|
}
|
||||||
pub const fn body(&self) -> &Body {
|
pub const fn body(&self) -> &Body {
|
||||||
|
@ -26,7 +28,7 @@ impl ForgeNotification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, derive_more::Constructor)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Constructor)]
|
||||||
pub struct Body(String);
|
pub struct Body(String);
|
||||||
impl Body {
|
impl Body {
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
|
@ -1,16 +1,15 @@
|
||||||
//
|
//
|
||||||
use crate as config;
|
use crate::config::{BranchName, RepoBranches};
|
||||||
|
|
||||||
use derive_more::Constructor;
|
use derive_more::Constructor;
|
||||||
|
|
||||||
#[derive(Debug, Constructor, derive_with::With)]
|
#[derive(Debug, Constructor, derive_with::With)]
|
||||||
pub struct Push {
|
pub struct Push {
|
||||||
branch: config::BranchName,
|
branch: BranchName,
|
||||||
sha: String,
|
sha: String,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
impl Push {
|
impl Push {
|
||||||
pub fn branch(&self, repo_branches: &crate::RepoBranches) -> Option<Branch> {
|
pub fn branch(&self, repo_branches: &RepoBranches) -> Option<Branch> {
|
||||||
if self.branch == repo_branches.main() {
|
if self.branch == repo_branches.main() {
|
||||||
return Some(Branch::Main);
|
return Some(Branch::Main);
|
||||||
}
|
}
|
|
@ -1 +1,4 @@
|
||||||
|
mod config;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
pub use config::*;
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! message {
|
macro_rules! message {
|
||||||
($name:ident: $value:ty: $docs:literal) => {
|
($name:ident: $value:ty: $docs:literal) => {
|
||||||
git_next_config::newtype!($name: $value: $docs);
|
git_next_core::newtype!($name: $value: $docs);
|
||||||
impl actix::prelude::Message for $name {
|
impl actix::prelude::Message for $name {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($name:ident: $docs:literal) => {
|
($name:ident: $docs:literal) => {
|
||||||
git_next_config::newtype!($name: $docs);
|
git_next_core::newtype!($name: $docs);
|
||||||
impl actix::prelude::Message for $name {
|
impl actix::prelude::Message for $name {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($name:ident: $value:ty => $result:ty: $docs:literal) => {
|
($name:ident: $value:ty => $result:ty: $docs:literal) => {
|
||||||
git_next_config::newtype!($name is a $value: $docs);
|
git_next_core::newtype!($name is a $value: $docs);
|
||||||
impl actix::prelude::Message for $name {
|
impl actix::prelude::Message for $name {
|
||||||
type Result = $result;
|
type Result = $result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($name:ident => $result:ty: $docs:literal) => {
|
($name:ident => $result:ty: $docs:literal) => {
|
||||||
git_next_config::newtype!($name: $docs);
|
git_next_core::newtype!($name: $docs);
|
||||||
impl actix::prelude::Message for $name {
|
impl actix::prelude::Message for $name {
|
||||||
type Result = $result;
|
type Result = $result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
mod message;
|
mod message;
|
||||||
|
mod newtype;
|
||||||
|
|
|
@ -7,7 +7,7 @@ repository = { workspace = true }
|
||||||
description = "Forgejo support for git-next, the trunk-based development manager"
|
description = "Forgejo support for git-next, the trunk-based development manager"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
git-next-config = { workspace = true }
|
git-next-core = { workspace = true }
|
||||||
git-next-git = { workspace = true }
|
git-next-git = { workspace = true }
|
||||||
|
|
||||||
# logging
|
# logging
|
||||||
|
|
|
@ -5,7 +5,9 @@ mod tests;
|
||||||
mod webhook;
|
mod webhook;
|
||||||
|
|
||||||
use git::forge::commit::Status;
|
use git::forge::commit::Status;
|
||||||
use git_next_config as config;
|
use git_next_core::{
|
||||||
|
self as core, server, ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId,
|
||||||
|
};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network::{self, Network};
|
use kxio::network::{self, Network};
|
||||||
|
@ -30,24 +32,20 @@ impl git::ForgeLike for ForgeJo {
|
||||||
"forgejo".to_string()
|
"forgejo".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_message_authorised(
|
fn is_message_authorised(&self, msg: &ForgeNotification, expected: &WebhookAuth) -> bool {
|
||||||
&self,
|
|
||||||
msg: &config::ForgeNotification,
|
|
||||||
expected: &config::WebhookAuth,
|
|
||||||
) -> bool {
|
|
||||||
let authorization = msg.header("authorization");
|
let authorization = msg.header("authorization");
|
||||||
tracing::info!(?authorization, %expected, "is message authorised?");
|
tracing::info!(?authorization, %expected, "is message authorised?");
|
||||||
authorization
|
authorization
|
||||||
.and_then(|header| header.strip_prefix("Basic ").map(|v| v.to_owned()))
|
.and_then(|header| header.strip_prefix("Basic ").map(|v| v.to_owned()))
|
||||||
.and_then(|value| config::WebhookAuth::try_new(value.as_str()).ok())
|
.and_then(|value| WebhookAuth::try_new(value.as_str()).ok())
|
||||||
.map(|auth| &auth == expected)
|
.map(|auth| &auth == expected)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_webhook_body(
|
fn parse_webhook_body(
|
||||||
&self,
|
&self,
|
||||||
body: &config::webhook::forge_notification::Body,
|
body: &core::webhook::forge_notification::Body,
|
||||||
) -> git::forge::webhook::Result<config::webhook::Push> {
|
) -> git::forge::webhook::Result<core::webhook::Push> {
|
||||||
webhook::parse_body(body)
|
webhook::parse_body(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,22 +94,19 @@ impl git::ForgeLike for ForgeJo {
|
||||||
|
|
||||||
async fn list_webhooks(
|
async fn list_webhooks(
|
||||||
&self,
|
&self,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<Vec<config::WebhookId>> {
|
) -> git::forge::webhook::Result<Vec<WebhookId>> {
|
||||||
webhook::list(&self.repo_details, webhook_url, &self.net).await
|
webhook::list(&self.repo_details, webhook_url, &self.net).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn unregister_webhook(
|
async fn unregister_webhook(&self, webhook_id: &WebhookId) -> git::forge::webhook::Result<()> {
|
||||||
&self,
|
|
||||||
webhook_id: &config::WebhookId,
|
|
||||||
) -> git::forge::webhook::Result<()> {
|
|
||||||
webhook::unregister(webhook_id, &self.repo_details, &self.net).await
|
webhook::unregister(webhook_id, &self.repo_details, &self.net).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn register_webhook(
|
async fn register_webhook(
|
||||||
&self,
|
&self,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<config::RegisteredWebhook> {
|
) -> git::forge::webhook::Result<RegisteredWebhook> {
|
||||||
webhook::register(&self.repo_details, webhook_url, &self.net).await
|
webhook::register(&self.repo_details, webhook_url, &self.net).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use crate::ForgeJo;
|
||||||
use git_next_git as git;
|
use git_next_core::{
|
||||||
|
server::{InboundWebhook, WebhookUrl},
|
||||||
|
BranchName, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias,
|
||||||
|
RepoBranches, RepoPath, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId,
|
||||||
|
};
|
||||||
|
use git_next_git::{self as git, forge::commit::Status, ForgeLike as _};
|
||||||
|
|
||||||
|
use assert2::let_assert;
|
||||||
|
use kxio::network::{self, MockNetwork, StatusCode};
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
mod forgejo {
|
mod forgejo {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use assert2::let_assert;
|
|
||||||
|
|
||||||
use crate::ForgeJo;
|
|
||||||
use git::ForgeLike as _;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_name() {
|
fn should_return_name() {
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
|
@ -65,8 +73,6 @@ mod forgejo {
|
||||||
|
|
||||||
mod parse_webhook_body {
|
mod parse_webhook_body {
|
||||||
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -77,7 +83,7 @@ mod forgejo {
|
||||||
let next = repo_branches.next();
|
let next = repo_branches.next();
|
||||||
let sha = given::a_name();
|
let sha = given::a_name();
|
||||||
let message = given::a_name();
|
let message = given::a_name();
|
||||||
let body = config::webhook::forge_notification::Body::new(
|
let body = git_next_core::webhook::forge_notification::Body::new(
|
||||||
json!({"ref":format!("refs/heads/{next}"),"after":sha,"head_commit":{"message":message}})
|
json!({"ref":format!("refs/heads/{next}"),"after":sha,"head_commit":{"message":message}})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
|
@ -86,7 +92,7 @@ mod forgejo {
|
||||||
assert_eq!(push.message(), message);
|
assert_eq!(push.message(), message);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
push.branch(&repo_branches),
|
push.branch(&repo_branches),
|
||||||
Some(config::webhook::push::Branch::Next)
|
Some(git_next_core::webhook::push::Branch::Next)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,15 +100,14 @@ mod forgejo {
|
||||||
fn should_error_invalid_body() {
|
fn should_error_invalid_body() {
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
|
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
|
||||||
let body =
|
let body = git_next_core::webhook::forge_notification::Body::new(
|
||||||
config::webhook::forge_notification::Body::new(r#"{"type":"invalid"}"#.to_string());
|
r#"{"type":"invalid"}"#.to_string(),
|
||||||
|
);
|
||||||
let_assert!(Err(_) = forge.parse_webhook_body(&body));
|
let_assert!(Err(_) = forge.parse_webhook_body(&body));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod commit_status {
|
mod commit_status {
|
||||||
use git_next_git::forge::commit::Status;
|
|
||||||
use kxio::network::StatusCode;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -186,10 +191,6 @@ mod forgejo {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod list_webhooks {
|
mod list_webhooks {
|
||||||
use git_next_config::WebhookId;
|
|
||||||
use git_next_git::ForgeLike as _;
|
|
||||||
|
|
||||||
use crate::tests::forgejo::with;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -200,7 +201,6 @@ mod forgejo {
|
||||||
let webhook_url = given::any_webhook_url();
|
let webhook_url = given::any_webhook_url();
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
let hook_id_1 = given::a_forgejo_webhook_id();
|
let hook_id_1 = given::a_forgejo_webhook_id();
|
||||||
let hook_id_2 = given::a_forgejo_webhook_id();
|
let hook_id_2 = given::a_forgejo_webhook_id();
|
||||||
|
@ -245,7 +245,6 @@ mod forgejo {
|
||||||
let webhook_url = given::a_webhook_url(&given::a_forge_alias(), &given::a_repo_alias());
|
let webhook_url = given::a_webhook_url(&given::a_forge_alias(), &given::a_repo_alias());
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
|
||||||
|
@ -263,8 +262,6 @@ mod forgejo {
|
||||||
|
|
||||||
mod unregister_webhook {
|
mod unregister_webhook {
|
||||||
use super::*;
|
use super::*;
|
||||||
use git_next_git::ForgeLike;
|
|
||||||
use kxio::network::StatusCode;
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn should_delete_webhook() {
|
async fn should_delete_webhook() {
|
||||||
|
@ -272,7 +269,6 @@ mod forgejo {
|
||||||
let repo_details = given::repo_details(&fs);
|
let repo_details = given::repo_details(&fs);
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
let webhook_id = given::a_webhook_id();
|
let webhook_id = given::a_webhook_id();
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
@ -297,7 +293,6 @@ mod forgejo {
|
||||||
let repo_details = given::repo_details(&fs);
|
let repo_details = given::repo_details(&fs);
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
let webhook_id = given::a_webhook_id();
|
let webhook_id = given::a_webhook_id();
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
@ -321,14 +316,8 @@ mod forgejo {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod register_webhook {
|
mod register_webhook {
|
||||||
use crate::tests::forgejo::with;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use git_next_config::WebhookId;
|
|
||||||
use kxio::network::StatusCode;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn should_register_a_new_webhook() {
|
async fn should_register_a_new_webhook() {
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
|
@ -341,7 +330,6 @@ mod forgejo {
|
||||||
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
|
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
@ -403,7 +391,6 @@ mod forgejo {
|
||||||
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
|
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
@ -456,7 +443,6 @@ mod forgejo {
|
||||||
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
|
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
@ -497,7 +483,6 @@ mod forgejo {
|
||||||
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
given::a_webhook_url(repo_details.forge.forge_alias(), &repo_details.repo_alias);
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
|
|
||||||
let mut net = given::a_network();
|
let mut net = given::a_network();
|
||||||
|
@ -526,11 +511,7 @@ mod forgejo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mod with {
|
mod with {
|
||||||
use serde::Serialize;
|
use super::*;
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use git_next_config::{server::WebhookUrl, Hostname, RepoPath};
|
|
||||||
use kxio::network::{self, StatusCode};
|
|
||||||
|
|
||||||
pub fn get_webhooks_by_page(
|
pub fn get_webhooks_by_page(
|
||||||
page: u8,
|
page: u8,
|
||||||
|
@ -589,11 +570,6 @@ mod forgejo {
|
||||||
}
|
}
|
||||||
mod given {
|
mod given {
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use kxio::network::{MockNetwork, StatusCode};
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn a_commit_state(
|
pub fn a_commit_state(
|
||||||
|
@ -616,7 +592,6 @@ mod forgejo {
|
||||||
) -> String {
|
) -> String {
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
let token = repo_details.forge.token().expose_secret();
|
let token = repo_details.forge.token().expose_secret();
|
||||||
format!(
|
format!(
|
||||||
"https://{hostname}/api/v1/repos/{repo_path}/commits/{commit}/status?token={token}"
|
"https://{hostname}/api/v1/repos/{repo_path}/commits/{commit}/status?token={token}"
|
||||||
|
@ -624,15 +599,15 @@ mod forgejo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Header {
|
pub enum Header {
|
||||||
Valid(config::WebhookAuth),
|
Valid(WebhookAuth),
|
||||||
Missing,
|
Missing,
|
||||||
NonBasic,
|
NonBasic,
|
||||||
NonUlid,
|
NonUlid,
|
||||||
WrongUlid,
|
WrongUlid,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_message(header: Header) -> config::ForgeNotification {
|
pub fn a_webhook_message(header: Header) -> ForgeNotification {
|
||||||
config::ForgeNotification::new(
|
ForgeNotification::new(
|
||||||
given::a_forge_alias(),
|
given::a_forge_alias(),
|
||||||
given::a_repo_alias(),
|
given::a_repo_alias(),
|
||||||
given::webhook_headers(header),
|
given::webhook_headers(header),
|
||||||
|
@ -656,7 +631,7 @@ mod forgejo {
|
||||||
Header::WrongUlid => {
|
Header::WrongUlid => {
|
||||||
headers.insert(
|
headers.insert(
|
||||||
"authorization".to_string(),
|
"authorization".to_string(),
|
||||||
format!("Basic {}", config::WebhookAuth::generate()),
|
format!("Basic {}", WebhookAuth::generate()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,38 +650,35 @@ mod forgejo {
|
||||||
rand::thread_rng().next_u32().into()
|
rand::thread_rng().next_u32().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_auth() -> config::WebhookAuth {
|
pub fn a_webhook_auth() -> WebhookAuth {
|
||||||
config::WebhookAuth::generate()
|
WebhookAuth::generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_message_body() -> config::webhook::forge_notification::Body {
|
pub fn a_webhook_message_body() -> git_next_core::webhook::forge_notification::Body {
|
||||||
config::webhook::forge_notification::Body::new(a_name())
|
git_next_core::webhook::forge_notification::Body::new(a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repo_branches() -> config::RepoBranches {
|
pub fn repo_branches() -> RepoBranches {
|
||||||
config::RepoBranches::new(a_name(), a_name(), a_name())
|
RepoBranches::new(a_name(), a_name(), a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_forge_alias() -> config::ForgeAlias {
|
pub fn a_forge_alias() -> ForgeAlias {
|
||||||
config::ForgeAlias::new(a_name())
|
ForgeAlias::new(a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_repo_alias() -> config::RepoAlias {
|
pub fn a_repo_alias() -> RepoAlias {
|
||||||
config::RepoAlias::new(a_name())
|
RepoAlias::new(a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_network() -> kxio::network::MockNetwork {
|
pub fn a_network() -> kxio::network::MockNetwork {
|
||||||
kxio::network::MockNetwork::new()
|
kxio::network::MockNetwork::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_url(
|
pub fn a_webhook_url(forge_alias: &ForgeAlias, repo_alias: &RepoAlias) -> WebhookUrl {
|
||||||
forge_alias: &config::ForgeAlias,
|
InboundWebhook::new(a_name()).url(forge_alias, repo_alias)
|
||||||
repo_alias: &config::RepoAlias,
|
|
||||||
) -> git_next_config::server::WebhookUrl {
|
|
||||||
config::server::InboundWebhook::new(a_name()).url(forge_alias, repo_alias)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn any_webhook_url() -> git_next_config::server::WebhookUrl {
|
pub fn any_webhook_url() -> WebhookUrl {
|
||||||
a_webhook_url(&a_forge_alias(), &a_repo_alias())
|
a_webhook_url(&a_forge_alias(), &a_repo_alias())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,23 +695,23 @@ mod forgejo {
|
||||||
generate(5)
|
generate(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_id() -> config::WebhookId {
|
pub fn a_webhook_id() -> WebhookId {
|
||||||
config::WebhookId::new(a_name())
|
WebhookId::new(a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_branch_name() -> config::BranchName {
|
pub fn a_branch_name() -> BranchName {
|
||||||
config::BranchName::new(a_name())
|
BranchName::new(a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_git_dir(fs: &kxio::fs::FileSystem) -> config::GitDir {
|
pub fn a_git_dir(fs: &kxio::fs::FileSystem) -> GitDir {
|
||||||
let dir_name = a_name();
|
let dir_name = a_name();
|
||||||
let dir = fs.base().join(dir_name);
|
let dir = fs.base().join(dir_name);
|
||||||
config::GitDir::new(dir, config::git_dir::StoragePathType::Internal)
|
GitDir::new(dir, StoragePathType::Internal)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_forge_config() -> config::ForgeConfig {
|
pub fn a_forge_config() -> ForgeConfig {
|
||||||
config::ForgeConfig::new(
|
ForgeConfig::new(
|
||||||
config::ForgeType::MockForge,
|
ForgeType::MockForge,
|
||||||
a_name(),
|
a_name(),
|
||||||
a_name(),
|
a_name(),
|
||||||
a_name(),
|
a_name(),
|
||||||
|
@ -747,11 +719,11 @@ mod forgejo {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_server_repo_config() -> config::ServerRepoConfig {
|
pub fn a_server_repo_config() -> ServerRepoConfig {
|
||||||
let main = a_branch_name().unwrap();
|
let main = a_branch_name().unwrap();
|
||||||
let next = a_branch_name().unwrap();
|
let next = a_branch_name().unwrap();
|
||||||
let dev = a_branch_name().unwrap();
|
let dev = a_branch_name().unwrap();
|
||||||
config::ServerRepoConfig::new(
|
ServerRepoConfig::new(
|
||||||
format!("{}/{}", a_name(), a_name()),
|
format!("{}/{}", a_name(), a_name()),
|
||||||
main.clone(),
|
main.clone(),
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use git_next_core::{server::WebhookUrl, WebhookId};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
|
|
||||||
use crate::webhook::Hook;
|
use crate::webhook::Hook;
|
||||||
|
|
||||||
pub async fn list(
|
pub async fn list(
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &WebhookUrl,
|
||||||
net: &network::Network,
|
net: &network::Network,
|
||||||
) -> git::forge::webhook::Result<Vec<config::WebhookId>> {
|
) -> git::forge::webhook::Result<Vec<WebhookId>> {
|
||||||
let mut ids: Vec<config::WebhookId> = vec![];
|
let mut ids: Vec<WebhookId> = vec![];
|
||||||
let hostname = &repo_details.forge.hostname();
|
let hostname = &repo_details.forge.hostname();
|
||||||
let repo_path = &repo_details.repo_path;
|
let repo_path = &repo_details.repo_path;
|
||||||
let mut page = 1;
|
let mut page = 1;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use git_next_core::{webhook, BranchName, WebhookId};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod list;
|
mod list;
|
||||||
|
@ -19,8 +20,8 @@ struct Hook {
|
||||||
config: HashMap<String, String>,
|
config: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
impl Hook {
|
impl Hook {
|
||||||
fn id(&self) -> config::WebhookId {
|
fn id(&self) -> WebhookId {
|
||||||
config::WebhookId::new(format!("{}", self.id))
|
WebhookId::new(format!("{}", self.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +33,14 @@ pub struct Push {
|
||||||
head_commit: HeadCommit,
|
head_commit: HeadCommit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Push> for config::webhook::Push {
|
impl TryFrom<Push> for webhook::Push {
|
||||||
type Error = git::forge::webhook::Error;
|
type Error = git::forge::webhook::Error;
|
||||||
fn try_from(push: Push) -> Result<Self, Self::Error> {
|
fn try_from(push: Push) -> Result<Self, Self::Error> {
|
||||||
let branch = push
|
let branch = push
|
||||||
.reference
|
.reference
|
||||||
.splitn(3, '/') // should be of the form 'refs/heads/branchname'
|
.splitn(3, '/') // should be of the form 'refs/heads/branchname'
|
||||||
.nth(2)
|
.nth(2)
|
||||||
.map(config::BranchName::new)
|
.map(BranchName::new)
|
||||||
.ok_or(git::forge::webhook::Error::UnknownBranch(push.reference))?;
|
.ok_or(git::forge::webhook::Error::UnknownBranch(push.reference))?;
|
||||||
Ok(Self::new(branch, push.after, push.head_commit.message))
|
Ok(Self::new(branch, push.after, push.head_commit.message))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//
|
//
|
||||||
use crate as forgejo;
|
use crate as forgejo;
|
||||||
use git_next_config as config;
|
|
||||||
|
use git_next_core::webhook;
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
pub fn parse_body(
|
pub fn parse_body(
|
||||||
body: &config::webhook::forge_notification::Body,
|
body: &webhook::forge_notification::Body,
|
||||||
) -> git::forge::webhook::Result<config::webhook::Push> {
|
) -> git::forge::webhook::Result<webhook::Push> {
|
||||||
serde_json::from_str::<forgejo::webhook::Push>(body.as_str())?.try_into()
|
serde_json::from_str::<forgejo::webhook::Push>(body.as_str())?.try_into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//
|
//
|
||||||
|
use git_next_core::{server, RegisteredWebhook, WebhookAuth, WebhookId};
|
||||||
use git_next_config as config;
|
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
|
@ -12,9 +11,9 @@ use crate::webhook::Hook;
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
net: &network::Network,
|
net: &network::Network,
|
||||||
) -> git::forge::webhook::Result<config::RegisteredWebhook> {
|
) -> git::forge::webhook::Result<RegisteredWebhook> {
|
||||||
let Some(repo_config) = repo_details.repo_config.clone() else {
|
let Some(repo_config) = repo_details.repo_config.clone() else {
|
||||||
return Err(git::forge::webhook::Error::NoRepoConfig);
|
return Err(git::forge::webhook::Error::NoRepoConfig);
|
||||||
};
|
};
|
||||||
|
@ -34,7 +33,7 @@ pub async fn register(
|
||||||
));
|
));
|
||||||
let repo_alias = &repo_details.repo_alias;
|
let repo_alias = &repo_details.repo_alias;
|
||||||
let headers = network::NetRequestHeaders::new().with("Content-Type", "application/json");
|
let headers = network::NetRequestHeaders::new().with("Content-Type", "application/json");
|
||||||
let authorisation = config::WebhookAuth::generate();
|
let authorisation = WebhookAuth::generate();
|
||||||
let body = network::json!({
|
let body = network::json!({
|
||||||
"active": true,
|
"active": true,
|
||||||
"authorization_header": authorisation.header_value(),
|
"authorization_header": authorisation.header_value(),
|
||||||
|
@ -64,8 +63,8 @@ pub async fn register(
|
||||||
return Err(git::forge::webhook::Error::NetworkResponseEmpty);
|
return Err(git::forge::webhook::Error::NetworkResponseEmpty);
|
||||||
};
|
};
|
||||||
info!(webhook_id = %hook.id, "Webhook registered");
|
info!(webhook_id = %hook.id, "Webhook registered");
|
||||||
Ok(config::RegisteredWebhook::new(
|
Ok(RegisteredWebhook::new(
|
||||||
config::WebhookId::new(format!("{}", hook.id)),
|
WebhookId::new(format!("{}", hook.id)),
|
||||||
authorisation,
|
authorisation,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use git_next_core::WebhookId;
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
|
|
||||||
pub async fn unregister(
|
pub async fn unregister(
|
||||||
webhook_id: &config::WebhookId,
|
webhook_id: &WebhookId,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
net: &network::Network,
|
net: &network::Network,
|
||||||
) -> git::forge::webhook::Result<()> {
|
) -> git::forge::webhook::Result<()> {
|
||||||
|
|
|
@ -7,7 +7,7 @@ repository = { workspace = true }
|
||||||
description = "GitHub support for git-next, the trunk-based development manager"
|
description = "GitHub support for git-next, the trunk-based development manager"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
git-next-config = { workspace = true }
|
git-next-core = { workspace = true }
|
||||||
git-next-git = { workspace = true }
|
git-next-git = { workspace = true }
|
||||||
|
|
||||||
# own version for UserAgent requests to github.com
|
# own version for UserAgent requests to github.com
|
||||||
|
|
|
@ -7,7 +7,9 @@ mod webhook;
|
||||||
|
|
||||||
use crate as github;
|
use crate as github;
|
||||||
use git::forge::commit::Status;
|
use git::forge::commit::Status;
|
||||||
use git_next_config as config;
|
use git_next_core::{
|
||||||
|
self as core, server, ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId,
|
||||||
|
};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use derive_more::Constructor;
|
use derive_more::Constructor;
|
||||||
|
@ -26,15 +28,11 @@ impl git::ForgeLike for Github {
|
||||||
"github".to_string()
|
"github".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_message_authorised(
|
fn is_message_authorised(&self, msg: &ForgeNotification, webhook_auth: &WebhookAuth) -> bool {
|
||||||
&self,
|
|
||||||
msg: &config::ForgeNotification,
|
|
||||||
webhook_auth: &config::WebhookAuth,
|
|
||||||
) -> bool {
|
|
||||||
github::webhook::is_authorised(msg, webhook_auth)
|
github::webhook::is_authorised(msg, webhook_auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_ignore_message(&self, message: &config::ForgeNotification) -> bool {
|
fn should_ignore_message(&self, message: &ForgeNotification) -> bool {
|
||||||
let Some(event) = message.header("x-github-event") else {
|
let Some(event) = message.header("x-github-event") else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -48,8 +46,8 @@ impl git::ForgeLike for Github {
|
||||||
|
|
||||||
fn parse_webhook_body(
|
fn parse_webhook_body(
|
||||||
&self,
|
&self,
|
||||||
body: &config::webhook::forge_notification::Body,
|
body: &core::webhook::forge_notification::Body,
|
||||||
) -> git::forge::webhook::Result<config::webhook::push::Push> {
|
) -> git::forge::webhook::Result<core::webhook::push::Push> {
|
||||||
github::webhook::parse_body(body)
|
github::webhook::parse_body(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,23 +57,20 @@ impl git::ForgeLike for Github {
|
||||||
|
|
||||||
async fn list_webhooks(
|
async fn list_webhooks(
|
||||||
&self,
|
&self,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<Vec<config::WebhookId>> {
|
) -> git::forge::webhook::Result<Vec<WebhookId>> {
|
||||||
github::webhook::list(self, webhook_url).await
|
github::webhook::list(self, webhook_url).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn unregister_webhook(
|
async fn unregister_webhook(&self, webhook_id: &WebhookId) -> git::forge::webhook::Result<()> {
|
||||||
&self,
|
|
||||||
webhook_id: &config::WebhookId,
|
|
||||||
) -> git::forge::webhook::Result<()> {
|
|
||||||
github::webhook::unregister(self, webhook_id).await
|
github::webhook::unregister(self, webhook_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook
|
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook
|
||||||
async fn register_webhook(
|
async fn register_webhook(
|
||||||
&self,
|
&self,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<config::RegisteredWebhook> {
|
) -> git::forge::webhook::Result<RegisteredWebhook> {
|
||||||
github::webhook::register(self, webhook_url).await
|
github::webhook::register(self, webhook_url).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,11 +100,11 @@ struct GithubHook {
|
||||||
config: Config,
|
config: Config,
|
||||||
}
|
}
|
||||||
impl GithubHook {
|
impl GithubHook {
|
||||||
pub fn id(&self) -> config::WebhookId {
|
pub fn id(&self) -> WebhookId {
|
||||||
config::WebhookId::new(format!("{}", self.id))
|
WebhookId::new(format!("{}", self.id))
|
||||||
}
|
}
|
||||||
pub fn url(&self) -> config::server::WebhookUrl {
|
pub fn url(&self) -> server::WebhookUrl {
|
||||||
config::server::WebhookUrl::new(self.config.url.clone())
|
server::WebhookUrl::new(self.config.url.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use crate::{Github, GithubState, GithubStatus};
|
||||||
use git_next_git as git;
|
use git_next_core::{
|
||||||
|
server::{InboundWebhook, WebhookUrl},
|
||||||
|
webhook,
|
||||||
|
webhook::forge_notification::Body,
|
||||||
|
ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias,
|
||||||
|
RepoBranches, RepoPath, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId,
|
||||||
|
};
|
||||||
|
use git_next_git::{self as git, forge::commit::Status, ForgeLike};
|
||||||
|
|
||||||
|
use assert2::let_assert;
|
||||||
|
use kxio::network::{self, MockNetwork, StatusCode};
|
||||||
|
use rand::RngCore;
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
mod github {
|
mod github {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use assert2::let_assert;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use crate::Github;
|
|
||||||
use config::{
|
|
||||||
webhook::forge_notification::Body, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType,
|
|
||||||
GitDir, RepoAlias, RepoBranches, ServerRepoConfig, WebhookAuth,
|
|
||||||
};
|
|
||||||
use git::ForgeLike as _;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_name() {
|
fn should_return_name() {
|
||||||
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
|
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
|
||||||
|
@ -53,8 +59,6 @@ mod github {
|
||||||
|
|
||||||
mod parse_webhook_body {
|
mod parse_webhook_body {
|
||||||
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -73,7 +77,7 @@ mod github {
|
||||||
assert_eq!(push.message(), message);
|
assert_eq!(push.message(), message);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
push.branch(&repo_branches),
|
push.branch(&repo_branches),
|
||||||
Some(config::webhook::push::Branch::Next)
|
Some(webhook::push::Branch::Next)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +90,6 @@ mod github {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod commit_status {
|
mod commit_status {
|
||||||
use git_next_git::forge::commit::Status;
|
|
||||||
use kxio::network::StatusCode;
|
|
||||||
|
|
||||||
use crate::GithubState;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -154,10 +154,6 @@ mod github {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod list_webhooks {
|
mod list_webhooks {
|
||||||
use git_next_config::WebhookId;
|
|
||||||
use git_next_git::ForgeLike as _;
|
|
||||||
|
|
||||||
use crate::tests::github::with;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -221,8 +217,6 @@ mod github {
|
||||||
|
|
||||||
mod unregister_webhook {
|
mod unregister_webhook {
|
||||||
use super::*;
|
use super::*;
|
||||||
use git_next_git::ForgeLike;
|
|
||||||
use kxio::network::StatusCode;
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn should_delete_webhook() {
|
async fn should_delete_webhook() {
|
||||||
|
@ -269,14 +263,9 @@ mod github {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod register_webhook {
|
mod register_webhook {
|
||||||
use crate::tests::github::with;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use git_next_config::WebhookId;
|
|
||||||
use kxio::network::StatusCode;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn should_register_a_new_webhook() {
|
async fn should_register_a_new_webhook() {
|
||||||
let repo_details = given::repo_details();
|
let repo_details = given::repo_details();
|
||||||
|
@ -451,12 +440,8 @@ mod github {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod with {
|
pub mod with {
|
||||||
use serde::Serialize;
|
use super::*;
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use git_next_config::{server::WebhookUrl, Hostname, RepoPath};
|
|
||||||
use kxio::network::{self, StatusCode};
|
|
||||||
|
|
||||||
pub fn get_webhooks_by_page(
|
pub fn get_webhooks_by_page(
|
||||||
page: u8,
|
page: u8,
|
||||||
|
@ -508,15 +493,6 @@ mod github {
|
||||||
|
|
||||||
mod given {
|
mod given {
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use git_next_config::{server::InboundWebhook, WebhookId};
|
|
||||||
use kxio::network::{MockNetwork, StatusCode};
|
|
||||||
use rand::RngCore;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::{GithubState, GithubStatus};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn commit_states(
|
pub fn commit_states(
|
||||||
|
@ -626,10 +602,7 @@ mod github {
|
||||||
a_name(),
|
a_name(),
|
||||||
BTreeMap::default(),
|
BTreeMap::default(),
|
||||||
),
|
),
|
||||||
GitDir::new(
|
GitDir::new(PathBuf::default(), StoragePathType::External),
|
||||||
PathBuf::default(),
|
|
||||||
config::git_dir::StoragePathType::External,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,13 +617,10 @@ mod github {
|
||||||
kxio::network::MockNetwork::new()
|
kxio::network::MockNetwork::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_url(
|
pub fn a_webhook_url(forge_alias: &ForgeAlias, repo_alias: &RepoAlias) -> WebhookUrl {
|
||||||
forge_alias: &ForgeAlias,
|
|
||||||
repo_alias: &RepoAlias,
|
|
||||||
) -> git_next_config::server::WebhookUrl {
|
|
||||||
InboundWebhook::new(a_name()).url(forge_alias, repo_alias)
|
InboundWebhook::new(a_name()).url(forge_alias, repo_alias)
|
||||||
}
|
}
|
||||||
pub fn any_webhook_url() -> git_next_config::server::WebhookUrl {
|
pub fn any_webhook_url() -> WebhookUrl {
|
||||||
given::a_webhook_url(&given::a_forge_alias(), &given::a_repo_alias())
|
given::a_webhook_url(&given::a_forge_alias(), &given::a_repo_alias())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
|
||||||
|
|
||||||
pub fn is_authorised(msg: &config::ForgeNotification, webhook_auth: &config::WebhookAuth) -> bool {
|
use git_next_core::{ForgeNotification, WebhookAuth};
|
||||||
|
|
||||||
|
pub fn is_authorised(msg: &ForgeNotification, webhook_auth: &WebhookAuth) -> bool {
|
||||||
msg.header("x-hub-signature-256")
|
msg.header("x-hub-signature-256")
|
||||||
.map(|x| x.trim_matches('"').to_string())
|
.map(|x| x.trim_matches('"').to_string())
|
||||||
.and_then(|sha| sha.strip_prefix("sha256=").map(|k| k.to_string()))
|
.and_then(|sha| sha.strip_prefix("sha256=").map(|k| k.to_string()))
|
||||||
|
@ -20,9 +21,9 @@ pub fn is_authorised(msg: &config::ForgeNotification, webhook_auth: &config::Web
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn sign_body(
|
pub fn sign_body(
|
||||||
webhook_auth: &config::WebhookAuth,
|
webhook_auth: &WebhookAuth,
|
||||||
body: &config::webhook::forge_notification::Body,
|
body: &git_next_core::webhook::forge_notification::Body,
|
||||||
) -> std::option::Option<String> {
|
) -> Option<String> {
|
||||||
let payload = body.as_str();
|
let payload = body.as_str();
|
||||||
use hmac::Mac;
|
use hmac::Mac;
|
||||||
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
|
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
//
|
//
|
||||||
use crate as github;
|
use crate as github;
|
||||||
use git_next_config as config;
|
use git_next_core::{server, WebhookId};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
|
|
||||||
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#list-repository-webhooks
|
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#list-repository-webhooks
|
||||||
pub async fn list(
|
pub async fn list(
|
||||||
github: &github::Github,
|
github: &github::Github,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<Vec<config::WebhookId>> {
|
) -> git::forge::webhook::Result<Vec<WebhookId>> {
|
||||||
let mut ids: Vec<config::WebhookId> = vec![];
|
let mut ids: Vec<WebhookId> = vec![];
|
||||||
let repo_details = &github.repo_details;
|
let repo_details = &github.repo_details;
|
||||||
let hostname = &repo_details.forge.hostname();
|
let hostname = &repo_details.forge.hostname();
|
||||||
let net = &github.net;
|
let net = &github.net;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use git_next_core::{webhook, ApiToken, BranchName};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
mod authorised;
|
mod authorised;
|
||||||
|
@ -17,7 +17,7 @@ pub use unregister::unregister;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub use authorised::sign_body;
|
pub use authorised::sign_body;
|
||||||
|
|
||||||
pub fn headers(token: &config::ApiToken) -> kxio::network::NetRequestHeaders {
|
pub fn headers(token: &ApiToken) -> kxio::network::NetRequestHeaders {
|
||||||
use secrecy::ExposeSecret;
|
use secrecy::ExposeSecret;
|
||||||
kxio::network::NetRequestHeaders::default()
|
kxio::network::NetRequestHeaders::default()
|
||||||
.with("Accept", "application/vnd.github+json")
|
.with("Accept", "application/vnd.github+json")
|
||||||
|
@ -44,14 +44,14 @@ pub struct HeadCommit {
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Push> for config::webhook::Push {
|
impl TryFrom<Push> for webhook::Push {
|
||||||
type Error = git::forge::webhook::Error;
|
type Error = git::forge::webhook::Error;
|
||||||
fn try_from(push: Push) -> Result<Self, Self::Error> {
|
fn try_from(push: Push) -> Result<Self, Self::Error> {
|
||||||
let branch = push
|
let branch = push
|
||||||
.reference
|
.reference
|
||||||
.splitn(3, '/') // should be of the form 'refs/heads/branchname'
|
.splitn(3, '/') // should be of the form 'refs/heads/branchname'
|
||||||
.nth(2)
|
.nth(2)
|
||||||
.map(config::BranchName::new)
|
.map(BranchName::new)
|
||||||
.ok_or(git::forge::webhook::Error::UnknownBranch(push.reference))?;
|
.ok_or(git::forge::webhook::Error::UnknownBranch(push.reference))?;
|
||||||
Ok(Self::new(branch, push.after, push.head_commit.message))
|
Ok(Self::new(branch, push.after, push.head_commit.message))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//
|
//
|
||||||
use crate as github;
|
use crate as github;
|
||||||
use git_next_config as config;
|
|
||||||
|
use git_next_core::webhook;
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
pub fn parse_body(
|
pub fn parse_body(
|
||||||
body: &config::webhook::forge_notification::Body,
|
body: &webhook::forge_notification::Body,
|
||||||
) -> git::forge::webhook::Result<config::webhook::push::Push> {
|
) -> git::forge::webhook::Result<webhook::push::Push> {
|
||||||
serde_json::from_str::<github::webhook::Push>(body.as_str())?.try_into()
|
serde_json::from_str::<github::webhook::Push>(body.as_str())?.try_into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
use crate::{self as github, webhook};
|
use crate::{self as github, webhook};
|
||||||
use git_next_config as config;
|
use git_next_core::{server, RegisteredWebhook, WebhookAuth, WebhookId};
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
|
@ -8,8 +8,8 @@ use kxio::network;
|
||||||
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook
|
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
github: &github::Github,
|
github: &github::Github,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &server::WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<config::RegisteredWebhook> {
|
) -> git::forge::webhook::Result<RegisteredWebhook> {
|
||||||
let repo_details = &github.repo_details;
|
let repo_details = &github.repo_details;
|
||||||
if repo_details.repo_config.is_none() {
|
if repo_details.repo_config.is_none() {
|
||||||
return Err(git::forge::webhook::Error::NoRepoConfig);
|
return Err(git::forge::webhook::Error::NoRepoConfig);
|
||||||
|
@ -23,7 +23,7 @@ pub async fn register(
|
||||||
|
|
||||||
let net = &github.net;
|
let net = &github.net;
|
||||||
let hostname = repo_details.forge.hostname();
|
let hostname = repo_details.forge.hostname();
|
||||||
let authorisation = config::WebhookAuth::generate();
|
let authorisation = WebhookAuth::generate();
|
||||||
let request = network::NetRequest::new(
|
let request = network::NetRequest::new(
|
||||||
network::RequestMethod::Post,
|
network::RequestMethod::Post,
|
||||||
network::NetUrl::new(format!(
|
network::NetUrl::new(format!(
|
||||||
|
@ -55,8 +55,8 @@ pub async fn register(
|
||||||
return Err(git::forge::webhook::Error::NetworkResponseEmpty);
|
return Err(git::forge::webhook::Error::NetworkResponseEmpty);
|
||||||
};
|
};
|
||||||
tracing::info!(webhook_id = %hook.id, "Webhook registered");
|
tracing::info!(webhook_id = %hook.id, "Webhook registered");
|
||||||
Ok(config::RegisteredWebhook::new(
|
Ok(RegisteredWebhook::new(
|
||||||
config::WebhookId::new(format!("{}", hook.id)),
|
WebhookId::new(format!("{}", hook.id)),
|
||||||
authorisation,
|
authorisation,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//
|
//
|
||||||
use crate as github;
|
use crate as github;
|
||||||
use git_next_config as config;
|
|
||||||
|
use git_next_core::WebhookId;
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
|
@ -8,7 +9,7 @@ use kxio::network;
|
||||||
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#delete-a-repository-webhook
|
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#delete-a-repository-webhook
|
||||||
pub async fn unregister(
|
pub async fn unregister(
|
||||||
github: &github::Github,
|
github: &github::Github,
|
||||||
webhook_id: &config::WebhookId,
|
webhook_id: &WebhookId,
|
||||||
) -> git::forge::webhook::Result<()> {
|
) -> git::forge::webhook::Result<()> {
|
||||||
let net = &github.net;
|
let net = &github.net;
|
||||||
let repo_details = &github.repo_details;
|
let repo_details = &github.repo_details;
|
||||||
|
|
|
@ -12,7 +12,7 @@ forgejo = ["git-next-forge-forgejo"]
|
||||||
github = ["git-next-forge-github"]
|
github = ["git-next-forge-github"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
git-next-config = { workspace = true }
|
git-next-core = { workspace = true }
|
||||||
git-next-git = { workspace = true }
|
git-next-git = { workspace = true }
|
||||||
git-next-forge-forgejo = { workspace = true, optional = true }
|
git-next-forge-forgejo = { workspace = true, optional = true }
|
||||||
git-next-forge-github = { workspace = true, optional = true }
|
git-next-forge-github = { workspace = true, optional = true }
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//
|
//
|
||||||
use git_next_forge_forgejo as forgejo;
|
use git_next_core::ForgeType;
|
||||||
use git_next_forge_github as github;
|
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
use kxio::network::Network;
|
use kxio::network::Network;
|
||||||
|
|
||||||
|
@ -18,12 +17,10 @@ impl Forge {
|
||||||
pub fn create(repo_details: git::RepoDetails, net: Network) -> Box<dyn git::ForgeLike> {
|
pub fn create(repo_details: git::RepoDetails, net: Network) -> Box<dyn git::ForgeLike> {
|
||||||
match repo_details.forge.forge_type() {
|
match repo_details.forge.forge_type() {
|
||||||
#[cfg(feature = "forgejo")]
|
#[cfg(feature = "forgejo")]
|
||||||
git_next_config::ForgeType::ForgeJo => {
|
ForgeType::ForgeJo => Box::new(git_next_forge_forgejo::ForgeJo::new(repo_details, net)),
|
||||||
Box::new(forgejo::ForgeJo::new(repo_details, net))
|
|
||||||
}
|
|
||||||
#[cfg(feature = "github")]
|
#[cfg(feature = "github")]
|
||||||
git_next_config::ForgeType::GitHub => Box::new(github::Github::new(repo_details, net)),
|
ForgeType::GitHub => Box::new(git_next_forge_github::Github::new(repo_details, net)),
|
||||||
git_next_config::ForgeType::MockForge => unreachable!(),
|
ForgeType::MockForge => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
//
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use git_next_config as config;
|
use git_next_core::{self as core, GitDir, RepoConfigSource, StoragePathType};
|
||||||
use git_next_git::{self as git, RepoDetails};
|
use git_next_git::{self as git, RepoDetails};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_forgejo_name() {
|
fn test_forgejo_name() {
|
||||||
let net = Network::new_mock();
|
let net = Network::new_mock();
|
||||||
let repo_details = given_repo_details(config::ForgeType::ForgeJo);
|
let repo_details = given_repo_details(ForgeType::ForgeJo);
|
||||||
let forge = Forge::create(repo_details, net);
|
let forge = Forge::create(repo_details, net);
|
||||||
assert_eq!(forge.name(), "forgejo");
|
assert_eq!(forge.name(), "forgejo");
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ fn test_forgejo_name() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_github_name() {
|
fn test_github_name() {
|
||||||
let net = Network::new_mock();
|
let net = Network::new_mock();
|
||||||
let repo_details = given_repo_details(config::ForgeType::GitHub);
|
let repo_details = given_repo_details(ForgeType::GitHub);
|
||||||
let forge = Forge::create(repo_details, net);
|
let forge = Forge::create(repo_details, net);
|
||||||
assert_eq!(forge.name(), "github");
|
assert_eq!(forge.name(), "github");
|
||||||
}
|
}
|
||||||
|
@ -27,19 +27,13 @@ fn given_fs() -> kxio::fs::FileSystem {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn given_repo_details(forge_type: config::ForgeType) -> RepoDetails {
|
fn given_repo_details(forge_type: ForgeType) -> RepoDetails {
|
||||||
let fs = given_fs();
|
let fs = given_fs();
|
||||||
git::common::repo_details(
|
git::common::repo_details(
|
||||||
1,
|
1,
|
||||||
git::Generation::default(),
|
git::Generation::default(),
|
||||||
config::common::forge_details(1, forge_type),
|
core::common::forge_details(1, forge_type),
|
||||||
Some(config::common::repo_config(
|
Some(core::common::repo_config(1, RepoConfigSource::Repo)),
|
||||||
1,
|
GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal),
|
||||||
config::RepoConfigSource::Repo,
|
|
||||||
)),
|
|
||||||
config::GitDir::new(
|
|
||||||
fs.base().to_path_buf(),
|
|
||||||
config::git_dir::StoragePathType::Internal,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,12 @@ repository = { workspace = true }
|
||||||
description = "git support for git-next, the trunk-based development manager"
|
description = "git support for git-next, the trunk-based development manager"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
git-next-config = { workspace = true }
|
git-next-core = { workspace = true }
|
||||||
|
|
||||||
# logging
|
# logging
|
||||||
# console-subscriber = { workspace = true }
|
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
# tracing-subscriber = { workspace = true }
|
|
||||||
|
|
||||||
# # base64 decoding
|
|
||||||
# base64 = { workspace = true }
|
|
||||||
#
|
|
||||||
# git
|
# git
|
||||||
# # gix = { workspace = true }
|
|
||||||
gix = { workspace = true }
|
gix = { workspace = true }
|
||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
|
|
||||||
|
@ -27,7 +21,6 @@ kxio = { workspace = true }
|
||||||
|
|
||||||
# TOML parsing
|
# TOML parsing
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
# toml = { workspace = true }
|
|
||||||
|
|
||||||
# webhooks - user notification
|
# webhooks - user notification
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
|
@ -35,26 +28,13 @@ serde = { workspace = true }
|
||||||
# Secrets and Password
|
# Secrets and Password
|
||||||
secrecy = { workspace = true }
|
secrecy = { workspace = true }
|
||||||
|
|
||||||
# # Conventional Commit check
|
|
||||||
# git-conventional = { workspace = true }
|
|
||||||
#
|
|
||||||
# # Webhooks
|
|
||||||
# bytes = { workspace = true }
|
|
||||||
# ulid = { workspace = true }
|
|
||||||
# warp = { workspace = true }
|
|
||||||
|
|
||||||
# error handling
|
# error handling
|
||||||
derive_more = { workspace = true }
|
derive_more = { workspace = true }
|
||||||
derive-with = { workspace = true }
|
derive-with = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
# # file watcher
|
|
||||||
# inotify = { workspace = true }
|
|
||||||
|
|
||||||
# Actors
|
# Actors
|
||||||
actix = { workspace = true }
|
actix = { workspace = true }
|
||||||
# actix-rt = { workspace = true }
|
|
||||||
# tokio = { workspace = true }
|
|
||||||
|
|
||||||
mockall = { workspace = true }
|
mockall = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use config::newtype;
|
|
||||||
use derive_more::Display;
|
|
||||||
//
|
//
|
||||||
use git_next_config as config;
|
use git_next_core::{newtype, webhook};
|
||||||
|
|
||||||
|
use derive_more::Display;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -30,8 +30,8 @@ impl Commit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<config::webhook::Push> for Commit {
|
impl From<webhook::Push> for Commit {
|
||||||
fn from(value: config::webhook::Push) -> Self {
|
fn from(value: webhook::Push) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
Sha::new(value.sha().to_owned()),
|
Sha::new(value.sha().to_owned()),
|
||||||
Message::new(value.message().to_owned()),
|
Message::new(value.message().to_owned()),
|
||||||
|
@ -50,18 +50,14 @@ pub struct Histories {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod log {
|
pub mod log {
|
||||||
|
use git_next_core::BranchName;
|
||||||
use git_next_config as config;
|
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Error>;
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("branch: {branch}, error: {error}")]
|
#[error("branch: {branch}, error: {error}")]
|
||||||
Gix {
|
Gix { branch: BranchName, error: String },
|
||||||
branch: config::BranchName,
|
|
||||||
error: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("lock")]
|
#[error("lock")]
|
||||||
Lock,
|
Lock,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
use git_next_config::{
|
use git_next_core::{
|
||||||
common::{branch_name, repo_alias, repo_path},
|
common::{branch_name, repo_alias, repo_path},
|
||||||
ForgeDetails, GitDir, RepoConfig,
|
ForgeDetails, GitDir, RepoConfig,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
//
|
||||||
use crate as git;
|
use crate as git;
|
||||||
use git_next_config as config;
|
|
||||||
|
use git_next_core::{
|
||||||
|
server::WebhookUrl, webhook, ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId,
|
||||||
|
};
|
||||||
|
|
||||||
#[mockall::automock]
|
#[mockall::automock]
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
|
@ -8,43 +12,33 @@ pub trait ForgeLike: std::fmt::Debug + Send + Sync {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
|
|
||||||
/// Checks that the message has a valid authorisation.
|
/// Checks that the message has a valid authorisation.
|
||||||
fn is_message_authorised(
|
fn is_message_authorised(&self, message: &ForgeNotification, expected: &WebhookAuth) -> bool;
|
||||||
&self,
|
|
||||||
message: &config::ForgeNotification,
|
|
||||||
expected: &config::WebhookAuth,
|
|
||||||
) -> bool;
|
|
||||||
|
|
||||||
/// Checks if the message should be ignored.
|
/// Checks if the message should be ignored.
|
||||||
///
|
///
|
||||||
/// Default implementation says that no messages should be ignored.
|
/// Default implementation says that no messages should be ignored.
|
||||||
fn should_ignore_message(&self, _message: &config::ForgeNotification) -> bool {
|
fn should_ignore_message(&self, _message: &ForgeNotification) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the webhook body into Some(Push) struct if appropriate, or None if not.
|
/// Parses the webhook body into Some(Push) struct if appropriate, or None if not.
|
||||||
fn parse_webhook_body(
|
fn parse_webhook_body(
|
||||||
&self,
|
&self,
|
||||||
body: &config::webhook::forge_notification::Body,
|
body: &webhook::forge_notification::Body,
|
||||||
) -> git::forge::webhook::Result<config::webhook::push::Push>;
|
) -> git::forge::webhook::Result<webhook::push::Push>;
|
||||||
|
|
||||||
/// Checks the results of any (e.g. CI) status checks for the commit.
|
/// Checks the results of any (e.g. CI) status checks for the commit.
|
||||||
async fn commit_status(&self, commit: &git::Commit) -> git::forge::commit::Status;
|
async fn commit_status(&self, commit: &git::Commit) -> git::forge::commit::Status;
|
||||||
|
|
||||||
// Lists all the webhooks
|
// Lists all the webhooks
|
||||||
async fn list_webhooks(
|
async fn list_webhooks(&self, url: &WebhookUrl) -> git::forge::webhook::Result<Vec<WebhookId>>;
|
||||||
&self,
|
|
||||||
url: &config::server::WebhookUrl,
|
|
||||||
) -> git::forge::webhook::Result<Vec<config::WebhookId>>;
|
|
||||||
|
|
||||||
// Unregisters a webhook
|
// Unregisters a webhook
|
||||||
async fn unregister_webhook(
|
async fn unregister_webhook(&self, webhook: &WebhookId) -> git::forge::webhook::Result<()>;
|
||||||
&self,
|
|
||||||
webhook: &config::WebhookId,
|
|
||||||
) -> git::forge::webhook::Result<()>;
|
|
||||||
|
|
||||||
// Registers a webhook
|
// Registers a webhook
|
||||||
async fn register_webhook(
|
async fn register_webhook(
|
||||||
&self,
|
&self,
|
||||||
webhook_url: &config::server::WebhookUrl,
|
webhook_url: &WebhookUrl,
|
||||||
) -> git::forge::webhook::Result<config::RegisteredWebhook>;
|
) -> git::forge::webhook::Result<RegisteredWebhook>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use git_next_config::newtype;
|
use git_next_core::newtype;
|
||||||
|
|
||||||
newtype!(Generation: u32, Display, Default, Copy: r#"A counter for the server generation.
|
newtype!(Generation: u32, Display, Default, Copy: r#"A counter for the server generation.
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//
|
//
|
||||||
use crate as git;
|
use git_next_core::newtype;
|
||||||
use derive_more::Display;
|
|
||||||
use git_next_config::newtype;
|
|
||||||
|
|
||||||
use crate::Commit;
|
use derive_more::Display;
|
||||||
|
|
||||||
|
use crate::{commit::Sha, Commit};
|
||||||
|
|
||||||
newtype!(GitRef: String, Display: "A git reference to a git commit.");
|
newtype!(GitRef: String, Display: "A git reference to a git commit.");
|
||||||
impl From<Commit> for GitRef {
|
impl From<Commit> for GitRef {
|
||||||
|
@ -11,8 +11,8 @@ impl From<Commit> for GitRef {
|
||||||
Self(value.sha().to_string())
|
Self(value.sha().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<git::commit::Sha> for GitRef {
|
impl From<Sha> for GitRef {
|
||||||
fn from(value: git::commit::Sha) -> Self {
|
fn from(value: Sha) -> Self {
|
||||||
Self(value.to_string())
|
Self(value.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use git_next_config::{Hostname, RepoPath};
|
//
|
||||||
|
use derive_more::{Constructor, Display};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, derive_more::Constructor, derive_more::Display)]
|
use git_next_core::{Hostname, RepoPath};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Constructor, Display)]
|
||||||
#[display("{}:{}", host, repo_path)]
|
#[display("{}:{}", host, repo_path)]
|
||||||
pub struct GitRemote {
|
pub struct GitRemote {
|
||||||
host: Hostname,
|
host: Hostname,
|
||||||
|
|
|
@ -23,6 +23,6 @@ pub use generation::Generation;
|
||||||
pub use git_ref::GitRef;
|
pub use git_ref::GitRef;
|
||||||
pub use git_remote::GitRemote;
|
pub use git_remote::GitRemote;
|
||||||
pub use repo_details::RepoDetails;
|
pub use repo_details::RepoDetails;
|
||||||
pub use repository::OpenRepository;
|
|
||||||
pub use repository::Repository;
|
pub use repository::Repository;
|
||||||
|
pub use repository::RepositoryFactory;
|
||||||
pub use user_notification::UserNotification;
|
pub use user_notification::UserNotification;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use super::GitRef;
|
//
|
||||||
use crate as git;
|
use crate::{self as git, repository::open::OpenRepositoryLike};
|
||||||
use git_next_config as config;
|
use git_next_core::BranchName;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Force {
|
pub enum Force {
|
||||||
No,
|
No,
|
||||||
From(GitRef),
|
From(git::GitRef),
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for Force {
|
impl std::fmt::Display for Force {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -47,9 +47,9 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(
|
pub fn reset(
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
to_commit: &git::GitRef,
|
to_commit: &git::GitRef,
|
||||||
force: &git::push::Force,
|
force: &git::push::Force,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
|
//
|
||||||
|
use crate::{
|
||||||
|
repository::open::{oreal::RealOpenRepository, OpenRepositoryLike},
|
||||||
|
Generation, GitRemote,
|
||||||
|
};
|
||||||
|
use git_next_core::{
|
||||||
|
pike, BranchName, ForgeAlias, ForgeConfig, ForgeDetails, GitDir, Hostname, RemoteUrl,
|
||||||
|
RepoAlias, RepoConfig, RepoPath, ServerRepoConfig, StoragePathType,
|
||||||
|
};
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use config::{
|
|
||||||
BranchName, ForgeAlias, ForgeConfig, ForgeDetails, GitDir, RepoAlias, RepoConfig, RepoPath,
|
|
||||||
ServerRepoConfig, StoragePathType,
|
|
||||||
};
|
|
||||||
use git_next_config::{self as config, pike, RemoteUrl};
|
|
||||||
use secrecy::Secret;
|
use secrecy::Secret;
|
||||||
|
|
||||||
use crate::repository::{OpenRepositoryLike, RealOpenRepository};
|
|
||||||
|
|
||||||
use super::{Generation, GitRemote};
|
|
||||||
|
|
||||||
/// The derived information about a repo, used to interact with it
|
/// The derived information about a repo, used to interact with it
|
||||||
#[derive(Clone, Debug, derive_more::Display, derive_with::With)]
|
#[derive(Clone, Debug, derive_more::Display, derive_with::With)]
|
||||||
#[display("gen-{}:{}:{}/{}", generation, forge.forge_type(), forge.forge_alias(), repo_alias )]
|
#[display("gen-{}:{}:{}/{}", generation, forge.forge_type(), forge.forge_alias(), repo_alias )]
|
||||||
|
@ -68,7 +69,7 @@ impl RepoDetails {
|
||||||
GitRemote::new(self.forge.hostname().clone(), self.repo_path.clone())
|
GitRemote::new(self.forge.hostname().clone(), self.repo_path.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_hostname(mut self, hostname: config::Hostname) -> Self {
|
pub fn with_hostname(mut self, hostname: Hostname) -> Self {
|
||||||
let forge = self.forge;
|
let forge = self.forge;
|
||||||
self.forge = forge.with_hostname(hostname);
|
self.forge = forge.with_hostname(hostname);
|
||||||
self
|
self
|
||||||
|
@ -101,7 +102,7 @@ impl RepoDetails {
|
||||||
Ok(repo)
|
Ok(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remote_url(&self) -> Option<git_next_config::RemoteUrl> {
|
pub fn remote_url(&self) -> Option<RemoteUrl> {
|
||||||
use secrecy::ExposeSecret;
|
use secrecy::ExposeSecret;
|
||||||
RemoteUrl::parse(self.url().expose_secret())
|
RemoteUrl::parse(self.url().expose_secret())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
use super::RepoDetails;
|
//
|
||||||
use super::Result;
|
use crate::{
|
||||||
pub use crate::repository::open::OpenRepositoryLike;
|
repository::{
|
||||||
use crate::repository::{Direction, RealOpenRepository};
|
open::{oreal::RealOpenRepository, OpenRepositoryLike},
|
||||||
|
Direction, Result,
|
||||||
|
},
|
||||||
|
RepoDetails,
|
||||||
|
};
|
||||||
|
|
||||||
use derive_more::Deref as _;
|
use derive_more::Deref as _;
|
||||||
|
|
||||||
use std::sync::{atomic::AtomicBool, Arc, RwLock};
|
use std::sync::{atomic::AtomicBool, Arc, RwLock};
|
||||||
|
|
||||||
#[mockall::automock]
|
#[mockall::automock]
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
//
|
//
|
||||||
use super::RepoDetails;
|
use crate::{
|
||||||
use crate::repository::test::TestRepository;
|
repository::{
|
||||||
use crate::validation::remotes::validate_default_remotes;
|
open::{OpenRepository, OpenRepositoryLike},
|
||||||
pub use factory::RepositoryFactory;
|
test::TestRepository,
|
||||||
use git_next_config::{GitDir, RemoteUrl};
|
},
|
||||||
pub use open::otest::OnFetch;
|
validation::remotes::validate_default_remotes,
|
||||||
pub use open::otest::OnPush;
|
RepoDetails,
|
||||||
pub use open::OpenRepository;
|
};
|
||||||
pub use open::OpenRepositoryLike;
|
use git_next_core::{GitDir, RemoteUrl};
|
||||||
pub use open::RealOpenRepository;
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
pub mod factory;
|
pub mod factory;
|
||||||
pub mod open;
|
pub mod open;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
|
pub use factory::RepositoryFactory;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
@ -85,7 +87,7 @@ pub type Result<T> = core::result::Result<T, Error>;
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("invalid git dir: {0}")]
|
#[error("invalid git dir: {0}")]
|
||||||
InvalidGitDir(git_next_config::GitDir),
|
InvalidGitDir(GitDir),
|
||||||
|
|
||||||
#[error("kxiofs: {0}")]
|
#[error("kxiofs: {0}")]
|
||||||
KxioFs(#[from] kxio::fs::Error),
|
KxioFs(#[from] kxio::fs::Error),
|
||||||
|
|
|
@ -5,17 +5,18 @@ mod tests;
|
||||||
pub mod oreal;
|
pub mod oreal;
|
||||||
pub mod otest;
|
pub mod otest;
|
||||||
|
|
||||||
|
use crate as git;
|
||||||
|
use git::repository::{
|
||||||
|
open::{oreal::RealOpenRepository, otest::TestOpenRepository},
|
||||||
|
Direction,
|
||||||
|
};
|
||||||
|
use git_next_core::{BranchName, GitDir, RemoteUrl};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate as git;
|
|
||||||
use git::repository::Direction;
|
|
||||||
use git_next_config::{self as config, RemoteUrl};
|
|
||||||
pub use oreal::RealOpenRepository;
|
|
||||||
pub use otest::TestOpenRepository;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum OpenRepository {
|
pub enum OpenRepository {
|
||||||
/// A real git repository.
|
/// A real git repository.
|
||||||
|
@ -41,7 +42,7 @@ pub fn real(gix_repo: gix::Repository) -> OpenRepository {
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))] // don't test mocks
|
#[cfg(not(tarpaulin_include))] // don't test mocks
|
||||||
pub fn test(
|
pub fn test(
|
||||||
gitdir: &config::GitDir,
|
gitdir: &GitDir,
|
||||||
fs: kxio::fs::FileSystem,
|
fs: kxio::fs::FileSystem,
|
||||||
on_fetch: Vec<otest::OnFetch>,
|
on_fetch: Vec<otest::OnFetch>,
|
||||||
on_push: Vec<otest::OnPush>,
|
on_push: Vec<otest::OnPush>,
|
||||||
|
@ -52,13 +53,13 @@ pub fn test(
|
||||||
#[mockall::automock]
|
#[mockall::automock]
|
||||||
pub trait OpenRepositoryLike: std::fmt::Debug + Sync {
|
pub trait OpenRepositoryLike: std::fmt::Debug + Sync {
|
||||||
fn duplicate(&self) -> Box<dyn OpenRepositoryLike>;
|
fn duplicate(&self) -> Box<dyn OpenRepositoryLike>;
|
||||||
fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>>;
|
fn remote_branches(&self) -> git::push::Result<Vec<BranchName>>;
|
||||||
fn find_default_remote(&self, direction: Direction) -> Option<RemoteUrl>;
|
fn find_default_remote(&self, direction: Direction) -> Option<RemoteUrl>;
|
||||||
fn fetch(&self) -> Result<(), git::fetch::Error>;
|
fn fetch(&self) -> Result<(), git::fetch::Error>;
|
||||||
fn push(
|
fn push(
|
||||||
&self,
|
&self,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
to_commit: &git::GitRef,
|
to_commit: &git::GitRef,
|
||||||
force: &git::push::Force,
|
force: &git::push::Force,
|
||||||
) -> git::push::Result<()>;
|
) -> git::push::Result<()>;
|
||||||
|
@ -66,18 +67,14 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync {
|
||||||
/// List of commits in a branch, optionally up-to any specified commit.
|
/// List of commits in a branch, optionally up-to any specified commit.
|
||||||
fn commit_log(
|
fn commit_log(
|
||||||
&self,
|
&self,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
find_commits: &[git::Commit],
|
find_commits: &[git::Commit],
|
||||||
) -> git::commit::log::Result<Vec<git::Commit>>;
|
) -> git::commit::log::Result<Vec<git::Commit>>;
|
||||||
|
|
||||||
/// Read the contents of a file as a string.
|
/// Read the contents of a file as a string.
|
||||||
///
|
///
|
||||||
/// Only handles files in the root of the repo.
|
/// Only handles files in the root of the repo.
|
||||||
fn read_file(
|
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String>;
|
||||||
&self,
|
|
||||||
branch_name: &config::BranchName,
|
|
||||||
file_name: &Path,
|
|
||||||
) -> git::file::Result<String>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mock() -> Box<MockOpenRepositoryLike> {
|
pub fn mock() -> Box<MockOpenRepositoryLike> {
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
//
|
//
|
||||||
use crate::{self as git, repository::OpenRepositoryLike};
|
use crate::{self as git, repository::OpenRepositoryLike};
|
||||||
use config::BranchName;
|
|
||||||
use derive_more::Constructor;
|
|
||||||
use git_next_config::{self as config, RemoteUrl};
|
|
||||||
|
|
||||||
|
use git_next_core::{BranchName, Hostname, RemoteUrl, RepoPath};
|
||||||
|
|
||||||
|
use derive_more::Constructor;
|
||||||
use gix::bstr::BStr;
|
use gix::bstr::BStr;
|
||||||
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
use tracing::{info, warn};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Constructor)]
|
#[derive(Clone, Debug, Constructor)]
|
||||||
pub struct RealOpenRepository(Arc<RwLock<gix::ThreadSafeRepository>>);
|
pub struct RealOpenRepository(Arc<RwLock<gix::ThreadSafeRepository>>);
|
||||||
impl super::OpenRepositoryLike for RealOpenRepository {
|
impl super::OpenRepositoryLike for RealOpenRepository {
|
||||||
fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>> {
|
fn remote_branches(&self) -> git::push::Result<Vec<BranchName>> {
|
||||||
let refs = self
|
let refs = self
|
||||||
.0
|
.0
|
||||||
.read()
|
.read()
|
||||||
|
@ -87,7 +88,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
|
||||||
fn push(
|
fn push(
|
||||||
&self,
|
&self,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
to_commit: &git::GitRef,
|
to_commit: &git::GitRef,
|
||||||
force: &git::push::Force,
|
force: &git::push::Force,
|
||||||
) -> Result<(), git::push::Error> {
|
) -> Result<(), git::push::Error> {
|
||||||
|
@ -126,7 +127,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
|
||||||
|
|
||||||
fn commit_log(
|
fn commit_log(
|
||||||
&self,
|
&self,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
find_commits: &[git::Commit],
|
find_commits: &[git::Commit],
|
||||||
) -> Result<Vec<crate::Commit>, git::commit::log::Error> {
|
) -> Result<Vec<crate::Commit>, git::commit::log::Error> {
|
||||||
let limit = match find_commits.is_empty() {
|
let limit = match find_commits.is_empty() {
|
||||||
|
@ -187,11 +188,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(%branch_name, ?file_name))]
|
#[tracing::instrument(skip_all, fields(%branch_name, ?file_name))]
|
||||||
fn read_file(
|
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String> {
|
||||||
&self,
|
|
||||||
branch_name: &config::BranchName,
|
|
||||||
file_name: &Path,
|
|
||||||
) -> git::file::Result<String> {
|
|
||||||
self.0
|
self.0
|
||||||
.read()
|
.read()
|
||||||
.map_err(|_| git::file::Error::Lock)
|
.map_err(|_| git::file::Error::Lock)
|
||||||
|
@ -229,9 +226,6 @@ impl From<&RemoteUrl> for git::GitRemote {
|
||||||
let path = url.path.to_string();
|
let path = url.path.to_string();
|
||||||
let path = path.strip_prefix('/').map_or(path.as_str(), |path| path);
|
let path = path.strip_prefix('/').map_or(path.as_str(), |path| path);
|
||||||
let path = path.strip_suffix(".git").map_or(path, |path| path);
|
let path = path.strip_suffix(".git").map_or(path, |path| path);
|
||||||
Self::new(
|
Self::new(Hostname::new(host), RepoPath::new(path.to_string()))
|
||||||
config::Hostname::new(host),
|
|
||||||
config::RepoPath::new(path.to_string()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
//
|
//
|
||||||
use crate::{self as git, repository::OpenRepositoryLike};
|
use crate::{
|
||||||
|
self as git,
|
||||||
|
repository::open::{OpenRepositoryLike, RealOpenRepository},
|
||||||
|
};
|
||||||
|
|
||||||
|
use git_next_core::{BranchName, GitDir, RemoteUrl, RepoBranches};
|
||||||
|
|
||||||
use derive_more::{Constructor, Deref};
|
use derive_more::{Constructor, Deref};
|
||||||
use git_next_config::{self as config, RemoteUrl};
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type OnFetchFn =
|
pub type OnFetchFn = fn(&RepoBranches, &GitDir, &kxio::fs::FileSystem) -> git::fetch::Result<()>;
|
||||||
fn(&config::RepoBranches, &config::GitDir, &kxio::fs::FileSystem) -> git::fetch::Result<()>;
|
|
||||||
#[derive(Clone, Debug, Constructor)]
|
#[derive(Clone, Debug, Constructor)]
|
||||||
pub struct OnFetch {
|
pub struct OnFetch {
|
||||||
repo_branches: config::RepoBranches,
|
repo_branches: RepoBranches,
|
||||||
gitdir: config::GitDir,
|
gitdir: GitDir,
|
||||||
fs: kxio::fs::FileSystem,
|
fs: kxio::fs::FileSystem,
|
||||||
action: OnFetchFn,
|
action: OnFetchFn,
|
||||||
}
|
}
|
||||||
|
@ -25,17 +29,17 @@ impl OnFetch {
|
||||||
|
|
||||||
pub type OnPushFn = fn(
|
pub type OnPushFn = fn(
|
||||||
&git::RepoDetails,
|
&git::RepoDetails,
|
||||||
&config::BranchName,
|
&BranchName,
|
||||||
&git::GitRef,
|
&git::GitRef,
|
||||||
&git::push::Force,
|
&git::push::Force,
|
||||||
&config::RepoBranches,
|
&RepoBranches,
|
||||||
&config::GitDir,
|
&GitDir,
|
||||||
&kxio::fs::FileSystem,
|
&kxio::fs::FileSystem,
|
||||||
) -> git::push::Result<()>;
|
) -> git::push::Result<()>;
|
||||||
#[derive(Clone, Debug, Constructor)]
|
#[derive(Clone, Debug, Constructor)]
|
||||||
pub struct OnPush {
|
pub struct OnPush {
|
||||||
repo_branches: config::RepoBranches,
|
repo_branches: RepoBranches,
|
||||||
gitdir: config::GitDir,
|
gitdir: GitDir,
|
||||||
fs: kxio::fs::FileSystem,
|
fs: kxio::fs::FileSystem,
|
||||||
action: OnPushFn,
|
action: OnPushFn,
|
||||||
}
|
}
|
||||||
|
@ -43,7 +47,7 @@ impl OnPush {
|
||||||
pub fn invoke(
|
pub fn invoke(
|
||||||
&self,
|
&self,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
to_commit: &git::GitRef,
|
to_commit: &git::GitRef,
|
||||||
force: &git::push::Force,
|
force: &git::push::Force,
|
||||||
) -> git::push::Result<()> {
|
) -> git::push::Result<()> {
|
||||||
|
@ -65,11 +69,11 @@ pub struct TestOpenRepository {
|
||||||
fetch_counter: Arc<RwLock<usize>>,
|
fetch_counter: Arc<RwLock<usize>>,
|
||||||
on_push: Vec<OnPush>,
|
on_push: Vec<OnPush>,
|
||||||
push_counter: Arc<RwLock<usize>>,
|
push_counter: Arc<RwLock<usize>>,
|
||||||
real: git::repository::RealOpenRepository,
|
real: RealOpenRepository,
|
||||||
}
|
}
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
impl git::repository::OpenRepositoryLike for TestOpenRepository {
|
impl git::repository::OpenRepositoryLike for TestOpenRepository {
|
||||||
fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>> {
|
fn remote_branches(&self) -> git::push::Result<Vec<BranchName>> {
|
||||||
self.real.remote_branches()
|
self.real.remote_branches()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +100,7 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
|
||||||
fn push(
|
fn push(
|
||||||
&self,
|
&self,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
to_commit: &git::GitRef,
|
to_commit: &git::GitRef,
|
||||||
force: &git::push::Force,
|
force: &git::push::Force,
|
||||||
) -> git::push::Result<()> {
|
) -> git::push::Result<()> {
|
||||||
|
@ -120,17 +124,13 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
|
||||||
|
|
||||||
fn commit_log(
|
fn commit_log(
|
||||||
&self,
|
&self,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
find_commits: &[git::Commit],
|
find_commits: &[git::Commit],
|
||||||
) -> git::commit::log::Result<Vec<crate::Commit>> {
|
) -> git::commit::log::Result<Vec<crate::Commit>> {
|
||||||
self.real.commit_log(branch_name, find_commits)
|
self.real.commit_log(branch_name, find_commits)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_file(
|
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String> {
|
||||||
&self,
|
|
||||||
branch_name: &config::BranchName,
|
|
||||||
file_name: &Path,
|
|
||||||
) -> git::file::Result<String> {
|
|
||||||
self.real.read_file(branch_name, file_name)
|
self.real.read_file(branch_name, file_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
|
||||||
}
|
}
|
||||||
impl TestOpenRepository {
|
impl TestOpenRepository {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gitdir: &config::GitDir,
|
gitdir: &GitDir,
|
||||||
fs: kxio::fs::FileSystem,
|
fs: kxio::fs::FileSystem,
|
||||||
on_fetch: Vec<OnFetch>,
|
on_fetch: Vec<OnFetch>,
|
||||||
on_push: Vec<OnPush>,
|
on_push: Vec<OnPush>,
|
||||||
|
@ -154,11 +154,11 @@ impl TestOpenRepository {
|
||||||
fetch_counter: Arc::new(RwLock::new(0)),
|
fetch_counter: Arc::new(RwLock::new(0)),
|
||||||
on_push,
|
on_push,
|
||||||
push_counter: Arc::new(RwLock::new(0)),
|
push_counter: Arc::new(RwLock::new(0)),
|
||||||
real: git::repository::RealOpenRepository::new(Arc::new(RwLock::new(gix.into()))),
|
real: RealOpenRepository::new(Arc::new(RwLock::new(gix.into()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_origin(gitdir: &config::GitDir, fs: &kxio::fs::FileSystem) {
|
fn write_origin(gitdir: &GitDir, fs: &kxio::fs::FileSystem) {
|
||||||
let config_file = fs.base().join(gitdir.to_path_buf()).join(".git/config");
|
let config_file = fs.base().join(gitdir.to_path_buf()).join(".git/config");
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
let contents = fs
|
let contents = fs
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// assumes running in the git-next repo which should have main, next and dev as remote branches
|
// assumes running in the git-next repo which should have main, next and dev as remote branches
|
||||||
fn should_return_single_item_in_commit_log_when_not_searching() -> TestResult {
|
fn should_return_single_item_in_commit_log_when_not_searching() -> TestResult {
|
||||||
let_assert!(Ok(fs) = kxio::fs::temp());
|
let_assert!(Ok(fs) = kxio::fs::temp());
|
||||||
let gitdir = GitDir::new(
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
fs.base().to_path_buf(),
|
|
||||||
config::git_dir::StoragePathType::Internal,
|
|
||||||
);
|
|
||||||
let test_repository = git::repository::test(fs.clone());
|
let test_repository = git::repository::test(fs.clone());
|
||||||
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
||||||
let repo_config = &given::a_repo_config();
|
let repo_config = &given::a_repo_config();
|
||||||
|
@ -24,10 +22,7 @@ fn should_return_single_item_in_commit_log_when_not_searching() -> TestResult {
|
||||||
fn should_return_capacity_50_in_commit_log_when_searching_for_garbage() -> TestResult {
|
fn should_return_capacity_50_in_commit_log_when_searching_for_garbage() -> TestResult {
|
||||||
let_assert!(Ok(fs) = kxio::fs::temp());
|
let_assert!(Ok(fs) = kxio::fs::temp());
|
||||||
let branch_name = given::a_branch_name();
|
let branch_name = given::a_branch_name();
|
||||||
let gitdir = GitDir::new(
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
fs.base().to_path_buf(),
|
|
||||||
config::git_dir::StoragePathType::Internal,
|
|
||||||
);
|
|
||||||
let test_repository = git::repository::test(fs.clone());
|
let test_repository = git::repository::test(fs.clone());
|
||||||
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
||||||
for _ in [0; 60] {
|
for _ in [0; 60] {
|
||||||
|
@ -44,10 +39,7 @@ fn should_return_capacity_50_in_commit_log_when_searching_for_garbage() -> TestR
|
||||||
fn should_return_5_in_commit_log_when_searching_for_5th_item() -> TestResult {
|
fn should_return_5_in_commit_log_when_searching_for_5th_item() -> TestResult {
|
||||||
let_assert!(Ok(fs) = kxio::fs::temp(), "create temp directory");
|
let_assert!(Ok(fs) = kxio::fs::temp(), "create temp directory");
|
||||||
let branch_name = given::a_branch_name();
|
let branch_name = given::a_branch_name();
|
||||||
let gitdir = GitDir::new(
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
fs.base().to_path_buf(),
|
|
||||||
config::git_dir::StoragePathType::Internal,
|
|
||||||
);
|
|
||||||
let test_repository = git::repository::test(fs.clone());
|
let test_repository = git::repository::test(fs.clone());
|
||||||
let_assert!(
|
let_assert!(
|
||||||
Ok(open_repository) = test_repository.open(&gitdir),
|
Ok(open_repository) = test_repository.open(&gitdir),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -5,10 +6,7 @@ use super::*;
|
||||||
fn should_fetch_from_repo() {
|
fn should_fetch_from_repo() {
|
||||||
// uses the current repo and fetches from the remote server
|
// uses the current repo and fetches from the remote server
|
||||||
let_assert!(Ok(cwd) = std::env::current_dir());
|
let_assert!(Ok(cwd) = std::env::current_dir());
|
||||||
let gitdir = GitDir::new(
|
let gitdir = GitDir::new(cwd.join("../.."), StoragePathType::External);
|
||||||
cwd.join("../.."),
|
|
||||||
config::git_dir::StoragePathType::External,
|
|
||||||
);
|
|
||||||
let repo_details = given::repo_details(&given::a_filesystem()).with_gitdir(gitdir);
|
let repo_details = given::repo_details(&given::a_filesystem()).with_gitdir(gitdir);
|
||||||
let_assert!(Ok(repo) = crate::repository::factory::real().open(&repo_details));
|
let_assert!(Ok(repo) = crate::repository::factory::real().open(&repo_details));
|
||||||
let_assert!(Ok(_) = repo.fetch());
|
let_assert!(Ok(_) = repo.fetch());
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test_log::test]
|
#[test_log::test]
|
||||||
fn should_find_default_push_remote() {
|
fn should_find_default_push_remote() {
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), config::StoragePathType::External);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::External);
|
||||||
let repo_details = given::repo_details(&given::a_filesystem()).with_gitdir(gitdir);
|
let repo_details = given::repo_details(&given::a_filesystem()).with_gitdir(gitdir);
|
||||||
let url = repo_details.url();
|
let url = repo_details.url();
|
||||||
given::a_bare_repo_with_url(fs.base(), url.expose_secret(), &fs);
|
given::a_bare_repo_with_url(fs.base(), url.expose_secret(), &fs);
|
||||||
|
|
|
@ -2,21 +2,19 @@ use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_repos() {
|
fn should_return_repos() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = ForgeType::MockForge;
|
||||||
let hostname = given::a_name();
|
let hostname = given::a_name();
|
||||||
let user = given::a_name();
|
let user = given::a_name();
|
||||||
let token = given::a_name();
|
let token = given::a_name();
|
||||||
// alphabetical order by key
|
// alphabetical order by key
|
||||||
let red_name = format!("a-{}", given::a_name());
|
let red_name = format!("a-{}", given::a_name());
|
||||||
let blue_name = format!("b-{}", given::a_name());
|
let blue_name = format!("b-{}", given::a_name());
|
||||||
let red =
|
let red = ServerRepoConfig::new(red_name.clone(), given::a_name(), None, None, None, None);
|
||||||
config::ServerRepoConfig::new(red_name.clone(), given::a_name(), None, None, None, None);
|
let blue = ServerRepoConfig::new(blue_name.clone(), given::a_name(), None, None, None, None);
|
||||||
let blue =
|
|
||||||
config::ServerRepoConfig::new(blue_name.clone(), given::a_name(), None, None, None, None);
|
|
||||||
let mut repos = BTreeMap::new();
|
let mut repos = BTreeMap::new();
|
||||||
repos.insert(red_name.clone(), red.clone());
|
repos.insert(red_name.clone(), red.clone());
|
||||||
repos.insert(blue_name.clone(), blue.clone());
|
repos.insert(blue_name.clone(), blue.clone());
|
||||||
let fc = config::ForgeConfig::new(forge_type, hostname, user, token, repos);
|
let fc = ForgeConfig::new(forge_type, hostname, user, token, repos);
|
||||||
|
|
||||||
let returned_repos = fc.repos().collect::<Vec<_>>();
|
let returned_repos = fc.repos().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -24,77 +22,75 @@ fn should_return_repos() {
|
||||||
returned_repos,
|
returned_repos,
|
||||||
vec![
|
vec![
|
||||||
// alphabetical order by key
|
// alphabetical order by key
|
||||||
(config::RepoAlias::new(red_name.as_str()), &red),
|
(RepoAlias::new(red_name.as_str()), &red),
|
||||||
(config::RepoAlias::new(blue_name.as_str()), &blue),
|
(RepoAlias::new(blue_name.as_str()), &blue),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_forge_type() {
|
fn should_return_forge_type() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = ForgeType::MockForge;
|
||||||
let hostname = given::a_name();
|
let hostname = given::a_name();
|
||||||
let user = given::a_name();
|
let user = given::a_name();
|
||||||
let token = given::a_name();
|
let token = given::a_name();
|
||||||
let repos = BTreeMap::new();
|
let repos = BTreeMap::new();
|
||||||
let fc = config::ForgeConfig::new(forge_type, hostname, user, token, repos);
|
let fc = ForgeConfig::new(forge_type, hostname, user, token, repos);
|
||||||
|
|
||||||
assert_eq!(fc.forge_type(), config::ForgeType::MockForge);
|
assert_eq!(fc.forge_type(), ForgeType::MockForge);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_hostname() {
|
fn should_return_hostname() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = ForgeType::MockForge;
|
||||||
let hostname = given::a_name();
|
let hostname = given::a_name();
|
||||||
let user = given::a_name();
|
let user = given::a_name();
|
||||||
let token = given::a_name();
|
let token = given::a_name();
|
||||||
let repos = BTreeMap::new();
|
let repos = BTreeMap::new();
|
||||||
let fc = config::ForgeConfig::new(forge_type, hostname.clone(), user, token, repos);
|
let fc = ForgeConfig::new(forge_type, hostname.clone(), user, token, repos);
|
||||||
|
|
||||||
assert_eq!(fc.hostname(), config::Hostname::new(hostname));
|
assert_eq!(fc.hostname(), Hostname::new(hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_user() {
|
fn should_return_user() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = ForgeType::MockForge;
|
||||||
let hostname = given::a_name();
|
let hostname = given::a_name();
|
||||||
let user = given::a_name();
|
let user = given::a_name();
|
||||||
let token = given::a_name();
|
let token = given::a_name();
|
||||||
let repos = BTreeMap::new();
|
let repos = BTreeMap::new();
|
||||||
let fc = config::ForgeConfig::new(forge_type, hostname, user.clone(), token, repos);
|
let fc = ForgeConfig::new(forge_type, hostname, user.clone(), token, repos);
|
||||||
|
|
||||||
assert_eq!(fc.user(), config::User::new(user));
|
assert_eq!(fc.user(), User::new(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_token() {
|
fn should_return_token() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = ForgeType::MockForge;
|
||||||
let hostname = given::a_name();
|
let hostname = given::a_name();
|
||||||
let user = given::a_name();
|
let user = given::a_name();
|
||||||
let token = given::a_name();
|
let token = given::a_name();
|
||||||
let repos = BTreeMap::new();
|
let repos = BTreeMap::new();
|
||||||
let fc = config::ForgeConfig::new(forge_type, hostname, user, token.clone(), repos);
|
let fc = ForgeConfig::new(forge_type, hostname, user, token.clone(), repos);
|
||||||
|
|
||||||
assert_eq!(fc.token().expose_secret(), token.as_str());
|
assert_eq!(fc.token().expose_secret(), token.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_repo() {
|
fn should_return_repo() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = ForgeType::MockForge;
|
||||||
let hostname = given::a_name();
|
let hostname = given::a_name();
|
||||||
let user = given::a_name();
|
let user = given::a_name();
|
||||||
let token = given::a_name();
|
let token = given::a_name();
|
||||||
let red_name = given::a_name();
|
let red_name = given::a_name();
|
||||||
let blue_name = given::a_name();
|
let blue_name = given::a_name();
|
||||||
let red =
|
let red = ServerRepoConfig::new(red_name.clone(), given::a_name(), None, None, None, None);
|
||||||
config::ServerRepoConfig::new(red_name.clone(), given::a_name(), None, None, None, None);
|
let blue = ServerRepoConfig::new(blue_name.clone(), given::a_name(), None, None, None, None);
|
||||||
let blue =
|
|
||||||
config::ServerRepoConfig::new(blue_name.clone(), given::a_name(), None, None, None, None);
|
|
||||||
|
|
||||||
let mut repos = BTreeMap::new();
|
let mut repos = BTreeMap::new();
|
||||||
repos.insert(red_name.clone(), red.clone());
|
repos.insert(red_name.clone(), red.clone());
|
||||||
repos.insert(blue_name, blue);
|
repos.insert(blue_name, blue);
|
||||||
let fc = config::ForgeConfig::new(forge_type, hostname, user, token, repos);
|
let fc = ForgeConfig::new(forge_type, hostname, user, token, repos);
|
||||||
|
|
||||||
let returned_repo = fc.get_repo(red_name.as_str());
|
let returned_repo = fc.get_repo(red_name.as_str());
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
//
|
//
|
||||||
use crate as git;
|
use crate::{
|
||||||
|
self as git,
|
||||||
|
repository::RepositoryLike as _,
|
||||||
|
tests::{given, then},
|
||||||
|
};
|
||||||
|
use git_next_core::{
|
||||||
|
BranchName, ForgeConfig, ForgeType, GitDir, Hostname, RepoAlias, RepoBranches, RepoConfig,
|
||||||
|
RepoConfigSource, RepoPath, ServerRepoConfig, StoragePathType, User,
|
||||||
|
};
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
use config::GitDir;
|
|
||||||
use git::repository::RepositoryLike as _;
|
|
||||||
use git::tests::given;
|
|
||||||
use git::tests::then;
|
|
||||||
use git_next_config as config;
|
|
||||||
use secrecy::ExposeSecret;
|
use secrecy::ExposeSecret;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::path::PathBuf;
|
use std::{collections::BTreeMap, path::PathBuf};
|
||||||
|
|
||||||
type TestResult = Result<(), Box<dyn std::error::Error>>;
|
type TestResult = Result<(), Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -7,10 +8,7 @@ fn should_return_file() -> TestResult {
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
let file_name = given::a_pathbuf();
|
let file_name = given::a_pathbuf();
|
||||||
let contents = given::a_name();
|
let contents = given::a_name();
|
||||||
let gitdir = GitDir::new(
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
fs.base().to_path_buf(),
|
|
||||||
config::git_dir::StoragePathType::Internal,
|
|
||||||
);
|
|
||||||
|
|
||||||
let test_repository = git::repository::test(fs.clone());
|
let test_repository = git::repository::test(fs.clone());
|
||||||
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
||||||
|
@ -34,10 +32,7 @@ fn should_return_file() -> TestResult {
|
||||||
// assumes running in the git-next repo which should have main, next and dev as remote branches
|
// assumes running in the git-next repo which should have main, next and dev as remote branches
|
||||||
fn should_error_on_missing_file() -> TestResult {
|
fn should_error_on_missing_file() -> TestResult {
|
||||||
let_assert!(Ok(fs) = kxio::fs::temp());
|
let_assert!(Ok(fs) = kxio::fs::temp());
|
||||||
let gitdir = GitDir::new(
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
fs.base().to_path_buf(),
|
|
||||||
config::git_dir::StoragePathType::Internal,
|
|
||||||
);
|
|
||||||
let test_repository = git::repository::test(fs.clone());
|
let test_repository = git::repository::test(fs.clone());
|
||||||
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
||||||
let repo_config = &given::a_repo_config();
|
let repo_config = &given::a_repo_config();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -14,13 +15,13 @@ fn should_parse_toml() -> TestResult {
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
let rc = config::RepoConfig::parse(toml.as_str())?;
|
let rc = RepoConfig::parse(toml.as_str())?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rc,
|
rc,
|
||||||
config::RepoConfig::new(
|
RepoConfig::new(
|
||||||
config::RepoBranches::new(main, next, dev),
|
RepoBranches::new(main, next, dev),
|
||||||
config::RepoConfigSource::Repo // reading from repo is the default
|
RepoConfigSource::Repo // reading from repo is the default
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -31,8 +32,8 @@ fn should_return_branches() {
|
||||||
let main = given::a_name();
|
let main = given::a_name();
|
||||||
let next = given::a_name();
|
let next = given::a_name();
|
||||||
let dev = given::a_name();
|
let dev = given::a_name();
|
||||||
let branches = config::RepoBranches::new(main, next, dev);
|
let branches = RepoBranches::new(main, next, dev);
|
||||||
let repo_config = config::RepoConfig::new(branches.clone(), config::RepoConfigSource::Repo);
|
let repo_config = RepoConfig::new(branches.clone(), RepoConfigSource::Repo);
|
||||||
|
|
||||||
assert_eq!(repo_config.branches(), &branches);
|
assert_eq!(repo_config.branches(), &branches);
|
||||||
}
|
}
|
||||||
|
@ -41,10 +42,7 @@ fn should_return_source() {
|
||||||
let main = given::a_name();
|
let main = given::a_name();
|
||||||
let next = given::a_name();
|
let next = given::a_name();
|
||||||
let dev = given::a_name();
|
let dev = given::a_name();
|
||||||
let repo_config = config::RepoConfig::new(
|
let repo_config = RepoConfig::new(RepoBranches::new(main, next, dev), RepoConfigSource::Repo);
|
||||||
config::RepoBranches::new(main, next, dev),
|
|
||||||
config::RepoConfigSource::Repo,
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(repo_config.source(), config::RepoConfigSource::Repo);
|
assert_eq!(repo_config.source(), RepoConfigSource::Repo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -5,8 +6,7 @@ fn should_not_return_repo_config_when_no_branches() {
|
||||||
let main = None;
|
let main = None;
|
||||||
let next = None;
|
let next = None;
|
||||||
let dev = None;
|
let dev = None;
|
||||||
let src =
|
let src = ServerRepoConfig::new(given::a_name(), given::a_name(), None, main, next, dev);
|
||||||
config::ServerRepoConfig::new(given::a_name(), given::a_name(), None, main, next, dev);
|
|
||||||
|
|
||||||
let_assert!(None = src.repo_config());
|
let_assert!(None = src.repo_config());
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ fn should_return_repo_config_when_branches() {
|
||||||
let main = given::a_name();
|
let main = given::a_name();
|
||||||
let next = given::a_name();
|
let next = given::a_name();
|
||||||
let dev = given::a_name();
|
let dev = given::a_name();
|
||||||
let src = config::ServerRepoConfig::new(
|
let src = ServerRepoConfig::new(
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
None,
|
None,
|
||||||
|
@ -28,17 +28,14 @@ fn should_return_repo_config_when_branches() {
|
||||||
let_assert!(Some(rc) = src.repo_config());
|
let_assert!(Some(rc) = src.repo_config());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rc,
|
rc,
|
||||||
config::RepoConfig::new(
|
RepoConfig::new(RepoBranches::new(main, next, dev), RepoConfigSource::Server)
|
||||||
config::RepoBranches::new(main, next, dev),
|
|
||||||
config::RepoConfigSource::Server
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_repo() {
|
fn should_return_repo() {
|
||||||
let repo_path = given::a_name();
|
let repo_path = given::a_name();
|
||||||
let src = config::ServerRepoConfig::new(
|
let src = ServerRepoConfig::new(
|
||||||
repo_path.clone(),
|
repo_path.clone(),
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
None,
|
None,
|
||||||
|
@ -47,13 +44,13 @@ fn should_return_repo() {
|
||||||
Some(given::a_name()),
|
Some(given::a_name()),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(src.repo(), config::RepoPath::new(repo_path));
|
assert_eq!(src.repo(), RepoPath::new(repo_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_branch() {
|
fn should_return_branch() {
|
||||||
let branch = given::a_name();
|
let branch = given::a_name();
|
||||||
let src = config::ServerRepoConfig::new(
|
let src = ServerRepoConfig::new(
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
branch.clone(),
|
branch.clone(),
|
||||||
None,
|
None,
|
||||||
|
@ -62,13 +59,13 @@ fn should_return_branch() {
|
||||||
Some(given::a_name()),
|
Some(given::a_name()),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(src.branch(), config::BranchName::new(branch));
|
assert_eq!(src.branch(), BranchName::new(branch));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_gitdir() {
|
fn should_return_gitdir() {
|
||||||
let gitdir = given::a_name();
|
let gitdir = given::a_name();
|
||||||
let src = config::ServerRepoConfig::new(
|
let src = ServerRepoConfig::new(
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
Some(gitdir.clone().into()),
|
Some(gitdir.clone().into()),
|
||||||
|
@ -81,7 +78,7 @@ fn should_return_gitdir() {
|
||||||
src.gitdir(),
|
src.gitdir(),
|
||||||
Some(GitDir::new(
|
Some(GitDir::new(
|
||||||
PathBuf::default().join(gitdir),
|
PathBuf::default().join(gitdir),
|
||||||
config::StoragePathType::External,
|
StoragePathType::External,
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
//
|
//
|
||||||
use derive_more::Constructor;
|
use derive_more::Constructor;
|
||||||
|
|
||||||
use crate as git;
|
use crate::{
|
||||||
use git::repository::RepositoryLike;
|
self as git,
|
||||||
use git_next_config as config;
|
repository::{
|
||||||
|
open::{
|
||||||
|
otest::{OnFetch, OnPush},
|
||||||
|
OpenRepository,
|
||||||
|
},
|
||||||
|
RepositoryLike, Result,
|
||||||
|
},
|
||||||
|
RepoDetails,
|
||||||
|
};
|
||||||
|
use git_next_core::GitDir;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Constructor)]
|
#[derive(Clone, Debug, Constructor)]
|
||||||
pub struct TestRepository {
|
pub struct TestRepository {
|
||||||
|
@ -12,16 +21,16 @@ pub struct TestRepository {
|
||||||
on_push: Vec<git::repository::open::otest::OnPush>,
|
on_push: Vec<git::repository::open::otest::OnPush>,
|
||||||
}
|
}
|
||||||
impl TestRepository {
|
impl TestRepository {
|
||||||
pub fn on_fetch(&mut self, on_fetch: git::repository::OnFetch) {
|
pub fn on_fetch(&mut self, on_fetch: OnFetch) {
|
||||||
self.on_fetch.push(on_fetch);
|
self.on_fetch.push(on_fetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_push(&mut self, on_push: git::repository::OnPush) {
|
pub fn on_push(&mut self, on_push: OnPush) {
|
||||||
self.on_push.push(on_push);
|
self.on_push.push(on_push);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl RepositoryLike for TestRepository {
|
impl RepositoryLike for TestRepository {
|
||||||
fn open(&self, gitdir: &config::GitDir) -> super::Result<crate::OpenRepository> {
|
fn open(&self, gitdir: &GitDir) -> Result<OpenRepository> {
|
||||||
Ok(git::repository::open::test(
|
Ok(git::repository::open::test(
|
||||||
gitdir,
|
gitdir,
|
||||||
self.fs.clone(),
|
self.fs.clone(),
|
||||||
|
@ -30,10 +39,7 @@ impl RepositoryLike for TestRepository {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn git_clone(
|
fn git_clone(&self, _repo_details: &RepoDetails) -> Result<OpenRepository> {
|
||||||
&self,
|
|
||||||
_repo_details: &crate::RepoDetails,
|
|
||||||
) -> super::Result<crate::OpenRepository> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use git_next_config::{ApiToken, GitDir, StoragePathType};
|
//
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::tests::given;
|
|
||||||
|
|
||||||
// clone - can't test are this required a remote server (git_clone only works with https origins)
|
// clone - can't test are this required a remote server (git_clone only works with https origins)
|
||||||
// open
|
// open
|
||||||
// - outside storage path
|
// - outside storage path
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use crate as git;
|
//
|
||||||
|
use crate::{self as git, tests::given};
|
||||||
|
use git_next_core::{ApiToken, GitDir, StoragePathType};
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
|
|
||||||
mod factory;
|
mod factory;
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
#![allow(dead_code)]
|
//
|
||||||
|
use crate::{self as git, Generation, GitRef, GitRemote, RepoDetails};
|
||||||
|
use git_next_core::{
|
||||||
|
git_dir::StoragePathType, webhook, BranchName, ForgeAlias, ForgeConfig, ForgeType, GitDir,
|
||||||
|
Hostname, RemoteUrl, RepoAlias, RepoBranches, RepoConfig, RepoConfigSource, RepoPath,
|
||||||
|
ServerRepoConfig,
|
||||||
|
};
|
||||||
|
|
||||||
use crate as git;
|
use assert2::let_assert;
|
||||||
use git_next_config as config;
|
use secrecy::ExposeSecret;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
type TestResult = Result<(), Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
mod commit {
|
mod commit {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -36,7 +49,7 @@ mod commit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mod generation {
|
mod generation {
|
||||||
use crate::Generation;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_increment() {
|
fn should_increment() {
|
||||||
|
@ -49,12 +62,13 @@ mod generation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mod gitref {
|
mod gitref {
|
||||||
use crate::{commit, Commit, GitRef};
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_convert_from_commit() {
|
fn should_convert_from_commit() {
|
||||||
let commit = Commit::new(
|
let commit = git::Commit::new(
|
||||||
commit::Sha::new("sha".to_string()),
|
git::commit::Sha::new("sha".to_string()),
|
||||||
commit::Message::new("message".to_string()),
|
git::commit::Message::new("message".to_string()),
|
||||||
);
|
);
|
||||||
let gitref = GitRef::from(commit);
|
let gitref = GitRef::from(commit);
|
||||||
|
|
||||||
|
@ -62,9 +76,8 @@ mod gitref {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mod gitremote {
|
mod gitremote {
|
||||||
use git_next_config::{Hostname, RepoPath};
|
|
||||||
|
|
||||||
use crate::GitRemote;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_hostname() {
|
fn should_return_hostname() {
|
||||||
|
@ -85,7 +98,6 @@ mod gitremote {
|
||||||
}
|
}
|
||||||
mod push {
|
mod push {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::GitRef;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn force_no_should_display() {
|
fn force_no_should_display() {
|
||||||
|
@ -104,8 +116,6 @@ mod push {
|
||||||
|
|
||||||
mod reset {
|
mod reset {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests::given;
|
|
||||||
use assert2::let_assert;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_perform_a_fetch_then_push() {
|
fn should_perform_a_fetch_then_push() {
|
||||||
|
@ -141,15 +151,7 @@ mod push {
|
||||||
}
|
}
|
||||||
mod repo_details {
|
mod repo_details {
|
||||||
|
|
||||||
use std::{collections::BTreeMap, path::PathBuf};
|
use super::*;
|
||||||
|
|
||||||
use git_next_config::{
|
|
||||||
git_dir::StoragePathType, ForgeAlias, ForgeConfig, ForgeType, GitDir, Hostname, RepoAlias,
|
|
||||||
RepoPath, ServerRepoConfig,
|
|
||||||
};
|
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
|
|
||||||
use crate::{Generation, GitRemote, RepoDetails};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_origin() {
|
fn should_return_origin() {
|
||||||
|
@ -214,15 +216,7 @@ mod repo_details {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub mod given {
|
pub mod given {
|
||||||
use std::path::{Path, PathBuf};
|
use super::*;
|
||||||
|
|
||||||
use crate::{self as git, repository::open::MockOpenRepositoryLike};
|
|
||||||
use config::{
|
|
||||||
BranchName, ForgeAlias, ForgeConfig, ForgeType, GitDir, RepoAlias, RepoBranches,
|
|
||||||
RepoConfig, ServerRepoConfig,
|
|
||||||
};
|
|
||||||
use git::{tests::given, RepoDetails};
|
|
||||||
use git_next_config as config;
|
|
||||||
|
|
||||||
pub fn repo_branches() -> RepoBranches {
|
pub fn repo_branches() -> RepoBranches {
|
||||||
RepoBranches::new(
|
RepoBranches::new(
|
||||||
|
@ -264,7 +258,7 @@ pub mod given {
|
||||||
pub fn a_git_dir(fs: &kxio::fs::FileSystem) -> GitDir {
|
pub fn a_git_dir(fs: &kxio::fs::FileSystem) -> GitDir {
|
||||||
let dir_name = a_name();
|
let dir_name = a_name();
|
||||||
let dir = fs.base().join(dir_name);
|
let dir = fs.base().join(dir_name);
|
||||||
GitDir::new(dir, config::git_dir::StoragePathType::Internal)
|
GitDir::new(dir, StoragePathType::Internal)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_forge_config() -> ForgeConfig {
|
pub fn a_forge_config() -> ForgeConfig {
|
||||||
|
@ -292,7 +286,7 @@ pub mod given {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_repo_config() -> RepoConfig {
|
pub fn a_repo_config() -> RepoConfig {
|
||||||
RepoConfig::new(given::repo_branches(), config::RepoConfigSource::Repo)
|
RepoConfig::new(given::repo_branches(), RepoConfigSource::Repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_commit() -> git::Commit {
|
pub fn a_commit() -> git::Commit {
|
||||||
|
@ -315,35 +309,17 @@ pub mod given {
|
||||||
git::commit::Sha::new(a_name())
|
git::commit::Sha::new(a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_push(
|
pub fn a_webhook_push(sha: &git::commit::Sha, message: &git::commit::Message) -> webhook::Push {
|
||||||
sha: &git::commit::Sha,
|
|
||||||
message: &git::commit::Message,
|
|
||||||
) -> config::webhook::Push {
|
|
||||||
let branch = a_branch_name();
|
let branch = a_branch_name();
|
||||||
config::webhook::Push::new(branch, sha.to_string(), message.to_string())
|
webhook::Push::new(branch, sha.to_string(), message.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_filesystem() -> kxio::fs::FileSystem {
|
pub fn a_filesystem() -> kxio::fs::FileSystem {
|
||||||
kxio::fs::temp().unwrap_or_else(|e| panic!("{}", e))
|
kxio::fs::temp().unwrap_or_else(|e| panic!("{}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn an_open_repository(
|
pub fn a_hostname() -> Hostname {
|
||||||
fs: &kxio::fs::FileSystem,
|
Hostname::new(given::a_name())
|
||||||
) -> (
|
|
||||||
git::repository::open::MockOpenRepositoryLike,
|
|
||||||
git::RepoDetails,
|
|
||||||
) {
|
|
||||||
let open_repository = MockOpenRepositoryLike::new();
|
|
||||||
let gitdir = given::a_git_dir(fs);
|
|
||||||
let hostname = given::a_hostname();
|
|
||||||
let repo_details = given::repo_details(fs)
|
|
||||||
.with_gitdir(gitdir)
|
|
||||||
.with_hostname(hostname);
|
|
||||||
(open_repository, repo_details)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn a_hostname() -> config::Hostname {
|
|
||||||
config::Hostname::new(given::a_name())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repo_details(fs: &kxio::fs::FileSystem) -> git::RepoDetails {
|
pub fn repo_details(fs: &kxio::fs::FileSystem) -> git::RepoDetails {
|
||||||
|
@ -363,13 +339,6 @@ pub mod given {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_git_remote() -> git::GitRemote {
|
|
||||||
git::GitRemote::new(
|
|
||||||
config::Hostname::new(given::a_name()),
|
|
||||||
config::RepoPath::new(given::a_name()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
pub fn a_bare_repo_with_url(path: &Path, url: &str, fs: &kxio::fs::FileSystem) {
|
pub fn a_bare_repo_with_url(path: &Path, url: &str, fs: &kxio::fs::FileSystem) {
|
||||||
// create a basic bare repo
|
// create a basic bare repo
|
||||||
|
@ -389,17 +358,14 @@ pub mod given {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
pub fn a_remote_url() -> git_next_config::RemoteUrl {
|
pub fn a_remote_url() -> RemoteUrl {
|
||||||
let hostname = given::a_hostname();
|
let hostname = given::a_hostname();
|
||||||
let owner = given::a_name();
|
let owner = given::a_name();
|
||||||
let repo = given::a_name();
|
let repo = given::a_name();
|
||||||
git_next_config::RemoteUrl::parse(format!("git@{hostname}:{owner}/{repo}.git")).unwrap()
|
RemoteUrl::parse(format!("git@{hostname}:{owner}/{repo}.git")).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub mod then {
|
pub mod then {
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
type TestResult = Result<(), Box<dyn std::error::Error>>;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -407,8 +373,8 @@ pub mod then {
|
||||||
file_name: &Path,
|
file_name: &Path,
|
||||||
contents: &str,
|
contents: &str,
|
||||||
fs: &kxio::fs::FileSystem,
|
fs: &kxio::fs::FileSystem,
|
||||||
gitdir: &config::GitDir,
|
gitdir: &GitDir,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
) -> TestResult {
|
) -> TestResult {
|
||||||
// git checkout ${branch_name}
|
// git checkout ${branch_name}
|
||||||
git_checkout_new_branch(branch_name, gitdir)?;
|
git_checkout_new_branch(branch_name, gitdir)?;
|
||||||
|
@ -429,8 +395,8 @@ pub mod then {
|
||||||
|
|
||||||
pub fn create_a_commit_on_branch(
|
pub fn create_a_commit_on_branch(
|
||||||
fs: &kxio::fs::FileSystem,
|
fs: &kxio::fs::FileSystem,
|
||||||
gitdir: &config::GitDir,
|
gitdir: &GitDir,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
) -> TestResult {
|
) -> TestResult {
|
||||||
// git checkout ${branch_name}
|
// git checkout ${branch_name}
|
||||||
git_checkout_new_branch(branch_name, gitdir)?;
|
git_checkout_new_branch(branch_name, gitdir)?;
|
||||||
|
@ -451,8 +417,8 @@ pub mod then {
|
||||||
|
|
||||||
fn push_branch(
|
fn push_branch(
|
||||||
fs: &kxio::fs::FileSystem,
|
fs: &kxio::fs::FileSystem,
|
||||||
gitdir: &config::GitDir,
|
gitdir: &GitDir,
|
||||||
branch_name: &config::BranchName,
|
branch_name: &BranchName,
|
||||||
) -> TestResult {
|
) -> TestResult {
|
||||||
let gitrefs = fs
|
let gitrefs = fs
|
||||||
.base()
|
.base()
|
||||||
|
@ -468,10 +434,7 @@ pub mod then {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn git_checkout_new_branch(
|
pub fn git_checkout_new_branch(branch_name: &BranchName, gitdir: &GitDir) -> TestResult {
|
||||||
branch_name: &git_next_config::BranchName,
|
|
||||||
gitdir: &git_next_config::GitDir,
|
|
||||||
) -> TestResult {
|
|
||||||
exec(
|
exec(
|
||||||
format!("git checkout -b {}", branch_name),
|
format!("git checkout -b {}", branch_name),
|
||||||
std::process::Command::new("/usr/bin/git")
|
std::process::Command::new("/usr/bin/git")
|
||||||
|
@ -482,10 +445,7 @@ pub mod then {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn git_switch(
|
pub fn git_switch(branch_name: &BranchName, gitdir: &GitDir) -> TestResult {
|
||||||
branch_name: &git_next_config::BranchName,
|
|
||||||
gitdir: &git_next_config::GitDir,
|
|
||||||
) -> TestResult {
|
|
||||||
exec(
|
exec(
|
||||||
format!("git switch {}", branch_name),
|
format!("git switch {}", branch_name),
|
||||||
std::process::Command::new("/usr/bin/git")
|
std::process::Command::new("/usr/bin/git")
|
||||||
|
@ -517,7 +477,7 @@ pub mod then {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn git_add_file(gitdir: &git_next_config::GitDir, file: &Path) -> TestResult {
|
fn git_add_file(gitdir: &GitDir, file: &Path) -> TestResult {
|
||||||
exec(
|
exec(
|
||||||
format!("git add {file:?}"),
|
format!("git add {file:?}"),
|
||||||
std::process::Command::new("/usr/bin/git")
|
std::process::Command::new("/usr/bin/git")
|
||||||
|
@ -527,7 +487,7 @@ pub mod then {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn git_commit(gitdir: &git_next_config::GitDir, file: &Path) -> TestResult {
|
fn git_commit(gitdir: &GitDir, file: &Path) -> TestResult {
|
||||||
exec(
|
exec(
|
||||||
format!(r#"git commit -m"Added {file:?}""#),
|
format!(r#"git commit -m"Added {file:?}""#),
|
||||||
std::process::Command::new("/usr/bin/git")
|
std::process::Command::new("/usr/bin/git")
|
||||||
|
@ -540,7 +500,7 @@ pub mod then {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn git_log_all(gitdir: &config::GitDir) -> TestResult {
|
pub fn git_log_all(gitdir: &GitDir) -> TestResult {
|
||||||
exec(
|
exec(
|
||||||
"git log --all --oneline --decorate --graph".to_string(),
|
"git log --all --oneline --decorate --graph".to_string(),
|
||||||
std::process::Command::new("/usr/bin/git")
|
std::process::Command::new("/usr/bin/git")
|
||||||
|
@ -552,8 +512,8 @@ pub mod then {
|
||||||
|
|
||||||
pub fn get_sha_for_branch(
|
pub fn get_sha_for_branch(
|
||||||
fs: &kxio::fs::FileSystem,
|
fs: &kxio::fs::FileSystem,
|
||||||
gitdir: &git_next_config::GitDir,
|
gitdir: &GitDir,
|
||||||
branch_name: &git_next_config::BranchName,
|
branch_name: &BranchName,
|
||||||
) -> Result<git::commit::Sha, Box<dyn std::error::Error>> {
|
) -> Result<git::commit::Sha, Box<dyn std::error::Error>> {
|
||||||
let main_ref = fs
|
let main_ref = fs
|
||||||
.base()
|
.base()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
//
|
||||||
use crate::Commit;
|
use crate::Commit;
|
||||||
use git_next_config::{BranchName, ForgeAlias, RepoAlias};
|
|
||||||
|
use git_next_core::{BranchName, ForgeAlias, RepoAlias};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum UserNotification {
|
pub enum UserNotification {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
use crate::{self as git, UserNotification};
|
use crate::{self as git, repository::open::OpenRepositoryLike, RepoDetails, UserNotification};
|
||||||
use git_next_config as config;
|
use git_next_core::{BranchName, RepoConfig};
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Error>;
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ pub struct Positions {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate_positions(
|
pub fn validate_positions(
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
repo_config: config::RepoConfig,
|
repo_config: RepoConfig,
|
||||||
) -> Result<Positions> {
|
) -> Result<Positions> {
|
||||||
let main_branch = repo_config.branches().main();
|
let main_branch = repo_config.branches().main();
|
||||||
let next_branch = repo_config.branches().next();
|
let next_branch = repo_config.branches().next();
|
||||||
|
@ -77,11 +77,11 @@ pub fn validate_positions(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_next_to_main(
|
fn reset_next_to_main(
|
||||||
open_repository: &dyn crate::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
repo_details: &crate::RepoDetails,
|
repo_details: &RepoDetails,
|
||||||
main: &crate::Commit,
|
main: &git::Commit,
|
||||||
next: &crate::Commit,
|
next: &git::Commit,
|
||||||
next_branch: &config::BranchName,
|
next_branch: &BranchName,
|
||||||
) -> Result<Positions> {
|
) -> Result<Positions> {
|
||||||
git::push::reset(
|
git::push::reset(
|
||||||
open_repository,
|
open_repository,
|
||||||
|
@ -105,8 +105,8 @@ fn is_not_based_on(commits: &[crate::commit::Commit], needle: &crate::Commit) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_commit_histories(
|
fn get_commit_histories(
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
repo_config: &config::RepoConfig,
|
repo_config: &RepoConfig,
|
||||||
) -> git::commit::log::Result<git::commit::Histories> {
|
) -> git::commit::log::Result<git::commit::Histories> {
|
||||||
let main = (open_repository.commit_log(&repo_config.branches().main(), &[]))?;
|
let main = (open_repository.commit_log(&repo_config.branches().main(), &[]))?;
|
||||||
let main_head = [main[0].clone()];
|
let main_head = [main[0].clone()];
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use git_next_config::RemoteUrl;
|
//
|
||||||
use tracing::info;
|
use crate::{self as git, repository::open::OpenRepositoryLike};
|
||||||
|
use git_next_core::RemoteUrl;
|
||||||
|
|
||||||
use crate as git;
|
use tracing::info;
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn validate_default_remotes(
|
pub fn validate_default_remotes(
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let push_remote = open_repository
|
let push_remote = open_repository
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
//
|
//
|
||||||
use crate as git;
|
use crate::{
|
||||||
|
self as git,
|
||||||
use git::repository::RepositoryFactory as _;
|
repository::{
|
||||||
use git::repository::RepositoryLike as _;
|
open::otest::{OnFetch, OnPush},
|
||||||
use git::tests::given;
|
Direction,
|
||||||
use git_next_config as config;
|
},
|
||||||
|
tests::then,
|
||||||
|
};
|
||||||
|
use git::{
|
||||||
|
repository::{factory::RepositoryFactory as _, RepositoryLike as _},
|
||||||
|
tests::given,
|
||||||
|
validation::positions::validate_positions,
|
||||||
|
};
|
||||||
|
use git_next_core::{GitDir, StoragePathType};
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
|
|
||||||
mod repos {
|
mod repos {
|
||||||
|
|
||||||
use config::{git_dir::StoragePathType, GitDir};
|
|
||||||
|
|
||||||
use crate::repository::Direction;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -51,11 +55,6 @@ mod positions {
|
||||||
|
|
||||||
mod validate_positions {
|
mod validate_positions {
|
||||||
|
|
||||||
use config::{git_dir::StoragePathType, GitDir};
|
|
||||||
use git::validation::positions::validate_positions;
|
|
||||||
|
|
||||||
use git::tests::then;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -211,7 +210,7 @@ mod positions {
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
let mut test_repository = git::repository::test(fs.clone());
|
let mut test_repository = git::repository::test(fs.clone());
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -261,7 +260,7 @@ mod positions {
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
let mut test_repository = git::repository::test(fs.clone());
|
let mut test_repository = git::repository::test(fs.clone());
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -285,7 +284,7 @@ mod positions {
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
// second fetch as prep to push
|
// second fetch as prep to push
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -294,7 +293,7 @@ mod positions {
|
||||||
git::fetch::Result::Ok(())
|
git::fetch::Result::Ok(())
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
test_repository.on_push(git::repository::OnPush::new(
|
test_repository.on_push(OnPush::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -347,7 +346,7 @@ mod positions {
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
let mut test_repository = git::repository::test(fs.clone());
|
let mut test_repository = git::repository::test(fs.clone());
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -371,7 +370,7 @@ mod positions {
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
// second fetch as prep to push
|
// second fetch as prep to push
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -380,7 +379,7 @@ mod positions {
|
||||||
git::fetch::Result::Ok(())
|
git::fetch::Result::Ok(())
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
test_repository.on_push(git::repository::OnPush::new(
|
test_repository.on_push(OnPush::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -420,7 +419,7 @@ mod positions {
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
let mut test_repository = git::repository::test(fs.clone());
|
let mut test_repository = git::repository::test(fs.clone());
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -442,7 +441,7 @@ mod positions {
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
// second fetch as prep to push
|
// second fetch as prep to push
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -451,7 +450,7 @@ mod positions {
|
||||||
git::fetch::Result::Ok(())
|
git::fetch::Result::Ok(())
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
test_repository.on_push(git::repository::OnPush::new(
|
test_repository.on_push(OnPush::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -504,7 +503,7 @@ mod positions {
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
let mut test_repository = git::repository::test(fs.clone());
|
let mut test_repository = git::repository::test(fs.clone());
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -526,7 +525,7 @@ mod positions {
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
// second fetch as prep to push
|
// second fetch as prep to push
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -535,7 +534,7 @@ mod positions {
|
||||||
git::fetch::Result::Ok(())
|
git::fetch::Result::Ok(())
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
test_repository.on_push(git::repository::OnPush::new(
|
test_repository.on_push(OnPush::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
@ -575,7 +574,7 @@ mod positions {
|
||||||
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal);
|
||||||
let mut test_repository = git::repository::test(fs.clone());
|
let mut test_repository = git::repository::test(fs.clone());
|
||||||
let repo_config = given::a_repo_config();
|
let repo_config = given::a_repo_config();
|
||||||
test_repository.on_fetch(git::repository::OnFetch::new(
|
test_repository.on_fetch(OnFetch::new(
|
||||||
repo_config.branches().clone(),
|
repo_config.branches().clone(),
|
||||||
gitdir.clone(),
|
gitdir.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
|
|
|
@ -13,7 +13,6 @@ github = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
git-next-core = { workspace = true }
|
git-next-core = { workspace = true }
|
||||||
git-next-config = { workspace = true }
|
|
||||||
git-next-git = { workspace = true }
|
git-next-git = { workspace = true }
|
||||||
git-next-forge = { workspace = true }
|
git-next-forge = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
use crate::messages::MessageToken;
|
use crate::messages::MessageToken;
|
||||||
use git_next_config as config;
|
use git_next_core::RepoConfig;
|
||||||
use git_next_git as git;
|
use git_next_git::{self as git, repository::open::OpenRepositoryLike};
|
||||||
|
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
@ -12,8 +12,8 @@ pub fn advance_next(
|
||||||
next: &git::Commit,
|
next: &git::Commit,
|
||||||
dev_commit_history: &[git::Commit],
|
dev_commit_history: &[git::Commit],
|
||||||
repo_details: git::RepoDetails,
|
repo_details: git::RepoDetails,
|
||||||
repo_config: config::RepoConfig,
|
repo_config: RepoConfig,
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
message_token: MessageToken,
|
message_token: MessageToken,
|
||||||
) -> Result<MessageToken> {
|
) -> Result<MessageToken> {
|
||||||
let commit =
|
let commit =
|
||||||
|
@ -69,8 +69,8 @@ pub fn find_next_commit_on_dev(
|
||||||
pub fn advance_main(
|
pub fn advance_main(
|
||||||
next: git::Commit,
|
next: git::Commit,
|
||||||
repo_details: &git::RepoDetails,
|
repo_details: &git::RepoDetails,
|
||||||
repo_config: &config::RepoConfig,
|
repo_config: &RepoConfig,
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("Advancing main to next");
|
info!("Advancing main to next");
|
||||||
git::push::reset(
|
git::push::reset(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//
|
//
|
||||||
use crate as actor;
|
use crate as actor;
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
use git_next_core::RepoConfigSource;
|
||||||
|
|
||||||
impl Handler<actor::messages::AdvanceMain> for actor::RepoActor {
|
impl Handler<actor::messages::AdvanceMain> for actor::RepoActor {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
|
@ -31,10 +32,10 @@ impl Handler<actor::messages::AdvanceMain> for actor::RepoActor {
|
||||||
tracing::warn!("advance main: {err}");
|
tracing::warn!("advance main: {err}");
|
||||||
}
|
}
|
||||||
Ok(_) => match repo_config.source() {
|
Ok(_) => match repo_config.source() {
|
||||||
git_next_config::RepoConfigSource::Repo => {
|
RepoConfigSource::Repo => {
|
||||||
actor::do_send(addr, actor::messages::LoadConfigFromRepo, self.log.as_ref());
|
actor::do_send(addr, actor::messages::LoadConfigFromRepo, self.log.as_ref());
|
||||||
}
|
}
|
||||||
git_next_config::RepoConfigSource::Server => {
|
RepoConfigSource::Server => {
|
||||||
actor::do_send(
|
actor::do_send(
|
||||||
addr,
|
addr,
|
||||||
actor::messages::ValidateRepo::new(message_token),
|
actor::messages::ValidateRepo::new(message_token),
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
|
||||||
use crate::{self as actor, messages::WebhookNotification, RepoActorLog};
|
use crate::{self as actor, messages::WebhookNotification, RepoActorLog};
|
||||||
use git_next_config::WebhookAuth;
|
use git_next_core::{
|
||||||
use git_next_config::{
|
|
||||||
webhook::{push::Branch, Push},
|
webhook::{push::Branch, Push},
|
||||||
BranchName,
|
BranchName, WebhookAuth,
|
||||||
};
|
};
|
||||||
use git_next_git::{self as git, Commit, ForgeLike};
|
use git_next_git::{self as git, Commit, ForgeLike};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
//
|
||||||
|
use actix::prelude::*;
|
||||||
|
|
||||||
|
use derive_more::Deref;
|
||||||
|
use kxio::network::Network;
|
||||||
|
use messages::NotifyUser;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tracing::{info, warn, Instrument};
|
||||||
|
|
||||||
|
use git_next_core::{server, WebhookAuth, WebhookId};
|
||||||
|
use git_next_git::{
|
||||||
|
self as git,
|
||||||
|
repository::{factory::RepositoryFactory, open::OpenRepositoryLike},
|
||||||
|
UserNotification,
|
||||||
|
};
|
||||||
|
|
||||||
mod branch;
|
mod branch;
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
mod load;
|
mod load;
|
||||||
|
@ -7,18 +23,6 @@ mod notifications;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use actix::prelude::*;
|
|
||||||
|
|
||||||
use derive_more::Deref;
|
|
||||||
use git_next_config as config;
|
|
||||||
use git_next_git::{self as git, UserNotification};
|
|
||||||
use messages::NotifyUser;
|
|
||||||
|
|
||||||
use kxio::network::Network;
|
|
||||||
use tracing::{info, warn, Instrument};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct RepoActorLog(std::sync::Arc<std::sync::RwLock<Vec<String>>>);
|
pub struct RepoActorLog(std::sync::Arc<std::sync::RwLock<Vec<String>>>);
|
||||||
impl Deref for RepoActorLog {
|
impl Deref for RepoActorLog {
|
||||||
|
@ -39,14 +43,14 @@ pub struct RepoActor {
|
||||||
generation: git::Generation,
|
generation: git::Generation,
|
||||||
message_token: messages::MessageToken,
|
message_token: messages::MessageToken,
|
||||||
repo_details: git::RepoDetails,
|
repo_details: git::RepoDetails,
|
||||||
webhook: config::server::InboundWebhook,
|
webhook: server::InboundWebhook,
|
||||||
webhook_id: Option<config::WebhookId>, // INFO: if [None] then no webhook is configured
|
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
|
||||||
webhook_auth: Option<config::WebhookAuth>, // INFO: if [None] then no webhook is configured
|
webhook_auth: Option<WebhookAuth>, // INFO: if [None] then no webhook is configured
|
||||||
last_main_commit: Option<git::Commit>,
|
last_main_commit: Option<git::Commit>,
|
||||||
last_next_commit: Option<git::Commit>,
|
last_next_commit: Option<git::Commit>,
|
||||||
last_dev_commit: Option<git::Commit>,
|
last_dev_commit: Option<git::Commit>,
|
||||||
repository_factory: Box<dyn git::repository::RepositoryFactory>,
|
repository_factory: Box<dyn RepositoryFactory>,
|
||||||
open_repository: Option<Box<dyn git::repository::OpenRepositoryLike>>,
|
open_repository: Option<Box<dyn OpenRepositoryLike>>,
|
||||||
net: Network,
|
net: Network,
|
||||||
forge: Box<dyn git::ForgeLike>,
|
forge: Box<dyn git::ForgeLike>,
|
||||||
log: Option<RepoActorLog>,
|
log: Option<RepoActorLog>,
|
||||||
|
@ -57,10 +61,10 @@ impl RepoActor {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
repo_details: git::RepoDetails,
|
repo_details: git::RepoDetails,
|
||||||
forge: Box<dyn git::ForgeLike>,
|
forge: Box<dyn git::ForgeLike>,
|
||||||
webhook: config::server::InboundWebhook,
|
webhook: server::InboundWebhook,
|
||||||
generation: git::Generation,
|
generation: git::Generation,
|
||||||
net: Network,
|
net: Network,
|
||||||
repository_factory: Box<dyn git::repository::RepositoryFactory>,
|
repository_factory: Box<dyn RepositoryFactory>,
|
||||||
sleep_duration: std::time::Duration,
|
sleep_duration: std::time::Duration,
|
||||||
notify_user_recipient: Option<Recipient<NotifyUser>>,
|
notify_user_recipient: Option<Recipient<NotifyUser>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
//
|
//
|
||||||
use derive_more::Display;
|
use git_next_core::{server, BranchName, RepoConfig};
|
||||||
use std::path::PathBuf;
|
use git_next_git::{self as git, repository::open::OpenRepositoryLike};
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
use git_next_config as config;
|
use std::path::PathBuf;
|
||||||
use git_next_git as git;
|
|
||||||
|
use derive_more::Display;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
/// Loads the [RepoConfig] from the `.git-next.toml` file in the repository
|
/// Loads the [RepoConfig] from the `.git-next.toml` file in the repository
|
||||||
#[tracing::instrument(skip_all, fields(branch = %repo_details.branch))]
|
#[tracing::instrument(skip_all, fields(branch = %repo_details.branch))]
|
||||||
pub async fn config_from_repository(
|
pub async fn config_from_repository(
|
||||||
repo_details: git::RepoDetails,
|
repo_details: git::RepoDetails,
|
||||||
open_repository: &dyn git::repository::OpenRepositoryLike,
|
open_repository: &dyn OpenRepositoryLike,
|
||||||
) -> Result<config::RepoConfig> {
|
) -> Result<RepoConfig> {
|
||||||
info!("Loading .git-next.toml from repo");
|
info!("Loading .git-next.toml from repo");
|
||||||
let contents =
|
let contents =
|
||||||
open_repository.read_file(&repo_details.branch, &PathBuf::from(".git-next.toml"))?;
|
open_repository.read_file(&repo_details.branch, &PathBuf::from(".git-next.toml"))?;
|
||||||
let config = config::RepoConfig::parse(&contents)?;
|
let config = RepoConfig::parse(&contents)?;
|
||||||
let branches = open_repository.remote_branches()?;
|
let branches = open_repository.remote_branches()?;
|
||||||
required_branch(&config.branches().main(), &branches)?;
|
required_branch(&config.branches().main(), &branches)?;
|
||||||
required_branch(&config.branches().next(), &branches)?;
|
required_branch(&config.branches().next(), &branches)?;
|
||||||
|
@ -23,10 +24,7 @@ pub async fn config_from_repository(
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn required_branch(
|
fn required_branch(branch_name: &BranchName, branches: &[BranchName]) -> Result<()> {
|
||||||
branch_name: &config::BranchName,
|
|
||||||
branches: &[config::BranchName],
|
|
||||||
) -> Result<()> {
|
|
||||||
branches
|
branches
|
||||||
.iter()
|
.iter()
|
||||||
.find(|branch| *branch == branch_name)
|
.find(|branch| *branch == branch_name)
|
||||||
|
@ -41,7 +39,7 @@ pub enum Error {
|
||||||
File(#[from] git::file::Error),
|
File(#[from] git::file::Error),
|
||||||
|
|
||||||
#[display("config")]
|
#[display("config")]
|
||||||
Config(#[from] config::server::Error),
|
Config(#[from] server::Error),
|
||||||
|
|
||||||
#[display("toml")]
|
#[display("toml")]
|
||||||
Toml(#[from] toml::de::Error),
|
Toml(#[from] toml::de::Error),
|
||||||
|
@ -50,5 +48,5 @@ pub enum Error {
|
||||||
Push(#[from] git::push::Error),
|
Push(#[from] git::push::Error),
|
||||||
|
|
||||||
#[display("branch not found: {}", 0)]
|
#[display("branch not found: {}", 0)]
|
||||||
BranchNotFound(config::BranchName),
|
BranchNotFound(BranchName),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
//
|
//
|
||||||
use config::newtype;
|
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
|
|
||||||
use git::UserNotification;
|
use git::UserNotification;
|
||||||
use git_next_config as config;
|
|
||||||
use git_next_core::message;
|
|
||||||
use git_next_git as git;
|
use git_next_git as git;
|
||||||
|
|
||||||
|
use git_next_core::{
|
||||||
|
message, newtype, webhook, RegisteredWebhook, RepoConfig, WebhookAuth, WebhookId,
|
||||||
|
};
|
||||||
|
|
||||||
message!(LoadConfigFromRepo: "Request to load the `git-next.toml` from the git repo.");
|
message!(LoadConfigFromRepo: "Request to load the `git-next.toml` from the git repo.");
|
||||||
message!(CloneRepo: "Request to clone (or open) the git repo.");
|
message!(CloneRepo: "Request to clone (or open) the git repo.");
|
||||||
message!(ReceiveRepoConfig: config::RepoConfig: r#"Notification that the `git-next.toml` file has been loaded from the repo and parsed.
|
message!(ReceiveRepoConfig: RepoConfig: r#"Notification that the `git-next.toml` file has been loaded from the repo and parsed.
|
||||||
|
|
||||||
Contains the parsed contents of the `git-next.toml` file."#);
|
Contains the parsed contents of the `git-next.toml` file."#);
|
||||||
message!(ValidateRepo: MessageToken: r#"Request that the state of the branches in the git repo be assessed and generate any followup actions.
|
message!(ValidateRepo: MessageToken: r#"Request that the state of the branches in the git repo be assessed and generate any followup actions.
|
||||||
|
@ -19,20 +20,20 @@ This is the main function of `git-next` where decisions are made on what branche
|
||||||
Contains a [MessageToken] to reduce duplicate messages being sent. Only messages with the latest [MessageToken] are handled,
|
Contains a [MessageToken] to reduce duplicate messages being sent. Only messages with the latest [MessageToken] are handled,
|
||||||
all others are dropped."#);
|
all others are dropped."#);
|
||||||
|
|
||||||
message!(WebhookRegistered: (config::WebhookId, config::WebhookAuth): r#"Notification that a webhook has been registered with a forge.
|
message!(WebhookRegistered: (WebhookId, WebhookAuth): r#"Notification that a webhook has been registered with a forge.
|
||||||
|
|
||||||
Contains a tuple of the ID for the webhook returned from the forge, and the unique authorisation token that
|
Contains a tuple of the ID for the webhook returned from the forge, and the unique authorisation token that
|
||||||
incoming messages from the forge must provide."#);
|
incoming messages from the forge must provide."#);
|
||||||
impl WebhookRegistered {
|
impl WebhookRegistered {
|
||||||
pub const fn webhook_id(&self) -> &config::WebhookId {
|
pub const fn webhook_id(&self) -> &WebhookId {
|
||||||
&self.0 .0
|
&self.0 .0
|
||||||
}
|
}
|
||||||
pub const fn webhook_auth(&self) -> &config::WebhookAuth {
|
pub const fn webhook_auth(&self) -> &WebhookAuth {
|
||||||
&self.0 .1
|
&self.0 .1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<config::RegisteredWebhook> for WebhookRegistered {
|
impl From<RegisteredWebhook> for WebhookRegistered {
|
||||||
fn from(value: config::RegisteredWebhook) -> Self {
|
fn from(value: RegisteredWebhook) -> Self {
|
||||||
let webhook_id = value.id().clone();
|
let webhook_id = value.id().clone();
|
||||||
let webhook_auth = value.auth().clone();
|
let webhook_auth = value.auth().clone();
|
||||||
Self::from((webhook_id, webhook_auth))
|
Self::from((webhook_id, webhook_auth))
|
||||||
|
@ -63,5 +64,5 @@ message!(ReceiveCIStatus: (git::Commit, git::forge::commit::Status): r#"Notifica
|
||||||
Contains a tuple of the commit that was checked (the tip of the `next` branch) and the status."#); // commit and it's status
|
Contains a tuple of the commit that was checked (the tip of the `next` branch) and the status."#); // commit and it's status
|
||||||
message!(AdvanceNext: (git::Commit, Vec<git::Commit>): "Request to advance the `next` branch on to the next commit on the `dev branch."); // next commit and the dev commit history
|
message!(AdvanceNext: (git::Commit, Vec<git::Commit>): "Request to advance the `next` branch on to the next commit on the `dev branch."); // next commit and the dev commit history
|
||||||
message!(AdvanceMain: git::Commit: "Request to advance the `main` branch on to same commit as the `next` branch."); // next commit
|
message!(AdvanceMain: git::Commit: "Request to advance the `main` branch on to same commit as the `next` branch."); // next commit
|
||||||
message!(WebhookNotification: config::webhook::forge_notification::ForgeNotification: "Notification of a webhook message from the forge.");
|
message!(WebhookNotification: webhook::forge_notification::ForgeNotification: "Notification of a webhook message from the forge.");
|
||||||
message!(NotifyUser: UserNotification: "Request to send the message payload to the notification webhook");
|
message!(NotifyUser: UserNotification: "Request to send the message payload to the notification webhook");
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
//
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use git::repository::factory::MockRepositoryFactory;
|
|
||||||
use git_next_git::repository::open::MockOpenRepositoryLike;
|
|
||||||
|
|
||||||
pub fn fetch_ok(open_repository: &mut MockOpenRepositoryLike) {
|
pub fn fetch_ok(open_repository: &mut MockOpenRepositoryLike) {
|
||||||
expect::fetch(open_repository, Ok(()));
|
expect::fetch(open_repository, Ok(()));
|
||||||
}
|
}
|
||||||
|
@ -38,7 +35,7 @@ pub fn open_repository(
|
||||||
|
|
||||||
pub fn main_commit_log(
|
pub fn main_commit_log(
|
||||||
validation_repo: &mut MockOpenRepositoryLike,
|
validation_repo: &mut MockOpenRepositoryLike,
|
||||||
main_branch: config::BranchName,
|
main_branch: BranchName,
|
||||||
) -> git::Commit {
|
) -> git::Commit {
|
||||||
let main_commit = given::a_commit();
|
let main_commit = given::a_commit();
|
||||||
let main_branch_log = vec![main_commit.clone()];
|
let main_branch_log = vec![main_commit.clone()];
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
use config::git_dir::StoragePathType;
|
|
||||||
use git_next_config::RemoteUrl;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -53,11 +50,8 @@ pub fn a_network() -> kxio::network::MockNetwork {
|
||||||
kxio::network::MockNetwork::new()
|
kxio::network::MockNetwork::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_webhook_url(
|
pub fn a_webhook_url(forge_alias: &ForgeAlias, repo_alias: &RepoAlias) -> WebhookUrl {
|
||||||
forge_alias: &ForgeAlias,
|
InboundWebhook::new(a_name()).url(forge_alias, repo_alias)
|
||||||
repo_alias: &RepoAlias,
|
|
||||||
) -> git_next_config::server::WebhookUrl {
|
|
||||||
config::server::InboundWebhook::new(a_name()).url(forge_alias, repo_alias)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_name() -> String {
|
pub fn a_name() -> String {
|
||||||
|
@ -112,7 +106,7 @@ pub fn a_server_repo_config() -> ServerRepoConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_repo_config() -> RepoConfig {
|
pub fn a_repo_config() -> RepoConfig {
|
||||||
RepoConfig::new(given::repo_branches(), config::RepoConfigSource::Repo)
|
RepoConfig::new(given::repo_branches(), RepoConfigSource::Repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_named_commit(name: impl Into<String>) -> git::Commit {
|
pub fn a_named_commit(name: impl Into<String>) -> git::Commit {
|
||||||
|
@ -189,7 +183,7 @@ pub fn a_forge() -> Box<MockForgeLike> {
|
||||||
|
|
||||||
pub fn a_repo_actor(
|
pub fn a_repo_actor(
|
||||||
repo_details: git::RepoDetails,
|
repo_details: git::RepoDetails,
|
||||||
repository_factory: Box<dyn git::repository::RepositoryFactory>,
|
repository_factory: Box<dyn RepositoryFactory>,
|
||||||
forge: Box<dyn git::ForgeLike>,
|
forge: Box<dyn git::ForgeLike>,
|
||||||
net: kxio::network::Network,
|
net: kxio::network::Network,
|
||||||
) -> (actor::RepoActor, RepoActorLog) {
|
) -> (actor::RepoActor, RepoActorLog) {
|
||||||
|
@ -216,16 +210,16 @@ pub fn a_repo_actor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_hostname() -> config::Hostname {
|
pub fn a_hostname() -> Hostname {
|
||||||
config::Hostname::new(given::a_name())
|
Hostname::new(given::a_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_registered_webhook() -> RegisteredWebhook {
|
pub fn a_registered_webhook() -> RegisteredWebhook {
|
||||||
RegisteredWebhook::new(given::a_webhook_id(), given::a_webhook_auth())
|
RegisteredWebhook::new(given::a_webhook_id(), given::a_webhook_auth())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_push() -> config::webhook::Push {
|
pub fn a_push() -> webhook::Push {
|
||||||
config::webhook::Push::new(
|
webhook::Push::new(
|
||||||
given::a_branch_name("push"),
|
given::a_branch_name("push"),
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
given::a_name(),
|
given::a_name(),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue