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

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

32
Cargo.lock generated
View file

@ -1070,7 +1070,8 @@ dependencies = [
"derive_more",
"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"

View file

@ -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"] }

View file

@ -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 }

View file

@ -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);

View file

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

View file

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

View file

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

View file

@ -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};

View file

@ -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};

View file

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

View file

@ -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}"))
}

View file

@ -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;

View file

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

View file

@ -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;

View file

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

View file

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

View file

@ -1,4 +1,4 @@
use crate::config::{RepoBranches, RepoConfigSource};
use crate::core::config::{RepoBranches, RepoConfigSource};
/// Mapped from `.git-next.toml` file in target repo
/// Is also derived from the optional parameters in `git-next-server.toml` at

View file

@ -15,24 +15,10 @@ use serde::{Deserialize, Serialize};
use tracing::info;
use 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<T> = core::result::Result<T, Error>;
/// Mapped from the `git-next-server.toml` file
#[derive(
Clone,

View file

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

View file

@ -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<T> = core::result::Result<T, Box<dyn std::error::Error>>;
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 {

View file

@ -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)]

View file

@ -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)]

View file

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

View file

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

View file

@ -1,38 +1,36 @@
//
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
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),

View file

@ -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;

View file

@ -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<dyn ForgeLike>;
#[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<git::forge::commit::Status>;
// Lists all the webhooks
#[cfg(test)]
async fn list_webhooks(
&self,
repo_listen_url: &RepoListenUrl,

View file

@ -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)]

View file

@ -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;

View file

@ -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<RepoConfig>,
gitdir: GitDir,
forge: super::ForgeDetails,
repo_config: Option<super::RepoConfig>,
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,
}

View file

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

View file

@ -1,12 +1,16 @@
//
use crate::core::pike;
use crate::s;
use crate::{
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

View file

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

View file

@ -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<OpenRepository>;
fn open(&self, gitdir: &crate::core::GitDir) -> Result<open::OpenRepository>;
/// 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<OpenRepository>;
// /// 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<open::OpenRepository>;
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@ -98,39 +98,35 @@ pub type Result<T> = core::result::Result<T, Error>;
#[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<RemoteUrl>,

View file

@ -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<otest::OnFetch>,
on_push: Vec<otest::OnPush>,
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<dyn OpenRepositoryLike>;
// /// Creates a clone of the `OpenRepositoryLike`.
// #[cfg(test)]
// fn duplicate(&self) -> Box<dyn OpenRepositoryLike>;
/// 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<Vec<BranchName>>;
fn remote_branches(&self) -> Result<Vec<BranchName>>;
fn find_default_remote(&self, direction: Direction) -> Option<RemoteUrl>;
/// 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<Vec<git::Commit>>;
) -> Result<Vec<git::Commit>>;
/// 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<String>;
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result<String>;
}
#[cfg(test)]
pub(crate) fn mock() -> Box<MockOpenRepositoryLike> {
pub fn mock() -> Box<MockOpenRepositoryLike> {
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,
}
}

View file

@ -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<Vec<BranchName>> {
fn remote_branches(&self) -> Result<Vec<BranchName>> {
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::<Vec<_>>()
})?)
})
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::<Vec<_>>()
})?)
})
})?;
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<Vec<git::Commit>, git::commit::log::Error> {
) -> Result<Vec<git::Commit>> {
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<String> {
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result<String> {
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<dyn OpenRepositoryLike> {
Box::new(self.clone())
}
// #[cfg(test)]
// fn duplicate(&self) -> Box<dyn super::OpenRepositoryLike> {
// 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 {

View file

@ -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<Vec<BranchName>> {
fn remote_branches(&self) -> Result<Vec<BranchName>> {
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<Vec<git::Commit>> {
) -> Result<Vec<git::Commit>> {
self.real.commit_log(branch_name, find_commits)
}
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String> {
fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> Result<String> {
self.real.read_file(branch_name, file_name)
}
fn duplicate(&self) -> Box<dyn OpenRepositoryLike> {
Box::new(self.clone())
}
// fn duplicate(&self) -> Box<dyn super::OpenRepositoryLike> {
// Box::new(self.clone())
// }
}
impl TestOpenRepository {
pub(crate) fn new(

View file

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

View file

@ -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<dyn std::error::Error>>;
// type TestResult = Result<(), Box<dyn std::error::Error>>;
type TestResult = color_eyre::Result<()>;
mod commit_log;
mod fetch;

View file

@ -0,0 +1 @@

View file

@ -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<OpenRepository> {
todo!()
}
}

View file

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

View file

@ -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<dyn std::error::Error>>;
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<std::process::Output, std::io::Error>) -> TestResult {
fn exec(label: &str, output: Result<std::process::Output, std::io::Error>) -> 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<git::commit::Sha, Box<dyn std::error::Error>> {
) -> color_eyre::Result<git::commit::Sha> {
let main_ref = fs
.base()
.join(gitdir.to_path_buf())

View file

@ -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;

View file

@ -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<T> = core::result::Result<T, Error>;
#[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<git::commit::Histories> {
) -> Result<git::commit::Histories> {
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<T> = std::result::Result<T, PositionsError>;
#[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<git::fetch::Error> for Error {
fn from(value: git::fetch::Error) -> Self {
Self::Retryable(s!(value))
}
}
impl From<git::commit::log::Error> for Error {
fn from(value: git::commit::log::Error) -> Self {
Self::Retryable(s!(value))
}
}

View file

@ -1,7 +1,8 @@
//
use crate::{
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),

View file

@ -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!(

View file

@ -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);
};
}

View file

@ -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())
}

View file

@ -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,

View file

@ -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<dyn ForgeLike> {
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);

View file

@ -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")

View file

@ -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<dyn git::ForgeLike> {
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,

View file

@ -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 {

View file

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

View file

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

View file

@ -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,

View file

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

View file

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

View file

@ -1,6 +1,6 @@
//
use crate::core::git::{self, forge::commit::Status};
use crate::forges::github::{self as github, GithubState};
use git_next_core::git::{self, forge::commit::Status};
use github::GithubStatus;
/// Checks the results of any (e.g. CI) status checks for the commit.

View file

@ -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<dyn git::ForgeLike> {
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,

View file

@ -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(),

View file

@ -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<sha2::Sha256>;
@ -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<String> {
let payload = body.as_str();
let mut hmac = HmacSha256::new_from_slice(webhook_auth.to_string().as_bytes()).ok()?;

View file

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

View file

@ -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;

View file

@ -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,

View file

@ -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

View file

@ -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(

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