git-next/crates/git/src/validate.rs

75 lines
2.4 KiB
Rust
Raw Normal View History

use std::ops::Deref as _;
use git_next_config::{Hostname, RepoPath};
use gix::remote::Direction;
use tracing::info;
use super::{GitRemote, RepoDetails, Repository};
#[tracing::instrument(skip_all)]
pub fn validate(repository: &Repository, repo_details: &RepoDetails) -> Result<()> {
let git_remote = repo_details.git_remote();
let push_remote = find_default_remote(repository, Direction::Push)?;
let fetch_remote = find_default_remote(repository, Direction::Fetch)?;
info!(config = %git_remote, push = %push_remote, fetch = %fetch_remote, "Check remotes match");
if git_remote != push_remote {
return Err(Error::MismatchDefaultPushRemote {
found: push_remote,
expected: git_remote,
});
}
if git_remote != fetch_remote {
return Err(Error::MismatchDefaultFetchRemote {
found: fetch_remote,
expected: git_remote,
});
}
Ok(())
}
#[tracing::instrument(skip_all, fields(?direction))]
pub fn find_default_remote(
repository: &Repository,
direction: gix::remote::Direction,
) -> Result<GitRemote> {
let repository = repository.deref().to_thread_local();
let Some(Ok(remote)) = repository.find_default_remote(gix::remote::Direction::Push) else {
return Err(Error::NoDefaultPushRemote);
};
let Some(url) = remote.url(direction) else {
return Err(Error::NoUrlForDefaultPushRemote);
};
let Some(host) = url.host() else {
return Err(Error::NoHostnameForDefaultPushRemote);
};
let path = url.path.to_string();
let path = path.strip_prefix('/').map_or(path.as_str(), |path| path);
let path = path.strip_suffix(".git").map_or(path, |path| path);
info!(%host, %path, "found");
Ok(GitRemote::new(
2024-05-14 07:59:31 +01:00
Hostname::new(host),
RepoPath::new(path.to_string()),
))
}
type Result<T> = core::result::Result<T, Error>;
2024-05-14 16:28:17 +01:00
#[derive(Debug, derive_more::Display)]
pub enum Error {
NoDefaultPushRemote,
NoUrlForDefaultPushRemote,
NoHostnameForDefaultPushRemote,
UnableToOpenRepo(String),
Io(std::io::Error),
2024-05-14 16:28:17 +01:00
#[display("MismatchDefaultPushRemote(found: {found}, expected: {expected})")]
MismatchDefaultPushRemote {
found: GitRemote,
expected: GitRemote,
},
2024-05-14 16:28:17 +01:00
#[display("MismatchDefaultFetchRemote(found: {found}, expected: {expected})")]
MismatchDefaultFetchRemote {
found: GitRemote,
expected: GitRemote,
},
}
impl std::error::Error for Error {}