blob: 13b747eda7cacaf9859be5495c3ee7ea27bc87e6 [file] [log] [blame]
use std::convert::TryInto;
use gix_refspec::RefSpec;
use crate::{config, remote, Remote, Repository};
mod error {
use crate::bstr::BString;
/// The error returned by [`Repository::remote_at(…)`][crate::Repository::remote_at()].
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Url(#[from] gix_url::parse::Error),
#[error("The rewritten {kind} url {rewritten_url:?} failed to parse")]
RewrittenUrlInvalid {
kind: &'static str,
rewritten_url: BString,
source: gix_url::parse::Error,
},
}
}
pub use error::Error;
use crate::bstr::BString;
/// Initialization
impl<'repo> Remote<'repo> {
#[allow(clippy::too_many_arguments)]
pub(crate) fn from_preparsed_config(
name_or_url: Option<BString>,
url: Option<gix_url::Url>,
push_url: Option<gix_url::Url>,
fetch_specs: Vec<RefSpec>,
push_specs: Vec<RefSpec>,
should_rewrite_urls: bool,
fetch_tags: remote::fetch::Tags,
repo: &'repo Repository,
) -> Result<Self, Error> {
debug_assert!(
url.is_some() || push_url.is_some(),
"BUG: fetch or push url must be set at least"
);
let (url_alias, push_url_alias) = should_rewrite_urls
.then(|| rewrite_urls(&repo.config, url.as_ref(), push_url.as_ref()))
.unwrap_or(Ok((None, None)))?;
Ok(Remote {
name: name_or_url.map(Into::into),
url,
url_alias,
push_url,
push_url_alias,
fetch_specs,
push_specs,
fetch_tags,
repo,
})
}
pub(crate) fn from_fetch_url<Url, E>(
url: Url,
should_rewrite_urls: bool,
repo: &'repo Repository,
) -> Result<Self, Error>
where
Url: TryInto<gix_url::Url, Error = E>,
gix_url::parse::Error: From<E>,
{
Self::from_fetch_url_inner(
url.try_into().map_err(|err| Error::Url(err.into()))?,
should_rewrite_urls,
repo,
)
}
fn from_fetch_url_inner(
url: gix_url::Url,
should_rewrite_urls: bool,
repo: &'repo Repository,
) -> Result<Self, Error> {
let (url_alias, _) = should_rewrite_urls
.then(|| rewrite_urls(&repo.config, Some(&url), None))
.unwrap_or(Ok((None, None)))?;
Ok(Remote {
name: None,
url: Some(url),
url_alias,
push_url: None,
push_url_alias: None,
fetch_specs: Vec::new(),
push_specs: Vec::new(),
fetch_tags: Default::default(),
repo,
})
}
}
pub(crate) fn rewrite_url(
config: &config::Cache,
url: Option<&gix_url::Url>,
direction: remote::Direction,
) -> Result<Option<gix_url::Url>, Error> {
url.and_then(|url| config.url_rewrite().longest(url, direction))
.map(|url| {
gix_url::parse(url.as_ref()).map_err(|err| Error::RewrittenUrlInvalid {
kind: match direction {
remote::Direction::Fetch => "fetch",
remote::Direction::Push => "push",
},
source: err,
rewritten_url: url,
})
})
.transpose()
}
pub(crate) fn rewrite_urls(
config: &config::Cache,
url: Option<&gix_url::Url>,
push_url: Option<&gix_url::Url>,
) -> Result<(Option<gix_url::Url>, Option<gix_url::Url>), Error> {
let url_alias = rewrite_url(config, url, remote::Direction::Fetch)?;
let push_url_alias = rewrite_url(config, push_url, remote::Direction::Push)?;
Ok((url_alias, push_url_alias))
}