96 lines · 3.3 KB · Rust
RawDownload
use crate::bstr::{BStr, BString, ByteVec};use crate::remote::Direction;use git_features::threading::OwnShared; #[derive(Debug, Clone)]pub(crate) struct Replace {    find: BString,    with: OwnShared<BString>,} #[derive(Default, Debug, Clone)]pub(crate) struct Rewrite {    url_rewrite: Vec<Replace>,    push_url_rewrite: Vec<Replace>,} /// Initimpl Rewrite {    pub fn from_config(        config: &git_config::File<'static>,        mut filter: fn(&git_config::file::Metadata) -> bool,    ) -> Rewrite {        config            .sections_by_name_and_filter("url", &mut filter)            .map(|sections| {                let mut url_rewrite = Vec::new();                let mut push_url_rewrite = Vec::new();                for section in sections {                    let replace = match section.header().subsection_name() {                        Some(base) => OwnShared::new(base.to_owned()),                        None => continue,                    };                     for instead_of in section.values("insteadOf") {                        url_rewrite.push(Replace {                            with: OwnShared::clone(&replace),                            find: instead_of.into_owned(),                        });                    }                    for instead_of in section.values("pushInsteadOf") {                        push_url_rewrite.push(Replace {                            with: OwnShared::clone(&replace),                            find: instead_of.into_owned(),                        });                    }                }                Rewrite {                    url_rewrite,                    push_url_rewrite,                }            })            .unwrap_or_default()    }} /// Accessimpl Rewrite {    fn replacements_for(&self, direction: Direction) -> &[Replace] {        match direction {            Direction::Fetch => &self.url_rewrite,            Direction::Push => &self.push_url_rewrite,        }    }     pub fn longest(&self, url: &git_url::Url, direction: Direction) -> Option<BString> {        if self.replacements_for(direction).is_empty() {            None        } else {            let mut url = url.to_bstring();            self.rewrite_url_in_place(&mut url, direction).then(|| url)        }    }     /// Rewrite the given `url` of `direction` and return `true` if a replacement happened.    ///    /// Note that the result must still be checked for validity, it might not be a valid URL as we do a syntax-unaware replacement.    pub fn rewrite_url_in_place(&self, url: &mut BString, direction: Direction) -> bool {        self.replacements_for(direction)            .iter()            .fold(None::<(usize, &BStr)>, |mut acc, replace| {                if url.starts_with(replace.find.as_ref()) {                    let (bytes_matched, prev_rewrite_with) =                        acc.get_or_insert((replace.find.len(), replace.with.as_slice().into()));                    if *bytes_matched < replace.find.len() {                        *bytes_matched = replace.find.len();                        *prev_rewrite_with = replace.with.as_slice().into();                    }                };                acc            })            .map(|(bytes_matched, replace_with)| {                url.replace_range(..bytes_matched, replace_with);            })            .is_some()    }}