diff --git a/Cargo.lock b/Cargo.lock index 215149e..f6b50d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1070,7 +1070,8 @@ dependencies = [ "derive_more", "directories", "git-conventional", - "git-next-core", + "git-url-parse", + "gix", "hex", "hmac", "kameo", @@ -1080,6 +1081,7 @@ dependencies = [ "mockall", "notifica", "notify", + "pike", "pretty_assertions", "rand", "ratatui", @@ -1091,6 +1093,7 @@ dependencies = [ "serde_json", "sha2", "standardwebhooks", + "take-until", "test-log", "thiserror 2.0.11", "time", @@ -1104,33 +1107,6 @@ dependencies = [ "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]] name = "git-url-parse" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index baf4e3f..cbd6e61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ categories = ["development-tools"] # expect_used = "warn" [workspace.dependencies] -git-next-core = { path = "crates/core", version = "0.14" } # TUI ratatui = "0.29" @@ -59,6 +58,7 @@ git-url-parse = "0.4" # fs/network kxio = "5.1" +# kxio = { path = "../kxio/" } # TOML parsing serde = { version = "1.0", features = ["derive"] } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 39a6d10..5f053b8 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -26,7 +26,6 @@ tui = [ ] [dependencies] -git-next-core = { workspace = true } # TUI ratatui = { workspace = true, optional = true } @@ -93,6 +92,19 @@ hmac = { workspace = true } sha2 = { 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] # Testing assert2 = { workspace = true } diff --git a/crates/cli/src/alerts/desktop.rs b/crates/cli/src/alerts/desktop.rs index 8e79f5f..1ce9aa7 100644 --- a/crates/cli/src/alerts/desktop.rs +++ b/crates/cli/src/alerts/desktop.rs @@ -1,6 +1,6 @@ // 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) { let message = short_message(user_notification); diff --git a/crates/cli/src/alerts/email.rs b/crates/cli/src/alerts/email.rs index 2f12cbd..c76d7c1 100644 --- a/crates/cli/src/alerts/email.rs +++ b/crates/cli/src/alerts/email.rs @@ -1,5 +1,5 @@ // -use git_next_core::{ +use crate::core::{ git::UserNotification, server::{EmailConfig, SmtpConfig}, }; diff --git a/crates/cli/src/alerts/history.rs b/crates/cli/src/alerts/history.rs index de15a95..4898154 100644 --- a/crates/cli/src/alerts/history.rs +++ b/crates/cli/src/alerts/history.rs @@ -1,5 +1,5 @@ // -use git_next_core::git::UserNotification; +use crate::core::git::UserNotification; use tracing::info; use std::{ diff --git a/crates/cli/src/alerts/messages.rs b/crates/cli/src/alerts/messages.rs index 409d2ce..8e8d8a6 100644 --- a/crates/cli/src/alerts/messages.rs +++ b/crates/cli/src/alerts/messages.rs @@ -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"); diff --git a/crates/cli/src/alerts/mod.rs b/crates/cli/src/alerts/mod.rs index 00a3551..b52b873 100644 --- a/crates/cli/src/alerts/mod.rs +++ b/crates/cli/src/alerts/mod.rs @@ -1,7 +1,7 @@ // use derive_more::derive::Constructor; -use git_next_core::{git::UserNotification, server::Shout}; +use crate::core::{git::UserNotification, server::Shout}; pub use history::History; use kameo::{mailbox::unbounded::UnboundedMailbox, Actor}; diff --git a/crates/cli/src/alerts/tests/history.rs b/crates/cli/src/alerts/tests/history.rs index 8414209..c8b31a5 100644 --- a/crates/cli/src/alerts/tests/history.rs +++ b/crates/cli/src/alerts/tests/history.rs @@ -1,7 +1,7 @@ use std::time::Duration; +use crate::core::git::UserNotification; use assert2::let_assert; -use git_next_core::git::UserNotification; use crate::{alerts::History, repo::tests::given}; diff --git a/crates/cli/src/alerts/webhook.rs b/crates/cli/src/alerts/webhook.rs index 8c8f95b..5342bd2 100644 --- a/crates/cli/src/alerts/webhook.rs +++ b/crates/cli/src/alerts/webhook.rs @@ -1,5 +1,5 @@ // -use git_next_core::{git::UserNotification, server::OutboundWebhook}; +use crate::core::{git::UserNotification, server::OutboundWebhook}; use secrecy::ExposeSecret as _; use standardwebhooks::Webhook; diff --git a/crates/core/src/config/api_token.rs b/crates/cli/src/core/config/api_token.rs similarity index 100% rename from crates/core/src/config/api_token.rs rename to crates/cli/src/core/config/api_token.rs diff --git a/crates/core/src/config/branch_name.rs b/crates/cli/src/core/config/branch_name.rs similarity index 100% rename from crates/core/src/config/branch_name.rs rename to crates/cli/src/core/config/branch_name.rs diff --git a/crates/core/src/config/commit_count.rs b/crates/cli/src/core/config/commit_count.rs similarity index 100% rename from crates/core/src/config/commit_count.rs rename to crates/cli/src/core/config/commit_count.rs diff --git a/crates/core/src/config/common.rs b/crates/cli/src/core/config/common.rs similarity index 73% rename from crates/core/src/config/common.rs rename to crates/cli/src/core/config/common.rs index 3b37951..19bd069 100644 --- a/crates/core/src/config/common.rs +++ b/crates/cli/src/core/config/common.rs @@ -1,4 +1,4 @@ -use crate::config::{ +use crate::core::config::{ ApiToken, BranchName, ForgeAlias, ForgeDetails, ForgeType, Hostname, RepoAlias, RepoBranches, 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()) } -pub(crate) fn user(n: u32) -> User { +pub fn user(n: u32) -> User { User::new(format!("user-{n}")) } -pub(crate) fn hostname(n: u32) -> Hostname { +pub fn hostname(n: u32) -> Hostname { 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}")) } -pub(crate) fn branch_name(n: u32) -> BranchName { +pub fn branch_name(n: u32) -> BranchName { 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}")) } -pub(crate) fn repo_alias(n: u32) -> RepoAlias { +pub fn repo_alias(n: u32) -> RepoAlias { RepoAlias::new(format!("repo-alias-{n}")) } diff --git a/crates/core/src/config/forge_alias.rs b/crates/cli/src/core/config/forge_alias.rs similarity index 100% rename from crates/core/src/config/forge_alias.rs rename to crates/cli/src/core/config/forge_alias.rs diff --git a/crates/core/src/config/forge_config.rs b/crates/cli/src/core/config/forge_config.rs similarity index 93% rename from crates/core/src/config/forge_config.rs rename to crates/cli/src/core/config/forge_config.rs index 4f6c577..2266d4c 100644 --- a/crates/core/src/config/forge_config.rs +++ b/crates/cli/src/core/config/forge_config.rs @@ -1,9 +1,7 @@ use std::collections::BTreeMap; -use crate::{ - config::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User}, - s, -}; +use crate::core::config::{ApiToken, ForgeType, Hostname, RepoAlias, ServerRepoConfig, User}; +use crate::s; use super::CommitCount; diff --git a/crates/core/src/config/forge_details.rs b/crates/cli/src/core/config/forge_details.rs similarity index 94% rename from crates/core/src/config/forge_details.rs rename to crates/cli/src/core/config/forge_details.rs index 3dda4e8..1c50a25 100644 --- a/crates/core/src/config/forge_details.rs +++ b/crates/cli/src/core/config/forge_details.rs @@ -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; diff --git a/crates/core/src/config/forge_type.rs b/crates/cli/src/core/config/forge_type.rs similarity index 100% rename from crates/core/src/config/forge_type.rs rename to crates/cli/src/core/config/forge_type.rs diff --git a/crates/core/src/config/git_dir.rs b/crates/cli/src/core/config/git_dir.rs similarity index 100% rename from crates/core/src/config/git_dir.rs rename to crates/cli/src/core/config/git_dir.rs diff --git a/crates/core/src/config/graphs.rs b/crates/cli/src/core/config/graphs.rs similarity index 100% rename from crates/core/src/config/graphs.rs rename to crates/cli/src/core/config/graphs.rs diff --git a/crates/core/src/config/host_name.rs b/crates/cli/src/core/config/host_name.rs similarity index 100% rename from crates/core/src/config/host_name.rs rename to crates/cli/src/core/config/host_name.rs diff --git a/crates/core/src/config/mod.rs b/crates/cli/src/core/config/mod.rs similarity index 96% rename from crates/core/src/config/mod.rs rename to crates/cli/src/core/config/mod.rs index 9f6c82b..8c22eca 100644 --- a/crates/core/src/config/mod.rs +++ b/crates/cli/src/core/config/mod.rs @@ -2,7 +2,10 @@ mod api_token; mod branch_name; mod commit_count; + +#[cfg(test)] pub mod common; + mod forge_alias; mod forge_config; mod forge_details; @@ -53,4 +56,4 @@ pub use webhook::forge_notification::ForgeNotification; pub use webhook::id::WebhookId; // re-export -pub use pike::{pike, pike_opt, pike_res}; +pub use pike::pike; diff --git a/crates/core/src/config/registered_webhook.rs b/crates/cli/src/core/config/registered_webhook.rs similarity index 86% rename from crates/core/src/config/registered_webhook.rs rename to crates/cli/src/core/config/registered_webhook.rs index 5f3ece3..608dbc3 100644 --- a/crates/core/src/config/registered_webhook.rs +++ b/crates/cli/src/core/config/registered_webhook.rs @@ -1,5 +1,5 @@ // -use crate::config::{WebhookAuth, WebhookId}; +use crate::core::config::{WebhookAuth, WebhookId}; #[derive(Debug, derive_more::Constructor)] pub struct RegisteredWebhook { diff --git a/crates/core/src/config/remote_url.rs b/crates/cli/src/core/config/remote_url.rs similarity index 100% rename from crates/core/src/config/remote_url.rs rename to crates/cli/src/core/config/remote_url.rs diff --git a/crates/core/src/config/repo_alias.rs b/crates/cli/src/core/config/repo_alias.rs similarity index 100% rename from crates/core/src/config/repo_alias.rs rename to crates/cli/src/core/config/repo_alias.rs diff --git a/crates/core/src/config/repo_branches.rs b/crates/cli/src/core/config/repo_branches.rs similarity index 94% rename from crates/core/src/config/repo_branches.rs rename to crates/cli/src/core/config/repo_branches.rs index b4df8bc..4be2aca 100644 --- a/crates/core/src/config/repo_branches.rs +++ b/crates/cli/src/core/config/repo_branches.rs @@ -1,4 +1,4 @@ -use crate::config::BranchName; +use crate::core::config::BranchName; /// Mapped from `.git-next.toml` file at `branches` #[derive( diff --git a/crates/core/src/config/repo_config.rs b/crates/cli/src/core/config/repo_config.rs similarity index 94% rename from crates/core/src/config/repo_config.rs rename to crates/cli/src/core/config/repo_config.rs index 4a859c1..7a44e91 100644 --- a/crates/core/src/config/repo_config.rs +++ b/crates/cli/src/core/config/repo_config.rs @@ -1,4 +1,4 @@ -use crate::config::{RepoBranches, RepoConfigSource}; +use crate::core::config::{RepoBranches, RepoConfigSource}; /// Mapped from `.git-next.toml` file in target repo /// Is also derived from the optional parameters in `git-next-server.toml` at diff --git a/crates/core/src/config/repo_config_source.rs b/crates/cli/src/core/config/repo_config_source.rs similarity index 100% rename from crates/core/src/config/repo_config_source.rs rename to crates/cli/src/core/config/repo_config_source.rs diff --git a/crates/core/src/config/repo_path.rs b/crates/cli/src/core/config/repo_path.rs similarity index 100% rename from crates/core/src/config/repo_path.rs rename to crates/cli/src/core/config/repo_path.rs diff --git a/crates/core/src/config/server.rs b/crates/cli/src/core/config/server.rs similarity index 94% rename from crates/core/src/config/server.rs rename to crates/cli/src/core/config/server.rs index 23164f3..11c80f5 100644 --- a/crates/core/src/config/server.rs +++ b/crates/cli/src/core/config/server.rs @@ -15,24 +15,10 @@ use serde::{Deserialize, Serialize}; use tracing::info; use crate::{ - config::{ForgeAlias, ForgeConfig, RepoAlias}, - newtype, s, + core::config::{ForgeAlias, ForgeConfig, RepoAlias}, + 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 = core::result::Result; - /// Mapped from the `git-next-server.toml` file #[derive( Clone, diff --git a/crates/core/src/config/server_repo_config.rs b/crates/cli/src/core/config/server_repo_config.rs similarity index 98% rename from crates/core/src/config/server_repo_config.rs rename to crates/cli/src/core/config/server_repo_config.rs index 6b93f90..2a98067 100644 --- a/crates/core/src/config/server_repo_config.rs +++ b/crates/cli/src/core/config/server_repo_config.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use crate::{ - config::{ + core::config::{ git_dir::StoragePathType, BranchName, GitDir, RepoBranches, RepoConfig, RepoConfigSource, RepoPath, }, diff --git a/crates/core/src/config/tests.rs b/crates/cli/src/core/config/tests.rs similarity index 96% rename from crates/core/src/config/tests.rs rename to crates/cli/src/core/config/tests.rs index 1cff9df..95034d3 100644 --- a/crates/core/src/config/tests.rs +++ b/crates/cli/src/core/config/tests.rs @@ -7,16 +7,15 @@ use std::collections::BTreeMap; use std::path::PathBuf; use crate::{ + core::{ + server::{AppConfig, Http, Storage}, + webhook::push::Branch, + }, s, - server::{AppConfig, Http, Storage}, - webhook::push::Branch, }; mod url; -type Result = core::result::Result>; -type TestResult = Result<()>; - mod server_repo_config { use super::*; @@ -100,10 +99,12 @@ mod server_repo_config { } } mod repo_config { + use crate::Result; + use super::*; #[test] - fn should_parse_toml() -> TestResult { + fn should_parse_toml() -> Result<()> { let main = given::a_name(); let next = given::a_name(); let dev = given::a_name(); @@ -517,10 +518,12 @@ mod server { use super::*; mod load { + use crate::{err, Result}; + use super::*; #[test] - fn load_should_parse_app_config() -> TestResult { + fn load_should_parse_app_config() -> Result<()> { let app_config = given::an_app_config(); let fs = kxio::fs::temp()?; let_assert!(Ok(()) = write_app_config(&app_config, &fs), "write"); @@ -530,7 +533,7 @@ mod server { 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_addr = http.ip(); let http_port = app_config.listen_socket_addr()?.port(); @@ -553,11 +556,11 @@ mod server { .forges() .next() .map(|(fa, _)| fa) - .ok_or("forge missing")?; + .ok_or_else(|| err!("forge missing"))?; let forge_default = app_config .forge .get(forge_alias.as_ref()) - .ok_or("forge missing")?; + .ok_or_else(|| err!("forge missing"))?; let forge_type = forge_default.forge_type(); let forge_hostname = forge_default.hostname(); let forge_user = forge_default.user(); @@ -716,7 +719,7 @@ mod push { let message = given::a_name(); let push_event = { 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)); } @@ -727,7 +730,7 @@ mod push { let message = given::a_name(); let push_event = { 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)); } @@ -738,7 +741,7 @@ mod push { let message = given::a_name(); let push_event = { 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)); } @@ -749,7 +752,7 @@ mod push { let message = given::a_name(); let push_event = { 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); } @@ -761,7 +764,7 @@ mod push { let push_event = { let branch_name = repo_branches.main(); 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); } @@ -773,14 +776,14 @@ mod push { let push_event = { let branch_name = repo_branches.main(); 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); } } mod given { - use crate::server::{EmailConfig, Listen, ListenUrl, OutboundWebhook, Shout, SmtpConfig}; + use crate::core::server::{EmailConfig, Listen, ListenUrl, OutboundWebhook, Shout, SmtpConfig}; use super::*; use rand::Rng as _; @@ -911,8 +914,8 @@ mod given { RepoAlias::new(a_name()) } - pub fn a_webhook_message_body() -> crate::webhook::forge_notification::Body { - crate::webhook::forge_notification::Body::new(a_name()) + pub fn a_webhook_message_body() -> crate::core::webhook::forge_notification::Body { + crate::core::webhook::forge_notification::Body::new(a_name()) } pub fn some_repo_branches() -> RepoBranches { diff --git a/crates/core/src/config/tests/url.rs b/crates/cli/src/core/config/tests/url.rs similarity index 100% rename from crates/core/src/config/tests/url.rs rename to crates/cli/src/core/config/tests/url.rs diff --git a/crates/core/src/config/user.rs b/crates/cli/src/core/config/user.rs similarity index 100% rename from crates/core/src/config/user.rs rename to crates/cli/src/core/config/user.rs diff --git a/crates/core/src/config/webhook.rs b/crates/cli/src/core/config/webhook.rs similarity index 100% rename from crates/core/src/config/webhook.rs rename to crates/cli/src/core/config/webhook.rs diff --git a/crates/core/src/config/webhook/auth.rs b/crates/cli/src/core/config/webhook/auth.rs similarity index 100% rename from crates/core/src/config/webhook/auth.rs rename to crates/cli/src/core/config/webhook/auth.rs diff --git a/crates/core/src/config/webhook/forge_notification.rs b/crates/cli/src/core/config/webhook/forge_notification.rs similarity index 95% rename from crates/core/src/config/webhook/forge_notification.rs rename to crates/cli/src/core/config/webhook/forge_notification.rs index f66bbf4..5f97629 100644 --- a/crates/core/src/config/webhook/forge_notification.rs +++ b/crates/cli/src/core/config/webhook/forge_notification.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; 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. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, derive_more::Constructor)] diff --git a/crates/core/src/config/webhook/id.rs b/crates/cli/src/core/config/webhook/id.rs similarity index 100% rename from crates/core/src/config/webhook/id.rs rename to crates/cli/src/core/config/webhook/id.rs diff --git a/crates/core/src/config/webhook/push.rs b/crates/cli/src/core/config/webhook/push.rs similarity index 94% rename from crates/core/src/config/webhook/push.rs rename to crates/cli/src/core/config/webhook/push.rs index 6fd051d..5d65538 100644 --- a/crates/core/src/config/webhook/push.rs +++ b/crates/cli/src/core/config/webhook/push.rs @@ -1,5 +1,5 @@ // -use crate::config::{BranchName, RepoBranches}; +use crate::core::config::{BranchName, RepoBranches}; use derive_more::Constructor; #[derive(Clone, Debug, Constructor, PartialEq, Eq, derive_with::With)] diff --git a/crates/core/src/config/webhook/tests.rs b/crates/cli/src/core/config/webhook/tests.rs similarity index 90% rename from crates/core/src/config/webhook/tests.rs rename to crates/cli/src/core/config/webhook/tests.rs index dde11b8..8179bd8 100644 --- a/crates/core/src/config/webhook/tests.rs +++ b/crates/cli/src/core/config/webhook/tests.rs @@ -1,5 +1,6 @@ mod auth { - use crate::{s, WebhookAuth}; + use crate::core::WebhookAuth; + use crate::s; #[test] fn bytes() -> Result<(), Box> { diff --git a/crates/core/src/git/commit.rs b/crates/cli/src/core/git/commit.rs similarity index 76% rename from crates/core/src/git/commit.rs rename to crates/cli/src/core/git/commit.rs index 792100f..eeeb59f 100644 --- a/crates/core/src/git/commit.rs +++ b/crates/cli/src/core/git/commit.rs @@ -1,5 +1,6 @@ // -use crate::{newtype, webhook}; +use crate::core::webhook; +use crate::newtype; use derive_more::Display; use serde::Serialize; @@ -68,18 +69,3 @@ pub struct Histories { pub next: Vec, pub dev: Vec, } - -pub mod log { - use crate::BranchName; - - pub type Result = core::result::Result; - - #[derive(Debug, thiserror::Error)] - pub enum Error { - #[error("branch: {branch}, error: {error}")] - Gix { branch: BranchName, error: String }, - - #[error("lock")] - Lock, - } -} diff --git a/crates/core/src/git/file.rs b/crates/cli/src/core/git/file.rs similarity index 65% rename from crates/core/src/git/file.rs rename to crates/cli/src/core/git/file.rs index 7184cc6..01617f4 100644 --- a/crates/core/src/git/file.rs +++ b/crates/cli/src/core/git/file.rs @@ -1,38 +1,36 @@ // -pub type Result = core::result::Result; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("lock")] - Lock, + // #[error("lock")] + // Lock, - #[error("File not found: {}", 0)] - NotFound(String), + // #[error("File not found: {}", 0)] + // NotFound(String), - #[error("Unable to parse file contents")] - ParseContent, + // #[error("Unable to parse file contents")] + // ParseContent, - #[error("Unable to decode from base64")] - DecodeFromBase64, + // #[error("Unable to decode from base64")] + // DecodeFromBase64, - #[error("Unable to decode from UTF-8")] - DecodeFromUtf8, + // #[error("Unable to decode from UTF-8")] + // DecodeFromUtf8, - #[error("Unknown file encoding: {}", 0)] - UnknownEncoding(String), + // #[error("Unknown file encoding: {}", 0)] + // UnknownEncoding(String), - #[error("Not a file: {}", 0)] - NotFile(String), + // #[error("Not a file: {}", 0)] + // NotFile(String), - #[error("Unknown error (status: {})", 0)] - Unknown(String), + // #[error("Unknown error (status: {})", 0)] + // Unknown(String), - #[error("commit log: {0}")] - CommitLog(#[from] crate::git::commit::log::Error), - - #[error("commit not found")] - CommitNotFound, + // #[error("commit log: {0}")] + // CommitLog(#[from] crate::git::commit::log::Error), + // #[error("commit not found")] + // CommitNotFound, #[error("no tree in commit")] NoTreeInCommit(String), diff --git a/crates/core/src/git/forge/commit.rs b/crates/cli/src/core/git/forge/commit.rs similarity index 100% rename from crates/core/src/git/forge/commit.rs rename to crates/cli/src/core/git/forge/commit.rs diff --git a/crates/core/src/git/forge/mod.rs b/crates/cli/src/core/git/forge/mod.rs similarity index 81% rename from crates/core/src/git/forge/mod.rs rename to crates/cli/src/core/git/forge/mod.rs index 034b89c..243085f 100644 --- a/crates/core/src/git/forge/mod.rs +++ b/crates/cli/src/core/git/forge/mod.rs @@ -1,7 +1,9 @@ pub mod commit; -pub(super) mod r#trait; +pub mod r#trait; pub mod webhook; #[allow(clippy::module_name_repetitions)] pub use r#trait::ForgeLike; + +#[cfg(test)] pub use r#trait::MockForgeLike; diff --git a/crates/core/src/git/forge/trait.rs b/crates/cli/src/core/git/forge/trait.rs similarity index 96% rename from crates/core/src/git/forge/trait.rs rename to crates/cli/src/core/git/forge/trait.rs index b61b36d..67ef81e 100644 --- a/crates/core/src/git/forge/trait.rs +++ b/crates/cli/src/core/git/forge/trait.rs @@ -1,5 +1,5 @@ // -use crate::{ +use crate::core::{ git, server::RepoListenUrl, webhook, ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId, }; @@ -8,6 +8,8 @@ use crate::{ #[async_trait::async_trait] pub trait ForgeLike: std::fmt::Debug + Send + Sync { fn duplicate(&self) -> Box; + + #[cfg(test)] fn name(&self) -> String; /// Checks that the message has a valid authorisation. @@ -38,6 +40,7 @@ pub trait ForgeLike: std::fmt::Debug + Send + Sync { ) -> git::forge::webhook::Result; // Lists all the webhooks + #[cfg(test)] async fn list_webhooks( &self, repo_listen_url: &RepoListenUrl, diff --git a/crates/core/src/git/forge/webhook.rs b/crates/cli/src/core/git/forge/webhook.rs similarity index 100% rename from crates/core/src/git/forge/webhook.rs rename to crates/cli/src/core/git/forge/webhook.rs diff --git a/crates/core/src/git/generation.rs b/crates/cli/src/core/git/generation.rs similarity index 100% rename from crates/core/src/git/generation.rs rename to crates/cli/src/core/git/generation.rs diff --git a/crates/core/src/git/git_ref.rs b/crates/cli/src/core/git/git_ref.rs similarity index 100% rename from crates/core/src/git/git_ref.rs rename to crates/cli/src/core/git/git_ref.rs diff --git a/crates/core/src/git/git_remote.rs b/crates/cli/src/core/git/git_remote.rs similarity index 91% rename from crates/core/src/git/git_remote.rs rename to crates/cli/src/core/git/git_remote.rs index d4a6a8d..7af2334 100644 --- a/crates/core/src/git/git_remote.rs +++ b/crates/cli/src/core/git/git_remote.rs @@ -1,7 +1,7 @@ // use derive_more::{Constructor, Display}; -use crate::{Hostname, RepoPath}; +use crate::core::{Hostname, RepoPath}; #[derive(Clone, Debug, PartialEq, Eq, Constructor, Display)] #[display("{}:{}", host, repo_path)] diff --git a/crates/core/src/git/graph.rs b/crates/cli/src/core/git/graph.rs similarity index 97% rename from crates/core/src/git/graph.rs rename to crates/cli/src/core/git/graph.rs index 5c6c5f7..861f574 100644 --- a/crates/core/src/git/graph.rs +++ b/crates/cli/src/core/git/graph.rs @@ -3,7 +3,8 @@ use std::borrow::ToOwned; use take_until::TakeUntilExt; -use crate::{newtype, GitDir, RepoBranches}; +use crate::core::{GitDir, RepoBranches}; +use crate::newtype; use super::RepoDetails; diff --git a/crates/core/src/git/mod.rs b/crates/cli/src/core/git/mod.rs similarity index 64% rename from crates/core/src/git/mod.rs rename to crates/cli/src/core/git/mod.rs index 2c29f03..6a89398 100644 --- a/crates/core/src/git/mod.rs +++ b/crates/cli/src/core/git/mod.rs @@ -1,6 +1,5 @@ // pub mod commit; -pub mod fetch; pub mod file; pub mod forge; mod generation; @@ -18,38 +17,30 @@ mod tests; pub use commit::Commit; pub use forge::ForgeLike; -pub use forge::MockForgeLike; pub use generation::Generation; #[allow(clippy::module_name_repetitions)] pub use git_ref::GitRef; #[allow(clippy::module_name_repetitions)] pub use git_remote::GitRemote; pub use repo_details::RepoDetails; -pub use repository::Repository; pub use repository::RepositoryFactory; pub use user_notification::UserNotification; -use crate::common::branch_name; -use crate::common::repo_alias; -use crate::common::repo_path; -use crate::ForgeDetails; -use crate::GitDir; -use crate::RepoConfig; - +#[cfg(test)] #[must_use] pub fn repo_details( n: u32, generation: Generation, - forge: ForgeDetails, - repo_config: Option, - gitdir: GitDir, + forge: super::ForgeDetails, + repo_config: Option, + gitdir: super::GitDir, ) -> RepoDetails { RepoDetails { generation, - repo_alias: repo_alias(n), - repo_path: repo_path(n), + repo_alias: super::common::repo_alias(n), + repo_path: super::common::repo_path(n), gitdir, - branch: branch_name(n), + branch: super::common::branch_name(n), forge, repo_config, } diff --git a/crates/core/src/git/push.rs b/crates/cli/src/core/git/push.rs similarity index 57% rename from crates/core/src/git/push.rs rename to crates/cli/src/core/git/push.rs index b5136bc..9c1c2cc 100644 --- a/crates/core/src/git/push.rs +++ b/crates/cli/src/core/git/push.rs @@ -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)] pub enum Force { @@ -15,36 +19,6 @@ impl std::fmt::Display for Force { } } -pub type Result = core::result::Result; - -#[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), - - #[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), -} - /// 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 diff --git a/crates/core/src/git/repo_details.rs b/crates/cli/src/core/git/repo_details.rs similarity index 95% rename from crates/core/src/git/repo_details.rs rename to crates/cli/src/core/git/repo_details.rs index f4d2200..8183904 100644 --- a/crates/core/src/git/repo_details.rs +++ b/crates/cli/src/core/git/repo_details.rs @@ -1,12 +1,16 @@ // +use crate::core::pike; +use crate::s; use crate::{ + core::{ + BranchName, ForgeAlias, ForgeConfig, ForgeDetails, GitDir, RemoteUrl, RepoAlias, + RepoConfig, RepoPath, ServerRepoConfig, StoragePathType, + }, git::{ self, repository::open::{oreal::RealOpenRepository, OpenRepositoryLike}, Generation, }, - pike, s, BranchName, ForgeAlias, ForgeConfig, ForgeDetails, GitDir, Hostname, RemoteUrl, - RepoAlias, RepoConfig, RepoPath, ServerRepoConfig, StoragePathType, }; use std::sync::{Arc, RwLock}; @@ -70,8 +74,9 @@ impl RepoDetails { &self.gitdir } + #[cfg(test)] #[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; self.forge = forge.with_hostname(hostname); self diff --git a/crates/core/src/git/repository/factory.rs b/crates/cli/src/core/git/repository/factory.rs similarity index 96% rename from crates/core/src/git/repository/factory.rs rename to crates/cli/src/core/git/repository/factory.rs index 357a03a..5548a72 100644 --- a/crates/core/src/git/repository/factory.rs +++ b/crates/cli/src/core/git/repository/factory.rs @@ -41,9 +41,10 @@ pub fn real() -> Box { Box::new(RealRepositoryFactory) } +#[cfg(test)] #[must_use] -pub fn mock() -> Box { - Box::new(MockRepositoryFactory::new()) +pub fn mock() -> MockRepositoryFactory { + MockRepositoryFactory::new() } #[derive(Debug, Clone)] diff --git a/crates/core/src/git/repository/mod.rs b/crates/cli/src/core/git/repository/mod.rs similarity index 68% rename from crates/core/src/git/repository/mod.rs rename to crates/cli/src/core/git/repository/mod.rs index 4276cfb..dd1bb6b 100644 --- a/crates/core/src/git/repository/mod.rs +++ b/crates/cli/src/core/git/repository/mod.rs @@ -1,21 +1,18 @@ // use crate::{ + core::RemoteUrl, git::{ - self, - repository::{ - open::{OpenRepository, OpenRepositoryLike}, - test::TestRepository, - }, - validation::remotes::validate_default_remotes, + repository::open::OpenRepositoryLike, validation::remotes::validate_default_remotes, RepoDetails, }, - GitDir, RemoteUrl, }; use tracing::info; pub mod factory; pub mod open; + +#[cfg(test)] mod test; #[allow(clippy::module_name_repetitions)] @@ -24,19 +21,20 @@ pub use factory::RepositoryFactory; #[cfg(test)] mod tests; -#[derive(Clone, Debug)] -#[allow(clippy::large_enum_variant)] -pub enum Repository { - Real, - Test(TestRepository), -} +// #[cfg(test)] +// #[derive(Clone, Debug)] +// #[allow(clippy::large_enum_variant)] +// pub enum Repository { +// Real, +// Test(test::TestRepository), +// } #[cfg(test)] -pub(crate) const fn test( +pub const fn test( fs: kxio::fs::FileSystem, - forge_details: crate::ForgeDetails, -) -> TestRepository { - TestRepository::new(fs, vec![], vec![], forge_details) + forge_details: crate::core::ForgeDetails, +) -> test::TestRepository { + test::TestRepository::new(fs, vec![], vec![], forge_details) } /// Opens a repository, cloning if necessary @@ -60,6 +58,7 @@ pub fn open( Ok(open_repository) } +#[cfg(test)] #[allow(clippy::module_name_repetitions)] pub trait RepositoryLike { /// Opens the repository. @@ -67,15 +66,16 @@ pub trait RepositoryLike { /// # Errors /// /// Will return an `Err` if the repository can't be opened. - fn open(&self, gitdir: &GitDir) -> Result; + fn open(&self, gitdir: &crate::core::GitDir) -> Result; - /// Clones the git repository from the remote server. - /// - /// # Errors - /// - /// Will return an `Err` if there are any network connectivity issues - /// connecting with the server. - fn git_clone(&self, repo_details: &RepoDetails) -> Result; + // /// Clones the git repository from the remote server. + // /// + // /// # Errors + // /// + // /// Will return an `Err` if there are any network connectivity issues + // /// connecting with the server. + // #[cfg(test)] + // fn git_clone(&self, repo_details: &RepoDetails) -> Result; } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -98,39 +98,35 @@ pub type Result = core::result::Result; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("invalid git dir: {0}")] - InvalidGitDir(GitDir), - + // #[error("invalid git dir: {0}")] + // InvalidGitDir(GitDir), #[error("kxiofs: {0}")] KxioFs(#[from] kxio::fs::Error), - #[error("io: {0}")] - Io(std::io::Error), + // #[error("io: {0}")] + // Io(std::io::Error), - #[error("git exec wait: {0}")] - Wait(std::io::Error), - - #[error("git exec spawn: {0}")] - Spawn(std::io::Error), + // #[error("git exec wait: {0}")] + // Wait(std::io::Error), + // #[error("git exec spawn: {0}")] + // Spawn(std::io::Error), #[error("validation: {0}")] Validation(String), #[error("git clone: {0}")] Clone(String), - #[error("git fetch: {0}")] - FetchError(#[from] git::fetch::Error), - + // #[error("git fetch: {0}")] + // FetchError(#[from] git::fetch::Error), #[error("open: {0}")] Open(String), #[error("git fetch: {0}")] Fetch(String), - #[error("fake repository lock")] - FakeLock, - + // #[error("fake repository lock")] + // FakeLock, #[error("MismatchDefaultFetchRemote(found: {found:?}, expected: {expected:?})")] MismatchDefaultFetchRemote { found: Box, diff --git a/crates/core/src/git/repository/open/mod.rs b/crates/cli/src/core/git/repository/open/mod.rs similarity index 68% rename from crates/core/src/git/repository/open/mod.rs rename to crates/cli/src/core/git/repository/open/mod.rs index edacb96..d2abbb3 100644 --- a/crates/core/src/git/repository/open/mod.rs +++ b/crates/cli/src/core/git/repository/open/mod.rs @@ -3,56 +3,55 @@ mod tests; pub mod oreal; + +#[cfg(test)] pub mod otest; use crate::{ - git, - git::repository::{ - open::{oreal::RealOpenRepository, otest::TestOpenRepository}, - Direction, - }, - BranchName, GitDir, RemoteUrl, + core::{BranchName, RemoteUrl}, + git::{self, repository::Direction}, + Result, }; -use std::{ - path::Path, - sync::{Arc, RwLock}, -}; +use std::path::Path; +#[cfg(test)] #[allow(clippy::module_name_repetitions)] #[derive(Clone, Debug)] pub enum OpenRepository { - /// A real git repository. - /// - /// This variant is the normal implementation for use in production code. - Real(RealOpenRepository), - + // /// A real git repository. + // /// + // /// This variant is the normal implementation for use in production code. + // #[cfg(test)] + // Real(oreal::RealOpenRepository), /// A real git repository, but with preprogrammed responses to network access. /// /// This variant is for use only in testing. Requests to methods /// that would require network access, such as to the git remote /// server will result in an error, unless a predefined change /// has been scheduled for that request. - Test(TestOpenRepository), + Test(otest::TestOpenRepository), } -#[cfg(not(tarpaulin_include))] -pub fn real(gix_repo: gix::Repository, forge_details: crate::ForgeDetails) -> OpenRepository { - OpenRepository::Real(oreal::RealOpenRepository::new( - Arc::new(RwLock::new(gix_repo.into())), - forge_details, - )) -} +// #[cfg(test)] +// #[cfg(not(tarpaulin_include))] +// pub fn real(gix_repo: gix::Repository, forge_details: crate::core::ForgeDetails) -> OpenRepository { +// OpenRepository::Real(oreal::RealOpenRepository::new( +// std::sync::Arc::new(std::sync::RwLock::new(gix_repo.into())), +// forge_details, +// )) +// } +#[cfg(test)] #[cfg(not(tarpaulin_include))] // don't test mocks -pub(crate) fn test( - gitdir: &GitDir, +pub fn test( + gitdir: &crate::core::GitDir, fs: &kxio::fs::FileSystem, on_fetch: Vec, on_push: Vec, - forge_details: crate::ForgeDetails, + forge_details: crate::core::ForgeDetails, ) -> OpenRepository { - OpenRepository::Test(TestOpenRepository::new( + OpenRepository::Test(otest::TestOpenRepository::new( gitdir, fs, on_fetch, @@ -64,8 +63,9 @@ pub(crate) fn test( #[allow(clippy::module_name_repetitions)] #[mockall::automock] pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send { - /// Creates a clone of the `OpenRepositoryLike`. - fn duplicate(&self) -> Box; + // /// Creates a clone of the `OpenRepositoryLike`. + // #[cfg(test)] + // fn duplicate(&self) -> Box; /// 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 /// the remote server. - fn remote_branches(&self) -> git::push::Result>; + fn remote_branches(&self) -> Result>; fn find_default_remote(&self, direction: Direction) -> Option; /// 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 /// 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` /// @@ -96,7 +96,7 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send { branch_name: &BranchName, to_commit: &git::GitRef, force: &git::push::Force, - ) -> git::push::Result<()>; + ) -> Result<()>; /// 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, branch_name: &BranchName, find_commits: &[git::Commit], - ) -> git::commit::log::Result>; + ) -> Result>; /// Read the contents of a file as a string. /// @@ -117,20 +117,21 @@ pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send { /// # Errors /// /// 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; + fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result; } #[cfg(test)] -pub(crate) fn mock() -> Box { +pub fn mock() -> Box { Box::new(MockOpenRepositoryLike::new()) } +#[cfg(test)] impl std::ops::Deref for OpenRepository { type Target = dyn OpenRepositoryLike; fn deref(&self) -> &Self::Target { match self { - Self::Real(real) => real, + // Self::Real(real) => real, Self::Test(test) => test, } } diff --git a/crates/core/src/git/repository/open/oreal.rs b/crates/cli/src/core/git/repository/open/oreal.rs similarity index 63% rename from crates/core/src/git/repository/open/oreal.rs rename to crates/cli/src/core/git/repository/open/oreal.rs index e975e2f..2071b33 100644 --- a/crates/core/src/git/repository/open/oreal.rs +++ b/crates/cli/src/core/git/repository/open/oreal.rs @@ -1,8 +1,9 @@ // use crate::{ - git::{self, repository::OpenRepositoryLike}, - s, BranchName, ForgeDetails, Hostname, RemoteUrl, RepoPath, + core::{BranchName, ForgeDetails, Hostname, RemoteUrl, RepoPath}, + err, git, }; +use crate::{s, Result}; use derive_more::Constructor; use gix::bstr::BStr; @@ -11,7 +12,6 @@ use tracing::{info, warn}; use std::{ borrow::ToOwned, path::Path, - result::Result, sync::{Arc, RwLock}, }; @@ -21,26 +21,29 @@ pub struct RealOpenRepository { forge_details: ForgeDetails, } impl super::OpenRepositoryLike for RealOpenRepository { - fn remote_branches(&self) -> git::push::Result> { + fn remote_branches(&self) -> Result> { let refs = self .inner .read() - .map_err(|_| git::push::Error::Lock) + .map_err(|_| err!("read")) .and_then(|repo| { - Ok(repo.to_thread_local().references()?).and_then(|refs| { - Ok(refs.remote_branches().map(|rb| { - rb.filter_map(Result::ok) - .map(|r| r.name().to_owned()) - .map(|n| s!(n)) - .filter_map(|p| { - p.strip_prefix("refs/remotes/origin/") - .map(ToOwned::to_owned) - }) - .filter(|b| b.as_str() != "HEAD") - .map(BranchName::new) - .collect::>() - })?) - }) + repo.to_thread_local() + .references() + .map_err(|_| err!("thread local references")) + .and_then(|refs| { + Ok(refs.remote_branches().map(|rb| { + rb.filter_map(Result::ok) + .map(|r| r.name().to_owned()) + .map(|n| s!(n)) + .filter_map(|p| { + p.strip_prefix("refs/remotes/origin/") + .map(ToOwned::to_owned) + }) + .filter(|b| b.as_str() != "HEAD") + .map(BranchName::new) + .collect::>() + })?) + }) })?; Ok(refs) } @@ -66,12 +69,12 @@ impl super::OpenRepositoryLike for RealOpenRepository { #[tracing::instrument(skip_all)] #[cfg(not(tarpaulin_include))] // would require writing to external service - fn fetch(&self) -> Result<(), git::fetch::Error> { + fn fetch(&self) -> Result<()> { if self .find_default_remote(git::repository::Direction::Fetch) .is_none() { - return Err(git::fetch::Error::NoFetchRemoteFound); + return Err(err!("No Fetch Remote Found")); } info!("Fetching"); gix::command::prepare("/usr/bin/git fetch --prune") @@ -79,7 +82,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { git_dir: Some( self.inner .read() - .map_err(|_| git::fetch::Error::Lock) + .map_err(|_| err!("Lock")) .map(|r| r.git_dir().to_path_buf())?, ), ..Default::default() @@ -101,7 +104,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { branch_name: &BranchName, to_commit: &git::GitRef, force: &git::push::Force, - ) -> Result<(), git::push::Error> { + ) -> Result<()> { use secrecy::ExposeSecret as _; let origin = repo_details.origin(); @@ -120,7 +123,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { let git_dir = self .inner .read() - .map_err(|_| git::push::Error::Lock) + .map_err(|_| err!("Lock")) .map(|r| r.git_dir().to_path_buf())?; let ctx = gix::diff::command::Context { git_dir: Some(git_dir), @@ -140,7 +143,7 @@ impl super::OpenRepositoryLike for RealOpenRepository { &self, branch_name: &BranchName, find_commits: &[git::Commit], - ) -> Result, git::commit::log::Error> { + ) -> Result> { let limit: usize = if find_commits.is_empty() { 1 } else { @@ -148,63 +151,60 @@ impl super::OpenRepositoryLike for RealOpenRepository { .max_dev_commits() .map_or(25, |commit_count| commit_count.clone().peel() as usize) }; - self.inner - .read() - .map_err(|_| git::commit::log::Error::Lock) - .map(|repo| { - let branch = format!("remotes/origin/{branch_name}"); - let branch = BStr::new(&branch); - let thread_local = repo.to_thread_local(); - let branch_head = thread_local - .rev_parse_single(branch) + self.inner.read().map_err(|_| err!("Lock")).map(|repo| { + let branch = format!("remotes/origin/{branch_name}"); + let branch = BStr::new(&branch); + let thread_local = repo.to_thread_local(); + let branch_head = thread_local + .rev_parse_single(branch) + .map_err(|e| s!(e)) + .map_err(as_gix_error(branch_name.clone()))?; + 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(as_gix_error(branch_name.clone()))?; - let object = branch_head + let commit = item .object() .map_err(|e| s!(e)) .map_err(as_gix_error(branch_name.clone()))?; - let commit = object - .try_into_commit() + let id = commit.id(); + let message = commit + .message_raw() .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(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; - } + 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; } - Ok(commits) - })? + commits.push(commit); + } + Ok(commits) + })? } #[tracing::instrument(skip_all, fields(%branch_name, ?file_name))] - fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result { + fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result { self.inner .read() - .map_err(|_| git::file::Error::Lock) + .map_err(|_| err!("Lock")) .and_then(|repo| { let thread_local = repo.to_thread_local(); 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 { - Box::new(self.clone()) - } + // #[cfg(test)] + // fn duplicate(&self) -> Box { + // Box::new(self.clone()) + // } } -fn as_gix_error(branch: BranchName) -> impl FnOnce(String) -> git::commit::log::Error { - |error| git::commit::log::Error::Gix { branch, error } +fn as_gix_error(branch: BranchName) -> impl FnOnce(String) -> color_eyre::eyre::Error { + move |error| err!("gix: branch: {branch}: {error}") } impl From<&RemoteUrl> for git::GitRemote { diff --git a/crates/core/src/git/repository/open/otest.rs b/crates/cli/src/core/git/repository/open/otest.rs similarity index 81% rename from crates/core/src/git/repository/open/otest.rs rename to crates/cli/src/core/git/repository/open/otest.rs index 556f044..9d2d715 100644 --- a/crates/core/src/git/repository/open/otest.rs +++ b/crates/cli/src/core/git/repository/open/otest.rs @@ -1,10 +1,11 @@ // +use crate::s; use crate::{ - git::{ - self, - repository::open::{OpenRepositoryLike, RealOpenRepository}, + core::{ + git::{self, repository::open::oreal::RealOpenRepository}, + BranchName, ForgeDetails, GitDir, RemoteUrl, RepoBranches, }, - s, BranchName, ForgeDetails, GitDir, RemoteUrl, RepoBranches, + err, Result, }; use derive_more::Constructor; @@ -14,7 +15,7 @@ use std::{ 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)] pub struct OnFetch { repo_branches: RepoBranches, @@ -29,7 +30,7 @@ impl OnFetch { /// /// 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. - pub fn invoke(&self) -> git::fetch::Result<()> { + pub fn invoke(&self) -> Result<()> { (self.action)(&self.repo_branches, &self.gitdir, &self.fs) } } @@ -42,7 +43,7 @@ pub type OnPushFn = fn( &RepoBranches, &GitDir, &kxio::fs::FileSystem, -) -> git::push::Result<()>; +) -> Result<()>; #[derive(Clone, Debug, Constructor)] pub struct OnPush { repo_branches: RepoBranches, @@ -63,7 +64,7 @@ impl OnPush { branch_name: &BranchName, to_commit: &git::GitRef, force: &git::push::Force, - ) -> git::push::Result<()> { + ) -> Result<()> { (self.action)( repo_details, branch_name, @@ -86,7 +87,7 @@ pub struct TestOpenRepository { } #[cfg(not(tarpaulin_include))] impl git::repository::OpenRepositoryLike for TestOpenRepository { - fn remote_branches(&self) -> git::push::Result> { + fn remote_branches(&self) -> Result> { self.real.remote_branches() } @@ -94,14 +95,11 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository { self.real.find_default_remote(direction) } - fn fetch(&self) -> Result<(), git::fetch::Error> { - let i: usize = *self - .fetch_counter - .read() - .map_err(|_| git::fetch::Error::Lock)?; + fn fetch(&self) -> Result<()> { + let i: usize = *self.fetch_counter.read().map_err(|_| err!("Lock"))?; self.fetch_counter .write() - .map_err(|_| git::fetch::Error::Lock) + .map_err(|_| err!("Lock")) .map(|mut c| *c += 1)?; #[allow(clippy::expect_used)] self.on_fetch @@ -116,15 +114,12 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository { branch_name: &BranchName, to_commit: &git::GitRef, force: &git::push::Force, - ) -> git::push::Result<()> { - let i: usize = *self - .push_counter - .read() - .map_err(|_| git::fetch::Error::Lock)?; + ) -> Result<()> { + let i: usize = *self.push_counter.read().map_err(|_| err!("Lock"))?; println!("Push: {i}"); self.push_counter .write() - .map_err(|_| git::fetch::Error::Lock) + .map_err(|_| err!("Lock")) .map(|mut c| *c += 1)?; #[allow(clippy::expect_used)] self.on_push @@ -137,17 +132,17 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository { &self, branch_name: &BranchName, find_commits: &[git::Commit], - ) -> git::commit::log::Result> { + ) -> Result> { self.real.commit_log(branch_name, find_commits) } - fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result { + fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result { self.real.read_file(branch_name, file_name) } - fn duplicate(&self) -> Box { - Box::new(self.clone()) - } + // fn duplicate(&self) -> Box { + // Box::new(self.clone()) + // } } impl TestOpenRepository { pub(crate) fn new( diff --git a/crates/core/src/git/repository/open/tests/commit_log.rs b/crates/cli/src/core/git/repository/open/tests/commit_log.rs similarity index 99% rename from crates/core/src/git/repository/open/tests/commit_log.rs rename to crates/cli/src/core/git/repository/open/tests/commit_log.rs index 322c5d6..576aace 100644 --- a/crates/core/src/git/repository/open/tests/commit_log.rs +++ b/crates/cli/src/core/git/repository/open/tests/commit_log.rs @@ -1,6 +1,6 @@ use std::ops::Deref as _; -use crate::CommitCount; +use crate::core::CommitCount; // use super::*; diff --git a/crates/core/src/git/repository/open/tests/fetch.rs b/crates/cli/src/core/git/repository/open/tests/fetch.rs similarity index 100% rename from crates/core/src/git/repository/open/tests/fetch.rs rename to crates/cli/src/core/git/repository/open/tests/fetch.rs diff --git a/crates/core/src/git/repository/open/tests/find_default_remote.rs b/crates/cli/src/core/git/repository/open/tests/find_default_remote.rs similarity index 100% rename from crates/core/src/git/repository/open/tests/find_default_remote.rs rename to crates/cli/src/core/git/repository/open/tests/find_default_remote.rs diff --git a/crates/core/src/git/repository/open/tests/forge_config.rs b/crates/cli/src/core/git/repository/open/tests/forge_config.rs similarity index 100% rename from crates/core/src/git/repository/open/tests/forge_config.rs rename to crates/cli/src/core/git/repository/open/tests/forge_config.rs diff --git a/crates/core/src/git/repository/open/tests/mod.rs b/crates/cli/src/core/git/repository/open/tests/mod.rs similarity index 54% rename from crates/core/src/git/repository/open/tests/mod.rs rename to crates/cli/src/core/git/repository/open/tests/mod.rs index 39fc23a..e6a7955 100644 --- a/crates/core/src/git/repository/open/tests/mod.rs +++ b/crates/cli/src/core/git/repository/open/tests/mod.rs @@ -1,12 +1,14 @@ // use crate::{ + core::{ + BranchName, ForgeConfig, ForgeType, GitDir, Hostname, RepoAlias, RepoBranches, RepoConfig, + RepoConfigSource, RepoPath, ServerRepoConfig, StoragePathType, User, + }, git::{ self, repository::RepositoryLike as _, tests::{given, then}, }, - BranchName, ForgeConfig, ForgeType, GitDir, Hostname, RepoAlias, RepoBranches, RepoConfig, - RepoConfigSource, RepoPath, ServerRepoConfig, StoragePathType, User, }; use assert2::let_assert; @@ -14,7 +16,8 @@ use secrecy::ExposeSecret; use std::{collections::BTreeMap, path::PathBuf}; -type TestResult = Result<(), Box>; +// type TestResult = Result<(), Box>; +type TestResult = color_eyre::Result<()>; mod commit_log; mod fetch; diff --git a/crates/cli/src/core/git/repository/open/tests/read_file.rs b/crates/cli/src/core/git/repository/open/tests/read_file.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/cli/src/core/git/repository/open/tests/read_file.rs @@ -0,0 +1 @@ + diff --git a/crates/core/src/git/repository/open/tests/repo_config.rs b/crates/cli/src/core/git/repository/open/tests/repo_config.rs similarity index 100% rename from crates/core/src/git/repository/open/tests/repo_config.rs rename to crates/cli/src/core/git/repository/open/tests/repo_config.rs diff --git a/crates/core/src/git/repository/open/tests/server_repo_config.rs b/crates/cli/src/core/git/repository/open/tests/server_repo_config.rs similarity index 100% rename from crates/core/src/git/repository/open/tests/server_repo_config.rs rename to crates/cli/src/core/git/repository/open/tests/server_repo_config.rs diff --git a/crates/core/src/git/repository/test.rs b/crates/cli/src/core/git/repository/test.rs similarity index 87% rename from crates/core/src/git/repository/test.rs rename to crates/cli/src/core/git/repository/test.rs index 44af530..537a461 100644 --- a/crates/core/src/git/repository/test.rs +++ b/crates/cli/src/core/git/repository/test.rs @@ -2,6 +2,7 @@ use derive_more::Constructor; use crate::{ + core::{ForgeDetails, GitDir}, git::{ self, repository::{ @@ -11,9 +12,7 @@ use crate::{ }, RepositoryLike, Result, }, - RepoDetails, }, - ForgeDetails, GitDir, }; #[allow(clippy::module_name_repetitions)] @@ -43,8 +42,4 @@ impl RepositoryLike for TestRepository { self.forge_details.clone(), )) } - - fn git_clone(&self, _repo_details: &RepoDetails) -> Result { - todo!() - } } diff --git a/crates/core/src/git/repository/tests/factory.rs b/crates/cli/src/core/git/repository/tests/factory.rs similarity index 100% rename from crates/core/src/git/repository/tests/factory.rs rename to crates/cli/src/core/git/repository/tests/factory.rs diff --git a/crates/core/src/git/repository/tests/mod.rs b/crates/cli/src/core/git/repository/tests/mod.rs similarity index 80% rename from crates/core/src/git/repository/tests/mod.rs rename to crates/cli/src/core/git/repository/tests/mod.rs index a9204f9..7b842a1 100644 --- a/crates/core/src/git/repository/tests/mod.rs +++ b/crates/cli/src/core/git/repository/tests/mod.rs @@ -1,7 +1,7 @@ // use crate::{ + core::{ApiToken, GitDir, StoragePathType}, git::{self, tests::given}, - ApiToken, GitDir, StoragePathType, }; use assert2::let_assert; diff --git a/crates/core/src/git/repository/tests/validate.rs b/crates/cli/src/core/git/repository/tests/validate.rs similarity index 100% rename from crates/core/src/git/repository/tests/validate.rs rename to crates/cli/src/core/git/repository/tests/validate.rs diff --git a/crates/core/src/git/tests.rs b/crates/cli/src/core/git/tests.rs similarity index 88% rename from crates/core/src/git/tests.rs rename to crates/cli/src/core/git/tests.rs index 2955eb8..530258b 100644 --- a/crates/core/src/git/tests.rs +++ b/crates/cli/src/core/git/tests.rs @@ -1,9 +1,12 @@ // 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_dir::StoragePathType, - s, webhook, BranchName, ForgeAlias, ForgeConfig, ForgeType, GitDir, Hostname, RemoteUrl, - RepoAlias, RepoBranches, RepoConfig, RepoConfigSource, RepoPath, ServerRepoConfig, + s, Result, }; use assert2::let_assert; @@ -14,8 +17,6 @@ use std::{ path::{Path, PathBuf}, }; -type TestResult = Result<(), Box>; - mod commit { use super::*; @@ -180,7 +181,7 @@ mod repo_details { } } pub mod given { - use crate::ForgeDetails; + use crate::core::ForgeDetails; use super::*; @@ -200,9 +201,9 @@ pub mod given { RepoAlias::new(a_name()) } - pub fn a_pathbuf() -> PathBuf { - PathBuf::from(given::a_name()) - } + // pub fn a_pathbuf() -> PathBuf { + // PathBuf::from(given::a_name()) + // } pub fn a_name() -> String { use rand::Rng; @@ -296,9 +297,12 @@ pub mod given { 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(); - 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 { @@ -354,37 +358,39 @@ pub mod given { } pub mod then { + use crate::err; + use super::*; - pub fn commit_named_file_to_branch( - file_name: &Path, - contents: &str, - fs: &kxio::fs::FileSystem, - gitdir: &GitDir, - branch_name: &BranchName, - ) -> TestResult { - // git checkout ${branch_name} - git_checkout_new_branch(branch_name, gitdir)?; - // echo ${word} > file-${word} - let pathbuf = PathBuf::from(gitdir); - let file = fs.base().join(pathbuf).join(file_name); - #[allow(clippy::expect_used)] - fs.file(&file).write(contents)?; - // git add ${file} - git_add_file(gitdir, &file)?; - // git commit -m"Added ${file}" - git_commit(gitdir, &file)?; - - then::push_branch(fs, gitdir, branch_name)?; - - Ok(()) - } + // pub fn commit_named_file_to_branch( + // file_name: &Path, + // contents: &str, + // fs: &kxio::fs::FileSystem, + // gitdir: &GitDir, + // branch_name: &BranchName, + // ) -> Result<()> { + // // git checkout ${branch_name} + // git_checkout_new_branch(branch_name, gitdir)?; + // // echo ${word} > file-${word} + // let pathbuf = PathBuf::from(gitdir); + // let file = fs.base().join(pathbuf).join(file_name); + // #[allow(clippy::expect_used)] + // fs.file(&file).write(contents)?; + // // git add ${file} + // git_add_file(gitdir, &file)?; + // // git commit -m"Added ${file}" + // git_commit(gitdir, &file)?; + // + // then::push_branch(fs, gitdir, branch_name)?; + // + // Ok(()) + // } pub fn create_a_commit_on_branch( fs: &kxio::fs::FileSystem, gitdir: &GitDir, branch_name: &BranchName, - ) -> TestResult { + ) -> Result<()> { // git checkout ${branch_name} git_checkout_new_branch(branch_name, gitdir)?; // echo ${word} > file-${word} @@ -406,7 +412,7 @@ pub mod then { fs: &kxio::fs::FileSystem, gitdir: &GitDir, branch_name: &BranchName, - ) -> TestResult { + ) -> Result<()> { let gitrefs = fs .base() .join(gitdir.to_path_buf()) @@ -421,7 +427,7 @@ pub mod then { 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( &format!("git checkout -b {branch_name}"), std::process::Command::new("/usr/bin/git") @@ -432,7 +438,7 @@ pub mod then { Ok(()) } - pub fn git_switch(branch_name: &BranchName, gitdir: &GitDir) -> TestResult { + pub fn git_switch(branch_name: &BranchName, gitdir: &GitDir) -> Result<()> { exec( &format!("git switch {branch_name}"), std::process::Command::new("/usr/bin/git") @@ -442,7 +448,7 @@ pub mod then { ) } - fn exec(label: &str, output: Result) -> TestResult { + fn exec(label: &str, output: Result) -> Result<()> { println!("== {label}"); match output { Ok(output) => { @@ -459,12 +465,12 @@ pub mod then { } Err(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( &format!("git add {file:?}"), 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( &format!(r#"git commit -m"Added {file:?}""#), 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( "git log --all --oneline --decorate --graph", std::process::Command::new("/usr/bin/git") @@ -498,7 +504,7 @@ pub mod then { fs: &kxio::fs::FileSystem, gitdir: &GitDir, branch_name: &BranchName, - ) -> Result> { + ) -> color_eyre::Result { let main_ref = fs .base() .join(gitdir.to_path_buf()) diff --git a/crates/core/src/git/user_notification.rs b/crates/cli/src/core/git/user_notification.rs similarity index 98% rename from crates/core/src/git/user_notification.rs rename to crates/cli/src/core/git/user_notification.rs index 6095009..349a24f 100644 --- a/crates/core/src/git/user_notification.rs +++ b/crates/cli/src/core/git/user_notification.rs @@ -1,7 +1,8 @@ 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 super::graph::Log; diff --git a/crates/core/src/git/validation/mod.rs b/crates/cli/src/core/git/validation/mod.rs similarity index 100% rename from crates/core/src/git/validation/mod.rs rename to crates/cli/src/core/git/validation/mod.rs diff --git a/crates/core/src/git/validation/positions.rs b/crates/cli/src/core/git/validation/positions.rs similarity index 78% rename from crates/core/src/git/validation/positions.rs rename to crates/cli/src/core/git/validation/positions.rs index 85c2ef9..bc67585 100644 --- a/crates/core/src/git/validation/positions.rs +++ b/crates/cli/src/core/git/validation/positions.rs @@ -1,12 +1,11 @@ // use crate::{ - git::{self, repository::open::OpenRepositoryLike, RepoDetails, UserNotification}, - s, BranchName, RepoConfig, + core::{git::RepoDetails, BranchName, RepoConfig}, + git::{self, repository::open::OpenRepositoryLike, UserNotification}, + Result, }; use tracing::{debug, instrument}; -pub type Result = core::result::Result; - #[derive(Debug)] pub struct Positions { pub main: git::Commit, @@ -28,35 +27,32 @@ pub fn validate( open_repository: &dyn OpenRepositoryLike, repo_details: &git::RepoDetails, repo_config: &RepoConfig, -) -> Result<(Positions, git::graph::Log)> { +) -> PositionsResult<(Positions, git::graph::Log)> { let main_branch = repo_config.branches().main(); let next_branch = repo_config.branches().next(); let dev_branch = repo_config.branches().dev(); // 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 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 - let main = commit_histories - .main - .first() - .cloned() - .ok_or_else(|| Error::NonRetryable(format!("Branch has no commits: {main_branch}")))?; - let next = commit_histories - .next - .first() - .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}")))?; + let main = commit_histories.main.first().cloned().ok_or_else(|| { + PositionsError::NonRetryable(format!("Branch has no commits: {main_branch}")) + })?; + let next = commit_histories.next.first().cloned().ok_or_else(|| { + PositionsError::NonRetryable(format!("Branch has no commits: {next_branch}")) + })?; + let dev = commit_histories.dev.first().cloned().ok_or_else(|| { + PositionsError::NonRetryable(format!("Branch has no commits: {dev_branch}")) + })?; // Validations: // Dev must be on main branch, else the USER must rebase it if is_not_based_on(&commit_histories.dev, &main) { - return Err(Error::UserIntervention( + return Err(PositionsError::UserIntervention( UserNotification::DevNotBasedOnMain { forge_alias: repo_details.forge.forge_alias().clone(), repo_alias: repo_details.repo_alias.clone(), @@ -121,7 +117,7 @@ fn reset_next_to_main( main: &git::Commit, next: &git::Commit, next_branch: &BranchName, -) -> Error { +) -> PositionsError { match git::push::reset( open_repository, repo_details, @@ -129,8 +125,8 @@ fn reset_next_to_main( &main.clone().into(), &git::push::Force::From(next.clone().into()), ) { - Ok(()) => Error::Retryable(format!("Branch {next_branch} has been reset")), - Err(err) => Error::NonRetryable(format!( + Ok(()) => PositionsError::Retryable(format!("Branch {next_branch} has been reset")), + Err(err) => PositionsError::NonRetryable(format!( "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( open_repository: &dyn OpenRepositoryLike, repo_config: &RepoConfig, -) -> git::commit::log::Result { +) -> Result { debug!("main..."); let main = (open_repository.commit_log(&repo_config.branches().main(), &[]))?; let main_head = [main[0].clone()]; @@ -166,8 +162,9 @@ pub fn get_commit_histories( Ok(histories) } +pub type PositionsResult = std::result::Result; #[derive(Debug, thiserror::Error)] -pub enum Error { +pub enum PositionsError { #[error("{0} - will retry")] Retryable(String), @@ -177,13 +174,3 @@ pub enum Error { #[error("user intervention required")] UserIntervention(UserNotification), } -impl From for Error { - fn from(value: git::fetch::Error) -> Self { - Self::Retryable(s!(value)) - } -} -impl From for Error { - fn from(value: git::commit::log::Error) -> Self { - Self::Retryable(s!(value)) - } -} diff --git a/crates/core/src/git/validation/remotes.rs b/crates/cli/src/core/git/validation/remotes.rs similarity index 90% rename from crates/core/src/git/validation/remotes.rs rename to crates/cli/src/core/git/validation/remotes.rs index 8ab9a18..d9fd8b1 100644 --- a/crates/core/src/git/validation/remotes.rs +++ b/crates/cli/src/core/git/validation/remotes.rs @@ -1,7 +1,8 @@ // use crate::{ + core::RemoteUrl, git::{self, repository::open::OpenRepositoryLike}, - s, RemoteUrl, + s, }; #[tracing::instrument(skip_all)] @@ -44,12 +45,11 @@ pub enum Error { #[error("no default fetch remote")] NoDefaultFetchRemote, - #[error("no url for default push remote")] - NoUrlForDefaultPushRemote, - - #[error("no hostname for default push remote")] - NoHostnameForDefaultPushRemote, + // #[error("no url for default push remote")] + // NoUrlForDefaultPushRemote, + // #[error("no hostname for default push remote")] + // NoHostnameForDefaultPushRemote, #[error("unable to open repo: {0}")] UnableToOpenRepo(String), diff --git a/crates/core/src/git/validation/tests.rs b/crates/cli/src/core/git/validation/tests.rs similarity index 91% rename from crates/core/src/git/validation/tests.rs rename to crates/cli/src/core/git/validation/tests.rs index 05a8ea8..52d4352 100644 --- a/crates/core/src/git/validation/tests.rs +++ b/crates/cli/src/core/git/validation/tests.rs @@ -1,5 +1,6 @@ // use crate::{ + core::{GitDir, StoragePathType}, git::{ self, repository::{ @@ -10,7 +11,6 @@ use crate::{ tests::{given, then}, validation::positions::validate, }, - s, GitDir, StoragePathType, }; use assert2::let_assert; @@ -56,6 +56,10 @@ mod positions { mod validate { + use git::validation::positions::PositionsError; + + use crate::err; + use super::*; #[test] @@ -66,7 +70,7 @@ mod positions { let mut mock_open_repository = git::repository::open::mock(); mock_open_repository .expect_fetch() - .return_once(|| Err(git::fetch::Error::TestFailureExpected)); + .return_once(|| Err(err!("expected failure"))); let mut repository_factory = git::repository::factory::mock(); repository_factory .expect_open() @@ -81,10 +85,7 @@ mod positions { println!("{result:?}"); let_assert!(Err(err) = result, "validate"); - assert!(matches!( - err, - git::validation::positions::Error::Retryable(_) - )); + assert!(matches!(err, PositionsError::Retryable(_))); } #[test] @@ -100,10 +101,7 @@ mod positions { .expect_commit_log() .returning(move |branch_name, _| { if branch_name == &main_branch { - Err(git::commit::log::Error::Gix { - branch: branch_name.clone(), - error: s!("foo"), - }) + Err(err!("{branch_name}: foo")) } else { Ok(vec![]) } @@ -120,10 +118,7 @@ mod positions { let result = validate(&*open_repository, &repo_details, &repo_config); println!("{result:?}"); - assert!(matches!( - result, - Err(git::validation::positions::Error::Retryable(_)) - )); + assert!(matches!(result, Err(PositionsError::Retryable(_)))); } #[test] @@ -139,10 +134,7 @@ mod positions { .expect_commit_log() .returning(move |branch_name, _| { if branch_name == &next_branch { - Err(git::commit::log::Error::Gix { - branch: branch_name.clone(), - error: s!("foo"), - }) + Err(err!("{branch_name} foo")) } else { Ok(vec![given::a_commit()]) } @@ -159,10 +151,7 @@ mod positions { let result = validate(&*open_repository, &repo_details, &repo_config); println!("{result:?}"); - assert!(matches!( - result, - Err(git::validation::positions::Error::Retryable(_)) - )); + assert!(matches!(result, Err(PositionsError::Retryable(_)))); } #[test] @@ -178,10 +167,7 @@ mod positions { .expect_commit_log() .returning(move |branch_name, _| { if branch_name == &dev_branch { - Err(git::commit::log::Error::Gix { - branch: branch_name.clone(), - error: s!("foo"), - }) + Err(err!("{branch_name} foo")) } else { Ok(vec![given::a_commit()]) } @@ -198,10 +184,7 @@ mod positions { let result = validate(&*open_repository, &repo_details, &repo_config); println!("{result:?}"); - assert!(matches!( - result, - Err(git::validation::positions::Error::Retryable(_)) - )); + assert!(matches!(result, Err(PositionsError::Retryable(_)))); } #[test] @@ -232,7 +215,7 @@ mod positions { // add a commit to next 1 -> 4 then::create_a_commit_on_branch(fs, gitdir, &branches.next())?; then::git_log_all(gitdir)?; - git::fetch::Result::Ok(()) + Ok(()) }, )); let_assert!( @@ -250,7 +233,7 @@ mod positions { //then assert!(matches!( 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::git_log_all(gitdir)?; - git::fetch::Result::Ok(()) + Ok(()) }, )); // second fetch as prep to push @@ -293,7 +276,7 @@ mod positions { fs.deref().clone(), |_branches, _gitdir, _fs| { // don't change anything - git::fetch::Result::Ok(()) + Ok(()) }, )); test_repository.on_push(OnPush::new( @@ -318,7 +301,7 @@ mod positions { &git::push::Force::From(sha_next.into()), "should force push only if next is on expected sha" ); - git::push::Result::Ok(()) + Ok(()) }, )); let_assert!( @@ -336,10 +319,7 @@ mod positions { //then println!("Got: {err:?}"); // NOTE: assertions for correct push are in on_push above - assert!(matches!( - err, - git::validation::positions::Error::Retryable(_) - )); + assert!(matches!(err, PositionsError::Retryable(_))); } #[test] @@ -370,7 +350,7 @@ mod positions { then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?; then::git_log_all(gitdir)?; - git::fetch::Result::Ok(()) + Ok(()) }, )); // second fetch as prep to push @@ -380,7 +360,7 @@ mod positions { fs.deref().clone(), |_branches, _gitdir, _fs| { // don't change anything - git::fetch::Result::Ok(()) + Ok(()) }, )); test_repository.on_push(OnPush::new( @@ -388,7 +368,7 @@ mod positions { gitdir.clone(), fs.deref().clone(), |_repo_details, _branch_name, _gitref, _force, _repo_branches, _gitdir, _fs| { - git::push::Result::Err(git::push::Error::Lock) + Err(err!("Lock")) }, )); let_assert!( @@ -409,10 +389,7 @@ mod positions { Ok(_) = then::get_sha_for_branch(&fs, &gitdir, &repo_config.branches().next()), "load next branch sha" ); - assert!(matches!( - err, - git::validation::positions::Error::NonRetryable(_) - )); + assert!(matches!(err, PositionsError::NonRetryable(_))); } #[test] #[allow(clippy::expect_used)] @@ -441,7 +418,7 @@ mod positions { then::create_a_commit_on_branch(fs, gitdir, &branches.next())?; then::git_log_all(gitdir)?; - git::fetch::Result::Ok(()) + Ok(()) }, )); // second fetch as prep to push @@ -451,7 +428,7 @@ mod positions { fs.deref().clone(), |_branches, _gitdir, _fs| { // don't change anything - git::fetch::Result::Ok(()) + Ok(()) }, )); test_repository.on_push(OnPush::new( @@ -476,7 +453,7 @@ mod positions { &git::push::Force::From(sha_next.into()), "should force push only if next is on expected sha" ); - git::push::Result::Ok(()) + Ok(()) }, )); let_assert!( @@ -494,10 +471,7 @@ mod positions { //then println!("Got: {err:?}"); // NOTE: assertions for correct push are in on_push above - assert!(matches!( - err, - git::validation::positions::Error::Retryable(_) - )); + assert!(matches!(err, PositionsError::Retryable(_))); } #[test] @@ -528,7 +502,7 @@ mod positions { then::create_a_commit_on_branch(fs, gitdir, &branches.next())?; then::git_log_all(gitdir)?; - git::fetch::Result::Ok(()) + Ok(()) }, )); // second fetch as prep to push @@ -538,7 +512,7 @@ mod positions { fs.deref().clone(), |_branches, _gitdir, _fs| { // don't change anything - git::fetch::Result::Ok(()) + Ok(()) }, )); test_repository.on_push(OnPush::new( @@ -563,7 +537,7 @@ mod positions { &git::push::Force::From(sha_next.into()), "should force push only if next is on expected sha" ); - git::push::Result::Ok(()) + Ok(()) }, )); let_assert!( @@ -624,7 +598,7 @@ mod positions { then::create_a_commit_on_branch(fs, gitdir, &branches.dev())?; then::git_log_all(gitdir)?; - git::fetch::Result::Ok(()) + Ok(()) }, )); let_assert!( diff --git a/crates/core/src/macros/message.rs b/crates/cli/src/core/macros/message.rs similarity index 57% rename from crates/core/src/macros/message.rs rename to crates/cli/src/core/macros/message.rs index ab17a03..5a0fdc2 100644 --- a/crates/core/src/macros/message.rs +++ b/crates/cli/src/core/macros/message.rs @@ -1,15 +1,15 @@ #[macro_export] macro_rules! message { ($name:ident, $value:ty, $docs:literal) => { - git_next_core::newtype!($name, $value, $docs); + $crate::newtype!($name, $value, $docs); }; ($name:ident, $docs:literal) => { - git_next_core::newtype!($name, $docs); + $crate::newtype!($name, $docs); }; ($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) => { - git_next_core::newtype!($name, $docs); + $crate::newtype!($name, $docs); }; } diff --git a/crates/core/src/macros/mod.rs b/crates/cli/src/core/macros/mod.rs similarity index 100% rename from crates/core/src/macros/mod.rs rename to crates/cli/src/core/macros/mod.rs diff --git a/crates/core/src/macros/newtype.rs b/crates/cli/src/core/macros/newtype.rs similarity index 97% rename from crates/core/src/macros/newtype.rs rename to crates/cli/src/core/macros/newtype.rs index ccf8dfd..b20a21c 100644 --- a/crates/core/src/macros/newtype.rs +++ b/crates/cli/src/core/macros/newtype.rs @@ -34,6 +34,7 @@ macro_rules! newtype { )] pub struct $name($type); impl $name { + #[allow(dead_code)] pub fn new(value: impl Into<$type>) -> Self { Self(value.into()) } diff --git a/crates/core/src/macros/owned_string.rs b/crates/cli/src/core/macros/owned_string.rs similarity index 100% rename from crates/core/src/macros/owned_string.rs rename to crates/cli/src/core/macros/owned_string.rs diff --git a/crates/core/src/lib.rs b/crates/cli/src/core/mod.rs similarity index 100% rename from crates/core/src/lib.rs rename to crates/cli/src/core/mod.rs diff --git a/crates/cli/src/file_watcher.rs b/crates/cli/src/file_watcher.rs index e541422..88df7dc 100644 --- a/crates/cli/src/file_watcher.rs +++ b/crates/cli/src/file_watcher.rs @@ -6,7 +6,7 @@ use kameo::{mailbox::unbounded::UnboundedMailbox, message::Message, Actor}; use notify::{event::ModifyKind, RecommendedWatcher, Watcher}; use tracing::{error, info}; -use git_next_core::message; +use crate::message; use crate::{ default_on_actor_link_died, default_on_actor_panic, default_on_actor_stop, on_actor_start, diff --git a/crates/cli/src/forge/mod.rs b/crates/cli/src/forge/mod.rs index 3977354..ae84f5e 100644 --- a/crates/cli/src/forge/mod.rs +++ b/crates/cli/src/forge/mod.rs @@ -1,5 +1,5 @@ // -use git_next_core::git::{ForgeLike, RepoDetails}; +use crate::core::git::{ForgeLike, RepoDetails}; #[cfg(feature = "forgejo")] use crate::forges::forgejo::ForgeJo; @@ -16,9 +16,9 @@ impl Forge { pub fn create(repo_details: RepoDetails, net: Net) -> Box { match repo_details.forge.forge_type() { #[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")] - 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(net); diff --git a/crates/cli/src/forge/tests.rs b/crates/cli/src/forge/tests.rs index 78b12b8..c5ea080 100644 --- a/crates/cli/src/forge/tests.rs +++ b/crates/cli/src/forge/tests.rs @@ -2,7 +2,7 @@ #[cfg(any(feature = "forgejo", feature = "github"))] use super::*; -use git_next_core::{ +use crate::core::{ self as core, git::{self, RepoDetails}, GitDir, RepoConfigSource, StoragePathType, @@ -12,7 +12,7 @@ use git_next_core::{ #[test] fn test_forgejo_name() { 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()); assert_eq!(forge.name(), "forgejo"); mock_net.assert_no_unused_plans(); @@ -22,14 +22,14 @@ fn test_forgejo_name() { #[test] fn test_github_name() { 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()); assert_eq!(forge.name(), "github"); mock_net.assert_no_unused_plans(); } #[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| { println!("{e}"); panic!("fs") diff --git a/crates/cli/src/forges/forgejo/mod.rs b/crates/cli/src/forges/forgejo/mod.rs index abfc1f4..41f9210 100644 --- a/crates/cli/src/forges/forgejo/mod.rs +++ b/crates/cli/src/forges/forgejo/mod.rs @@ -6,7 +6,7 @@ mod webhook; use std::borrow::ToOwned; -use git_next_core::{ +use crate::core::{ self as core, git::{self, forge::commit::Status}, server::RepoListenUrl, @@ -31,6 +31,8 @@ impl git::ForgeLike for ForgeJo { fn duplicate(&self) -> Box { Box::new(self.clone()) } + + #[cfg(test)] fn name(&self) -> String { "forgejo".to_string() } @@ -74,6 +76,7 @@ impl git::ForgeLike for ForgeJo { Ok(status) } + #[cfg(test)] async fn list_webhooks( &self, repo_listen_url: &RepoListenUrl, diff --git a/crates/cli/src/forges/forgejo/tests.rs b/crates/cli/src/forges/forgejo/tests.rs index b6120da..a415ada 100644 --- a/crates/cli/src/forges/forgejo/tests.rs +++ b/crates/cli/src/forges/forgejo/tests.rs @@ -3,7 +3,7 @@ use crate::forges::forgejo::ForgeJo; -use git_next_core::{ +use crate::core::{ git::{self, forge::commit::Status, ForgeLike as _}, server::{ListenUrl, RepoListenUrl}, BranchName, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias, @@ -99,7 +99,7 @@ mod forgejo { let next = repo_branches.next(); let sha = 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}}) .to_string(), ); @@ -108,7 +108,7 @@ mod forgejo { assert_eq!(push.message(), message); assert_eq!( 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(); } @@ -118,7 +118,7 @@ mod forgejo { let fs = given::a_filesystem(); let mock_net = given::a_network(); 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(), ); let_assert!(Err(_) = forge.parse_webhook_body(&body)); @@ -651,8 +651,8 @@ mod forgejo { } mod given { + use crate::core::server::RepoListenUrl; use git::RepoDetails; - use git_next_core::server::RepoListenUrl; use kxio::net::{MockNet, StatusCode}; use super::*; @@ -739,8 +739,8 @@ mod forgejo { WebhookAuth::generate() } - pub fn a_webhook_message_body() -> git_next_core::webhook::forge_notification::Body { - git_next_core::webhook::forge_notification::Body::new(a_name()) + pub fn a_webhook_message_body() -> crate::core::webhook::forge_notification::Body { + crate::core::webhook::forge_notification::Body::new(a_name()) } pub fn repo_branches() -> RepoBranches { diff --git a/crates/cli/src/forges/forgejo/webhook/list.rs b/crates/cli/src/forges/forgejo/webhook/list.rs index 206718d..123e7d1 100644 --- a/crates/cli/src/forges/forgejo/webhook/list.rs +++ b/crates/cli/src/forges/forgejo/webhook/list.rs @@ -1,5 +1,5 @@ // -use git_next_core::{git, server::RepoListenUrl, WebhookId}; +use crate::core::{git, server::RepoListenUrl, WebhookId}; use kxio::net::Net; use crate::forges::forgejo::webhook::Hook; diff --git a/crates/cli/src/forges/forgejo/webhook/mod.rs b/crates/cli/src/forges/forgejo/webhook/mod.rs index e004e2f..5788f2c 100644 --- a/crates/cli/src/forges/forgejo/webhook/mod.rs +++ b/crates/cli/src/forges/forgejo/webhook/mod.rs @@ -1,5 +1,5 @@ // -use git_next_core::{git, webhook, BranchName, WebhookId}; +use crate::core::{git, webhook, BranchName, WebhookId}; use std::collections::HashMap; diff --git a/crates/cli/src/forges/forgejo/webhook/parser.rs b/crates/cli/src/forges/forgejo/webhook/parser.rs index a934aa5..69c97d3 100644 --- a/crates/cli/src/forges/forgejo/webhook/parser.rs +++ b/crates/cli/src/forges/forgejo/webhook/parser.rs @@ -1,7 +1,7 @@ // use crate::forges::forgejo; -use git_next_core::{git, webhook}; +use crate::core::{git, webhook}; pub fn parse_body( body: &webhook::forge_notification::Body, diff --git a/crates/cli/src/forges/forgejo/webhook/register.rs b/crates/cli/src/forges/forgejo/webhook/register.rs index f735073..b2e8353 100644 --- a/crates/cli/src/forges/forgejo/webhook/register.rs +++ b/crates/cli/src/forges/forgejo/webhook/register.rs @@ -1,5 +1,5 @@ // -use git_next_core::{ +use crate::core::{ git::{self, forge::webhook::Error}, server::RepoListenUrl, RegisteredWebhook, WebhookAuth, WebhookId, diff --git a/crates/cli/src/forges/forgejo/webhook/unregister.rs b/crates/cli/src/forges/forgejo/webhook/unregister.rs index f50dbb2..37609f5 100644 --- a/crates/cli/src/forges/forgejo/webhook/unregister.rs +++ b/crates/cli/src/forges/forgejo/webhook/unregister.rs @@ -1,5 +1,5 @@ // -use git_next_core::{git, WebhookId}; +use crate::core::{git, WebhookId}; use kxio::net::Net; use secrecy::ExposeSecret as _; diff --git a/crates/cli/src/forges/github/commit.rs b/crates/cli/src/forges/github/commit.rs index 27c5b16..70590ce 100644 --- a/crates/cli/src/forges/github/commit.rs +++ b/crates/cli/src/forges/github/commit.rs @@ -1,6 +1,6 @@ // +use crate::core::git::{self, forge::commit::Status}; use crate::forges::github::{self as github, GithubState}; -use git_next_core::git::{self, forge::commit::Status}; use github::GithubStatus; /// Checks the results of any (e.g. CI) status checks for the commit. diff --git a/crates/cli/src/forges/github/mod.rs b/crates/cli/src/forges/github/mod.rs index fdbe779..e485bfc 100644 --- a/crates/cli/src/forges/github/mod.rs +++ b/crates/cli/src/forges/github/mod.rs @@ -5,12 +5,12 @@ mod tests; mod commit; pub mod webhook; -use crate::forges::github; -use git_next_core::{ +use crate::core::{ self as core, git, server::{self, RepoListenUrl}, ForgeNotification, RegisteredWebhook, WebhookAuth, WebhookId, }; +use crate::forges::github; use derive_more::Constructor; @@ -24,6 +24,8 @@ impl git::ForgeLike for Github { fn duplicate(&self) -> Box { Box::new(self.clone()) } + + #[cfg(test)] fn name(&self) -> String { "github".to_string() } @@ -58,6 +60,7 @@ impl git::ForgeLike for Github { github::commit::status(self, commit).await } + #[cfg(test)] async fn list_webhooks( &self, repo_listen_url: &RepoListenUrl, diff --git a/crates/cli/src/forges/github/tests/mod.rs b/crates/cli/src/forges/github/tests/mod.rs index 9d9c951..49b861d 100644 --- a/crates/cli/src/forges/github/tests/mod.rs +++ b/crates/cli/src/forges/github/tests/mod.rs @@ -1,14 +1,14 @@ // #![allow(clippy::expect_used)] -use crate::forges::github::{Github, GithubState, GithubStatus}; -use git_next_core::{ +use crate::core::{ git::{self, forge::commit::Status, ForgeLike}, server::ListenUrl, webhook::{self, forge_notification::Body}, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RepoAlias, RepoBranches, RepoPath, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId, }; +use crate::forges::github::{Github, GithubState, GithubStatus}; use assert2::let_assert; use kxio::net::{MockNet, StatusCode}; @@ -488,7 +488,7 @@ mod github { } pub mod with { - use git_next_core::server::RepoListenUrl; + use crate::core::server::RepoListenUrl; use super::*; @@ -546,8 +546,8 @@ mod github { mod given { + use crate::core::server::RepoListenUrl; use git::RepoDetails; - use git_next_core::server::RepoListenUrl; use super::*; @@ -657,7 +657,7 @@ mod github { ), &a_forge_alias(), &ForgeConfig::new( - ForgeType::ForgeJo, + ForgeType::GitHub, a_name(), a_name(), a_name(), diff --git a/crates/cli/src/forges/github/webhook/authorisation.rs b/crates/cli/src/forges/github/webhook/authorisation.rs index 8b1a19d..e558e74 100644 --- a/crates/cli/src/forges/github/webhook/authorisation.rs +++ b/crates/cli/src/forges/github/webhook/authorisation.rs @@ -2,7 +2,7 @@ use std::string::ToString; -use git_next_core::{ForgeNotification, WebhookAuth}; +use crate::core::{ForgeNotification, WebhookAuth}; use hmac::Mac; type HmacSha256 = hmac::Hmac; @@ -25,7 +25,7 @@ pub fn is_authorised(msg: &ForgeNotification, webhook_auth: &WebhookAuth) -> boo #[cfg(test)] pub fn sign_body( webhook_auth: &WebhookAuth, - body: &git_next_core::webhook::forge_notification::Body, + body: &crate::core::webhook::forge_notification::Body, ) -> Option { let payload = body.as_str(); let mut hmac = HmacSha256::new_from_slice(webhook_auth.to_string().as_bytes()).ok()?; diff --git a/crates/cli/src/forges/github/webhook/list.rs b/crates/cli/src/forges/github/webhook/list.rs index 4f8ee97..8b093ac 100644 --- a/crates/cli/src/forges/github/webhook/list.rs +++ b/crates/cli/src/forges/github/webhook/list.rs @@ -1,6 +1,6 @@ // +use crate::core::{git, server::RepoListenUrl, WebhookId}; 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 pub async fn list( diff --git a/crates/cli/src/forges/github/webhook/mod.rs b/crates/cli/src/forges/github/webhook/mod.rs index 59bfbbe..8a51c4d 100644 --- a/crates/cli/src/forges/github/webhook/mod.rs +++ b/crates/cli/src/forges/github/webhook/mod.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; // -use git_next_core::{git, webhook, ApiToken, BranchName}; +use crate::core::{git, webhook, ApiToken, BranchName}; pub mod authorisation; mod list; diff --git a/crates/cli/src/forges/github/webhook/parser.rs b/crates/cli/src/forges/github/webhook/parser.rs index ec62a6e..1d78d3c 100644 --- a/crates/cli/src/forges/github/webhook/parser.rs +++ b/crates/cli/src/forges/github/webhook/parser.rs @@ -1,7 +1,7 @@ // use crate::forges::github; -use git_next_core::{git, webhook}; +use crate::core::{git, webhook}; pub fn parse_body( body: &webhook::forge_notification::Body, diff --git a/crates/cli/src/forges/github/webhook/register.rs b/crates/cli/src/forges/github/webhook/register.rs index df2f9cd..42e92ce 100644 --- a/crates/cli/src/forges/github/webhook/register.rs +++ b/crates/cli/src/forges/github/webhook/register.rs @@ -1,6 +1,6 @@ // +use crate::core::{git, server::RepoListenUrl, RegisteredWebhook, WebhookAuth, WebhookId}; use crate::forges::github::{self as github, webhook}; -use git_next_core::{git, server::RepoListenUrl, RegisteredWebhook, WebhookAuth, WebhookId}; use serde_json::json; // https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook diff --git a/crates/cli/src/forges/github/webhook/unregister.rs b/crates/cli/src/forges/github/webhook/unregister.rs index 3024532..11f43f9 100644 --- a/crates/cli/src/forges/github/webhook/unregister.rs +++ b/crates/cli/src/forges/github/webhook/unregister.rs @@ -1,6 +1,6 @@ // +use crate::core::{git, WebhookId}; 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 pub async fn unregister( diff --git a/crates/cli/src/macros/send.rs b/crates/cli/src/macros/send.rs index da0fe3f..209f53a 100644 --- a/crates/cli/src/macros/send.rs +++ b/crates/cli/src/macros/send.rs @@ -1,12 +1,15 @@ // #[macro_export] macro_rules! tell { - ($actor_ref:expr, $message:expr) => { + ($actor_ref:expr, $message:expr) => {{ + tracing::info!(msg = stringify!($message), "about to send"); tell!(stringify!($actor_ref), $actor_ref, $message) - }; + }}; ($actor_name:expr, $actor_ref:expr, $message:expr) => {{ - tracing::debug!(actor = $actor_name, msg = stringify!($message), "send"); - $actor_ref.tell($message).await + tracing::info!(actor = $actor_name, msg = stringify!($message), "send"); + let response = $actor_ref.tell($message).await; + tracing::info!(actor = $actor_name, msg = stringify!($message), "sent"); + response }}; } diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 42cab06..3f8a694 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -3,6 +3,7 @@ mod alerts; mod base_actor; +mod core; mod file_watcher; mod forge; mod init; @@ -21,13 +22,16 @@ mod tests; mod webhook; -use git_next_core::git; +use crate::core::git; use kameo::actor::{pubsub::PubSub, ActorRef}; use std::path::PathBuf; use clap::Parser; -use color_eyre::Result; + +pub use color_eyre::eyre::eyre as err; +pub use color_eyre::Result; + use kxio::{fs, net}; pub type MessageBus = ActorRef>; diff --git a/crates/cli/src/repo/branch.rs b/crates/cli/src/repo/branch.rs index 0decb75..5bfca86 100644 --- a/crates/cli/src/repo/branch.rs +++ b/crates/cli/src/repo/branch.rs @@ -1,7 +1,7 @@ // use crate::repo::messages::MessageToken; -use git_next_core::{ +use crate::core::{ git::{ commit::Message, push::{reset, Force}, @@ -10,22 +10,35 @@ use git_next_core::{ }, RepoConfig, }; +use crate::Result; -use derive_more::Display; use tracing::{info, instrument, warn}; +#[derive(Debug, PartialEq, Eq, derive_more::Display)] +pub enum AdvanceError { + /// The next commit message is invalid (non-conventional) + UnconventionalCommitMessage { reason: String }, + /// The next commit has a 'WIP:' commit message prefix + NextCommitIsWIP, + /// The next commit is already on dev + #[cfg(test)] + NextIsDev, + /// Unexpected error + Unexpected(String), +} + // advance next to the next commit towards the head of the dev branch #[instrument(fields(next), skip_all)] pub fn advance_next( - commit: Option, - force: git_next_core::git::push::Force, + commit: Commit, + force: crate::core::git::push::Force, repo_details: &RepoDetails, repo_config: &RepoConfig, open_repository: &dyn OpenRepositoryLike, message_token: MessageToken, -) -> Result { - let commit = commit.ok_or_else(|| Error::NextAtDev)?; +) -> Result { validate_commit_message(commit.message())?; + info!("Advancing next to commit '{}'", commit); reset( open_repository, @@ -33,15 +46,17 @@ pub fn advance_next( &repo_config.branches().next(), &commit.into(), &force, - )?; + ) + .map_err(|err| err.to_string()) + .map_err(AdvanceError::Unexpected)?; Ok(message_token) } #[instrument] -fn validate_commit_message(message: &Message) -> Result<()> { +fn validate_commit_message(message: &Message) -> Result<(), AdvanceError> { let message = &message.to_string(); if message.to_ascii_lowercase().starts_with("wip") { - return Err(Error::IsWorkInProgress); + return Err(AdvanceError::NextCommitIsWIP); } match ::git_conventional::Commit::parse(message) { Ok(commit) => { @@ -50,7 +65,7 @@ fn validate_commit_message(message: &Message) -> Result<()> { } Err(err) => { warn!(?err, "Fail"); - Err(Error::InvalidCommitMessage { + Err(AdvanceError::UnconventionalCommitMessage { reason: err.kind().to_string(), }) } @@ -70,6 +85,7 @@ pub fn find_next_commit_on_dev( }; if commit == main { force = Force::From(GitRef::from(next.sha().clone())); + // next_commit.replace(commit); break; }; next_commit.replace(commit); @@ -95,20 +111,3 @@ pub fn advance_main( )?; Ok(()) } - -pub type Result = std::result::Result; - -#[derive(Debug, thiserror::Error, Display)] -pub enum Error { - #[display("push: {}", 0)] - Push(#[from] crate::git::push::Error), - - #[display("no commits to advance next to")] - NextAtDev, - - #[display("commit is a Work-in-progress")] - IsWorkInProgress, - - #[display("commit message is not in conventional commit format: {reason}")] - InvalidCommitMessage { reason: String }, -} diff --git a/crates/cli/src/repo/handlers/advance_main.rs b/crates/cli/src/repo/handlers/advance_main.rs index c076026..1a77265 100644 --- a/crates/cli/src/repo/handlers/advance_main.rs +++ b/crates/cli/src/repo/handlers/advance_main.rs @@ -1,5 +1,5 @@ // -use git_next_core::{git, RepoConfigSource}; +use crate::core::{git, RepoConfigSource}; use color_eyre::Result; use kameo::message::{Context, Message}; diff --git a/crates/cli/src/repo/handlers/advance_next.rs b/crates/cli/src/repo/handlers/advance_next.rs index bf5ba8c..f5c9f98 100644 --- a/crates/cli/src/repo/handlers/advance_next.rs +++ b/crates/cli/src/repo/handlers/advance_next.rs @@ -1,10 +1,11 @@ // use color_eyre::Result; use kameo::message::{Context, Message}; -use tracing::warn; +use tracing::{instrument, warn}; -use git_next_core::git; +use crate::core::git; +use crate::repo::logger; use crate::{ repo::{ branch::{advance_next, find_next_commit_on_dev}, @@ -18,31 +19,43 @@ use crate::{ impl Message for RepoActor { type Reply = Result<()>; + #[instrument(skip(self, ctx))] async fn handle( &mut self, msg: AdvanceNext, ctx: Context<'_, Self, Self::Reply>, ) -> Self::Reply { + tracing::debug!("start"); + logger(self.log.as_ref(), "start: AdvanceNext").await; let Some(repo_config) = &self.repo_details.repo_config else { + tracing::debug!("repo details.repo_config is unset"); return Ok(()); }; let Some(open_repository) = &self.open_repository else { + tracing::debug!("no open repository"); return Ok(()); }; + tracing::debug!("prerequisites okay"); let AdvanceNextPayload { next, main, dev_commit_history, } = msg.peel(); + tracing::debug!(?next, ?main, ?dev_commit_history, "can we advance?"); let (commit, force) = find_next_commit_on_dev(&next, &main, &dev_commit_history); - if let Some(commit) = &commit { - self.update_tui(RepoUpdate::AdvancingNext { - commit: commit.clone(), - force: force.clone(), - }) - .await?; + tracing::debug!(?commit, ?force, "advance?"); + let Some(commit) = commit else { + tracing::debug!("next is on dev - not advancing next"); + self.alert_tui("Next is on Dev").await?; + return Ok(()); }; + tracing::debug!(?commit, "we have a commit to advance to"); + self.update_tui(RepoUpdate::AdvancingNext { + commit: commit.clone(), + force: force.clone(), + }) + .await?; match advance_next( commit, force, @@ -61,7 +74,9 @@ impl Message for RepoActor { Err(err) => self.alert_tui(format!("fetching: {err}")).await?, } // INFO: pause to allow any CI checks to be started + tracing::debug!(duration_ms = %self.sleep_duration.as_millis(), "sleeping to allow CI to start"); tokio::time::sleep(self.sleep_duration).await; + tracing::debug!("sleeping for CI finished"); Ok(do_send( &ctx.actor_ref(), ValidateRepo::new(message_token), diff --git a/crates/cli/src/repo/handlers/clone_repo.rs b/crates/cli/src/repo/handlers/clone_repo.rs index ce804a8..d144ab4 100644 --- a/crates/cli/src/repo/handlers/clone_repo.rs +++ b/crates/cli/src/repo/handlers/clone_repo.rs @@ -3,7 +3,7 @@ use color_eyre::Result; use kameo::message::{Context, Message}; use tracing::{debug, instrument, warn}; -use git_next_core::git; +use crate::core::git; use crate::{ repo::{ diff --git a/crates/cli/src/repo/handlers/load_config_from_repo.rs b/crates/cli/src/repo/handlers/load_config_from_repo.rs index 22113c7..a3e70e3 100644 --- a/crates/cli/src/repo/handlers/load_config_from_repo.rs +++ b/crates/cli/src/repo/handlers/load_config_from_repo.rs @@ -3,7 +3,7 @@ use color_eyre::Result; use kameo::message::{Context, Message}; use tracing::{debug, instrument}; -use git_next_core::git::UserNotification; +use crate::core::git::UserNotification; use crate::{ repo::{ diff --git a/crates/cli/src/repo/handlers/receive_ci_status.rs b/crates/cli/src/repo/handlers/receive_ci_status.rs index 6bfdddb..73638e9 100644 --- a/crates/cli/src/repo/handlers/receive_ci_status.rs +++ b/crates/cli/src/repo/handlers/receive_ci_status.rs @@ -3,7 +3,7 @@ use color_eyre::Result; use kameo::message::{Context, Message}; use tracing::debug; -use git_next_core::git::{forge::commit::Status, graph, UserNotification}; +use crate::core::git::{forge::commit::Status, graph, UserNotification}; use crate::{ repo::{ diff --git a/crates/cli/src/repo/handlers/register_webhook.rs b/crates/cli/src/repo/handlers/register_webhook.rs index 4fa9b72..4aebaea 100644 --- a/crates/cli/src/repo/handlers/register_webhook.rs +++ b/crates/cli/src/repo/handlers/register_webhook.rs @@ -12,7 +12,7 @@ use crate::{ server::actor::messages::RepoUpdate, }; -use git_next_core::git::UserNotification; +use crate::core::git::UserNotification; impl Message for RepoActor { type Reply = Result<()>; diff --git a/crates/cli/src/repo/handlers/validate_repo.rs b/crates/cli/src/repo/handlers/validate_repo.rs index 9d12f66..a6ff9ea 100644 --- a/crates/cli/src/repo/handlers/validate_repo.rs +++ b/crates/cli/src/repo/handlers/validate_repo.rs @@ -1,10 +1,16 @@ // use std::collections::HashMap; -use color_eyre::Result; use kameo::message::{Context, Message}; use tracing::{debug, info, instrument, warn}; +use crate::core::git::{ + push::Force, + validation::positions::{validate, Positions, PositionsError}, + UserNotification, +}; +use crate::s; +use crate::Result; use crate::{ repo::{ do_send, logger, @@ -13,12 +19,6 @@ use crate::{ }, server::actor::messages::RepoUpdate, }; -use git_next_core::git::{ - push::Force, - validation::positions::{validate, Error, Positions}, - UserNotification, -}; -use git_next_core::s; impl Message for RepoActor { type Reply = Result<()>; @@ -69,6 +69,7 @@ impl Message for RepoActor { return Ok(()); }; logger(self.log.as_ref(), "have repo config").await; + info!("validating positions"); match validate(&**open_repository, &self.repo_details, &repo_config) { Ok(( Positions { @@ -80,6 +81,7 @@ impl Message for RepoActor { }, git_log, )) => { + info!("positions - ok"); let mut positions = HashMap::new(); positions .entry(s!(s!(main.sha())[0..7])) @@ -120,13 +122,14 @@ impl Message for RepoActor { self.log.as_ref(), ) .await?; + info!("advance next sent"); } else { info!("do nothing"); self.update_tui(RepoUpdate::Okay { main, next, dev }) .await?; } } - Err(Error::Retryable(message)) => { + Err(PositionsError::Retryable(message)) => { warn!(?message, "Retryable"); self.alert_tui(format!("retryable: {message}")).await?; logger(self.log.as_ref(), message).await; @@ -139,7 +142,7 @@ impl Message for RepoActor { ) .await?; } - Err(Error::UserIntervention(user_notification)) => { + Err(PositionsError::UserIntervention(user_notification)) => { warn!(?user_notification, "User Intervention"); self.alert_tui(format!("USER INTERVENTION: {user_notification}")) .await?; @@ -155,7 +158,7 @@ impl Message for RepoActor { ) .await?; } - Err(Error::NonRetryable(message)) => { + Err(PositionsError::NonRetryable(message)) => { warn!(?message, "NonRetryable"); self.alert_tui(format!("Error: {message}")).await?; logger(self.log.as_ref(), message).await; diff --git a/crates/cli/src/repo/handlers/webhook_notification.rs b/crates/cli/src/repo/handlers/webhook_notification.rs index 7095b9e..e06eaf9 100644 --- a/crates/cli/src/repo/handlers/webhook_notification.rs +++ b/crates/cli/src/repo/handlers/webhook_notification.rs @@ -3,7 +3,7 @@ use color_eyre::Result; use kameo::message::{Context, Message}; use tracing::{info, instrument, warn}; -use git_next_core::{ +use crate::core::{ git::{Commit, ForgeLike}, webhook::{push::Branch, Push}, BranchName, WebhookAuth, diff --git a/crates/cli/src/repo/load.rs b/crates/cli/src/repo/load.rs index d52eb86..06c758f 100644 --- a/crates/cli/src/repo/load.rs +++ b/crates/cli/src/repo/load.rs @@ -1,12 +1,14 @@ // -use git_next_core::{ - git::{repository::open::OpenRepositoryLike, RepoDetails}, - BranchName, RepoConfig, +use crate::{ + core::{ + git::{repository::open::OpenRepositoryLike, RepoDetails}, + BranchName, RepoConfig, + }, + err, Result, }; use std::path::PathBuf; -use derive_more::Display; use tracing::{info, instrument}; /// Loads the [RepoConfig] from the `.git-next.toml` file in the repository @@ -30,26 +32,6 @@ fn required_branch(branch_name: &BranchName, branches: &[BranchName]) -> Result< branches .iter() .find(|branch| *branch == branch_name) - .ok_or_else(|| Error::BranchNotFound(branch_name.clone()))?; + .ok_or_else(|| err!(branch_name.clone()))?; Ok(()) } - -pub type Result = std::result::Result; - -#[derive(Debug, thiserror::Error, Display)] -pub enum Error { - #[display("file")] - File(#[from] crate::git::file::Error), - - #[display("config")] - Config(#[from] git_next_core::server::Error), - - #[display("toml")] - Toml(#[from] toml::de::Error), - - #[display("push")] - Push(#[from] crate::git::push::Error), - - #[display("branch not found: {}", 0)] - BranchNotFound(BranchName), -} diff --git a/crates/cli/src/repo/messages.rs b/crates/cli/src/repo/messages.rs index 5a9fa86..70b000d 100644 --- a/crates/cli/src/repo/messages.rs +++ b/crates/cli/src/repo/messages.rs @@ -1,10 +1,12 @@ // use derive_more::Display; -use git_next_core::{ +use crate::core::{ git::{forge::commit::Status, Commit, UserNotification}, - message, newtype, ForgeNotification, RegisteredWebhook, RepoConfig, WebhookAuth, WebhookId, + ForgeNotification, RegisteredWebhook, RepoConfig, WebhookAuth, WebhookId, }; +use crate::message; +use crate::newtype; message!( LoadConfigFromRepo, diff --git a/crates/cli/src/repo/mod.rs b/crates/cli/src/repo/mod.rs index 4984874..158a228 100644 --- a/crates/cli/src/repo/mod.rs +++ b/crates/cli/src/repo/mod.rs @@ -8,7 +8,7 @@ use kxio::net::Net; use tokio::sync::RwLock; use tracing::{debug, info, instrument, warn}; -use git_next_core::{ +use crate::core::{ git::{ self, repository::{factory::RepositoryFactory, open::OpenRepositoryLike}, diff --git a/crates/cli/src/repo/notifications.rs b/crates/cli/src/repo/notifications.rs index 9b70c89..59635f6 100644 --- a/crates/cli/src/repo/notifications.rs +++ b/crates/cli/src/repo/notifications.rs @@ -1,90 +1,84 @@ // - -use crate::repo::messages::NotifyUser; - -use git_next_core::git::UserNotification; - -use serde_json::json; - -impl NotifyUser { - pub fn as_json(&self, timestamp: time::OffsetDateTime) -> serde_json::Value { - let timestamp = timestamp.unix_timestamp().to_string(); - match &**self { - UserNotification::CICheckFailed { - forge_alias, - repo_alias, - commit, - log, - } => json!({ - "type": "cicheck.failed", - "timestamp": timestamp, - "data": { - "forge_alias": forge_alias, - "repo_alias": repo_alias, - "commit": { - "sha": commit.sha(), - "message": commit.message() - }, - "log": **log - } - }), - UserNotification::RepoConfigLoadFailure { - forge_alias, - repo_alias, - reason, - } => json!({ - "type": "config.load.failed", - "timestamp": timestamp, - "data": { - "forge_alias": forge_alias, - "repo_alias": repo_alias, - "reason": reason - } - }), - UserNotification::WebhookRegistration { - forge_alias, - repo_alias, - reason, - } => json!({ - "type": "webhook.registration.failed", - "timestamp": timestamp, - "data": { - "forge_alias": forge_alias, - "repo_alias": repo_alias, - "reason": reason - } - }), - UserNotification::DevNotBasedOnMain { - forge_alias, - repo_alias, - dev_branch, - main_branch, - dev_commit, - main_commit, - log, - } => json!({ - "type": "branch.dev.not-on-main", - "timestamp": timestamp, - "data": { - "forge_alias": forge_alias, - "repo_alias": repo_alias, - "branches": { - "dev": dev_branch, - "main": main_branch - }, - "commits": { - "dev": { - "sha": dev_commit.sha(), - "message": dev_commit.message() - }, - "main": { - "sha": main_commit.sha(), - "message": main_commit.message() - } - }, - "log": **log - } - }), - } - } +#[cfg(test)] +impl super::messages::NotifyUser { + // pub fn as_json(&self, timestamp: time::OffsetDateTime) -> serde_json::Value { + // let timestamp = timestamp.unix_timestamp().to_string(); + // match &**self { + // crate::core::git::UserNotification::CICheckFailed { + // forge_alias, + // repo_alias, + // commit, + // log, + // } => serde_json::json!({ + // "type": "cicheck.failed", + // "timestamp": timestamp, + // "data": { + // "forge_alias": forge_alias, + // "repo_alias": repo_alias, + // "commit": { + // "sha": commit.sha(), + // "message": commit.message() + // }, + // "log": **log + // } + // }), + // crate::core::git::UserNotification::RepoConfigLoadFailure { + // forge_alias, + // repo_alias, + // reason, + // } => serde_json::json!({ + // "type": "config.load.failed", + // "timestamp": timestamp, + // "data": { + // "forge_alias": forge_alias, + // "repo_alias": repo_alias, + // "reason": reason + // } + // }), + // crate::core::git::UserNotification::WebhookRegistration { + // forge_alias, + // repo_alias, + // reason, + // } => serde_json::json!({ + // "type": "webhook.registration.failed", + // "timestamp": timestamp, + // "data": { + // "forge_alias": forge_alias, + // "repo_alias": repo_alias, + // "reason": reason + // } + // }), + // crate::core::git::UserNotification::DevNotBasedOnMain { + // forge_alias, + // repo_alias, + // dev_branch, + // main_branch, + // dev_commit, + // main_commit, + // log, + // } => serde_json::json!({ + // "type": "branch.dev.not-on-main", + // "timestamp": timestamp, + // "data": { + // "forge_alias": forge_alias, + // "repo_alias": repo_alias, + // "branches": { + // "dev": dev_branch, + // "main": main_branch + // }, + // "commits": { + // "dev": { + // "sha": dev_commit.sha(), + // "message": dev_commit.message() + // }, + // "main": { + // "sha": main_commit.sha(), + // "message": main_commit.message() + // } + // }, + // "log": **log + // } + // }), + // } + // } } diff --git a/crates/cli/src/repo/tests/branch/advance_main.rs b/crates/cli/src/repo/tests/branch/advance_main.rs index 45ffc6d..420a601 100644 --- a/crates/cli/src/repo/tests/branch/advance_main.rs +++ b/crates/cli/src/repo/tests/branch/advance_main.rs @@ -1,7 +1,6 @@ -use crate::git; - // use super::*; +use crate::err; #[test] fn push_is_error_should_error() { @@ -10,14 +9,11 @@ fn push_is_error_should_error() { let repo_config = given::a_repo_config(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); expect::fetch_ok(&mut open_repository); - expect::push(&mut open_repository, Err(git::push::Error::Lock)); + expect::push(&mut open_repository, Err(err!("on-push"))); let_assert!( Err(err) = branch::advance_main(commit, &repo_details, &repo_config, &open_repository) ); - assert!(matches!( - err, - branch::Error::Push(crate::git::push::Error::Lock) - )); + assert_eq!(err.to_string(), "on-push"); } #[test] diff --git a/crates/cli/src/repo/tests/branch/advance_next.rs b/crates/cli/src/repo/tests/branch/advance_next.rs index 38be667..86a78e9 100644 --- a/crates/cli/src/repo/tests/branch/advance_next.rs +++ b/crates/cli/src/repo/tests/branch/advance_next.rs @@ -1,5 +1,6 @@ // -use crate::repo::branch::find_next_commit_on_dev; +use crate::repo::branch::{find_next_commit_on_dev, AdvanceError}; +use crate::Result; use super::*; @@ -11,9 +12,12 @@ fn advance_next_sut( repo_config: &RepoConfig, open_repository: &dyn OpenRepositoryLike, message_token: MessageToken, -) -> branch::Result { +) -> Result { let (commit, force) = find_next_commit_on_dev(next, main, dev_commit_history); - branch::advance_next( + let Some(commit) = commit else { + return Err(AdvanceError::NextIsDev); + }; + crate::repo::branch::advance_next( commit, force, repo_details, @@ -49,7 +53,7 @@ mod when_at_dev { ) ); tracing::debug!("Got: {err}"); - assert!(matches!(err, branch::Error::NextAtDev)); + assert_eq!(err, AdvanceError::NextIsDev); } } @@ -84,24 +88,28 @@ mod can_advance { ) ); tracing::debug!("Got: {err}"); - assert!(matches!(err, branch::Error::IsWorkInProgress)); + assert_eq!(err, AdvanceError::NextCommitIsWIP); } } mod to_invalid_commit { + use crate::err; + // commit on dev is either invalid message or a WIP use super::*; #[test] - fn should_not_push_and_error() { + fn should_not_push_on_error() { let next = given::a_commit(); let main = &next; let dev = given::a_commit(); let dev_commit_history = &[dev, next.clone()]; let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); - let (open_repository, repo_details) = given::an_open_repository(&fs); - // no on_push defined - so any call to push will cause an error + let (mut open_repository, repo_details) = given::an_open_repository(&fs); + open_repository + .expect_fetch() + .return_once(|| Err(err!("test"))); let message_token = given::a_message_token(); let_assert!( Err(err) = advance_next_sut( @@ -115,11 +123,7 @@ mod can_advance { ) ); tracing::debug!("Got: {err}"); - assert!(matches!( - err, - branch::Error::InvalidCommitMessage{reason} - if reason == "Missing type in the commit summary, expected `type: description`" - )); + assert_eq!(err.to_string(), "test"); } } @@ -128,6 +132,8 @@ mod can_advance { use super::*; mod push_is_err { + use crate::{err, s}; + // the git push command fails use super::*; @@ -141,7 +147,7 @@ mod can_advance { let repo_config = given::a_repo_config(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); expect::fetch_ok(&mut open_repository); - expect::push(&mut open_repository, Err(git::push::Error::Lock)); + expect::push(&mut open_repository, Err(err!("on-push"))); let message_token = given::a_message_token(); let_assert!( Err(err) = advance_next_sut( @@ -155,7 +161,7 @@ mod can_advance { ) ); tracing::debug!("Got: {err:?}"); - assert!(matches!(err, branch::Error::Push(git::push::Error::Lock))); + assert_eq!(err, AdvanceError::Unexpected(s!("on-push"))); } } diff --git a/crates/cli/src/repo/tests/branch/mod.rs b/crates/cli/src/repo/tests/branch/mod.rs index 874ecb3..64cba68 100644 --- a/crates/cli/src/repo/tests/branch/mod.rs +++ b/crates/cli/src/repo/tests/branch/mod.rs @@ -1,5 +1,5 @@ -use git_next_core::git::push::Force; -use git_next_core::git::GitRef; +use crate::core::git::push::Force; +use crate::core::git::GitRef; // use super::*; @@ -7,7 +7,6 @@ use super::*; mod advance_main; mod advance_next; -use crate::git; use crate::repo::branch; #[tokio::test] diff --git a/crates/cli/src/repo/tests/expect.rs b/crates/cli/src/repo/tests/expect.rs index 16fe882..bd4bc59 100644 --- a/crates/cli/src/repo/tests/expect.rs +++ b/crates/cli/src/repo/tests/expect.rs @@ -1,4 +1,4 @@ -use git_next_core::git::fetch; +use crate::Result; // use super::*; @@ -7,7 +7,7 @@ pub fn fetch_ok(open_repository: &mut MockOpenRepositoryLike) { expect::fetch(open_repository, Ok(())); } -pub fn fetch(open_repository: &mut MockOpenRepositoryLike, result: Result<(), fetch::Error>) { +pub fn fetch(open_repository: &mut MockOpenRepositoryLike, result: Result<()>) { open_repository .expect_fetch() .times(1) @@ -18,10 +18,7 @@ pub fn push_ok(open_repository: &mut MockOpenRepositoryLike) { expect::push(open_repository, Ok(())); } -pub fn push( - open_repository: &mut MockOpenRepositoryLike, - result: Result<(), crate::git::push::Error>, -) { +pub fn push(open_repository: &mut MockOpenRepositoryLike, result: Result<()>) { open_repository .expect_push() .times(1) diff --git a/crates/cli/src/repo/tests/given.rs b/crates/cli/src/repo/tests/given.rs index 79fff6a..d5e8154 100644 --- a/crates/cli/src/repo/tests/given.rs +++ b/crates/cli/src/repo/tests/given.rs @@ -1,15 +1,16 @@ -use crate::{ - alerts::{AlertsActor, History}, - server::{actor::messages::ServerUpdate, ServerActor}, -}; - // use super::*; -use git_next_core::server::ListenUrl; +use git::forge::MockForgeLike; use kameo::actor::{pubsub::PubSub, ActorRef}; use kxio::{fs::FileSystem, net::Net}; +use crate::{ + alerts::{AlertsActor, History}, + core::server::ListenUrl, + server::{actor::messages::ServerUpdate, ServerActor}, +}; + pub fn has_all_valid_remote_defaults( open_repository: &mut MockOpenRepositoryLike, repo_details: &RepoDetails, @@ -148,7 +149,7 @@ pub fn a_commit_with_message(message: impl Into) -> } pub fn a_commit_message() -> crate::git::commit::Message { - crate::git::commit::Message::new(a_name()) + crate::git::commit::Message::new(format!("test: {}", a_name())) } pub fn a_named_commit_sha(name: impl Into) -> Sha { diff --git a/crates/cli/src/repo/tests/handlers/advance_main.rs b/crates/cli/src/repo/tests/handlers/advance_main.rs index daacea1..102b648 100644 --- a/crates/cli/src/repo/tests/handlers/advance_main.rs +++ b/crates/cli/src/repo/tests/handlers/advance_main.rs @@ -1,10 +1,10 @@ -use crate::{repo::messages::AdvanceMain, tell}; +use crate::{repo::messages::AdvanceMain, tell, Result}; // use super::*; #[tokio::test] -async fn when_repo_config_should_fetch_then_push_then_revalidate() -> TestResult { +async fn when_repo_config_should_fetch_then_push_then_revalidate() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, mut repo_details) = given::an_open_repository(&fs); @@ -49,7 +49,7 @@ async fn when_repo_config_should_fetch_then_push_then_revalidate() -> TestResult } #[test_log::test(tokio::test)] -async fn when_app_config_should_fetch_then_push_then_revalidate() -> TestResult { +async fn when_app_config_should_fetch_then_push_then_revalidate() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, mut repo_details) = given::an_open_repository(&fs); diff --git a/crates/cli/src/repo/tests/handlers/advance_next.rs b/crates/cli/src/repo/tests/handlers/advance_next.rs index 612c9d5..bf0413b 100644 --- a/crates/cli/src/repo/tests/handlers/advance_next.rs +++ b/crates/cli/src/repo/tests/handlers/advance_next.rs @@ -2,14 +2,14 @@ use std::time::Duration; use crate::{ repo::messages::{AdvanceNext, AdvanceNextPayload}, - tell, + tell, Result, }; // use super::*; #[test_log::test(tokio::test)] -async fn should_fetch_then_push_then_revalidate() -> TestResult { +async fn should_fetch_then_push_then_revalidate() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); diff --git a/crates/cli/src/repo/tests/handlers/check_ci_status.rs b/crates/cli/src/repo/tests/handlers/check_ci_status.rs index f951e7c..8c3f48d 100644 --- a/crates/cli/src/repo/tests/handlers/check_ci_status.rs +++ b/crates/cli/src/repo/tests/handlers/check_ci_status.rs @@ -1,15 +1,17 @@ -use crate::{repo::messages::CheckCIStatus, tell}; +use git::forge::MockForgeLike; + +use crate::{repo::messages::CheckCIStatus, tell, Result}; // use super::*; #[tokio::test] -async fn should_passthrough_to_receive_ci_status() -> TestResult { +async fn should_passthrough_to_receive_ci_status() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); let next_commit = given::a_named_commit("next"); - let mut forge = git::MockForgeLike::new(); + let mut forge = MockForgeLike::new(); forge .expect_commit_status() .with(mockall::predicate::eq(next_commit.clone())) diff --git a/crates/cli/src/repo/tests/handlers/clone_repo.rs b/crates/cli/src/repo/tests/handlers/clone_repo.rs index a46b4bc..c89902e 100644 --- a/crates/cli/src/repo/tests/handlers/clone_repo.rs +++ b/crates/cli/src/repo/tests/handlers/clone_repo.rs @@ -1,12 +1,12 @@ use kxio::net::Net; -use crate::tell; +use crate::{err, tell, Result}; // use super::*; #[test_log::test(tokio::test)] -async fn should_clone() -> TestResult { +async fn should_clone() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, /* mut */ repo_details) = given::an_open_repository(&fs); @@ -42,7 +42,7 @@ async fn should_clone() -> TestResult { tick(1).await; cloned .read() - .map_err(|e| e.to_string()) + .map_err(|e| err!(e.to_string())) .map(|o| assert_eq!(o.len(), 1))?; net.assert_no_unused_plans(); @@ -50,7 +50,7 @@ async fn should_clone() -> TestResult { } #[tokio::test] -async fn should_open() -> TestResult { +async fn should_open() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -87,7 +87,7 @@ async fn should_open() -> TestResult { tick(1).await; opened .read() - .map_err(|e| e.to_string()) + .map_err(|e| err!(e.to_string())) .map(|o| assert_eq!(o.len(), 1))?; net.assert_no_unused_plans(); @@ -98,7 +98,7 @@ async fn should_open() -> TestResult { /// branches. When it doesn't we should load the `.git-next.yaml` from from the /// repo and get the branch names from there by sending a [LoadConfigFromRepo] message. #[tokio::test] -async fn when_server_has_no_repo_config_should_send_load_from_repo() -> TestResult { +async fn when_server_has_no_repo_config_should_send_load_from_repo() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, mut repo_details) = given::an_open_repository(&fs); @@ -137,7 +137,7 @@ async fn when_server_has_no_repo_config_should_send_load_from_repo() -> TestResu /// The server config can optionally include the names of the main, next and dev /// branches. When it does we should register the webhook by sending [RegisterWebhook] message. #[test_log::test(tokio::test)] -async fn when_server_has_repo_config_should_send_register_webhook() -> TestResult { +async fn when_server_has_repo_config_should_send_register_webhook() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -165,7 +165,7 @@ async fn when_server_has_repo_config_should_send_register_webhook() -> TestResul //then tick(1).await; - debug!(?log, ""); + tracing::debug!(?log, ""); log.require_message_containing("send: RegisterWebhook") .await?; net.assert_no_unused_plans(); diff --git a/crates/cli/src/repo/tests/handlers/load_config_from_repo.rs b/crates/cli/src/repo/tests/handlers/load_config_from_repo.rs index a685efd..4294775 100644 --- a/crates/cli/src/repo/tests/handlers/load_config_from_repo.rs +++ b/crates/cli/src/repo/tests/handlers/load_config_from_repo.rs @@ -1,10 +1,10 @@ -use crate::{repo::messages::LoadConfigFromRepo, tell}; +use crate::{err, repo::messages::LoadConfigFromRepo, tell, Result}; // use super::*; #[tokio::test] -async fn when_read_file_ok_should_send_config_loaded() -> TestResult { +async fn when_read_file_ok_should_send_config_loaded() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -46,13 +46,13 @@ async fn when_read_file_ok_should_send_config_loaded() -> TestResult { } #[tokio::test] -async fn when_read_file_err_should_notify_user() -> TestResult { +async fn when_read_file_err_should_notify_user() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); open_repository .expect_read_file() - .return_once(move |_, _| Err(git::file::Error::FileNotFound)); + .return_once(move |_, _| Err(err!("FileNotFound"))); //when let (addr, log) = when::start_actor_with_open_repository( diff --git a/crates/cli/src/repo/tests/handlers/loaded_config.rs b/crates/cli/src/repo/tests/handlers/loaded_config.rs index 2587d53..b37d4ce 100644 --- a/crates/cli/src/repo/tests/handlers/loaded_config.rs +++ b/crates/cli/src/repo/tests/handlers/loaded_config.rs @@ -1,10 +1,10 @@ // -use crate::{repo::messages::ReceiveRepoConfig, tell}; +use crate::{err, repo::messages::ReceiveRepoConfig, tell, Result}; use super::*; #[tokio::test] -async fn should_store_repo_config_in_actor() -> TestResult { +async fn should_store_repo_config_in_actor() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); @@ -25,7 +25,7 @@ async fn should_store_repo_config_in_actor() -> TestResult { let reo_actor_view = addr .ask(ExamineActor) .await - .map_err(|e| format!("examine actor: {e:?}"))?; + .map_err(|e| err!("examine actor: {e:?}"))?; assert_eq!( reo_actor_view.repo_details.repo_config, Some(new_repo_config) @@ -34,7 +34,7 @@ async fn should_store_repo_config_in_actor() -> TestResult { } #[test_log::test(tokio::test)] -async fn should_register_webhook() -> TestResult { +async fn should_register_webhook() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); diff --git a/crates/cli/src/repo/tests/handlers/receive_ci_status.rs b/crates/cli/src/repo/tests/handlers/receive_ci_status.rs index c6ee07d..ed60a4a 100644 --- a/crates/cli/src/repo/tests/handlers/receive_ci_status.rs +++ b/crates/cli/src/repo/tests/handlers/receive_ci_status.rs @@ -2,13 +2,13 @@ use std::time::Duration; use git::forge::commit::Status; -use crate::{repo::messages::ReceiveCIStatus, tell}; +use crate::{repo::messages::ReceiveCIStatus, tell, Result}; // use super::*; #[test_log::test(tokio::test)] -async fn when_pass_should_advance_main_to_next() -> TestResult { +async fn when_pass_should_advance_main_to_next() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); @@ -33,7 +33,7 @@ async fn when_pass_should_advance_main_to_next() -> TestResult { } #[test_log::test(tokio::test)] -async fn when_pending_should_recheck_ci_status() -> TestResult { +async fn when_pending_should_recheck_ci_status() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); @@ -58,7 +58,7 @@ async fn when_pending_should_recheck_ci_status() -> TestResult { } #[test_log::test(tokio::test)] -async fn when_fail_should_recheck_after_delay() -> TestResult { +async fn when_fail_should_recheck_after_delay() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); @@ -82,7 +82,7 @@ async fn when_fail_should_recheck_after_delay() -> TestResult { } #[test_log::test(tokio::test)] -async fn when_fail_should_notify_user() -> TestResult { +async fn when_fail_should_notify_user() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); diff --git a/crates/cli/src/repo/tests/handlers/register_webhook.rs b/crates/cli/src/repo/tests/handlers/register_webhook.rs index 71a5ae0..eba837c 100644 --- a/crates/cli/src/repo/tests/handlers/register_webhook.rs +++ b/crates/cli/src/repo/tests/handlers/register_webhook.rs @@ -1,16 +1,18 @@ -use crate::{repo::messages::RegisterWebhook, tell}; +use git::forge::MockForgeLike; + +use crate::{repo::messages::RegisterWebhook, tell, Result}; // use super::*; #[tokio::test] -async fn when_registered_ok_should_send_webhook_registered() -> TestResult { +async fn when_registered_ok_should_send_webhook_registered() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); let registered_webhook = given::a_registered_webhook(); - let mut forge = git::MockForgeLike::new(); + let mut forge = MockForgeLike::new(); forge .expect_register_webhook() .return_once(move |_| Ok(registered_webhook)); @@ -30,12 +32,12 @@ async fn when_registered_ok_should_send_webhook_registered() -> TestResult { } #[tokio::test] -async fn when_registered_error_should_send_notify_user() -> TestResult { +async fn when_registered_error_should_send_notify_user() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); - let mut forge = git::MockForgeLike::new(); + let mut forge = MockForgeLike::new(); forge.expect_register_webhook().return_once(move |_| { Err(git::forge::webhook::Error::FailedToRegister( "foo".to_string(), diff --git a/crates/cli/src/repo/tests/handlers/validate_repo.rs b/crates/cli/src/repo/tests/handlers/validate_repo.rs index 27ee2c7..df23237 100644 --- a/crates/cli/src/repo/tests/handlers/validate_repo.rs +++ b/crates/cli/src/repo/tests/handlers/validate_repo.rs @@ -2,15 +2,16 @@ use kxio::net::Net; use crate::{ + err, repo::messages::{AdvanceNext, AdvanceNextPayload, ValidateRepo}, - tell, + tell, Result, }; use super::*; #[test_log::test(tokio::test)] async fn repo_with_next_not_an_ancestor_of_dev_and_dev_on_main_should_be_reset_to_main( -) -> TestResult { +) -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -21,7 +22,8 @@ async fn repo_with_next_not_an_ancestor_of_dev_and_dev_on_main_should_be_reset_t // commit_log main let main_commit = expect::main_commit_log(&mut open_repository, branches.main()); // next - based on main - let next_branch_log = vec![given::a_commit(), main_commit.clone()]; + let next_commit = given::a_commit(); + let next_branch_log = vec![next_commit.clone(), main_commit.clone()]; // dev - based on main, but not on next let dev_branch_log = vec![main_commit.clone()]; // commit_log next - based on main, but not a parent of dev @@ -31,11 +33,12 @@ async fn repo_with_next_not_an_ancestor_of_dev_and_dev_on_main_should_be_reset_t .with(eq(branches.next()), eq([main_commit.clone()])) .return_once(move |_, _| Ok(next_branch_log)); // commit_log dev + let dev_branch_log_clone = dev_branch_log.clone(); open_repository .expect_commit_log() .times(1) - .with(eq(branches.dev()), eq([main_commit])) - .return_once(|_, _| Ok(dev_branch_log)); + .with(eq(branches.dev()), eq([main_commit.clone()])) + .return_once(|_, _| Ok(dev_branch_log_clone)); // expect to reset the branch expect::fetch_ok(&mut open_repository); expect::push_ok(&mut open_repository); @@ -48,7 +51,7 @@ async fn repo_with_next_not_an_ancestor_of_dev_and_dev_on_main_should_be_reset_t ); tell!(addr, ValidateRepo::new(MessageToken::default()))?; - //then + // then log.require_message_containing(format!("Branch {} has been reset", branches.next())) .await?; Ok(()) @@ -56,7 +59,7 @@ async fn repo_with_next_not_an_ancestor_of_dev_and_dev_on_main_should_be_reset_t #[test_log::test(tokio::test)] async fn repo_with_next_not_an_ancestor_of_dev_and_dev_ahead_of_main_should_be_reset_to_dev( -) -> TestResult { +) -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -111,7 +114,7 @@ async fn repo_with_next_not_an_ancestor_of_dev_and_dev_ahead_of_main_should_be_r } #[test_log::test(tokio::test)] -async fn repo_with_next_not_on_or_near_main_should_be_reset() -> TestResult { +async fn repo_with_next_not_on_or_near_main_should_be_reset() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -156,7 +159,7 @@ async fn repo_with_next_not_on_or_near_main_should_be_reset() -> TestResult { } #[test_log::test(tokio::test)] -async fn repo_with_next_not_based_on_main_should_be_reset() -> TestResult { +async fn repo_with_next_not_based_on_main_should_be_reset() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -201,7 +204,7 @@ async fn repo_with_next_not_based_on_main_should_be_reset() -> TestResult { } #[test_log::test(tokio::test)] -async fn repo_with_next_ahead_of_main_should_check_ci_status() -> TestResult { +async fn repo_with_next_ahead_of_main_should_check_ci_status() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -245,7 +248,7 @@ async fn repo_with_next_ahead_of_main_should_check_ci_status() -> TestResult { } #[test_log::test(tokio::test)] -async fn repo_with_dev_and_next_on_main_should_do_nothing() -> TestResult { +async fn repo_with_dev_and_next_on_main_should_do_nothing() -> Result<()> { // Do nothing, when the situation changes we will hear about it via a webhook //given let fs = given::a_filesystem(); @@ -289,7 +292,7 @@ async fn repo_with_dev_and_next_on_main_should_do_nothing() -> TestResult { } #[test_log::test(tokio::test)] -async fn repo_with_dev_ahead_of_next_should_advance_next() -> TestResult { +async fn repo_with_dev_ahead_of_next_should_advance_next() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -340,7 +343,7 @@ async fn repo_with_dev_ahead_of_next_should_advance_next() -> TestResult { } #[test_log::test(tokio::test)] -async fn repo_with_dev_not_ahead_of_main_should_notify_user() -> TestResult { +async fn repo_with_dev_not_ahead_of_main_should_notify_user() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -385,7 +388,7 @@ async fn repo_with_dev_not_ahead_of_main_should_notify_user() -> TestResult { } #[test_log::test(tokio::test)] -async fn should_accept_message_with_current_token() -> TestResult { +async fn should_accept_message_with_current_token() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -393,7 +396,7 @@ async fn should_accept_message_with_current_token() -> TestResult { let server_actor_ref = given::a_server_actor(fs.as_real(), net.clone()); let (actor, log) = given::a_repo_actor( repo_details, - git::repository::factory::mock(), + Box::new(git::repository::factory::mock()), given::a_forge(), server_actor_ref, net.clone(), @@ -411,7 +414,7 @@ async fn should_accept_message_with_current_token() -> TestResult { } #[test_log::test(tokio::test)] -async fn should_accept_message_with_new_token() -> TestResult { +async fn should_accept_message_with_new_token() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -420,7 +423,7 @@ async fn should_accept_message_with_new_token() -> TestResult { //when let (actor, log) = given::a_repo_actor( repo_details, - git::repository::factory::mock(), + Box::new(git::repository::factory::mock()), given::a_forge(), given::a_server_actor(fs.as_real(), net.clone()), net.clone(), @@ -436,7 +439,7 @@ async fn should_accept_message_with_new_token() -> TestResult { } #[test_log::test(tokio::test)] -async fn should_reject_message_with_expired_token() -> TestResult { +async fn should_reject_message_with_expired_token() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -445,7 +448,7 @@ async fn should_reject_message_with_expired_token() -> TestResult { //when let (actor, log) = given::a_repo_actor( repo_details, - git::repository::factory::mock(), + Box::new(git::repository::factory::mock()), given::a_forge(), given::a_server_actor(fs.as_real(), net.clone()), net.clone(), @@ -462,14 +465,14 @@ async fn should_reject_message_with_expired_token() -> TestResult { #[test_log::test(tokio::test)] // NOTE: failed then passed on retry: count = 6 -async fn should_send_validate_repo_when_retryable_error() -> TestResult { +async fn should_send_validate_repo_when_retryable_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); open_repository.expect_fetch().return_once(|| Ok(())); open_repository .expect_commit_log() - .return_once(|_, _| Err(git::commit::log::Error::Lock)); + .return_once(|_, _| Err(err!("Lock"))); //when let (addr, log) = when::start_actor_with_open_repository( @@ -487,7 +490,7 @@ async fn should_send_validate_repo_when_retryable_error() -> TestResult { } #[test_log::test(tokio::test)] -async fn should_send_notify_user_when_non_retryable_error() -> TestResult { +async fn should_send_notify_user_when_non_retryable_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); diff --git a/crates/cli/src/repo/tests/handlers/webhook_notification.rs b/crates/cli/src/repo/tests/handlers/webhook_notification.rs index d987944..417c888 100644 --- a/crates/cli/src/repo/tests/handlers/webhook_notification.rs +++ b/crates/cli/src/repo/tests/handlers/webhook_notification.rs @@ -1,12 +1,12 @@ use kxio::net::Net; -use crate::{repo::messages::WebhookNotification, tell}; +use crate::{err, repo::messages::WebhookNotification, tell, Result}; // use super::*; #[tokio::test] -async fn when_no_expected_auth_token_drop_notification() -> TestResult { +async fn when_no_expected_auth_token_drop_notification() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -41,7 +41,7 @@ async fn when_no_expected_auth_token_drop_notification() -> TestResult { } #[tokio::test] -async fn when_no_repo_config_drop_notification() -> TestResult { +async fn when_no_repo_config_drop_notification() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs).with_repo_config(None); @@ -76,7 +76,7 @@ async fn when_no_repo_config_drop_notification() -> TestResult { } #[tokio::test] -async fn when_message_auth_is_invalid_drop_notification() -> TestResult { +async fn when_message_auth_is_invalid_drop_notification() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -115,7 +115,7 @@ async fn when_message_auth_is_invalid_drop_notification() -> TestResult { } #[tokio::test] -async fn when_message_is_ignorable_drop_notification() -> TestResult { +async fn when_message_is_ignorable_drop_notification() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -158,7 +158,7 @@ async fn when_message_is_ignorable_drop_notification() -> TestResult { } #[tokio::test] -async fn when_message_is_not_a_push_drop_notification() -> TestResult { +async fn when_message_is_not_a_push_drop_notification() -> Result<()> { //given let fs = given::a_filesystem(); let repo_details = given::repo_details(&fs); @@ -201,7 +201,7 @@ async fn when_message_is_not_a_push_drop_notification() -> TestResult { } #[tokio::test] -async fn when_message_is_push_on_unknown_branch_drop_notification() -> TestResult { +async fn when_message_is_push_on_unknown_branch_drop_notification() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -249,7 +249,7 @@ async fn when_message_is_push_on_unknown_branch_drop_notification() -> TestResul } #[tokio::test] -async fn when_message_is_push_already_seen_commit_to_main() -> TestResult { +async fn when_message_is_push_already_seen_commit_to_main() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -299,7 +299,7 @@ async fn when_message_is_push_already_seen_commit_to_main() -> TestResult { } #[tokio::test] -async fn when_message_is_push_already_seen_commit_to_next() -> TestResult { +async fn when_message_is_push_already_seen_commit_to_next() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -349,7 +349,7 @@ async fn when_message_is_push_already_seen_commit_to_next() -> TestResult { } #[tokio::test] -async fn when_message_is_push_already_seen_commit_to_dev() -> TestResult { +async fn when_message_is_push_already_seen_commit_to_dev() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -399,7 +399,7 @@ async fn when_message_is_push_already_seen_commit_to_dev() -> TestResult { } #[tokio::test] -async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo() -> TestResult { +async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -441,7 +441,7 @@ async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo( let view = addr .ask(ExamineActor) .await - .map_err(|e| format!("examine actor: {e:?}"))?; + .map_err(|e| err!("examine actor: {e:?}"))?; assert_eq!(view.last_main_commit, Some(push_commit)); log.require_message_containing("send: ValidateRepo").await?; net.assert_no_unused_plans(); @@ -449,7 +449,7 @@ async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo( } #[tokio::test] -async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo() -> TestResult { +async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -491,7 +491,7 @@ async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo( let view = addr .ask(ExamineActor) .await - .map_err(|e| format!("examine actor: {e:?}"))?; + .map_err(|e| err!("examine actor: {e:?}"))?; assert_eq!(view.last_next_commit, Some(push_commit)); log.require_message_containing("send: ValidateRepo").await?; net.assert_no_unused_plans(); @@ -499,7 +499,7 @@ async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo( } #[tokio::test] -async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo() -> TestResult { +async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo() -> Result<()> { //given let fs = given::a_filesystem(); let repo_config = given::a_repo_config(); @@ -541,7 +541,7 @@ async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo() let view = addr .ask(ExamineActor) .await - .map_err(|e| format!("examine actor: {e:?}"))?; + .map_err(|e| err!("examine actor: {e:?}"))?; assert_eq!(view.last_dev_commit, Some(push_commit)); log.require_message_containing("send: ValidateRepo").await?; net.assert_no_unused_plans(); diff --git a/crates/cli/src/repo/tests/handlers/webhook_registered.rs b/crates/cli/src/repo/tests/handlers/webhook_registered.rs index fca374e..5021efb 100644 --- a/crates/cli/src/repo/tests/handlers/webhook_registered.rs +++ b/crates/cli/src/repo/tests/handlers/webhook_registered.rs @@ -1,10 +1,10 @@ -use crate::{repo::messages::WebhookRegistered, tell}; +use crate::{err, repo::messages::WebhookRegistered, tell, Result}; // use super::*; #[tokio::test] -async fn should_store_webhook_details() -> TestResult { +async fn should_store_webhook_details() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); @@ -27,14 +27,14 @@ async fn should_store_webhook_details() -> TestResult { let view = addr .ask(ExamineActor) .await - .map_err(|e| format!("examine actor: {e:?}"))?; + .map_err(|e| err!("examine actor: {e:?}"))?; assert_eq!(view.webhook_id, Some(webhook_id)); assert_eq!(view.webhook_auth, Some(webhook_auth)); Ok(()) } #[tokio::test] -async fn should_send_validate_repo_message() -> TestResult { +async fn should_send_validate_repo_message() -> Result<()> { //given let fs = given::a_filesystem(); let (open_repository, repo_details) = given::an_open_repository(&fs); diff --git a/crates/cli/src/repo/tests/load.rs b/crates/cli/src/repo/tests/load.rs index 924d15a..30a93b9 100644 --- a/crates/cli/src/repo/tests/load.rs +++ b/crates/cli/src/repo/tests/load.rs @@ -1,29 +1,26 @@ // use super::*; -use crate::git::file; use crate::repo::load; +use crate::{err, s, Result}; #[tokio::test] -async fn when_file_not_found_should_error() -> TestResult { +async fn when_file_not_found_should_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); open_repository .expect_read_file() - .returning(|_, _| Err(file::Error::FileNotFound)); + .returning(|_, _| Err(err!("FileNotFound"))); //when let_assert!(Err(err) = load::config_from_repository(&repo_details, &open_repository).await); //then - debug!("Got: {err:?}"); - assert!(matches!( - err, - load::Error::File(crate::git::file::Error::FileNotFound) - )); + tracing::debug!("Got: {err:?}"); + assert_eq!(err.to_string(), s!("FileNotFound")); Ok(()) } #[tokio::test] -async fn when_file_format_invalid_should_error() -> TestResult { +async fn when_file_format_invalid_should_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -34,13 +31,13 @@ async fn when_file_format_invalid_should_error() -> TestResult { //when let_assert!(Err(err) = load::config_from_repository(&repo_details, &open_repository).await); //then - debug!("Got: {err:?}"); - assert!(matches!(err, load::Error::Toml(_))); + tracing::debug!("Got: {err:?}"); + assert!(err.to_string().starts_with("TOML parse error at")); Ok(()) } #[tokio::test] -async fn when_main_branch_is_missing_should_error() -> TestResult { +async fn when_main_branch_is_missing_should_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -66,13 +63,13 @@ async fn when_main_branch_is_missing_should_error() -> TestResult { //when let_assert!(Err(err) = load::config_from_repository(&repo_details, &open_repository).await); //then - debug!("Got: {err:?}"); - assert!(matches!(err, load::Error::BranchNotFound(branch) if branch == main)); + tracing::debug!("Got: {err:?}"); + assert_eq!(err.to_string(), main.to_string()); Ok(()) } #[tokio::test] -async fn when_next_branch_is_missing_should_error() -> TestResult { +async fn when_next_branch_is_missing_should_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -98,13 +95,13 @@ async fn when_next_branch_is_missing_should_error() -> TestResult { //when let_assert!(Err(err) = load::config_from_repository(&repo_details, &open_repository).await); //then - debug!("Got: {err:?}"); - assert!(matches!(err, load::Error::BranchNotFound(branch) if branch == next)); + tracing::debug!("Got: {err:?}"); + assert_eq!(err.to_string(), next.to_string()); Ok(()) } #[tokio::test] -async fn when_dev_branch_is_missing_should_error() -> TestResult { +async fn when_dev_branch_is_missing_should_error() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -130,13 +127,13 @@ async fn when_dev_branch_is_missing_should_error() -> TestResult { //when let_assert!(Err(err) = load::config_from_repository(&repo_details, &open_repository).await); //then - debug!("Got: {err:?}"); - assert!(matches!(err, load::Error::BranchNotFound(branch) if branch == dev)); + tracing::debug!("Got: {err:?}"); + assert_eq!(err.to_string(), dev.to_string()); Ok(()) } #[tokio::test] -async fn when_valid_file_should_return_repo_config() -> TestResult { +async fn when_valid_file_should_return_repo_config() -> Result<()> { //given let fs = given::a_filesystem(); let (mut open_repository, repo_details) = given::an_open_repository(&fs); @@ -163,7 +160,7 @@ async fn when_valid_file_should_return_repo_config() -> TestResult { //when let_assert!(Ok(result) = load::config_from_repository(&repo_details, &open_repository).await); //then - debug!("Got: {result:?}"); + tracing::debug!("Got: {result:?}"); assert_eq!(result, repo_config); Ok(()) } diff --git a/crates/cli/src/repo/tests/mod.rs b/crates/cli/src/repo/tests/mod.rs index a4e1d97..0a430f4 100644 --- a/crates/cli/src/repo/tests/mod.rs +++ b/crates/cli/src/repo/tests/mod.rs @@ -5,9 +5,10 @@ use crate::{ messages::{CloneRepo, MessageToken}, ActorLog, RepoActor, }, + Result, }; -use git_next_core::{ +use crate::core::{ git::{ commit::Sha, repository::{ @@ -15,14 +16,14 @@ use git_next_core::{ open::{MockOpenRepositoryLike, OpenRepositoryLike}, Direction, }, - Commit, ForgeLike, Generation, MockForgeLike, RepoDetails, + Commit, ForgeLike, Generation, RepoDetails, }, - message, webhook::{forge_notification::Body, Push}, BranchName, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RegisteredWebhook, RemoteUrl, RepoAlias, RepoBranches, RepoConfig, RepoConfigSource, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId, }; +use crate::message; use assert2::let_assert; use kameo::{ @@ -30,7 +31,6 @@ use kameo::{ Reply, }; use mockall::predicate::eq; -use tracing::{debug, error}; use std::{ collections::{BTreeMap, HashMap}, @@ -38,8 +38,6 @@ use std::{ time::Duration, }; -type TestResult = Result<(), Box>; - mod branch; mod expect; pub mod given; @@ -55,9 +53,9 @@ impl ActorLog { pub async fn no_message_contains( &self, needle: impl AsRef + Send + std::fmt::Display, - ) -> TestResult { + ) -> Result<()> { if self.find_in_messages(needle.as_ref()).await? { - error!(?self, ""); + tracing::error!(?self, ""); panic!("found unexpected message: {needle}"); } Ok(()) @@ -66,26 +64,24 @@ impl ActorLog { pub async fn require_message_containing( &self, needle: impl AsRef + Send + std::fmt::Display, - ) -> TestResult { + ) -> Result<()> { if !self.find_in_messages(needle.as_ref()).await? { - error!(?self, ""); + tracing::error!(?self, ""); panic!("expected message not found: {needle}"); } Ok(()) } - async fn find_in_messages( - &self, - needle: impl AsRef + Send, - ) -> Result> { + async fn find_in_messages(&self, needle: impl AsRef + Send) -> Result { // Very short sleep to allow tests to get a chance to tick // This should be enough for most tests. - tokio::time::sleep(Duration::from_millis(5)).await; - let found = self - .read() - .await - .iter() - .any(|message| message.contains(needle.as_ref())); + tracing::debug!(" ! sleeping..."); + tokio::time::sleep(Duration::from_millis(50)).await; + tracing::debug!(" ! {}", needle.as_ref()); + let found = self.read().await.iter().any(|message| { + tracing::debug!(" ? {message}"); + message.contains(needle.as_ref()) + }); Ok(found) } } diff --git a/crates/cli/src/repo/tests/when.rs b/crates/cli/src/repo/tests/when.rs index 350a8e5..109b7f1 100644 --- a/crates/cli/src/repo/tests/when.rs +++ b/crates/cli/src/repo/tests/when.rs @@ -31,7 +31,8 @@ pub fn start_actor_with_open_repository( let fs = given::a_filesystem(); let net: Net = given::a_network().into(); let server_actor_ref: ActorRef = given::a_server_actor(fs.as_real(), net.clone()); - let (actor, log) = given::a_repo_actor(repo_details, mock(), forge, server_actor_ref, net); + let (actor, log) = + given::a_repo_actor(repo_details, Box::new(mock()), forge, server_actor_ref, net); let actor = actor.with_open_repository(Some(open_repository)); (kameo::spawn(actor), log) } diff --git a/crates/cli/src/root.rs b/crates/cli/src/root.rs index 94fca5c..4c2c30b 100644 --- a/crates/cli/src/root.rs +++ b/crates/cli/src/root.rs @@ -4,9 +4,10 @@ use std::time::Duration; +use crate::core::git::RepositoryFactory; +use crate::s; use color_eyre::Result; use derive_more::derive::Constructor; -use git_next_core::{git::RepositoryFactory, s}; use kameo::{ actor::{pubsub::PubSub, ActorRef}, mailbox::unbounded::UnboundedMailbox, diff --git a/crates/cli/src/server/actor/handlers/file_updated.rs b/crates/cli/src/server/actor/handlers/file_updated.rs index 18a5d37..3466e5b 100644 --- a/crates/cli/src/server/actor/handlers/file_updated.rs +++ b/crates/cli/src/server/actor/handlers/file_updated.rs @@ -2,7 +2,7 @@ use color_eyre::Result; use kameo::message::{Context, Message}; -use git_next_core::server::AppConfig; +use crate::core::server::AppConfig; use tracing::debug; use crate::{ diff --git a/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs b/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs index bc60481..ad33c51 100644 --- a/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs +++ b/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs @@ -5,7 +5,7 @@ use kameo::{ message::{Context, Message}, }; -use git_next_core::{ForgeAlias, RepoAlias}; +use crate::core::{ForgeAlias, RepoAlias}; use crate::{ alerts::messages::UpdateShout, diff --git a/crates/cli/src/server/actor/messages.rs b/crates/cli/src/server/actor/messages.rs index 3b5e165..a1f6a56 100644 --- a/crates/cli/src/server/actor/messages.rs +++ b/crates/cli/src/server/actor/messages.rs @@ -4,13 +4,13 @@ use std::net::SocketAddr; use derive_more::Constructor; use tokio::sync::mpsc::Sender; -use git_next_core::{ +use crate::core::{ git::{self, forge::commit::Status, graph::Log, Commit}, - message, server::{AppConfig, Storage}, webhook::{push::Branch, Push}, ForgeAlias, RepoAlias, RepoBranches, RepoConfig, }; +use crate::message; // receive server config message!( diff --git a/crates/cli/src/server/actor/mod.rs b/crates/cli/src/server/actor/mod.rs index 9cdbf66..56c8b1a 100644 --- a/crates/cli/src/server/actor/mod.rs +++ b/crates/cli/src/server/actor/mod.rs @@ -10,11 +10,13 @@ use kxio::{fs::FileSystem, net::Net}; use tokio::sync::mpsc::Sender; use tracing::{error, instrument, warn}; -use git_next_core::{ - git::{repository::factory::RepositoryFactory, Generation, RepoDetails}, - s, - server::{self, AppConfig, ListenUrl, Storage}, - ForgeAlias, ForgeConfig, GitDir, RepoAlias, ServerRepoConfig, StoragePathType, +use crate::{ + core::{ + git::{repository::factory::RepositoryFactory, Generation, RepoDetails}, + server::{AppConfig, ListenUrl, Storage}, + ForgeAlias, ForgeConfig, GitDir, RepoAlias, ServerRepoConfig, StoragePathType, + }, + err, Result, }; use crate::{ @@ -22,7 +24,7 @@ use crate::{ forge::Forge, on_actor_link_died, on_actor_panic, on_actor_start, on_actor_stop, repo::RepoActor, - spawn, tell, + s, spawn, tell, webhook::{router::WebhookRouterActor, WebhookActor}, MessageBus, }; @@ -35,26 +37,6 @@ mod tests; mod handlers; pub mod messages; -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - #[display("Failed to create data directories")] - FailedToCreateDataDirectory(kxio::fs::Error), - - #[display("The forge data path is not a directory: {path:?}")] - ForgeDirIsNotDirectory { - path: PathBuf, - }, - - Config(server::Error), - - Io(std::io::Error), - - General(String), -} -impl std::error::Error for Error {} - -type Result = core::result::Result; - #[allow(clippy::module_name_repetitions)] #[derive(derive_with::With)] #[with(message_log)] @@ -157,7 +139,7 @@ impl ServerActor { let path_handle = self.fs.path(&path); if path_handle.exists()? { if !path_handle.is_dir()? { - return Err(Error::ForgeDirIsNotDirectory { path }); + return Err(err!("ForgeDirIsNotDirectory {}", path.display())); } } else { tracing::info!(%forge_name, ?path_handle, "creating storage"); @@ -285,7 +267,7 @@ impl ServerActor { if let Some(t) = self.shutdown_trigger.take() { t.send(message) .await - .map_err(|e| format!("failed sending shutdown trigger: {e:?}"))?; + .map_err(|e| err!("failed sending shutdown trigger: {e:?}"))?; } Ok(()) } @@ -309,7 +291,7 @@ impl ServerActor { } if cfg!(not(test)) { tell!(ctx.actor_ref(), msg) - .map_err(|e| format!("failed sending: {log_message}: {e:?}"))?; + .map_err(|e| err!("failed sending: {log_message}: {e:?}"))?; } Ok(()) } diff --git a/crates/cli/src/server/actor/tests/receive_app_config.rs b/crates/cli/src/server/actor/tests/receive_app_config.rs index d690845..a25cc55 100644 --- a/crates/cli/src/server/actor/tests/receive_app_config.rs +++ b/crates/cli/src/server/actor/tests/receive_app_config.rs @@ -6,7 +6,7 @@ use std::{ use kameo::actor::pubsub::PubSub; -use git_next_core::{ +use crate::core::{ git, server::{AppConfig, Http, Listen, ListenUrl, Shout, Storage}, }; @@ -37,7 +37,7 @@ async fn when_webhook_url_has_trailing_slash_should_not_send() -> TestResult { mock_net.clone().into(), alerts, file_update_subs, - repo, + Box::new(repo), duration, ); diff --git a/crates/cli/src/server/mod.rs b/crates/cli/src/server/mod.rs index 85362b5..ad4003e 100644 --- a/crates/cli/src/server/mod.rs +++ b/crates/cli/src/server/mod.rs @@ -6,7 +6,7 @@ use kxio::{fs::FileSystem, net::Net}; use tokio::sync::RwLock; use tracing::info; -use git_next_core::git::RepositoryFactory; +use crate::core::git::RepositoryFactory; use crate::{root::RootActor, tell}; diff --git a/crates/cli/src/server/tests.rs b/crates/cli/src/server/tests.rs index f1301cf..877d343 100644 --- a/crates/cli/src/server/tests.rs +++ b/crates/cli/src/server/tests.rs @@ -1,15 +1,16 @@ // -use assert2::let_assert; -use git_next_core::{ - self as core, - git::{self, repository::Direction, validation::remotes::validate_default_remotes}, - ApiToken, ForgeType, GitDir, Hostname, RepoBranches, RepoConfig, RepoConfigSource, RepoPath, - StoragePathType, User, +use crate::{ + core::{ + self as core, + git::{self, repository::Direction, validation::remotes::validate_default_remotes}, + ApiToken, ForgeType, GitDir, Hostname, RepoBranches, RepoConfig, RepoConfigSource, + RepoPath, StoragePathType, User, + }, + Result, }; +use assert2::let_assert; use secrecy::SecretString; -type Result = std::result::Result>; - #[test] fn test_repo_config_load() -> Result<()> { let toml = r#"[branches] diff --git a/crates/cli/src/tests.rs b/crates/cli/src/tests.rs index fab2935..ff7336a 100644 --- a/crates/cli/src/tests.rs +++ b/crates/cli/src/tests.rs @@ -1,9 +1,9 @@ -type TestResult = Result<(), Box>; - +// mod init { - use super::*; + use crate::Result; + #[test] - fn should_not_update_file_if_it_exists() -> TestResult { + fn should_not_update_file_if_it_exists() -> Result<()> { let fs = kxio::fs::temp()?; let file = fs.base().join(".git-next.toml"); fs.file(&file).write("contents")?; @@ -20,7 +20,7 @@ mod init { } #[test] - fn should_create_default_file_if_not_exists() -> TestResult { + fn should_create_default_file_if_not_exists() -> Result<()> { let fs = kxio::fs::temp()?; crate::init::run(&fs)?; @@ -38,3 +38,28 @@ mod init { Ok(()) } } + +mod errors { + // all errors should be Send + const fn is_send() {} + + #[test] + const fn core_git_file_error_is_send() { + is_send::(); + } + + #[test] + const fn core_git_repository_error_is_send() { + is_send::(); + } + + #[test] + const fn core_git_forge_webhook_error_is_send() { + is_send::(); + } + + #[test] + const fn core_git_validation_remotes_error_is_send() { + is_send::(); + } +} diff --git a/crates/cli/src/tui/actor/messages.rs b/crates/cli/src/tui/actor/messages.rs index b47cbc8..fd1f123 100644 --- a/crates/cli/src/tui/actor/messages.rs +++ b/crates/cli/src/tui/actor/messages.rs @@ -1,4 +1,4 @@ // -use git_next_core::message; +use crate::message; message!(Tick => std::io::Result<()>, "Update the TUI"); diff --git a/crates/cli/src/tui/actor/model.rs b/crates/cli/src/tui/actor/model.rs index 1ef6188..4cddc59 100644 --- a/crates/cli/src/tui/actor/model.rs +++ b/crates/cli/src/tui/actor/model.rs @@ -17,10 +17,11 @@ use ratatui::{ use tracing::info; use tui_scrollview::ScrollViewState; -use git_next_core::{ +use crate::core::{ git::{self, graph::Log, Commit}, - newtype, s, ForgeAlias, RepoAlias, RepoBranches, + ForgeAlias, RepoAlias, RepoBranches, }; +use crate::{newtype, s}; use crate::{ server::actor::messages::ValidAppConfig, diff --git a/crates/cli/src/tui/actor/tests.rs b/crates/cli/src/tui/actor/tests.rs index 66d6f54..d5983ac 100644 --- a/crates/cli/src/tui/actor/tests.rs +++ b/crates/cli/src/tui/actor/tests.rs @@ -1,7 +1,7 @@ // mod model { mod repo_state { - use git_next_core::{git::graph::Log, RepoBranches}; + use crate::core::{git::graph::Log, RepoBranches}; use ratatui::style::Style; use crate::{ diff --git a/crates/cli/src/tui/components/configured_app.rs b/crates/cli/src/tui/components/configured_app.rs index 3230ec5..3cee33b 100644 --- a/crates/cli/src/tui/components/configured_app.rs +++ b/crates/cli/src/tui/components/configured_app.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use git_next_core::ForgeAlias; +use crate::core::ForgeAlias; use ratatui::{ buffer::Buffer, layout::{Direction, Layout, Rect, Size}, diff --git a/crates/cli/src/tui/components/forge/collapsed.rs b/crates/cli/src/tui/components/forge/collapsed.rs index 707054f..99d16e3 100644 --- a/crates/cli/src/tui/components/forge/collapsed.rs +++ b/crates/cli/src/tui/components/forge/collapsed.rs @@ -1,5 +1,5 @@ // -use git_next_core::ForgeAlias; +use crate::core::ForgeAlias; use ratatui::{buffer::Buffer, layout::Rect, text::Text, widgets::Widget}; use crate::tui::components::HeightContraintLength; diff --git a/crates/cli/src/tui/components/forge/expanded.rs b/crates/cli/src/tui/components/forge/expanded.rs index 143d280..d345996 100644 --- a/crates/cli/src/tui/components/forge/expanded.rs +++ b/crates/cli/src/tui/components/forge/expanded.rs @@ -1,7 +1,7 @@ // use std::collections::BTreeMap; -use git_next_core::{ForgeAlias, RepoAlias}; +use crate::core::{ForgeAlias, RepoAlias}; use ratatui::{ buffer::Buffer, layout::{Alignment, Direction, Layout, Rect}, diff --git a/crates/cli/src/tui/components/forge/mod.rs b/crates/cli/src/tui/components/forge/mod.rs index dcf350d..795d793 100644 --- a/crates/cli/src/tui/components/forge/mod.rs +++ b/crates/cli/src/tui/components/forge/mod.rs @@ -4,9 +4,9 @@ mod expanded; use std::collections::BTreeMap; +use crate::core::{ForgeAlias, RepoAlias}; use collapsed::CollapsedForgeWidget; use expanded::ExpandedForgeWidget; -use git_next_core::{ForgeAlias, RepoAlias}; use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use crate::tui::actor::{RepoState, UIRepoFilter, ViewState}; diff --git a/crates/cli/src/tui/components/history.rs b/crates/cli/src/tui/components/history.rs index 386d8d9..96afee2 100644 --- a/crates/cli/src/tui/components/history.rs +++ b/crates/cli/src/tui/components/history.rs @@ -1,5 +1,5 @@ // -use git_next_core::git::graph::Log; +use crate::core::git::graph::Log; use ratatui::{ style::{Color, Style}, text::{Line, Span, Text}, diff --git a/crates/cli/src/tui/components/repo/identity.rs b/crates/cli/src/tui/components/repo/identity.rs index ce20e41..6bf5085 100644 --- a/crates/cli/src/tui/components/repo/identity.rs +++ b/crates/cli/src/tui/components/repo/identity.rs @@ -1,7 +1,7 @@ use std::string::ToString; // -use git_next_core::{RepoAlias, RepoBranches}; +use crate::core::{RepoAlias, RepoBranches}; use ratatui::{ layout::Alignment, style::{Color, Style, Stylize as _}, diff --git a/crates/cli/src/tui/components/repo/mod.rs b/crates/cli/src/tui/components/repo/mod.rs index 5eacd0a..7bd3c60 100644 --- a/crates/cli/src/tui/components/repo/mod.rs +++ b/crates/cli/src/tui/components/repo/mod.rs @@ -3,7 +3,7 @@ mod identity; use std::string::String; -use git_next_core::{RepoAlias, RepoBranches}; +use crate::core::{RepoAlias, RepoBranches}; use crate::{ git, diff --git a/crates/cli/src/webhook/router.rs b/crates/cli/src/webhook/router.rs index ae254dc..11524c5 100644 --- a/crates/cli/src/webhook/router.rs +++ b/crates/cli/src/webhook/router.rs @@ -9,7 +9,7 @@ use kameo::{ }; use tracing::{debug, warn}; -use git_next_core::{ForgeAlias, RepoAlias}; +use crate::core::{ForgeAlias, RepoAlias}; use crate::{ repo::{messages::WebhookNotification, RepoActor}, diff --git a/crates/cli/src/webhook/server.rs b/crates/cli/src/webhook/server.rs index 577db6f..e21a26a 100644 --- a/crates/cli/src/webhook/server.rs +++ b/crates/cli/src/webhook/server.rs @@ -5,7 +5,7 @@ use color_eyre::Result; use kameo::actor::ActorRef; use tracing::{info, warn}; -use git_next_core::{webhook, ForgeAlias, ForgeNotification, RepoAlias}; +use crate::core::{webhook, ForgeAlias, ForgeNotification, RepoAlias}; use crate::{repo::messages::WebhookNotification, tell}; diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml deleted file mode 100644 index 46e73b4..0000000 --- a/crates/core/Cargo.toml +++ /dev/null @@ -1,65 +0,0 @@ -[package] -name = "git-next-core" -version = { workspace = true } -edition = { workspace = true } -license = { workspace = true } -repository = { workspace = true } -description = "core for git-next, the trunk-based development manager" - -[lints.clippy] -nursery = { level = "warn", priority = -1 } -pedantic = { level = "warn", priority = -1 } -unwrap_used = "warn" -expect_used = "warn" - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] } - -[features] -default = ["forgejo", "github"] -forgejo = [] -github = [] - -[dependencies] -# logging -tracing = { workspace = true } - -# fs/network -kxio = { 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 } -async-trait = { workspace = true } - -# Webhooks -ulid = { workspace = true } -time = { workspace = true } - -# boilerplate -derive_more = { workspace = true } -derive-with = { workspace = true } -thiserror = { workspace = true } -pike = { workspace = true } - -# TOML parsing -serde_json = { workspace = true } - -mockall = { workspace = true } - -#iters -take-until = { workspace = true } - -[dev-dependencies] -# Testing -assert2 = { workspace = true } -rand = { workspace = true } -test-log = { workspace = true } -pretty_assertions = { workspace = true } diff --git a/crates/core/README.md b/crates/core/README.md deleted file mode 100644 index ddc70e2..0000000 --- a/crates/core/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# git-next - -## Trunk-based developement manager. - -`git-next` is a combined server and command-line tool that enables trunk-based -development workflows where each commit must pass CI before being included in -the main branch. - -See [git-next](https://crates.io/crates/git-next) for more information. diff --git a/crates/core/src/git/fetch.rs b/crates/core/src/git/fetch.rs deleted file mode 100644 index a7443e6..0000000 --- a/crates/core/src/git/fetch.rs +++ /dev/null @@ -1,34 +0,0 @@ -// -pub type Result = core::result::Result; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("io")] - Io(#[from] std::io::Error), - - #[error("unable to open repo: {0}")] - UnableToOpenRepo(String), - - #[error("no remote found")] - NoFetchRemoteFound, - - #[error("remote connect: {0}")] - Connect(String), - - #[error("prepare: {0}")] - Prepare(String), - - #[error("receive: {0}")] - Receive(String), - - #[error("lock")] - Lock, - - #[cfg(test)] - #[error("expected failure in test")] - TestFailureExpected, - - #[cfg(test)] - #[error("test")] - TestResult(#[from] Box), -} diff --git a/crates/core/src/git/repository/open/tests/read_file.rs b/crates/core/src/git/repository/open/tests/read_file.rs deleted file mode 100644 index d29274a..0000000 --- a/crates/core/src/git/repository/open/tests/read_file.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::ops::Deref as _; - -// -use super::*; - -#[test] -// assumes running in the git-next repo which should have main, next and dev as remote branches -fn should_return_file() -> TestResult { - let_assert!(Ok(fs) = kxio::fs::temp()); - let repo_config = given::a_repo_config(); - let file_name = given::a_pathbuf(); - let contents = given::a_name(); - let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let forge_details = given::forge_details(); - - let test_repository = git::repository::test(fs.deref().clone(), forge_details); - let_assert!(Ok(open_repository) = test_repository.open(&gitdir)); - then::commit_named_file_to_branch( - &file_name, - &contents, - &fs, - &gitdir, - &repo_config.branches().main(), - )?; - // then::create_a_commit_on_branch(&fs, &gitdir, &repo_config.branches().main())?; - let_assert!( - Ok(result) = open_repository.read_file(&repo_config.branches().main(), &file_name), - "read file" - ); - assert_eq!(result, contents); - Ok(()) -} - -#[test] -// assumes running in the git-next repo which should have main, next and dev as remote branches -fn should_error_on_missing_file() -> TestResult { - let_assert!(Ok(fs) = kxio::fs::temp()); - let gitdir = GitDir::new(fs.base().to_path_buf(), StoragePathType::Internal); - let forge_details = given::forge_details(); - let test_repository = git::repository::test(fs.deref().clone(), forge_details); - let_assert!(Ok(open_repository) = test_repository.open(&gitdir)); - let repo_config = &given::a_repo_config(); - let branches = repo_config.branches(); - then::create_a_commit_on_branch(&fs, &gitdir, &branches.dev())?; - let_assert!( - Err(err) = open_repository.read_file(&branches.dev(), &given::a_pathbuf()), - "read file" - ); - eprintln!("err: {err:#?}"); - assert!(matches!(err, git::file::Error::FileNotFound)); - Ok(()) -} diff --git a/justfile b/justfile index 7568e21..1576884 100644 --- a/justfile +++ b/justfile @@ -3,6 +3,7 @@ build: set -e cargo fmt cargo fmt --check + forgejo-todo-checker --workspace $PWD --site https://git.kemitix.net --repo kemitix/git-next cargo machete cargo hack clippy cargo hack build @@ -11,6 +12,20 @@ build: # cargo test --example get # cargo mutants --jobs 4 +ci: + #!/usr/bin/env bash + set -e + cargo fmt + cargo fmt --check + forgejo-todo-checker --workspace $PWD --site https://git.kemitix.net --repo kemitix/git-next + cargo machete + cargo hack --feature-powerset clippy + cargo hack --feature-powerset build + cargo hack --feature-powerset test + cargo doc + # cargo test --example get + # cargo mutants --jobs 4 + test-in-docker: docker run --rm -u $(id -u):$(id -g) -v ${PWD}:/app/ git.kemitix.net/kemitix/rust:latest cargo test