refactor: merge core crate into cli crate
All checks were successful
Test / build (map[name:nightly]) (push) Successful in 11m12s
Test / build (map[name:stable]) (push) Successful in 11m19s
Release Please / Release-plz (push) Successful in 15s
Release Please / Docker image (push) Successful in 2m21s

This commit is contained in:
Paul Campbell 2025-01-23 20:20:39 +00:00
parent c8cc45ca7f
commit e5a5e508ff
160 changed files with 888 additions and 1113 deletions

32
Cargo.lock generated
View file

@ -1070,7 +1070,8 @@ dependencies = [
"derive_more", "derive_more",
"directories", "directories",
"git-conventional", "git-conventional",
"git-next-core", "git-url-parse",
"gix",
"hex", "hex",
"hmac", "hmac",
"kameo", "kameo",
@ -1080,6 +1081,7 @@ dependencies = [
"mockall", "mockall",
"notifica", "notifica",
"notify", "notify",
"pike",
"pretty_assertions", "pretty_assertions",
"rand", "rand",
"ratatui", "ratatui",
@ -1091,6 +1093,7 @@ dependencies = [
"serde_json", "serde_json",
"sha2", "sha2",
"standardwebhooks", "standardwebhooks",
"take-until",
"test-log", "test-log",
"thiserror 2.0.11", "thiserror 2.0.11",
"time", "time",
@ -1104,33 +1107,6 @@ dependencies = [
"warp", "warp",
] ]
[[package]]
name = "git-next-core"
version = "0.14.1"
dependencies = [
"assert2",
"async-trait",
"derive-with",
"derive_more",
"git-url-parse",
"gix",
"kxio",
"mockall",
"pike",
"pretty_assertions",
"rand",
"secrecy",
"serde",
"serde_json",
"take-until",
"test-log",
"thiserror 2.0.11",
"time",
"toml",
"tracing",
"ulid",
]
[[package]] [[package]]
name = "git-url-parse" name = "git-url-parse"
version = "0.4.5" version = "0.4.5"

View file

@ -22,7 +22,6 @@ categories = ["development-tools"]
# expect_used = "warn" # expect_used = "warn"
[workspace.dependencies] [workspace.dependencies]
git-next-core = { path = "crates/core", version = "0.14" }
# TUI # TUI
ratatui = "0.29" ratatui = "0.29"
@ -59,6 +58,7 @@ git-url-parse = "0.4"
# fs/network # fs/network
kxio = "5.1" kxio = "5.1"
# kxio = { path = "../kxio/" }
# TOML parsing # TOML parsing
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

View file

@ -26,7 +26,6 @@ tui = [
] ]
[dependencies] [dependencies]
git-next-core = { workspace = true }
# TUI # TUI
ratatui = { workspace = true, optional = true } ratatui = { workspace = true, optional = true }
@ -93,6 +92,19 @@ hmac = { workspace = true }
sha2 = { workspace = true } sha2 = { workspace = true }
hex = { workspace = true } hex = { workspace = true }
# Git
gix = { workspace = true }
git-url-parse = { workspace = true }
# boilerplate
pike = { workspace = true }
mockall = { workspace = true }
#iters
take-until = { workspace = true }
[dev-dependencies] [dev-dependencies]
# Testing # Testing
assert2 = { workspace = true } assert2 = { workspace = true }

View file

@ -1,6 +1,6 @@
// //
use crate::alerts::short_message; use crate::alerts::short_message;
use git_next_core::git::UserNotification; use crate::core::git::UserNotification;
pub(super) fn send_desktop_notification(user_notification: &UserNotification) { pub(super) fn send_desktop_notification(user_notification: &UserNotification) {
let message = short_message(user_notification); let message = short_message(user_notification);

View file

@ -1,5 +1,5 @@
// //
use git_next_core::{ use crate::core::{
git::UserNotification, git::UserNotification,
server::{EmailConfig, SmtpConfig}, server::{EmailConfig, SmtpConfig},
}; };

View file

@ -1,5 +1,5 @@
// //
use git_next_core::git::UserNotification; use crate::core::git::UserNotification;
use tracing::info; use tracing::info;
use std::{ use std::{

View file

@ -1,5 +1,6 @@
// //
use git_next_core::{git::UserNotification, message, server::Shout}; use crate::core::{git::UserNotification, server::Shout};
use crate::message;
message!(UpdateShout, Shout, "Updated Shout configuration"); message!(UpdateShout, Shout, "Updated Shout configuration");

View file

@ -1,7 +1,7 @@
// //
use derive_more::derive::Constructor; use derive_more::derive::Constructor;
use git_next_core::{git::UserNotification, server::Shout}; use crate::core::{git::UserNotification, server::Shout};
pub use history::History; pub use history::History;
use kameo::{mailbox::unbounded::UnboundedMailbox, Actor}; use kameo::{mailbox::unbounded::UnboundedMailbox, Actor};

View file

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use crate::core::git::UserNotification;
use assert2::let_assert; use assert2::let_assert;
use git_next_core::git::UserNotification;
use crate::{alerts::History, repo::tests::given}; use crate::{alerts::History, repo::tests::given};

View file

@ -1,5 +1,5 @@
// //
use git_next_core::{git::UserNotification, server::OutboundWebhook}; use crate::core::{git::UserNotification, server::OutboundWebhook};
use secrecy::ExposeSecret as _; use secrecy::ExposeSecret as _;
use standardwebhooks::Webhook; use standardwebhooks::Webhook;

View file

@ -1,4 +1,4 @@
use crate::config::{ use crate::core::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,
}; };
@ -15,31 +15,31 @@ pub fn forge_details(n: u32, forge_type: ForgeType) -> ForgeDetails {
) )
} }
pub(crate) fn api_token(n: u32) -> ApiToken { pub fn api_token(n: u32) -> ApiToken {
ApiToken::new(format!("api-{n}").into()) ApiToken::new(format!("api-{n}").into())
} }
pub(crate) fn user(n: u32) -> User { pub fn user(n: u32) -> User {
User::new(format!("user-{n}")) User::new(format!("user-{n}"))
} }
pub(crate) fn hostname(n: u32) -> Hostname { pub fn hostname(n: u32) -> Hostname {
Hostname::new(format!("hostname-{n}")) Hostname::new(format!("hostname-{n}"))
} }
pub(crate) fn forge_name(n: u32) -> ForgeAlias { pub fn forge_name(n: u32) -> ForgeAlias {
ForgeAlias::new(format!("forge-name-{n}")) ForgeAlias::new(format!("forge-name-{n}"))
} }
pub(crate) fn branch_name(n: u32) -> BranchName { pub fn branch_name(n: u32) -> BranchName {
BranchName::new(format!("branch-name-{n}")) BranchName::new(format!("branch-name-{n}"))
} }
pub(crate) fn repo_path(n: u32) -> RepoPath { pub fn repo_path(n: u32) -> RepoPath {
RepoPath::new(format!("repo-path-{n}")) RepoPath::new(format!("repo-path-{n}"))
} }
pub(crate) fn repo_alias(n: u32) -> RepoAlias { pub fn repo_alias(n: u32) -> RepoAlias {
RepoAlias::new(format!("repo-alias-{n}")) RepoAlias::new(format!("repo-alias-{n}"))
} }

View file

@ -1,9 +1,7 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::{ use crate::core::config::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User};
config::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User}, use crate::s;
s,
};
use super::CommitCount; use super::CommitCount;

View file

@ -1,4 +1,4 @@
use crate::config::{ApiToken, ForgeAlias, ForgeConfig, ForgeType, Hostname, User}; use crate::core::config::{ApiToken, ForgeAlias, ForgeConfig, ForgeType, Hostname, User};
use super::CommitCount; use super::CommitCount;

View file

@ -2,7 +2,10 @@
mod api_token; mod api_token;
mod branch_name; mod branch_name;
mod commit_count; mod commit_count;
#[cfg(test)]
pub mod common; pub mod common;
mod forge_alias; mod forge_alias;
mod forge_config; mod forge_config;
mod forge_details; mod forge_details;
@ -53,4 +56,4 @@ pub use webhook::forge_notification::ForgeNotification;
pub use webhook::id::WebhookId; pub use webhook::id::WebhookId;
// re-export // re-export
pub use pike::{pike, pike_opt, pike_res}; pub use pike::pike;

View file

@ -1,5 +1,5 @@
// //
use crate::config::{WebhookAuth, WebhookId}; use crate::core::config::{WebhookAuth, WebhookId};
#[derive(Debug, derive_more::Constructor)] #[derive(Debug, derive_more::Constructor)]
pub struct RegisteredWebhook { pub struct RegisteredWebhook {

View file

@ -1,4 +1,4 @@
use crate::config::BranchName; use crate::core::config::BranchName;
/// Mapped from `.git-next.toml` file at `branches` /// Mapped from `.git-next.toml` file at `branches`
#[derive( #[derive(

View file

@ -1,4 +1,4 @@
use crate::config::{RepoBranches, RepoConfigSource}; use crate::core::config::{RepoBranches, 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

View file

@ -15,24 +15,10 @@ use serde::{Deserialize, Serialize};
use tracing::info; use tracing::info;
use crate::{ use crate::{
config::{ForgeAlias, ForgeConfig, RepoAlias}, core::config::{ForgeAlias, ForgeConfig, RepoAlias},
newtype, s, newtype, s, Result,
}; };
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("fs: {0}")]
KxioFs(#[from] kxio::fs::Error),
#[error("deserialise toml: {0}")]
TomlDe(#[from] toml::de::Error),
#[error("parse IP addres/port: {0}")]
AddressParse(#[from] std::net::AddrParseError),
}
type Result<T> = core::result::Result<T, Error>;
/// Mapped from the `git-next-server.toml` file /// Mapped from the `git-next-server.toml` file
#[derive( #[derive(
Clone, Clone,

View file

@ -2,7 +2,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use crate::{ use crate::{
config::{ core::config::{
git_dir::StoragePathType, BranchName, GitDir, RepoBranches, RepoConfig, RepoConfigSource, git_dir::StoragePathType, BranchName, GitDir, RepoBranches, RepoConfig, RepoConfigSource,
RepoPath, RepoPath,
}, },

View file

@ -7,16 +7,15 @@ use std::collections::BTreeMap;
use std::path::PathBuf; use std::path::PathBuf;
use crate::{ use crate::{
core::{
server::{AppConfig, Http, Storage},
webhook::push::Branch,
},
s, s,
server::{AppConfig, Http, Storage},
webhook::push::Branch,
}; };
mod url; mod url;
type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
type TestResult = Result<()>;
mod server_repo_config { mod server_repo_config {
use super::*; use super::*;
@ -100,10 +99,12 @@ mod server_repo_config {
} }
} }
mod repo_config { mod repo_config {
use crate::Result;
use super::*; use super::*;
#[test] #[test]
fn should_parse_toml() -> TestResult { fn should_parse_toml() -> Result<()> {
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();
@ -517,10 +518,12 @@ mod server {
use super::*; use super::*;
mod load { mod load {
use crate::{err, Result};
use super::*; use super::*;
#[test] #[test]
fn load_should_parse_app_config() -> TestResult { fn load_should_parse_app_config() -> Result<()> {
let app_config = given::an_app_config(); let app_config = given::an_app_config();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let_assert!(Ok(()) = write_app_config(&app_config, &fs), "write"); let_assert!(Ok(()) = write_app_config(&app_config, &fs), "write");
@ -530,7 +533,7 @@ mod server {
Ok(()) Ok(())
} }
fn write_app_config(app_config: &AppConfig, fs: &kxio::fs::FileSystem) -> TestResult { fn write_app_config(app_config: &AppConfig, fs: &kxio::fs::FileSystem) -> Result<()> {
let http = &app_config.listen_socket_addr()?; let http = &app_config.listen_socket_addr()?;
let http_addr = http.ip(); let http_addr = http.ip();
let http_port = app_config.listen_socket_addr()?.port(); let http_port = app_config.listen_socket_addr()?.port();
@ -553,11 +556,11 @@ mod server {
.forges() .forges()
.next() .next()
.map(|(fa, _)| fa) .map(|(fa, _)| fa)
.ok_or("forge missing")?; .ok_or_else(|| err!("forge missing"))?;
let forge_default = app_config let forge_default = app_config
.forge .forge
.get(forge_alias.as_ref()) .get(forge_alias.as_ref())
.ok_or("forge missing")?; .ok_or_else(|| err!("forge missing"))?;
let forge_type = forge_default.forge_type(); let forge_type = forge_default.forge_type();
let forge_hostname = forge_default.hostname(); let forge_hostname = forge_default.hostname();
let forge_user = forge_default.user(); let forge_user = forge_default.user();
@ -716,7 +719,7 @@ mod push {
let message = given::a_name(); let message = given::a_name();
let push_event = { let push_event = {
let branch_name = repo_branches.main(); let branch_name = repo_branches.main();
crate::webhook::Push::new(branch_name, sha, message) crate::core::webhook::Push::new(branch_name, sha, message)
}; };
assert_eq!(push_event.branch(&repo_branches), Some(Branch::Main)); assert_eq!(push_event.branch(&repo_branches), Some(Branch::Main));
} }
@ -727,7 +730,7 @@ mod push {
let message = given::a_name(); let message = given::a_name();
let push_event = { let push_event = {
let branch_name = repo_branches.next(); let branch_name = repo_branches.next();
crate::webhook::Push::new(branch_name, sha, message) crate::core::webhook::Push::new(branch_name, sha, message)
}; };
assert_eq!(push_event.branch(&repo_branches), Some(Branch::Next)); assert_eq!(push_event.branch(&repo_branches), Some(Branch::Next));
} }
@ -738,7 +741,7 @@ mod push {
let message = given::a_name(); let message = given::a_name();
let push_event = { let push_event = {
let branch_name = repo_branches.dev(); let branch_name = repo_branches.dev();
crate::webhook::Push::new(branch_name, sha, message) crate::core::webhook::Push::new(branch_name, sha, message)
}; };
assert_eq!(push_event.branch(&repo_branches), Some(Branch::Dev)); assert_eq!(push_event.branch(&repo_branches), Some(Branch::Dev));
} }
@ -749,7 +752,7 @@ mod push {
let message = given::a_name(); let message = given::a_name();
let push_event = { let push_event = {
let branch_name = BranchName::new(given::a_name()); let branch_name = BranchName::new(given::a_name());
crate::webhook::Push::new(branch_name, sha, message) crate::core::webhook::Push::new(branch_name, sha, message)
}; };
assert_eq!(push_event.branch(&repo_branches), None); assert_eq!(push_event.branch(&repo_branches), None);
} }
@ -761,7 +764,7 @@ mod push {
let push_event = { let push_event = {
let branch_name = repo_branches.main(); let branch_name = repo_branches.main();
let sha = sha.clone(); let sha = sha.clone();
crate::webhook::Push::new(branch_name, sha, message) crate::core::webhook::Push::new(branch_name, sha, message)
}; };
assert_eq!(push_event.sha(), sha); assert_eq!(push_event.sha(), sha);
} }
@ -773,14 +776,14 @@ mod push {
let push_event = { let push_event = {
let branch_name = repo_branches.main(); let branch_name = repo_branches.main();
let message = message.clone(); let message = message.clone();
crate::webhook::Push::new(branch_name, sha, message) crate::core::webhook::Push::new(branch_name, sha, message)
}; };
assert_eq!(push_event.message(), message); assert_eq!(push_event.message(), message);
} }
} }
mod given { mod given {
use crate::server::{EmailConfig, Listen, ListenUrl, OutboundWebhook, Shout, SmtpConfig}; use crate::core::server::{EmailConfig, Listen, ListenUrl, OutboundWebhook, Shout, SmtpConfig};
use super::*; use super::*;
use rand::Rng as _; use rand::Rng as _;
@ -911,8 +914,8 @@ mod given {
RepoAlias::new(a_name()) RepoAlias::new(a_name())
} }
pub fn a_webhook_message_body() -> crate::webhook::forge_notification::Body { pub fn a_webhook_message_body() -> crate::core::webhook::forge_notification::Body {
crate::webhook::forge_notification::Body::new(a_name()) crate::core::webhook::forge_notification::Body::new(a_name())
} }
pub fn some_repo_branches() -> RepoBranches { pub fn some_repo_branches() -> RepoBranches {

View file

@ -3,7 +3,7 @@ use std::collections::BTreeMap;
use derive_more::Constructor; use derive_more::Constructor;
use crate::config::{ForgeAlias, RepoAlias}; use crate::core::config::{ForgeAlias, RepoAlias};
/// 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)]

View file

@ -1,5 +1,5 @@
// //
use crate::config::{BranchName, RepoBranches}; use crate::core::config::{BranchName, RepoBranches};
use derive_more::Constructor; use derive_more::Constructor;
#[derive(Clone, Debug, Constructor, PartialEq, Eq, derive_with::With)] #[derive(Clone, Debug, Constructor, PartialEq, Eq, derive_with::With)]

View file

@ -1,5 +1,6 @@
mod auth { mod auth {
use crate::{s, WebhookAuth}; use crate::core::WebhookAuth;
use crate::s;
#[test] #[test]
fn bytes() -> Result<(), Box<dyn std::error::Error>> { fn bytes() -> Result<(), Box<dyn std::error::Error>> {

View file

@ -1,5 +1,6 @@
// //
use crate::{newtype, webhook}; use crate::core::webhook;
use crate::newtype;
use derive_more::Display; use derive_more::Display;
use serde::Serialize; use serde::Serialize;
@ -68,18 +69,3 @@ pub struct Histories {
pub next: Vec<Commit>, pub next: Vec<Commit>,
pub dev: Vec<Commit>, pub dev: Vec<Commit>,
} }
pub mod log {
use crate::BranchName;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("branch: {branch}, error: {error}")]
Gix { branch: BranchName, error: String },
#[error("lock")]
Lock,
}
}

View file

@ -1,38 +1,36 @@
// //
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
#[error("lock")] // #[error("lock")]
Lock, // Lock,
#[error("File not found: {}", 0)] // #[error("File not found: {}", 0)]
NotFound(String), // NotFound(String),
#[error("Unable to parse file contents")] // #[error("Unable to parse file contents")]
ParseContent, // ParseContent,
#[error("Unable to decode from base64")] // #[error("Unable to decode from base64")]
DecodeFromBase64, // DecodeFromBase64,
#[error("Unable to decode from UTF-8")] // #[error("Unable to decode from UTF-8")]
DecodeFromUtf8, // DecodeFromUtf8,
#[error("Unknown file encoding: {}", 0)] // #[error("Unknown file encoding: {}", 0)]
UnknownEncoding(String), // UnknownEncoding(String),
#[error("Not a file: {}", 0)] // #[error("Not a file: {}", 0)]
NotFile(String), // NotFile(String),
#[error("Unknown error (status: {})", 0)] // #[error("Unknown error (status: {})", 0)]
Unknown(String), // Unknown(String),
#[error("commit log: {0}")] // #[error("commit log: {0}")]
CommitLog(#[from] crate::git::commit::log::Error), // CommitLog(#[from] crate::git::commit::log::Error),
#[error("commit not found")]
CommitNotFound,
// #[error("commit not found")]
// CommitNotFound,
#[error("no tree in commit")] #[error("no tree in commit")]
NoTreeInCommit(String), NoTreeInCommit(String),

View file

@ -1,7 +1,9 @@
pub mod commit; pub mod commit;
pub(super) mod r#trait; pub mod r#trait;
pub mod webhook; pub mod webhook;
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub use r#trait::ForgeLike; pub use r#trait::ForgeLike;
#[cfg(test)]
pub use r#trait::MockForgeLike; pub use r#trait::MockForgeLike;

View file

@ -1,5 +1,5 @@
// //
use crate::{ use crate::core::{
git, server::RepoListenUrl, webhook, ForgeNotification, RegisteredWebhook, WebhookAuth, git, server::RepoListenUrl, webhook, ForgeNotification, RegisteredWebhook, WebhookAuth,
WebhookId, WebhookId,
}; };
@ -8,6 +8,8 @@ use crate::{
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait ForgeLike: std::fmt::Debug + Send + Sync { pub trait ForgeLike: std::fmt::Debug + Send + Sync {
fn duplicate(&self) -> Box<dyn ForgeLike>; fn duplicate(&self) -> Box<dyn ForgeLike>;
#[cfg(test)]
fn name(&self) -> String; fn name(&self) -> String;
/// Checks that the message has a valid authorisation. /// Checks that the message has a valid authorisation.
@ -38,6 +40,7 @@ pub trait ForgeLike: std::fmt::Debug + Send + Sync {
) -> git::forge::webhook::Result<git::forge::commit::Status>; ) -> git::forge::webhook::Result<git::forge::commit::Status>;
// Lists all the webhooks // Lists all the webhooks
#[cfg(test)]
async fn list_webhooks( async fn list_webhooks(
&self, &self,
repo_listen_url: &RepoListenUrl, repo_listen_url: &RepoListenUrl,

View file

@ -1,7 +1,7 @@
// //
use derive_more::{Constructor, Display}; use derive_more::{Constructor, Display};
use crate::{Hostname, RepoPath}; use crate::core::{Hostname, RepoPath};
#[derive(Clone, Debug, PartialEq, Eq, Constructor, Display)] #[derive(Clone, Debug, PartialEq, Eq, Constructor, Display)]
#[display("{}:{}", host, repo_path)] #[display("{}:{}", host, repo_path)]

View file

@ -3,7 +3,8 @@ use std::borrow::ToOwned;
use take_until::TakeUntilExt; use take_until::TakeUntilExt;
use crate::{newtype, GitDir, RepoBranches}; use crate::core::{GitDir, RepoBranches};
use crate::newtype;
use super::RepoDetails; use super::RepoDetails;

View file

@ -1,6 +1,5 @@
// //
pub mod commit; pub mod commit;
pub mod fetch;
pub mod file; pub mod file;
pub mod forge; pub mod forge;
mod generation; mod generation;
@ -18,38 +17,30 @@ mod tests;
pub use commit::Commit; pub use commit::Commit;
pub use forge::ForgeLike; pub use forge::ForgeLike;
pub use forge::MockForgeLike;
pub use generation::Generation; pub use generation::Generation;
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub use git_ref::GitRef; pub use git_ref::GitRef;
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub use git_remote::GitRemote; pub use git_remote::GitRemote;
pub use repo_details::RepoDetails; pub use repo_details::RepoDetails;
pub use repository::Repository;
pub use repository::RepositoryFactory; pub use repository::RepositoryFactory;
pub use user_notification::UserNotification; pub use user_notification::UserNotification;
use crate::common::branch_name; #[cfg(test)]
use crate::common::repo_alias;
use crate::common::repo_path;
use crate::ForgeDetails;
use crate::GitDir;
use crate::RepoConfig;
#[must_use] #[must_use]
pub fn repo_details( pub fn repo_details(
n: u32, n: u32,
generation: Generation, generation: Generation,
forge: ForgeDetails, forge: super::ForgeDetails,
repo_config: Option<RepoConfig>, repo_config: Option<super::RepoConfig>,
gitdir: GitDir, gitdir: super::GitDir,
) -> RepoDetails { ) -> RepoDetails {
RepoDetails { RepoDetails {
generation, generation,
repo_alias: repo_alias(n), repo_alias: super::common::repo_alias(n),
repo_path: repo_path(n), repo_path: super::common::repo_path(n),
gitdir, gitdir,
branch: branch_name(n), branch: super::common::branch_name(n),
forge, forge,
repo_config, repo_config,
} }

View file

@ -1,5 +1,9 @@
// //
use crate::{git, git::repository::open::OpenRepositoryLike, BranchName}; use crate::{
core::BranchName,
git::{self, repository::open::OpenRepositoryLike},
Result,
};
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum Force { pub enum Force {
@ -15,36 +19,6 @@ impl std::fmt::Display for Force {
} }
} }
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("io")]
Io(#[from] std::io::Error),
#[error("network: {0}")]
Network(#[from] kxio::net::Error),
#[error("fetch: {0}")]
Fetch(#[from] git::fetch::Error),
#[error("lock")]
Lock,
#[error("gix open: {0}")]
Open(#[from] Box<gix::open::Error>),
#[error("gix iter: {0}")]
GixIter(#[from] gix::reference::iter::Error),
#[error("gix iter init: {0}")]
GixIterInit(#[from] gix::reference::iter::init::Error),
#[cfg(test)]
#[error("test")]
TestResult(#[from] Box<dyn std::error::Error>),
}
/// Resets the position of a branch in the remote repo /// Resets the position of a branch in the remote repo
/// ///
/// Performs a 'git fetch' first to ensure we have up-to-date branch positions before /// Performs a 'git fetch' first to ensure we have up-to-date branch positions before

View file

@ -1,12 +1,16 @@
// //
use crate::core::pike;
use crate::s;
use crate::{ use crate::{
core::{
BranchName, ForgeAlias, ForgeConfig, ForgeDetails, GitDir, RemoteUrl, RepoAlias,
RepoConfig, RepoPath, ServerRepoConfig, StoragePathType,
},
git::{ git::{
self, self,
repository::open::{oreal::RealOpenRepository, OpenRepositoryLike}, repository::open::{oreal::RealOpenRepository, OpenRepositoryLike},
Generation, Generation,
}, },
pike, s, BranchName, ForgeAlias, ForgeConfig, ForgeDetails, GitDir, Hostname, RemoteUrl,
RepoAlias, RepoConfig, RepoPath, ServerRepoConfig, StoragePathType,
}; };
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -70,8 +74,9 @@ impl RepoDetails {
&self.gitdir &self.gitdir
} }
#[cfg(test)]
#[must_use] #[must_use]
pub fn with_hostname(mut self, hostname: Hostname) -> Self { pub fn with_hostname(mut self, hostname: crate::core::Hostname) -> Self {
let forge = self.forge; let forge = self.forge;
self.forge = forge.with_hostname(hostname); self.forge = forge.with_hostname(hostname);
self self

View file

@ -41,9 +41,10 @@ pub fn real() -> Box<dyn RepositoryFactory> {
Box::new(RealRepositoryFactory) Box::new(RealRepositoryFactory)
} }
#[cfg(test)]
#[must_use] #[must_use]
pub fn mock() -> Box<MockRepositoryFactory> { pub fn mock() -> MockRepositoryFactory {
Box::new(MockRepositoryFactory::new()) MockRepositoryFactory::new()
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -1,21 +1,18 @@
// //
use crate::{ use crate::{
core::RemoteUrl,
git::{ git::{
self, repository::open::OpenRepositoryLike, validation::remotes::validate_default_remotes,
repository::{
open::{OpenRepository, OpenRepositoryLike},
test::TestRepository,
},
validation::remotes::validate_default_remotes,
RepoDetails, RepoDetails,
}, },
GitDir, RemoteUrl,
}; };
use tracing::info; use tracing::info;
pub mod factory; pub mod factory;
pub mod open; pub mod open;
#[cfg(test)]
mod test; mod test;
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
@ -24,19 +21,20 @@ pub use factory::RepositoryFactory;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
#[derive(Clone, Debug)] // #[cfg(test)]
#[allow(clippy::large_enum_variant)] // #[derive(Clone, Debug)]
pub enum Repository { // #[allow(clippy::large_enum_variant)]
Real, // pub enum Repository {
Test(TestRepository), // Real,
} // Test(test::TestRepository),
// }
#[cfg(test)] #[cfg(test)]
pub(crate) const fn test( pub const fn test(
fs: kxio::fs::FileSystem, fs: kxio::fs::FileSystem,
forge_details: crate::ForgeDetails, forge_details: crate::core::ForgeDetails,
) -> TestRepository { ) -> test::TestRepository {
TestRepository::new(fs, vec![], vec![], forge_details) test::TestRepository::new(fs, vec![], vec![], forge_details)
} }
/// Opens a repository, cloning if necessary /// Opens a repository, cloning if necessary
@ -60,6 +58,7 @@ pub fn open(
Ok(open_repository) Ok(open_repository)
} }
#[cfg(test)]
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub trait RepositoryLike { pub trait RepositoryLike {
/// Opens the repository. /// Opens the repository.
@ -67,15 +66,16 @@ pub trait RepositoryLike {
/// # Errors /// # Errors
/// ///
/// Will return an `Err` if the repository can't be opened. /// Will return an `Err` if the repository can't be opened.
fn open(&self, gitdir: &GitDir) -> Result<OpenRepository>; fn open(&self, gitdir: &crate::core::GitDir) -> Result<open::OpenRepository>;
/// Clones the git repository from the remote server. // /// Clones the git repository from the remote server.
/// // ///
/// # Errors // /// # Errors
/// // ///
/// Will return an `Err` if there are any network connectivity issues // /// Will return an `Err` if there are any network connectivity issues
/// connecting with the server. // /// connecting with the server.
fn git_clone(&self, repo_details: &RepoDetails) -> Result<OpenRepository>; // #[cfg(test)]
// fn git_clone(&self, repo_details: &RepoDetails) -> Result<open::OpenRepository>;
} }
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@ -98,39 +98,35 @@ 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(GitDir), // InvalidGitDir(GitDir),
#[error("kxiofs: {0}")] #[error("kxiofs: {0}")]
KxioFs(#[from] kxio::fs::Error), KxioFs(#[from] kxio::fs::Error),
#[error("io: {0}")] // #[error("io: {0}")]
Io(std::io::Error), // Io(std::io::Error),
#[error("git exec wait: {0}")] // #[error("git exec wait: {0}")]
Wait(std::io::Error), // Wait(std::io::Error),
#[error("git exec spawn: {0}")]
Spawn(std::io::Error),
// #[error("git exec spawn: {0}")]
// Spawn(std::io::Error),
#[error("validation: {0}")] #[error("validation: {0}")]
Validation(String), Validation(String),
#[error("git clone: {0}")] #[error("git clone: {0}")]
Clone(String), Clone(String),
#[error("git fetch: {0}")] // #[error("git fetch: {0}")]
FetchError(#[from] git::fetch::Error), // FetchError(#[from] git::fetch::Error),
#[error("open: {0}")] #[error("open: {0}")]
Open(String), Open(String),
#[error("git fetch: {0}")] #[error("git fetch: {0}")]
Fetch(String), Fetch(String),
#[error("fake repository lock")] // #[error("fake repository lock")]
FakeLock, // FakeLock,
#[error("MismatchDefaultFetchRemote(found: {found:?}, expected: {expected:?})")] #[error("MismatchDefaultFetchRemote(found: {found:?}, expected: {expected:?})")]
MismatchDefaultFetchRemote { MismatchDefaultFetchRemote {
found: Box<RemoteUrl>, found: Box<RemoteUrl>,

View file

@ -3,56 +3,55 @@
mod tests; mod tests;
pub mod oreal; pub mod oreal;
#[cfg(test)]
pub mod otest; pub mod otest;
use crate::{ use crate::{
git, core::{BranchName, RemoteUrl},
git::repository::{ git::{self, repository::Direction},
open::{oreal::RealOpenRepository, otest::TestOpenRepository}, Result,
Direction,
},
BranchName, GitDir, RemoteUrl,
}; };
use std::{ use std::path::Path;
path::Path,
sync::{Arc, RwLock},
};
#[cfg(test)]
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum OpenRepository { pub enum OpenRepository {
/// A real git repository. // /// A real git repository.
/// // ///
/// This variant is the normal implementation for use in production code. // /// This variant is the normal implementation for use in production code.
Real(RealOpenRepository), // #[cfg(test)]
// Real(oreal::RealOpenRepository),
/// A real git repository, but with preprogrammed responses to network access. /// A real git repository, but with preprogrammed responses to network access.
/// ///
/// This variant is for use only in testing. Requests to methods /// This variant is for use only in testing. Requests to methods
/// that would require network access, such as to the git remote /// that would require network access, such as to the git remote
/// server will result in an error, unless a predefined change /// server will result in an error, unless a predefined change
/// has been scheduled for that request. /// has been scheduled for that request.
Test(TestOpenRepository), Test(otest::TestOpenRepository),
} }
#[cfg(not(tarpaulin_include))] // #[cfg(test)]
pub fn real(gix_repo: gix::Repository, forge_details: crate::ForgeDetails) -> OpenRepository { // #[cfg(not(tarpaulin_include))]
OpenRepository::Real(oreal::RealOpenRepository::new( // pub fn real(gix_repo: gix::Repository, forge_details: crate::core::ForgeDetails) -> OpenRepository {
Arc::new(RwLock::new(gix_repo.into())), // OpenRepository::Real(oreal::RealOpenRepository::new(
forge_details, // std::sync::Arc::new(std::sync::RwLock::new(gix_repo.into())),
)) // forge_details,
} // ))
// }
#[cfg(test)]
#[cfg(not(tarpaulin_include))] // don't test mocks #[cfg(not(tarpaulin_include))] // don't test mocks
pub(crate) fn test( pub fn test(
gitdir: &GitDir, gitdir: &crate::core::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>,
forge_details: crate::ForgeDetails, forge_details: crate::core::ForgeDetails,
) -> OpenRepository { ) -> OpenRepository {
OpenRepository::Test(TestOpenRepository::new( OpenRepository::Test(otest::TestOpenRepository::new(
gitdir, gitdir,
fs, fs,
on_fetch, on_fetch,
@ -64,8 +63,9 @@ pub(crate) fn test(
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
#[mockall::automock] #[mockall::automock]
pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send { pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
/// Creates a clone of the `OpenRepositoryLike`. // /// Creates a clone of the `OpenRepositoryLike`.
fn duplicate(&self) -> Box<dyn OpenRepositoryLike>; // #[cfg(test)]
// fn duplicate(&self) -> Box<dyn OpenRepositoryLike>;
/// Returns a `Vec` of all the branches in the remote repo. /// Returns a `Vec` of all the branches in the remote repo.
/// ///
@ -73,7 +73,7 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
/// ///
/// Will return `Err` if there are any network connectivity issues with /// Will return `Err` if there are any network connectivity issues with
/// the remote server. /// the remote server.
fn remote_branches(&self) -> git::push::Result<Vec<BranchName>>; fn remote_branches(&self) -> Result<Vec<BranchName>>;
fn find_default_remote(&self, direction: Direction) -> Option<RemoteUrl>; fn find_default_remote(&self, direction: Direction) -> Option<RemoteUrl>;
/// Performs a `git fetch` /// Performs a `git fetch`
@ -82,7 +82,7 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
/// ///
/// Will return an `Err` if their is no remote fetch defined in .git/config, or /// Will return an `Err` if their is no remote fetch defined in .git/config, or
/// if there are any network connectivity issues with the remote server. /// if there are any network connectivity issues with the remote server.
fn fetch(&self) -> Result<(), git::fetch::Error>; fn fetch(&self) -> Result<()>;
/// Performs a `git push` /// Performs a `git push`
/// ///
@ -96,7 +96,7 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
branch_name: &BranchName, branch_name: &BranchName,
to_commit: &git::GitRef, to_commit: &git::GitRef,
force: &git::push::Force, force: &git::push::Force,
) -> git::push::Result<()>; ) -> Result<()>;
/// List of commits in a branch, optionally up-to any specified commit. /// List of commits in a branch, optionally up-to any specified commit.
/// ///
@ -108,7 +108,7 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
&self, &self,
branch_name: &BranchName, branch_name: &BranchName,
find_commits: &[git::Commit], find_commits: &[git::Commit],
) -> git::commit::log::Result<Vec<git::Commit>>; ) -> Result<Vec<git::Commit>>;
/// Read the contents of a file as a string. /// Read the contents of a file as a string.
/// ///
@ -117,20 +117,21 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
/// # Errors /// # Errors
/// ///
/// Will return `Err` if the file does not exists on the specified branch. /// Will return `Err` if the file does not exists on the specified branch.
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String>; fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result<String>;
} }
#[cfg(test)] #[cfg(test)]
pub(crate) fn mock() -> Box<MockOpenRepositoryLike> { pub fn mock() -> Box<MockOpenRepositoryLike> {
Box::new(MockOpenRepositoryLike::new()) Box::new(MockOpenRepositoryLike::new())
} }
#[cfg(test)]
impl std::ops::Deref for OpenRepository { impl std::ops::Deref for OpenRepository {
type Target = dyn OpenRepositoryLike; type Target = dyn OpenRepositoryLike;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match self { match self {
Self::Real(real) => real, // Self::Real(real) => real,
Self::Test(test) => test, Self::Test(test) => test,
} }
} }

View file

@ -1,8 +1,9 @@
// //
use crate::{ use crate::{
git::{self, repository::OpenRepositoryLike}, core::{BranchName, ForgeDetails, Hostname, RemoteUrl, RepoPath},
s, BranchName, ForgeDetails, Hostname, RemoteUrl, RepoPath, err, git,
}; };
use crate::{s, Result};
use derive_more::Constructor; use derive_more::Constructor;
use gix::bstr::BStr; use gix::bstr::BStr;
@ -11,7 +12,6 @@ use tracing::{info, warn};
use std::{ use std::{
borrow::ToOwned, borrow::ToOwned,
path::Path, path::Path,
result::Result,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -21,26 +21,29 @@ pub struct RealOpenRepository {
forge_details: ForgeDetails, forge_details: ForgeDetails,
} }
impl super::OpenRepositoryLike for RealOpenRepository { impl super::OpenRepositoryLike for RealOpenRepository {
fn remote_branches(&self) -> git::push::Result<Vec<BranchName>> { fn remote_branches(&self) -> Result<Vec<BranchName>> {
let refs = self let refs = self
.inner .inner
.read() .read()
.map_err(|_| git::push::Error::Lock) .map_err(|_| err!("read"))
.and_then(|repo| { .and_then(|repo| {
Ok(repo.to_thread_local().references()?).and_then(|refs| { repo.to_thread_local()
Ok(refs.remote_branches().map(|rb| { .references()
rb.filter_map(Result::ok) .map_err(|_| err!("thread local references"))
.map(|r| r.name().to_owned()) .and_then(|refs| {
.map(|n| s!(n)) Ok(refs.remote_branches().map(|rb| {
.filter_map(|p| { rb.filter_map(Result::ok)
p.strip_prefix("refs/remotes/origin/") .map(|r| r.name().to_owned())
.map(ToOwned::to_owned) .map(|n| s!(n))
}) .filter_map(|p| {
.filter(|b| b.as_str() != "HEAD") p.strip_prefix("refs/remotes/origin/")
.map(BranchName::new) .map(ToOwned::to_owned)
.collect::<Vec<_>>() })
})?) .filter(|b| b.as_str() != "HEAD")
}) .map(BranchName::new)
.collect::<Vec<_>>()
})?)
})
})?; })?;
Ok(refs) Ok(refs)
} }
@ -66,12 +69,12 @@ impl super::OpenRepositoryLike for RealOpenRepository {
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
#[cfg(not(tarpaulin_include))] // would require writing to external service #[cfg(not(tarpaulin_include))] // would require writing to external service
fn fetch(&self) -> Result<(), git::fetch::Error> { fn fetch(&self) -> Result<()> {
if self if self
.find_default_remote(git::repository::Direction::Fetch) .find_default_remote(git::repository::Direction::Fetch)
.is_none() .is_none()
{ {
return Err(git::fetch::Error::NoFetchRemoteFound); return Err(err!("No Fetch Remote Found"));
} }
info!("Fetching"); info!("Fetching");
gix::command::prepare("/usr/bin/git fetch --prune") gix::command::prepare("/usr/bin/git fetch --prune")
@ -79,7 +82,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
git_dir: Some( git_dir: Some(
self.inner self.inner
.read() .read()
.map_err(|_| git::fetch::Error::Lock) .map_err(|_| err!("Lock"))
.map(|r| r.git_dir().to_path_buf())?, .map(|r| r.git_dir().to_path_buf())?,
), ),
..Default::default() ..Default::default()
@ -101,7 +104,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
branch_name: &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<()> {
use secrecy::ExposeSecret as _; use secrecy::ExposeSecret as _;
let origin = repo_details.origin(); let origin = repo_details.origin();
@ -120,7 +123,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
let git_dir = self let git_dir = self
.inner .inner
.read() .read()
.map_err(|_| git::push::Error::Lock) .map_err(|_| err!("Lock"))
.map(|r| r.git_dir().to_path_buf())?; .map(|r| r.git_dir().to_path_buf())?;
let ctx = gix::diff::command::Context { let ctx = gix::diff::command::Context {
git_dir: Some(git_dir), git_dir: Some(git_dir),
@ -140,7 +143,7 @@ impl super::OpenRepositoryLike for RealOpenRepository {
&self, &self,
branch_name: &BranchName, branch_name: &BranchName,
find_commits: &[git::Commit], find_commits: &[git::Commit],
) -> Result<Vec<git::Commit>, git::commit::log::Error> { ) -> Result<Vec<git::Commit>> {
let limit: usize = if find_commits.is_empty() { let limit: usize = if find_commits.is_empty() {
1 1
} else { } else {
@ -148,63 +151,60 @@ impl super::OpenRepositoryLike for RealOpenRepository {
.max_dev_commits() .max_dev_commits()
.map_or(25, |commit_count| commit_count.clone().peel() as usize) .map_or(25, |commit_count| commit_count.clone().peel() as usize)
}; };
self.inner self.inner.read().map_err(|_| err!("Lock")).map(|repo| {
.read() let branch = format!("remotes/origin/{branch_name}");
.map_err(|_| git::commit::log::Error::Lock) let branch = BStr::new(&branch);
.map(|repo| { let thread_local = repo.to_thread_local();
let branch = format!("remotes/origin/{branch_name}"); let branch_head = thread_local
let branch = BStr::new(&branch); .rev_parse_single(branch)
let thread_local = repo.to_thread_local(); .map_err(|e| s!(e))
let branch_head = thread_local .map_err(as_gix_error(branch_name.clone()))?;
.rev_parse_single(branch) let object = branch_head
.object()
.map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?;
let commit = object
.try_into_commit()
.map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?;
let walk = thread_local
.rev_walk([commit.id])
.all()
.map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?;
let mut commits = vec![];
for item in walk.take(limit) {
let item = item
.map_err(|e| s!(e)) .map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?; .map_err(as_gix_error(branch_name.clone()))?;
let object = branch_head let commit = item
.object() .object()
.map_err(|e| s!(e)) .map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?; .map_err(as_gix_error(branch_name.clone()))?;
let commit = object let id = commit.id();
.try_into_commit() let message = commit
.message_raw()
.map_err(|e| s!(e)) .map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?; .map_err(as_gix_error(branch_name.clone()))?;
let walk = thread_local let commit = git::Commit::new(
.rev_walk([commit.id]) git::commit::Sha::new(s!(id)),
.all() git::commit::Message::new(s!(message)),
.map_err(|e| s!(e)) );
.map_err(as_gix_error(branch_name.clone()))?; if find_commits.contains(&commit) {
let mut commits = vec![];
for item in walk.take(limit) {
let item = item
.map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?;
let commit = item
.object()
.map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?;
let id = commit.id();
let message = commit
.message_raw()
.map_err(|e| s!(e))
.map_err(as_gix_error(branch_name.clone()))?;
let commit = git::Commit::new(
git::commit::Sha::new(s!(id)),
git::commit::Message::new(s!(message)),
);
if find_commits.contains(&commit) {
commits.push(commit);
break;
}
commits.push(commit); commits.push(commit);
break;
} }
Ok(commits) commits.push(commit);
})? }
Ok(commits)
})?
} }
#[tracing::instrument(skip_all, fields(%branch_name, ?file_name))] #[tracing::instrument(skip_all, fields(%branch_name, ?file_name))]
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String> { fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result<String> {
self.inner self.inner
.read() .read()
.map_err(|_| git::file::Error::Lock) .map_err(|_| err!("Lock"))
.and_then(|repo| { .and_then(|repo| {
let thread_local = repo.to_thread_local(); let thread_local = repo.to_thread_local();
let fref = thread_local.find_reference(format!("origin/{branch_name}").as_str())?; let fref = thread_local.find_reference(format!("origin/{branch_name}").as_str())?;
@ -223,13 +223,14 @@ impl super::OpenRepositoryLike for RealOpenRepository {
}) })
} }
fn duplicate(&self) -> Box<dyn OpenRepositoryLike> { // #[cfg(test)]
Box::new(self.clone()) // fn duplicate(&self) -> Box<dyn super::OpenRepositoryLike> {
} // Box::new(self.clone())
// }
} }
fn as_gix_error(branch: BranchName) -> impl FnOnce(String) -> git::commit::log::Error { fn as_gix_error(branch: BranchName) -> impl FnOnce(String) -> color_eyre::eyre::Error {
|error| git::commit::log::Error::Gix { branch, error } move |error| err!("gix: branch: {branch}: {error}")
} }
impl From<&RemoteUrl> for git::GitRemote { impl From<&RemoteUrl> for git::GitRemote {

View file

@ -1,10 +1,11 @@
// //
use crate::s;
use crate::{ use crate::{
git::{ core::{
self, git::{self, repository::open::oreal::RealOpenRepository},
repository::open::{OpenRepositoryLike, RealOpenRepository}, BranchName, ForgeDetails, GitDir, RemoteUrl, RepoBranches,
}, },
s, BranchName, ForgeDetails, GitDir, RemoteUrl, RepoBranches, err, Result,
}; };
use derive_more::Constructor; use derive_more::Constructor;
@ -14,7 +15,7 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
pub type OnFetchFn = fn(&RepoBranches, &GitDir, &kxio::fs::FileSystem) -> git::fetch::Result<()>; pub type OnFetchFn = fn(&RepoBranches, &GitDir, &kxio::fs::FileSystem) -> Result<()>;
#[derive(Clone, Debug, Constructor)] #[derive(Clone, Debug, Constructor)]
pub struct OnFetch { pub struct OnFetch {
repo_branches: RepoBranches, repo_branches: RepoBranches,
@ -29,7 +30,7 @@ impl OnFetch {
/// ///
/// Will return any `Err` if there is no fetch remote defined in .git/config /// Will return any `Err` if there is no fetch remote defined in .git/config
/// of if there are any network connectivity issues with the remote server. /// of if there are any network connectivity issues with the remote server.
pub fn invoke(&self) -> git::fetch::Result<()> { pub fn invoke(&self) -> Result<()> {
(self.action)(&self.repo_branches, &self.gitdir, &self.fs) (self.action)(&self.repo_branches, &self.gitdir, &self.fs)
} }
} }
@ -42,7 +43,7 @@ pub type OnPushFn = fn(
&RepoBranches, &RepoBranches,
&GitDir, &GitDir,
&kxio::fs::FileSystem, &kxio::fs::FileSystem,
) -> git::push::Result<()>; ) -> Result<()>;
#[derive(Clone, Debug, Constructor)] #[derive(Clone, Debug, Constructor)]
pub struct OnPush { pub struct OnPush {
repo_branches: RepoBranches, repo_branches: RepoBranches,
@ -63,7 +64,7 @@ impl OnPush {
branch_name: &BranchName, branch_name: &BranchName,
to_commit: &git::GitRef, to_commit: &git::GitRef,
force: &git::push::Force, force: &git::push::Force,
) -> git::push::Result<()> { ) -> Result<()> {
(self.action)( (self.action)(
repo_details, repo_details,
branch_name, branch_name,
@ -86,7 +87,7 @@ pub struct TestOpenRepository {
} }
#[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<BranchName>> { fn remote_branches(&self) -> Result<Vec<BranchName>> {
self.real.remote_branches() self.real.remote_branches()
} }
@ -94,14 +95,11 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
self.real.find_default_remote(direction) self.real.find_default_remote(direction)
} }
fn fetch(&self) -> Result<(), git::fetch::Error> { fn fetch(&self) -> Result<()> {
let i: usize = *self let i: usize = *self.fetch_counter.read().map_err(|_| err!("Lock"))?;
.fetch_counter
.read()
.map_err(|_| git::fetch::Error::Lock)?;
self.fetch_counter self.fetch_counter
.write() .write()
.map_err(|_| git::fetch::Error::Lock) .map_err(|_| err!("Lock"))
.map(|mut c| *c += 1)?; .map(|mut c| *c += 1)?;
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
self.on_fetch self.on_fetch
@ -116,15 +114,12 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
branch_name: &BranchName, branch_name: &BranchName,
to_commit: &git::GitRef, to_commit: &git::GitRef,
force: &git::push::Force, force: &git::push::Force,
) -> git::push::Result<()> { ) -> Result<()> {
let i: usize = *self let i: usize = *self.push_counter.read().map_err(|_| err!("Lock"))?;
.push_counter
.read()
.map_err(|_| git::fetch::Error::Lock)?;
println!("Push: {i}"); println!("Push: {i}");
self.push_counter self.push_counter
.write() .write()
.map_err(|_| git::fetch::Error::Lock) .map_err(|_| err!("Lock"))
.map(|mut c| *c += 1)?; .map(|mut c| *c += 1)?;
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
self.on_push self.on_push
@ -137,17 +132,17 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
&self, &self,
branch_name: &BranchName, branch_name: &BranchName,
find_commits: &[git::Commit], find_commits: &[git::Commit],
) -> git::commit::log::Result<Vec<git::Commit>> { ) -> Result<Vec<git::Commit>> {
self.real.commit_log(branch_name, find_commits) self.real.commit_log(branch_name, find_commits)
} }
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String> { fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result<String> {
self.real.read_file(branch_name, file_name) self.real.read_file(branch_name, file_name)
} }
fn duplicate(&self) -> Box<dyn OpenRepositoryLike> { // fn duplicate(&self) -> Box<dyn super::OpenRepositoryLike> {
Box::new(self.clone()) // Box::new(self.clone())
} // }
} }
impl TestOpenRepository { impl TestOpenRepository {
pub(crate) fn new( pub(crate) fn new(

View file

@ -1,6 +1,6 @@
use std::ops::Deref as _; use std::ops::Deref as _;
use crate::CommitCount; use crate::core::CommitCount;
// //
use super::*; use super::*;

View file

@ -1,12 +1,14 @@
// //
use crate::{ use crate::{
core::{
BranchName, ForgeConfig, ForgeType, GitDir, Hostname, RepoAlias, RepoBranches, RepoConfig,
RepoConfigSource, RepoPath, ServerRepoConfig, StoragePathType, User,
},
git::{ git::{
self, self,
repository::RepositoryLike as _, repository::RepositoryLike as _,
tests::{given, then}, tests::{given, then},
}, },
BranchName, ForgeConfig, ForgeType, GitDir, Hostname, RepoAlias, RepoBranches, RepoConfig,
RepoConfigSource, RepoPath, ServerRepoConfig, StoragePathType, User,
}; };
use assert2::let_assert; use assert2::let_assert;
@ -14,7 +16,8 @@ use secrecy::ExposeSecret;
use std::{collections::BTreeMap, path::PathBuf}; use std::{collections::BTreeMap, path::PathBuf};
type TestResult = Result<(), Box<dyn std::error::Error>>; // type TestResult = Result<(), Box<dyn std::error::Error>>;
type TestResult = color_eyre::Result<()>;
mod commit_log; mod commit_log;
mod fetch; mod fetch;

View file

@ -0,0 +1 @@

View file

@ -2,6 +2,7 @@
use derive_more::Constructor; use derive_more::Constructor;
use crate::{ use crate::{
core::{ForgeDetails, GitDir},
git::{ git::{
self, self,
repository::{ repository::{
@ -11,9 +12,7 @@ use crate::{
}, },
RepositoryLike, Result, RepositoryLike, Result,
}, },
RepoDetails,
}, },
ForgeDetails, GitDir,
}; };
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
@ -43,8 +42,4 @@ impl RepositoryLike for TestRepository {
self.forge_details.clone(), self.forge_details.clone(),
)) ))
} }
fn git_clone(&self, _repo_details: &RepoDetails) -> Result<OpenRepository> {
todo!()
}
} }

View file

@ -1,7 +1,7 @@
// //
use crate::{ use crate::{
core::{ApiToken, GitDir, StoragePathType},
git::{self, tests::given}, git::{self, tests::given},
ApiToken, GitDir, StoragePathType,
}; };
use assert2::let_assert; use assert2::let_assert;

View file

@ -1,9 +1,12 @@
// //
use crate::{ use crate::{
core::{
git_dir::StoragePathType, BranchName, ForgeAlias, ForgeConfig, ForgeType, GitDir, Hostname,
RemoteUrl, RepoAlias, RepoBranches, RepoConfig, RepoConfigSource, RepoPath,
ServerRepoConfig,
},
git::{self, Generation, GitRef, GitRemote, RepoDetails}, git::{self, Generation, GitRef, GitRemote, RepoDetails},
git_dir::StoragePathType, s, Result,
s, webhook, BranchName, ForgeAlias, ForgeConfig, ForgeType, GitDir, Hostname, RemoteUrl,
RepoAlias, RepoBranches, RepoConfig, RepoConfigSource, RepoPath, ServerRepoConfig,
}; };
use assert2::let_assert; use assert2::let_assert;
@ -14,8 +17,6 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
type TestResult = Result<(), Box<dyn std::error::Error>>;
mod commit { mod commit {
use super::*; use super::*;
@ -180,7 +181,7 @@ mod repo_details {
} }
} }
pub mod given { pub mod given {
use crate::ForgeDetails; use crate::core::ForgeDetails;
use super::*; use super::*;
@ -200,9 +201,9 @@ pub mod given {
RepoAlias::new(a_name()) RepoAlias::new(a_name())
} }
pub fn a_pathbuf() -> PathBuf { // pub fn a_pathbuf() -> PathBuf {
PathBuf::from(given::a_name()) // PathBuf::from(given::a_name())
} // }
pub fn a_name() -> String { pub fn a_name() -> String {
use rand::Rng; use rand::Rng;
@ -296,9 +297,12 @@ pub mod given {
git::commit::Sha::new(a_name()) git::commit::Sha::new(a_name())
} }
pub fn a_webhook_push(sha: &git::commit::Sha, message: &git::commit::Message) -> webhook::Push { pub fn a_webhook_push(
sha: &git::commit::Sha,
message: &git::commit::Message,
) -> crate::core::webhook::Push {
let branch = a_branch_name(); let branch = a_branch_name();
webhook::Push::new(branch, s!(sha), s!(message)) crate::core::webhook::Push::new(branch, s!(sha), s!(message))
} }
pub fn a_filesystem() -> kxio::fs::TempFileSystem { pub fn a_filesystem() -> kxio::fs::TempFileSystem {
@ -354,37 +358,39 @@ pub mod given {
} }
pub mod then { pub mod then {
use crate::err;
use super::*; use super::*;
pub fn commit_named_file_to_branch( // pub fn commit_named_file_to_branch(
file_name: &Path, // file_name: &Path,
contents: &str, // contents: &str,
fs: &kxio::fs::FileSystem, // fs: &kxio::fs::FileSystem,
gitdir: &GitDir, // gitdir: &GitDir,
branch_name: &BranchName, // branch_name: &BranchName,
) -> TestResult { // ) -> Result<()> {
// git checkout ${branch_name} // // git checkout ${branch_name}
git_checkout_new_branch(branch_name, gitdir)?; // git_checkout_new_branch(branch_name, gitdir)?;
// echo ${word} > file-${word} // // echo ${word} > file-${word}
let pathbuf = PathBuf::from(gitdir); // let pathbuf = PathBuf::from(gitdir);
let file = fs.base().join(pathbuf).join(file_name); // let file = fs.base().join(pathbuf).join(file_name);
#[allow(clippy::expect_used)] // #[allow(clippy::expect_used)]
fs.file(&file).write(contents)?; // fs.file(&file).write(contents)?;
// git add ${file} // // git add ${file}
git_add_file(gitdir, &file)?; // git_add_file(gitdir, &file)?;
// git commit -m"Added ${file}" // // git commit -m"Added ${file}"
git_commit(gitdir, &file)?; // git_commit(gitdir, &file)?;
//
then::push_branch(fs, gitdir, branch_name)?; // then::push_branch(fs, gitdir, branch_name)?;
//
Ok(()) // Ok(())
} // }
pub fn create_a_commit_on_branch( pub fn create_a_commit_on_branch(
fs: &kxio::fs::FileSystem, fs: &kxio::fs::FileSystem,
gitdir: &GitDir, gitdir: &GitDir,
branch_name: &BranchName, branch_name: &BranchName,
) -> TestResult { ) -> Result<()> {
// git checkout ${branch_name} // git checkout ${branch_name}
git_checkout_new_branch(branch_name, gitdir)?; git_checkout_new_branch(branch_name, gitdir)?;
// echo ${word} > file-${word} // echo ${word} > file-${word}
@ -406,7 +412,7 @@ pub mod then {
fs: &kxio::fs::FileSystem, fs: &kxio::fs::FileSystem,
gitdir: &GitDir, gitdir: &GitDir,
branch_name: &BranchName, branch_name: &BranchName,
) -> TestResult { ) -> Result<()> {
let gitrefs = fs let gitrefs = fs
.base() .base()
.join(gitdir.to_path_buf()) .join(gitdir.to_path_buf())
@ -421,7 +427,7 @@ pub mod then {
Ok(()) Ok(())
} }
pub fn git_checkout_new_branch(branch_name: &BranchName, gitdir: &GitDir) -> TestResult { pub fn git_checkout_new_branch(branch_name: &BranchName, gitdir: &GitDir) -> Result<()> {
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")
@ -432,7 +438,7 @@ pub mod then {
Ok(()) Ok(())
} }
pub fn git_switch(branch_name: &BranchName, gitdir: &GitDir) -> TestResult { pub fn git_switch(branch_name: &BranchName, gitdir: &GitDir) -> Result<()> {
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")
@ -442,7 +448,7 @@ pub mod then {
) )
} }
fn exec(label: &str, output: Result<std::process::Output, std::io::Error>) -> TestResult { fn exec(label: &str, output: Result<std::process::Output, std::io::Error>) -> Result<()> {
println!("== {label}"); println!("== {label}");
match output { match output {
Ok(output) => { Ok(output) => {
@ -459,12 +465,12 @@ pub mod then {
} }
Err(err) => { Err(err) => {
println!("ERROR: {err:#?}"); println!("ERROR: {err:#?}");
Ok(Err(err)?) Err(err!(err))
} }
} }
} }
fn git_add_file(gitdir: &GitDir, file: &Path) -> TestResult { fn git_add_file(gitdir: &GitDir, file: &Path) -> Result<()> {
exec( exec(
&format!("git add {file:?}"), &format!("git add {file:?}"),
std::process::Command::new("/usr/bin/git") std::process::Command::new("/usr/bin/git")
@ -474,7 +480,7 @@ pub mod then {
) )
} }
fn git_commit(gitdir: &GitDir, file: &Path) -> TestResult { fn git_commit(gitdir: &GitDir, file: &Path) -> Result<()> {
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")
@ -484,7 +490,7 @@ pub mod then {
) )
} }
pub fn git_log_all(gitdir: &GitDir) -> TestResult { pub fn git_log_all(gitdir: &GitDir) -> Result<()> {
exec( exec(
"git log --all --oneline --decorate --graph", "git log --all --oneline --decorate --graph",
std::process::Command::new("/usr/bin/git") std::process::Command::new("/usr/bin/git")
@ -498,7 +504,7 @@ pub mod then {
fs: &kxio::fs::FileSystem, fs: &kxio::fs::FileSystem,
gitdir: &GitDir, gitdir: &GitDir,
branch_name: &BranchName, branch_name: &BranchName,
) -> Result<git::commit::Sha, Box<dyn std::error::Error>> { ) -> color_eyre::Result<git::commit::Sha> {
let main_ref = fs let main_ref = fs
.base() .base()
.join(gitdir.to_path_buf()) .join(gitdir.to_path_buf())

View file

@ -1,7 +1,8 @@
use std::fmt::Display; use std::fmt::Display;
// //
use crate::{git::Commit, BranchName, ForgeAlias, RepoAlias}; use crate::core::{BranchName, ForgeAlias, RepoAlias};
use crate::git::Commit;
use serde_json::json; use serde_json::json;
use super::graph::Log; use super::graph::Log;

View file

@ -1,12 +1,11 @@
// //
use crate::{ use crate::{
git::{self, repository::open::OpenRepositoryLike, RepoDetails, UserNotification}, core::{git::RepoDetails, BranchName, RepoConfig},
s, BranchName, RepoConfig, git::{self, repository::open::OpenRepositoryLike, UserNotification},
Result,
}; };
use tracing::{debug, instrument}; use tracing::{debug, instrument};
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug)] #[derive(Debug)]
pub struct Positions { pub struct Positions {
pub main: git::Commit, pub main: git::Commit,
@ -28,35 +27,32 @@ pub fn validate(
open_repository: &dyn OpenRepositoryLike, open_repository: &dyn OpenRepositoryLike,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
repo_config: &RepoConfig, repo_config: &RepoConfig,
) -> Result<(Positions, git::graph::Log)> { ) -> PositionsResult<(Positions, git::graph::Log)> {
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();
let dev_branch = repo_config.branches().dev(); let dev_branch = repo_config.branches().dev();
// Collect Commit Histories for `main`, `next` and `dev` branches // Collect Commit Histories for `main`, `next` and `dev` branches
open_repository.fetch()?; open_repository
.fetch()
.map_err(|e| PositionsError::Retryable(e.to_string()))?;
let git_log = git::graph::log(repo_details); let git_log = git::graph::log(repo_details);
let commit_histories = get_commit_histories(open_repository, repo_config)?; let commit_histories = get_commit_histories(open_repository, repo_config)
.map_err(|e| PositionsError::Retryable(e.to_string()))?;
// branch tips // branch tips
let main = commit_histories let main = commit_histories.main.first().cloned().ok_or_else(|| {
.main PositionsError::NonRetryable(format!("Branch has no commits: {main_branch}"))
.first() })?;
.cloned() let next = commit_histories.next.first().cloned().ok_or_else(|| {
.ok_or_else(|| Error::NonRetryable(format!("Branch has no commits: {main_branch}")))?; PositionsError::NonRetryable(format!("Branch has no commits: {next_branch}"))
let next = commit_histories })?;
.next let dev = commit_histories.dev.first().cloned().ok_or_else(|| {
.first() PositionsError::NonRetryable(format!("Branch has no commits: {dev_branch}"))
.cloned() })?;
.ok_or_else(|| Error::NonRetryable(format!("Branch has no commits: {next_branch}")))?;
let dev = commit_histories
.dev
.first()
.cloned()
.ok_or_else(|| Error::NonRetryable(format!("Branch has no commits: {dev_branch}")))?;
// Validations: // Validations:
// Dev must be on main branch, else the USER must rebase it // Dev must be on main branch, else the USER must rebase it
if is_not_based_on(&commit_histories.dev, &main) { if is_not_based_on(&commit_histories.dev, &main) {
return Err(Error::UserIntervention( return Err(PositionsError::UserIntervention(
UserNotification::DevNotBasedOnMain { UserNotification::DevNotBasedOnMain {
forge_alias: repo_details.forge.forge_alias().clone(), forge_alias: repo_details.forge.forge_alias().clone(),
repo_alias: repo_details.repo_alias.clone(), repo_alias: repo_details.repo_alias.clone(),
@ -121,7 +117,7 @@ fn reset_next_to_main(
main: &git::Commit, main: &git::Commit,
next: &git::Commit, next: &git::Commit,
next_branch: &BranchName, next_branch: &BranchName,
) -> Error { ) -> PositionsError {
match git::push::reset( match git::push::reset(
open_repository, open_repository,
repo_details, repo_details,
@ -129,8 +125,8 @@ fn reset_next_to_main(
&main.clone().into(), &main.clone().into(),
&git::push::Force::From(next.clone().into()), &git::push::Force::From(next.clone().into()),
) { ) {
Ok(()) => Error::Retryable(format!("Branch {next_branch} has been reset")), Ok(()) => PositionsError::Retryable(format!("Branch {next_branch} has been reset")),
Err(err) => Error::NonRetryable(format!( Err(err) => PositionsError::NonRetryable(format!(
"Failed to reset branch '{next_branch}' to commit '{next}': {err}" "Failed to reset branch '{next_branch}' to commit '{next}': {err}"
)), )),
} }
@ -154,7 +150,7 @@ fn is_based_on(commits: &[git::commit::Commit], needle: &git::Commit) -> bool {
pub fn get_commit_histories( pub fn get_commit_histories(
open_repository: &dyn OpenRepositoryLike, open_repository: &dyn OpenRepositoryLike,
repo_config: &RepoConfig, repo_config: &RepoConfig,
) -> git::commit::log::Result<git::commit::Histories> { ) -> Result<git::commit::Histories> {
debug!("main..."); debug!("main...");
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()];
@ -166,8 +162,9 @@ pub fn get_commit_histories(
Ok(histories) Ok(histories)
} }
pub type PositionsResult<T> = std::result::Result<T, PositionsError>;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum PositionsError {
#[error("{0} - will retry")] #[error("{0} - will retry")]
Retryable(String), Retryable(String),
@ -177,13 +174,3 @@ pub enum Error {
#[error("user intervention required")] #[error("user intervention required")]
UserIntervention(UserNotification), UserIntervention(UserNotification),
} }
impl From<git::fetch::Error> for Error {
fn from(value: git::fetch::Error) -> Self {
Self::Retryable(s!(value))
}
}
impl From<git::commit::log::Error> for Error {
fn from(value: git::commit::log::Error) -> Self {
Self::Retryable(s!(value))
}
}

View file

@ -1,7 +1,8 @@
// //
use crate::{ use crate::{
core::RemoteUrl,
git::{self, repository::open::OpenRepositoryLike}, git::{self, repository::open::OpenRepositoryLike},
s, RemoteUrl, s,
}; };
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
@ -44,12 +45,11 @@ pub enum Error {
#[error("no default fetch remote")] #[error("no default fetch remote")]
NoDefaultFetchRemote, NoDefaultFetchRemote,
#[error("no url for default push remote")] // #[error("no url for default push remote")]
NoUrlForDefaultPushRemote, // NoUrlForDefaultPushRemote,
#[error("no hostname for default push remote")]
NoHostnameForDefaultPushRemote,
// #[error("no hostname for default push remote")]
// NoHostnameForDefaultPushRemote,
#[error("unable to open repo: {0}")] #[error("unable to open repo: {0}")]
UnableToOpenRepo(String), UnableToOpenRepo(String),

View file

@ -1,5 +1,6 @@
// //
use crate::{ use crate::{
core::{GitDir, StoragePathType},
git::{ git::{
self, self,
repository::{ repository::{
@ -10,7 +11,6 @@ use crate::{
tests::{given, then}, tests::{given, then},
validation::positions::validate, validation::positions::validate,
}, },
s, GitDir, StoragePathType,
}; };
use assert2::let_assert; use assert2::let_assert;
@ -56,6 +56,10 @@ mod positions {
mod validate { mod validate {
use git::validation::positions::PositionsError;
use crate::err;
use super::*; use super::*;
#[test] #[test]
@ -66,7 +70,7 @@ mod positions {
let mut mock_open_repository = git::repository::open::mock(); let mut mock_open_repository = git::repository::open::mock();
mock_open_repository mock_open_repository
.expect_fetch() .expect_fetch()
.return_once(|| Err(git::fetch::Error::TestFailureExpected)); .return_once(|| Err(err!("expected failure")));
let mut repository_factory = git::repository::factory::mock(); let mut repository_factory = git::repository::factory::mock();
repository_factory repository_factory
.expect_open() .expect_open()
@ -81,10 +85,7 @@ mod positions {
println!("{result:?}"); println!("{result:?}");
let_assert!(Err(err) = result, "validate"); let_assert!(Err(err) = result, "validate");
assert!(matches!( assert!(matches!(err, PositionsError::Retryable(_)));
err,
git::validation::positions::Error::Retryable(_)
));
} }
#[test] #[test]
@ -100,10 +101,7 @@ mod positions {
.expect_commit_log() .expect_commit_log()
.returning(move |branch_name, _| { .returning(move |branch_name, _| {
if branch_name == &main_branch { if branch_name == &main_branch {
Err(git::commit::log::Error::Gix { Err(err!("{branch_name}: foo"))
branch: branch_name.clone(),
error: s!("foo"),
})
} else { } else {
Ok(vec![]) Ok(vec![])
} }
@ -120,10 +118,7 @@ mod positions {
let result = validate(&*open_repository, &repo_details, &repo_config); let result = validate(&*open_repository, &repo_details, &repo_config);
println!("{result:?}"); println!("{result:?}");
assert!(matches!( assert!(matches!(result, Err(PositionsError::Retryable(_))));
result,
Err(git::validation::positions::Error::Retryable(_))
));
} }
#[test] #[test]
@ -139,10 +134,7 @@ mod positions {
.expect_commit_log() .expect_commit_log()
.returning(move |branch_name, _| { .returning(move |branch_name, _| {
if branch_name == &next_branch { if branch_name == &next_branch {
Err(git::commit::log::Error::Gix { Err(err!("{branch_name} foo"))
branch: branch_name.clone(),
error: s!("foo"),
})
} else { } else {
Ok(vec![given::a_commit()]) Ok(vec![given::a_commit()])
} }
@ -159,10 +151,7 @@ mod positions {
let result = validate(&*open_repository, &repo_details, &repo_config); let result = validate(&*open_repository, &repo_details, &repo_config);
println!("{result:?}"); println!("{result:?}");
assert!(matches!( assert!(matches!(result, Err(PositionsError::Retryable(_))));
result,
Err(git::validation::positions::Error::Retryable(_))
));
} }
#[test] #[test]
@ -178,10 +167,7 @@ mod positions {
.expect_commit_log() .expect_commit_log()
.returning(move |branch_name, _| { .returning(move |branch_name, _| {
if branch_name == &dev_branch { if branch_name == &dev_branch {
Err(git::commit::log::Error::Gix { Err(err!("{branch_name} foo"))
branch: branch_name.clone(),
error: s!("foo"),
})
} else { } else {
Ok(vec![given::a_commit()]) Ok(vec![given::a_commit()])
} }
@ -198,10 +184,7 @@ mod positions {
let result = validate(&*open_repository, &repo_details, &repo_config); let result = validate(&*open_repository, &repo_details, &repo_config);
println!("{result:?}"); println!("{result:?}");
assert!(matches!( assert!(matches!(result, Err(PositionsError::Retryable(_))));
result,
Err(git::validation::positions::Error::Retryable(_))
));
} }
#[test] #[test]
@ -232,7 +215,7 @@ mod positions {
// add a commit to next 1 -> 4 // add a commit to next 1 -> 4
then::create_a_commit_on_branch(fs, gitdir, &branches.next())?; then::create_a_commit_on_branch(fs, gitdir, &branches.next())?;
then::git_log_all(gitdir)?; then::git_log_all(gitdir)?;
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
let_assert!( let_assert!(
@ -250,7 +233,7 @@ mod positions {
//then //then
assert!(matches!( assert!(matches!(
err, err,
git::validation::positions::Error::UserIntervention(_) git::validation::positions::PositionsError::UserIntervention(_)
)); ));
} }
@ -283,7 +266,7 @@ mod positions {
then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?; then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?;
then::git_log_all(gitdir)?; then::git_log_all(gitdir)?;
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
// second fetch as prep to push // second fetch as prep to push
@ -293,7 +276,7 @@ mod positions {
fs.deref().clone(), fs.deref().clone(),
|_branches, _gitdir, _fs| { |_branches, _gitdir, _fs| {
// don't change anything // don't change anything
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
test_repository.on_push(OnPush::new( test_repository.on_push(OnPush::new(
@ -318,7 +301,7 @@ mod positions {
&git::push::Force::From(sha_next.into()), &git::push::Force::From(sha_next.into()),
"should force push only if next is on expected sha" "should force push only if next is on expected sha"
); );
git::push::Result::Ok(()) Ok(())
}, },
)); ));
let_assert!( let_assert!(
@ -336,10 +319,7 @@ mod positions {
//then //then
println!("Got: {err:?}"); println!("Got: {err:?}");
// NOTE: assertions for correct push are in on_push above // NOTE: assertions for correct push are in on_push above
assert!(matches!( assert!(matches!(err, PositionsError::Retryable(_)));
err,
git::validation::positions::Error::Retryable(_)
));
} }
#[test] #[test]
@ -370,7 +350,7 @@ mod positions {
then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?; then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?;
then::git_log_all(gitdir)?; then::git_log_all(gitdir)?;
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
// second fetch as prep to push // second fetch as prep to push
@ -380,7 +360,7 @@ mod positions {
fs.deref().clone(), fs.deref().clone(),
|_branches, _gitdir, _fs| { |_branches, _gitdir, _fs| {
// don't change anything // don't change anything
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
test_repository.on_push(OnPush::new( test_repository.on_push(OnPush::new(
@ -388,7 +368,7 @@ mod positions {
gitdir.clone(), gitdir.clone(),
fs.deref().clone(), fs.deref().clone(),
|_repo_details, _branch_name, _gitref, _force, _repo_branches, _gitdir, _fs| { |_repo_details, _branch_name, _gitref, _force, _repo_branches, _gitdir, _fs| {
git::push::Result::Err(git::push::Error::Lock) Err(err!("Lock"))
}, },
)); ));
let_assert!( let_assert!(
@ -409,10 +389,7 @@ mod positions {
Ok(_) = then::get_sha_for_branch(&fs, &gitdir, &repo_config.branches().next()), Ok(_) = then::get_sha_for_branch(&fs, &gitdir, &repo_config.branches().next()),
"load next branch sha" "load next branch sha"
); );
assert!(matches!( assert!(matches!(err, PositionsError::NonRetryable(_)));
err,
git::validation::positions::Error::NonRetryable(_)
));
} }
#[test] #[test]
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
@ -441,7 +418,7 @@ mod positions {
then::create_a_commit_on_branch(fs, gitdir, &branches.next())?; then::create_a_commit_on_branch(fs, gitdir, &branches.next())?;
then::git_log_all(gitdir)?; then::git_log_all(gitdir)?;
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
// second fetch as prep to push // second fetch as prep to push
@ -451,7 +428,7 @@ mod positions {
fs.deref().clone(), fs.deref().clone(),
|_branches, _gitdir, _fs| { |_branches, _gitdir, _fs| {
// don't change anything // don't change anything
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
test_repository.on_push(OnPush::new( test_repository.on_push(OnPush::new(
@ -476,7 +453,7 @@ mod positions {
&git::push::Force::From(sha_next.into()), &git::push::Force::From(sha_next.into()),
"should force push only if next is on expected sha" "should force push only if next is on expected sha"
); );
git::push::Result::Ok(()) Ok(())
}, },
)); ));
let_assert!( let_assert!(
@ -494,10 +471,7 @@ mod positions {
//then //then
println!("Got: {err:?}"); println!("Got: {err:?}");
// NOTE: assertions for correct push are in on_push above // NOTE: assertions for correct push are in on_push above
assert!(matches!( assert!(matches!(err, PositionsError::Retryable(_)));
err,
git::validation::positions::Error::Retryable(_)
));
} }
#[test] #[test]
@ -528,7 +502,7 @@ mod positions {
then::create_a_commit_on_branch(fs, gitdir, &branches.next())?; then::create_a_commit_on_branch(fs, gitdir, &branches.next())?;
then::git_log_all(gitdir)?; then::git_log_all(gitdir)?;
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
// second fetch as prep to push // second fetch as prep to push
@ -538,7 +512,7 @@ mod positions {
fs.deref().clone(), fs.deref().clone(),
|_branches, _gitdir, _fs| { |_branches, _gitdir, _fs| {
// don't change anything // don't change anything
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
test_repository.on_push(OnPush::new( test_repository.on_push(OnPush::new(
@ -563,7 +537,7 @@ mod positions {
&git::push::Force::From(sha_next.into()), &git::push::Force::From(sha_next.into()),
"should force push only if next is on expected sha" "should force push only if next is on expected sha"
); );
git::push::Result::Ok(()) Ok(())
}, },
)); ));
let_assert!( let_assert!(
@ -624,7 +598,7 @@ mod positions {
then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?; then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?;
then::git_log_all(gitdir)?; then::git_log_all(gitdir)?;
git::fetch::Result::Ok(()) Ok(())
}, },
)); ));
let_assert!( let_assert!(

View file

@ -1,15 +1,15 @@
#[macro_export] #[macro_export]
macro_rules! message { macro_rules! message {
($name:ident, $value:ty, $docs:literal) => { ($name:ident, $value:ty, $docs:literal) => {
git_next_core::newtype!($name, $value, $docs); $crate::newtype!($name, $value, $docs);
}; };
($name:ident, $docs:literal) => { ($name:ident, $docs:literal) => {
git_next_core::newtype!($name, $docs); $crate::newtype!($name, $docs);
}; };
($name:ident, $value:ty => $result:ty, $docs:literal) => { ($name:ident, $value:ty => $result:ty, $docs:literal) => {
git_next_core::newtype!($name, $value, $docs); $crate::newtype!($name, $value, $docs);
}; };
($name:ident => $result:ty, $docs:literal) => { ($name:ident => $result:ty, $docs:literal) => {
git_next_core::newtype!($name, $docs); $crate::newtype!($name, $docs);
}; };
} }

View file

@ -34,6 +34,7 @@ macro_rules! newtype {
)] )]
pub struct $name($type); pub struct $name($type);
impl $name { impl $name {
#[allow(dead_code)]
pub fn new(value: impl Into<$type>) -> Self { pub fn new(value: impl Into<$type>) -> Self {
Self(value.into()) Self(value.into())
} }

View file

@ -6,7 +6,7 @@ use kameo::{mailbox::unbounded::UnboundedMailbox, message::Message, Actor};
use notify::{event::ModifyKind, RecommendedWatcher, Watcher}; use notify::{event::ModifyKind, RecommendedWatcher, Watcher};
use tracing::{error, info}; use tracing::{error, info};
use git_next_core::message; use crate::message;
use crate::{ use crate::{
default_on_actor_link_died, default_on_actor_panic, default_on_actor_stop, on_actor_start, default_on_actor_link_died, default_on_actor_panic, default_on_actor_stop, on_actor_start,

View file

@ -1,5 +1,5 @@
// //
use git_next_core::git::{ForgeLike, RepoDetails}; use crate::core::git::{ForgeLike, RepoDetails};
#[cfg(feature = "forgejo")] #[cfg(feature = "forgejo")]
use crate::forges::forgejo::ForgeJo; use crate::forges::forgejo::ForgeJo;
@ -16,9 +16,9 @@ impl Forge {
pub fn create(repo_details: RepoDetails, net: Net) -> Box<dyn ForgeLike> { pub fn create(repo_details: RepoDetails, net: Net) -> Box<dyn ForgeLike> {
match repo_details.forge.forge_type() { match repo_details.forge.forge_type() {
#[cfg(feature = "forgejo")] #[cfg(feature = "forgejo")]
git_next_core::ForgeType::ForgeJo => Box::new(ForgeJo::new(repo_details, net)), crate::core::ForgeType::ForgeJo => Box::new(ForgeJo::new(repo_details, net)),
#[cfg(feature = "github")] #[cfg(feature = "github")]
git_next_core::ForgeType::GitHub => Box::new(Github::new(repo_details, net)), crate::core::ForgeType::GitHub => Box::new(Github::new(repo_details, net)),
_ => { _ => {
drop(repo_details); drop(repo_details);
drop(net); drop(net);

View file

@ -2,7 +2,7 @@
#[cfg(any(feature = "forgejo", feature = "github"))] #[cfg(any(feature = "forgejo", feature = "github"))]
use super::*; use super::*;
use git_next_core::{ use crate::core::{
self as core, self as core,
git::{self, RepoDetails}, git::{self, RepoDetails},
GitDir, RepoConfigSource, StoragePathType, GitDir, RepoConfigSource, StoragePathType,
@ -12,7 +12,7 @@ use git_next_core::{
#[test] #[test]
fn test_forgejo_name() { fn test_forgejo_name() {
let mock_net = kxio::net::mock(); let mock_net = kxio::net::mock();
let repo_details = given_repo_details(git_next_core::ForgeType::ForgeJo); let repo_details = given_repo_details(crate::core::ForgeType::ForgeJo);
let forge = Forge::create(repo_details, mock_net.clone().into()); let forge = Forge::create(repo_details, mock_net.clone().into());
assert_eq!(forge.name(), "forgejo"); assert_eq!(forge.name(), "forgejo");
mock_net.assert_no_unused_plans(); mock_net.assert_no_unused_plans();
@ -22,14 +22,14 @@ fn test_forgejo_name() {
#[test] #[test]
fn test_github_name() { fn test_github_name() {
let mock_net = kxio::net::mock(); let mock_net = kxio::net::mock();
let repo_details = given_repo_details(git_next_core::ForgeType::GitHub); let repo_details = given_repo_details(crate::core::ForgeType::GitHub);
let forge = Forge::create(repo_details, mock_net.clone().into()); let forge = Forge::create(repo_details, mock_net.clone().into());
assert_eq!(forge.name(), "github"); assert_eq!(forge.name(), "github");
mock_net.assert_no_unused_plans(); mock_net.assert_no_unused_plans();
} }
#[allow(dead_code)] #[allow(dead_code)]
fn given_repo_details(forge_type: git_next_core::ForgeType) -> RepoDetails { fn given_repo_details(forge_type: crate::core::ForgeType) -> RepoDetails {
let fs = kxio::fs::temp().unwrap_or_else(|e| { let fs = kxio::fs::temp().unwrap_or_else(|e| {
println!("{e}"); println!("{e}");
panic!("fs") panic!("fs")

View file

@ -6,7 +6,7 @@ mod webhook;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use git_next_core::{ use crate::core::{
self as core, self as core,
git::{self, forge::commit::Status}, git::{self, forge::commit::Status},
server::RepoListenUrl, server::RepoListenUrl,
@ -31,6 +31,8 @@ impl git::ForgeLike for ForgeJo {
fn duplicate(&self) -> Box<dyn git::ForgeLike> { fn duplicate(&self) -> Box<dyn git::ForgeLike> {
Box::new(self.clone()) Box::new(self.clone())
} }
#[cfg(test)]
fn name(&self) -> String { fn name(&self) -> String {
"forgejo".to_string() "forgejo".to_string()
} }
@ -74,6 +76,7 @@ impl git::ForgeLike for ForgeJo {
Ok(status) Ok(status)
} }
#[cfg(test)]
async fn list_webhooks( async fn list_webhooks(
&self, &self,
repo_listen_url: &RepoListenUrl, repo_listen_url: &RepoListenUrl,

View file

@ -3,7 +3,7 @@
use crate::forges::forgejo::ForgeJo; use crate::forges::forgejo::ForgeJo;
use git_next_core::{ use crate::core::{
git::{self, forge::commit::Status, ForgeLike as _}, git::{self, forge::commit::Status, ForgeLike as _},
server::{ListenUrl, RepoListenUrl}, server::{ListenUrl, RepoListenUrl},
BranchName, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias, BranchName, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias,
@ -99,7 +99,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 = git_next_core::webhook::forge_notification::Body::new( let body = crate::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(),
); );
@ -108,7 +108,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(git_next_core::webhook::push::Branch::Next) Some(crate::core::webhook::push::Branch::Next)
); );
mock_net.assert_no_unused_plans(); mock_net.assert_no_unused_plans();
} }
@ -118,7 +118,7 @@ mod forgejo {
let fs = given::a_filesystem(); let fs = given::a_filesystem();
let mock_net = given::a_network(); let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone()); let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let body = git_next_core::webhook::forge_notification::Body::new( let body = crate::core::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));
@ -651,8 +651,8 @@ mod forgejo {
} }
mod given { mod given {
use crate::core::server::RepoListenUrl;
use git::RepoDetails; use git::RepoDetails;
use git_next_core::server::RepoListenUrl;
use kxio::net::{MockNet, StatusCode}; use kxio::net::{MockNet, StatusCode};
use super::*; use super::*;
@ -739,8 +739,8 @@ mod forgejo {
WebhookAuth::generate() WebhookAuth::generate()
} }
pub fn a_webhook_message_body() -> git_next_core::webhook::forge_notification::Body { pub fn a_webhook_message_body() -> crate::core::webhook::forge_notification::Body {
git_next_core::webhook::forge_notification::Body::new(a_name()) crate::core::webhook::forge_notification::Body::new(a_name())
} }
pub fn repo_branches() -> RepoBranches { pub fn repo_branches() -> RepoBranches {

View file

@ -1,5 +1,5 @@
// //
use git_next_core::{git, server::RepoListenUrl, WebhookId}; use crate::core::{git, server::RepoListenUrl, WebhookId};
use kxio::net::Net; use kxio::net::Net;
use crate::forges::forgejo::webhook::Hook; use crate::forges::forgejo::webhook::Hook;

View file

@ -1,5 +1,5 @@
// //
use git_next_core::{git, webhook, BranchName, WebhookId}; use crate::core::{git, webhook, BranchName, WebhookId};
use std::collections::HashMap; use std::collections::HashMap;

View file

@ -1,7 +1,7 @@
// //
use crate::forges::forgejo; use crate::forges::forgejo;
use git_next_core::{git, webhook}; use crate::core::{git, webhook};
pub fn parse_body( pub fn parse_body(
body: &webhook::forge_notification::Body, body: &webhook::forge_notification::Body,

View file

@ -1,5 +1,5 @@
// //
use git_next_core::{ use crate::core::{
git::{self, forge::webhook::Error}, git::{self, forge::webhook::Error},
server::RepoListenUrl, server::RepoListenUrl,
RegisteredWebhook, WebhookAuth, WebhookId, RegisteredWebhook, WebhookAuth, WebhookId,

View file

@ -1,5 +1,5 @@
// //
use git_next_core::{git, WebhookId}; use crate::core::{git, WebhookId};
use kxio::net::Net; use kxio::net::Net;
use secrecy::ExposeSecret as _; use secrecy::ExposeSecret as _;

View file

@ -1,6 +1,6 @@
// //
use crate::core::git::{self, forge::commit::Status};
use crate::forges::github::{self as github, GithubState}; use crate::forges::github::{self as github, GithubState};
use git_next_core::git::{self, forge::commit::Status};
use github::GithubStatus; use github::GithubStatus;
/// 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.

View file

@ -5,12 +5,12 @@ mod tests;
mod commit; mod commit;
pub mod webhook; pub mod webhook;
use crate::forges::github; use crate::core::{
use git_next_core::{
self as core, git, self as core, git,
server::{self, RepoListenUrl}, server::{self, RepoListenUrl},
ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId, ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId,
}; };
use crate::forges::github;
use derive_more::Constructor; use derive_more::Constructor;
@ -24,6 +24,8 @@ impl git::ForgeLike for Github {
fn duplicate(&self) -> Box<dyn git::ForgeLike> { fn duplicate(&self) -> Box<dyn git::ForgeLike> {
Box::new(self.clone()) Box::new(self.clone())
} }
#[cfg(test)]
fn name(&self) -> String { fn name(&self) -> String {
"github".to_string() "github".to_string()
} }
@ -58,6 +60,7 @@ impl git::ForgeLike for Github {
github::commit::status(self, commit).await github::commit::status(self, commit).await
} }
#[cfg(test)]
async fn list_webhooks( async fn list_webhooks(
&self, &self,
repo_listen_url: &RepoListenUrl, repo_listen_url: &RepoListenUrl,

View file

@ -1,14 +1,14 @@
// //
#![allow(clippy::expect_used)] #![allow(clippy::expect_used)]
use crate::forges::github::{Github, GithubState, GithubStatus}; use crate::core::{
use git_next_core::{
git::{self, forge::commit::Status, ForgeLike}, git::{self, forge::commit::Status, ForgeLike},
server::ListenUrl, server::ListenUrl,
webhook::{self, forge_notification::Body}, webhook::{self, forge_notification::Body},
ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias,
RepoBranches, RepoPath, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId, RepoBranches, RepoPath, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId,
}; };
use crate::forges::github::{Github, GithubState, GithubStatus};
use assert2::let_assert; use assert2::let_assert;
use kxio::net::{MockNet, StatusCode}; use kxio::net::{MockNet, StatusCode};
@ -488,7 +488,7 @@ mod github {
} }
pub mod with { pub mod with {
use git_next_core::server::RepoListenUrl; use crate::core::server::RepoListenUrl;
use super::*; use super::*;
@ -546,8 +546,8 @@ mod github {
mod given { mod given {
use crate::core::server::RepoListenUrl;
use git::RepoDetails; use git::RepoDetails;
use git_next_core::server::RepoListenUrl;
use super::*; use super::*;
@ -657,7 +657,7 @@ mod github {
), ),
&a_forge_alias(), &a_forge_alias(),
&ForgeConfig::new( &ForgeConfig::new(
ForgeType::ForgeJo, ForgeType::GitHub,
a_name(), a_name(),
a_name(), a_name(),
a_name(), a_name(),

View file

@ -2,7 +2,7 @@
use std::string::ToString; use std::string::ToString;
use git_next_core::{ForgeNotification, WebhookAuth}; use crate::core::{ForgeNotification, WebhookAuth};
use hmac::Mac; use hmac::Mac;
type HmacSha256 = hmac::Hmac<sha2::Sha256>; type HmacSha256 = hmac::Hmac<sha2::Sha256>;
@ -25,7 +25,7 @@ pub fn is_authorised(msg: &ForgeNotification, webhook_auth: &WebhookAuth) -> boo
#[cfg(test)] #[cfg(test)]
pub fn sign_body( pub fn sign_body(
webhook_auth: &WebhookAuth, webhook_auth: &WebhookAuth,
body: &git_next_core::webhook::forge_notification::Body, body: &crate::core::webhook::forge_notification::Body,
) -> Option<String> { ) -> Option<String> {
let payload = body.as_str(); let payload = body.as_str();
let mut hmac = HmacSha256::new_from_slice(webhook_auth.to_string().as_bytes()).ok()?; let mut hmac = HmacSha256::new_from_slice(webhook_auth.to_string().as_bytes()).ok()?;

View file

@ -1,6 +1,6 @@
// //
use crate::core::{git, server::RepoListenUrl, WebhookId};
use crate::forges::github; use crate::forges::github;
use git_next_core::{git, server::RepoListenUrl, WebhookId};
// 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(

View file

@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
// //
use git_next_core::{git, webhook, ApiToken, BranchName}; use crate::core::{git, webhook, ApiToken, BranchName};
pub mod authorisation; pub mod authorisation;
mod list; mod list;

View file

@ -1,7 +1,7 @@
// //
use crate::forges::github; use crate::forges::github;
use git_next_core::{git, webhook}; use crate::core::{git, webhook};
pub fn parse_body( pub fn parse_body(
body: &webhook::forge_notification::Body, body: &webhook::forge_notification::Body,

View file

@ -1,6 +1,6 @@
// //
use crate::core::{git, server::RepoListenUrl, RegisteredWebhook, WebhookAuth, WebhookId};
use crate::forges::github::{self as github, webhook}; use crate::forges::github::{self as github, webhook};
use git_next_core::{git, server::RepoListenUrl, RegisteredWebhook, WebhookAuth, WebhookId};
use serde_json::json; use serde_json::json;
// 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

View file

@ -1,6 +1,6 @@
// //
use crate::core::{git, WebhookId};
use crate::forges::github; use crate::forges::github;
use git_next_core::{git, WebhookId};
// 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(

Some files were not shown because too many files have changed in this diff Show more