| 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)) |
| } |