You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.4 KiB
98 lines
2.4 KiB
use hex::ToHex;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_with::{serde_as, DisplayFromStr};
|
|
use sha2::{Digest, Sha256};
|
|
|
|
use crate::error::unexpected::{self, Mappable};
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
pub struct GitUrl {
|
|
pub parsed: http::uri::Uri,
|
|
}
|
|
|
|
impl std::str::FromStr for GitUrl {
|
|
type Err = unexpected::Error;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let parsed: http::Uri = s
|
|
.parse()
|
|
.map_unexpected_while(|| format!("parsing as url"))?;
|
|
|
|
let scheme = parsed
|
|
.scheme()
|
|
.map_unexpected_while(|| format!("extracting scheme"))?;
|
|
|
|
if scheme != "http" && scheme != "https" {
|
|
return Err(unexpected::Error::from(
|
|
"only http(s) git URLs are supported",
|
|
));
|
|
}
|
|
|
|
Ok(GitUrl { parsed })
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for GitUrl {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
self.parsed.fmt(f)
|
|
}
|
|
}
|
|
|
|
#[serde_as]
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
#[serde(tag = "kind")]
|
|
/// A unique description of an origin, from where a domain might be served.
|
|
pub enum Descr {
|
|
#[serde(rename = "git")]
|
|
Git {
|
|
#[serde_as(as = "DisplayFromStr")]
|
|
url: GitUrl,
|
|
branch_name: String,
|
|
},
|
|
}
|
|
|
|
impl Descr {
|
|
/// Returns a globally unique string for the Descr.
|
|
pub fn id(&self) -> String {
|
|
let mut h = Sha256::new();
|
|
|
|
let mut h_update = |b: &str| {
|
|
h.update(b);
|
|
h.update("\n");
|
|
};
|
|
|
|
match self {
|
|
Descr::Git { url, branch_name } => {
|
|
h_update("git");
|
|
h_update(url.parsed.to_string().as_str());
|
|
h_update(branch_name);
|
|
}
|
|
}
|
|
|
|
h.finalize().encode_hex::<String>()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod descr_tests {
|
|
|
|
#[test]
|
|
fn id() {
|
|
assert_eq!(
|
|
super::Descr::Git {
|
|
url: "https://foo".parse().unwrap(),
|
|
branch_name: String::from("bar"),
|
|
}
|
|
.id(),
|
|
"0b12637c1994e61db59ad9bea5fcaf5d2a1e5ecad00c58320271e721e4295ceb",
|
|
);
|
|
|
|
assert_eq!(
|
|
super::Descr::Git {
|
|
url: "http://foo".parse().unwrap(),
|
|
branch_name: String::from("bar"),
|
|
}
|
|
.id(),
|
|
"d14f4c75c938e46c2d9da05ea14b6e41ba86ac9945bb10c0b2f91faee1ec0bce",
|
|
);
|
|
}
|
|
}
|
|
|