Use repository Git remotes and SSH config
Some checks failed
Dependency security audit / rustsec (push) Has been cancelled
Some checks failed
Dependency security audit / rustsec (push) Has been cancelled
This commit is contained in:
@@ -13,7 +13,11 @@ use std::{
|
||||
|
||||
use cap_std::{ambient_authority, fs::Dir};
|
||||
use cap_tempfile::TempFile;
|
||||
#[cfg(not(any(target_os = "ios", target_os = "watchos")))]
|
||||
use gix::bstr::ByteSlice as _;
|
||||
use serde::Deserialize;
|
||||
#[cfg(not(any(target_os = "ios", target_os = "watchos")))]
|
||||
use sha2::{Digest as _, Sha256};
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
@@ -1694,7 +1698,14 @@ fn validate_config(
|
||||
});
|
||||
}
|
||||
};
|
||||
let git_remotes = validate_remotes(raw.git.remotes, Some(base))?;
|
||||
let configured_git_remotes = raw.git.remotes;
|
||||
#[cfg(not(any(target_os = "ios", target_os = "watchos")))]
|
||||
let git_remotes = match repository_git_remotes(&vault)? {
|
||||
Some(remotes) => remotes,
|
||||
None => validate_remotes(configured_git_remotes, Some(base))?,
|
||||
};
|
||||
#[cfg(any(target_os = "ios", target_os = "watchos"))]
|
||||
let git_remotes = validate_remotes(configured_git_remotes, Some(base))?;
|
||||
|
||||
Ok(Config {
|
||||
source,
|
||||
@@ -1715,6 +1726,75 @@ fn validate_config(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "ios", target_os = "watchos")))]
|
||||
fn repository_git_remotes(vault: &Path) -> Result<Option<Vec<GitRemote>>, ConfigError> {
|
||||
let path = vault.join(".git/config");
|
||||
if !path.is_file() {
|
||||
return Ok(None);
|
||||
}
|
||||
let config =
|
||||
gix_config::File::from_path_no_includes(path, gix_config::Source::Local).map_err(|_| {
|
||||
ConfigError::InvalidField {
|
||||
field: "git.repository_remotes",
|
||||
}
|
||||
})?;
|
||||
let mut remotes = Vec::new();
|
||||
if let Some(sections) = config.sections_by_name("remote") {
|
||||
for section in sections {
|
||||
let name = section
|
||||
.header()
|
||||
.subsection_name()
|
||||
.and_then(|name| name.to_str().ok())
|
||||
.ok_or(ConfigError::InvalidField {
|
||||
field: "git.repository_remotes",
|
||||
})?;
|
||||
let url = config
|
||||
.raw_value_by("remote", Some(name.into()), "url")
|
||||
.ok()
|
||||
.and_then(|url| url.to_str().ok().map(str::to_owned))
|
||||
.ok_or(ConfigError::InvalidRemoteUrl {
|
||||
name: name.to_owned(),
|
||||
})?;
|
||||
let endpoint =
|
||||
RemoteEndpoint::parse(&url).map_err(|_| ConfigError::InvalidRemoteUrl {
|
||||
name: name.to_owned(),
|
||||
})?;
|
||||
let remote = match endpoint {
|
||||
RemoteEndpoint::Https(ref endpoint) => GitRemote::https(
|
||||
name,
|
||||
&url,
|
||||
stable_identifier(
|
||||
"server",
|
||||
format!(
|
||||
"{}://{}:{}",
|
||||
endpoint.scheme(),
|
||||
endpoint.host_str().unwrap_or_default(),
|
||||
endpoint.port_or_known_default().unwrap_or(443)
|
||||
)
|
||||
.as_bytes(),
|
||||
),
|
||||
stable_identifier("repository", url.as_bytes()),
|
||||
)?,
|
||||
RemoteEndpoint::Ssh(_) => GitRemote::ssh(name, &url)?,
|
||||
};
|
||||
remotes.push(remote);
|
||||
}
|
||||
}
|
||||
Ok((!remotes.is_empty()).then_some(remotes))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "ios", target_os = "watchos")))]
|
||||
fn stable_identifier(prefix: &str, value: &[u8]) -> String {
|
||||
const HEX: &[u8; 16] = b"0123456789abcdef";
|
||||
let digest = Sha256::digest(value);
|
||||
let suffix: String = digest[..8]
|
||||
.iter()
|
||||
.flat_map(|byte| [HEX[(byte >> 4) as usize], HEX[(byte & 0x0f) as usize]])
|
||||
.map(char::from)
|
||||
.collect();
|
||||
format!("{prefix}-{suffix}")
|
||||
}
|
||||
|
||||
fn resolve_required_path(
|
||||
base: &Path,
|
||||
value: Option<PathBuf>,
|
||||
|
||||
Reference in New Issue
Block a user