summaryrefslogtreecommitdiffstats
path: root/vendor/gix/src/repository/remote.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix/src/repository/remote.rs')
-rw-r--r--vendor/gix/src/repository/remote.rs199
1 files changed, 199 insertions, 0 deletions
diff --git a/vendor/gix/src/repository/remote.rs b/vendor/gix/src/repository/remote.rs
new file mode 100644
index 000000000..e3f210899
--- /dev/null
+++ b/vendor/gix/src/repository/remote.rs
@@ -0,0 +1,199 @@
+#![allow(clippy::result_large_err)]
+use std::convert::TryInto;
+
+use crate::{bstr::BStr, config, remote, remote::find, Remote};
+
+impl crate::Repository {
+ /// Create a new remote available at the given `url`.
+ ///
+ /// It's configured to fetch included tags by default, similar to git.
+ /// See [`with_fetch_tags(…)`][Remote::with_fetch_tags()] for a way to change it.
+ pub fn remote_at<Url, E>(&self, url: Url) -> Result<Remote<'_>, remote::init::Error>
+ where
+ Url: TryInto<gix_url::Url, Error = E>,
+ gix_url::parse::Error: From<E>,
+ {
+ Remote::from_fetch_url(url, true, self)
+ }
+
+ /// Create a new remote available at the given `url` similarly to [`remote_at()`][crate::Repository::remote_at()],
+ /// but don't rewrite the url according to rewrite rules.
+ /// This eliminates a failure mode in case the rewritten URL is faulty, allowing to selectively [apply rewrite
+ /// rules][Remote::rewrite_urls()] later and do so non-destructively.
+ pub fn remote_at_without_url_rewrite<Url, E>(&self, url: Url) -> Result<Remote<'_>, remote::init::Error>
+ where
+ Url: TryInto<gix_url::Url, Error = E>,
+ gix_url::parse::Error: From<E>,
+ {
+ Remote::from_fetch_url(url, false, self)
+ }
+
+ /// Find the remote with the given `name_or_url` or report an error, similar to [`try_find_remote(…)`][Self::try_find_remote()].
+ ///
+ /// Note that we will obtain remotes only if we deem them [trustworthy][crate::open::Options::filter_config_section()].
+ pub fn find_remote<'a>(&self, name_or_url: impl Into<&'a BStr>) -> Result<Remote<'_>, find::existing::Error> {
+ let name_or_url = name_or_url.into();
+ Ok(self
+ .try_find_remote(name_or_url)
+ .ok_or_else(|| find::existing::Error::NotFound {
+ name: name_or_url.into(),
+ })??)
+ }
+
+ /// Find the default remote as configured, or `None` if no such configuration could be found.
+ ///
+ /// See [remote_default_name()][Self::remote_default_name()] for more information on the `direction` parameter.
+ pub fn find_default_remote(
+ &self,
+ direction: remote::Direction,
+ ) -> Option<Result<Remote<'_>, find::existing::Error>> {
+ self.remote_default_name(direction)
+ .map(|name| self.find_remote(name.as_ref()))
+ }
+
+ /// Find the remote with the given `name_or_url` or return `None` if it doesn't exist, for the purpose of fetching or pushing
+ /// data to a remote.
+ ///
+ /// There are various error kinds related to partial information or incorrectly formatted URLs or ref-specs.
+ /// Also note that the created `Remote` may have neither fetch nor push ref-specs set at all.
+ ///
+ /// Note that ref-specs are de-duplicated right away which may change their order. This doesn't affect matching in any way
+ /// as negations/excludes are applied after includes.
+ ///
+ /// We will only include information if we deem it [trustworthy][crate::open::Options::filter_config_section()].
+ pub fn try_find_remote<'a>(&self, name_or_url: impl Into<&'a BStr>) -> Option<Result<Remote<'_>, find::Error>> {
+ self.try_find_remote_inner(name_or_url, true)
+ }
+
+ /// Similar to [try_find_remote()][Self::try_find_remote()], but removes a failure mode if rewritten URLs turn out to be invalid
+ /// as it skips rewriting them.
+ /// Use this in conjunction with [`Remote::rewrite_urls()`] to non-destructively apply the rules and keep the failed urls unchanged.
+ pub fn try_find_remote_without_url_rewrite<'a>(
+ &self,
+ name_or_url: impl Into<&'a BStr>,
+ ) -> Option<Result<Remote<'_>, find::Error>> {
+ self.try_find_remote_inner(name_or_url, false)
+ }
+
+ fn try_find_remote_inner<'a>(
+ &self,
+ name_or_url: impl Into<&'a BStr>,
+ rewrite_urls: bool,
+ ) -> Option<Result<Remote<'_>, find::Error>> {
+ fn config_spec<T: config::tree::keys::Validate>(
+ specs: Vec<std::borrow::Cow<'_, BStr>>,
+ name_or_url: &BStr,
+ key: &'static config::tree::keys::Any<T>,
+ op: gix_refspec::parse::Operation,
+ ) -> Result<Vec<gix_refspec::RefSpec>, find::Error> {
+ let kind = key.name;
+ specs
+ .into_iter()
+ .map(|spec| {
+ key.try_into_refspec(spec, op).map_err(|err| find::Error::RefSpec {
+ remote_name: name_or_url.into(),
+ kind,
+ source: err,
+ })
+ })
+ .collect::<Result<Vec<_>, _>>()
+ .map(|mut specs| {
+ specs.sort();
+ specs.dedup();
+ specs
+ })
+ }
+
+ let mut filter = self.filter_config_section();
+ let name_or_url = name_or_url.into();
+ let mut config_url = |key: &'static config::tree::keys::Url, kind: &'static str| {
+ self.config
+ .resolved
+ .string_filter("remote", Some(name_or_url), key.name, &mut filter)
+ .map(|url| {
+ key.try_into_url(url).map_err(|err| find::Error::Url {
+ kind,
+ remote_name: name_or_url.into(),
+ source: err,
+ })
+ })
+ };
+ let url = config_url(&config::tree::Remote::URL, "fetch");
+ let push_url = config_url(&config::tree::Remote::PUSH_URL, "push");
+ let config = &self.config.resolved;
+
+ let fetch_specs = config
+ .strings_filter("remote", Some(name_or_url), "fetch", &mut filter)
+ .map(|specs| {
+ config_spec(
+ specs,
+ name_or_url,
+ &config::tree::Remote::FETCH,
+ gix_refspec::parse::Operation::Fetch,
+ )
+ });
+ let push_specs = config
+ .strings_filter("remote", Some(name_or_url), "push", &mut filter)
+ .map(|specs| {
+ config_spec(
+ specs,
+ name_or_url,
+ &config::tree::Remote::PUSH,
+ gix_refspec::parse::Operation::Push,
+ )
+ });
+ let fetch_tags = config
+ .string_filter("remote", Some(name_or_url), "tagOpt", &mut filter)
+ .map(|value| {
+ config::tree::Remote::TAG_OPT
+ .try_into_tag_opt(value)
+ .map_err(Into::into)
+ });
+ let fetch_tags = match fetch_tags {
+ Some(Ok(v)) => v,
+ Some(Err(err)) => return Some(Err(err)),
+ None => Default::default(),
+ };
+
+ match (url, fetch_specs, push_url, push_specs) {
+ (None, None, None, None) => None,
+ (None, _, None, _) => Some(Err(find::Error::UrlMissing)),
+ (url, fetch_specs, push_url, push_specs) => {
+ let url = match url {
+ Some(Ok(v)) => Some(v),
+ Some(Err(err)) => return Some(Err(err)),
+ None => None,
+ };
+ let push_url = match push_url {
+ Some(Ok(v)) => Some(v),
+ Some(Err(err)) => return Some(Err(err)),
+ None => None,
+ };
+ let fetch_specs = match fetch_specs {
+ Some(Ok(v)) => v,
+ Some(Err(err)) => return Some(Err(err)),
+ None => Vec::new(),
+ };
+ let push_specs = match push_specs {
+ Some(Ok(v)) => v,
+ Some(Err(err)) => return Some(Err(err)),
+ None => Vec::new(),
+ };
+
+ Some(
+ Remote::from_preparsed_config(
+ Some(name_or_url.to_owned()),
+ url,
+ push_url,
+ fetch_specs,
+ push_specs,
+ rewrite_urls,
+ fetch_tags,
+ self,
+ )
+ .map_err(Into::into),
+ )
+ }
+ }
+ }
+}