refactor: merge core crate into cli crate
This commit is contained in:
parent
c8cc45ca7f
commit
e5a5e508ff
160 changed files with 888 additions and 1113 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
use git_next_core::{
|
||||
use crate::core::{
|
||||
git::UserNotification,
|
||||
server::{EmailConfig, SmtpConfig},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
use git_next_core::git::UserNotification;
|
||||
use crate::core::git::UserNotification;
|
||||
use tracing::info;
|
||||
|
||||
use std::{
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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}"))
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
use crate::config::{WebhookAuth, WebhookId};
|
||||
use crate::core::config::{WebhookAuth, WebhookId};
|
||||
|
||||
#[derive(Debug, derive_more::Constructor)]
|
||||
pub struct RegisteredWebhook {
|
|
@ -1,4 +1,4 @@
|
|||
use crate::config::BranchName;
|
||||
use crate::core::config::BranchName;
|
||||
|
||||
/// Mapped from `.git-next.toml` file at `branches`
|
||||
#[derive(
|
|
@ -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
|
|
@ -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,
|
|
@ -2,7 +2,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use crate::{
|
||||
config::{
|
||||
core::config::{
|
||||
git_dir::StoragePathType, BranchName, GitDir, RepoBranches, RepoConfig, RepoConfigSource,
|
||||
RepoPath,
|
||||
},
|
|
@ -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 {
|
|
@ -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)]
|
|
@ -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)]
|
|
@ -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>> {
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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),
|
||||
|
|
@ -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;
|
|
@ -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,
|
|
@ -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)]
|
|
@ -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;
|
||||
|
|
@ -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,
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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)]
|
|
@ -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>,
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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 {
|
|
@ -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(
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Deref as _;
|
||||
|
||||
use crate::CommitCount;
|
||||
use crate::core::CommitCount;
|
||||
|
||||
//
|
||||
use super::*;
|
|
@ -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;
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -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!()
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
use crate::{
|
||||
core::{ApiToken, GitDir, StoragePathType},
|
||||
git::{self, tests::given},
|
||||
ApiToken, GitDir, StoragePathType,
|
||||
};
|
||||
|
||||
use assert2::let_assert;
|
|
@ -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())
|
|
@ -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;
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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),
|
||||
|
|
@ -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!(
|
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
use git_next_core::{git, webhook, BranchName, WebhookId};
|
||||
use crate::core::{git, webhook, BranchName, WebhookId};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
use git_next_core::{
|
||||
use crate::core::{
|
||||
git::{self, forge::webhook::Error},
|
||||
server::RepoListenUrl,
|
||||
RegisteredWebhook, WebhookAuth, WebhookId,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
use git_next_core::{git, WebhookId};
|
||||
use crate::core::{git, WebhookId};
|
||||
|
||||
use kxio::net::Net;
|
||||
use secrecy::ExposeSecret as _;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue