diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/pathdiff/src | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/pathdiff/src')
-rw-r--r-- | vendor/pathdiff/src/lib.rs | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/vendor/pathdiff/src/lib.rs b/vendor/pathdiff/src/lib.rs new file mode 100644 index 000000000..3860c2d91 --- /dev/null +++ b/vendor/pathdiff/src/lib.rs @@ -0,0 +1,222 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Adapted from rustc's path_relative_from +// https://github.com/rust-lang/rust/blob/e1d0de82cc40b666b88d4a6d2c9dcbc81d7ed27f/src/librustc_back/rpath.rs#L116-L158 + +use std::path::*; + +/// Construct a relative path from a provided base directory path to the provided path. +/// +/// ```rust +/// use pathdiff::diff_paths; +/// use std::path::*; +/// +/// let baz = "/foo/bar/baz"; +/// let bar = "/foo/bar"; +/// let quux = "/foo/bar/quux"; +/// assert_eq!(diff_paths(bar, baz), Some("../".into())); +/// assert_eq!(diff_paths(baz, bar), Some("baz".into())); +/// assert_eq!(diff_paths(quux, baz), Some("../quux".into())); +/// assert_eq!(diff_paths(baz, quux), Some("../baz".into())); +/// assert_eq!(diff_paths(bar, quux), Some("../".into())); +/// +/// assert_eq!(diff_paths(&baz, &bar.to_string()), Some("baz".into())); +/// assert_eq!(diff_paths(Path::new(baz), Path::new(bar).to_path_buf()), Some("baz".into())); +/// ``` +pub fn diff_paths<P, B>(path: P, base: B) -> Option<PathBuf> +where + P: AsRef<Path>, + B: AsRef<Path>, +{ + let path = path.as_ref(); + let base = base.as_ref(); + + if path.is_absolute() != base.is_absolute() { + if path.is_absolute() { + Some(PathBuf::from(path)) + } else { + None + } + } else { + let mut ita = path.components(); + let mut itb = base.components(); + let mut comps: Vec<Component> = vec![]; + loop { + match (ita.next(), itb.next()) { + (None, None) => break, + (Some(a), None) => { + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + (None, _) => comps.push(Component::ParentDir), + (Some(a), Some(b)) if comps.is_empty() && a == b => (), + (Some(a), Some(b)) if b == Component::CurDir => comps.push(a), + (Some(_), Some(b)) if b == Component::ParentDir => return None, + (Some(a), Some(_)) => { + comps.push(Component::ParentDir); + for _ in itb { + comps.push(Component::ParentDir); + } + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + } + } + Some(comps.iter().map(|c| c.as_os_str()).collect()) + } +} + +#[cfg(feature = "camino")] +mod utf8_paths { + use camino::{Utf8Component, Utf8Path, Utf8PathBuf}; + + /// Construct a relative UTF-8 path from a provided base directory path to the provided path. + /// + /// ```rust + /// # extern crate camino; + /// use camino::*; + /// use pathdiff::diff_utf8_paths; + /// + /// let baz = "/foo/bar/baz"; + /// let bar = "/foo/bar"; + /// let quux = "/foo/bar/quux"; + /// assert_eq!(diff_utf8_paths(bar, baz), Some("../".into())); + /// assert_eq!(diff_utf8_paths(baz, bar), Some("baz".into())); + /// assert_eq!(diff_utf8_paths(quux, baz), Some("../quux".into())); + /// assert_eq!(diff_utf8_paths(baz, quux), Some("../baz".into())); + /// assert_eq!(diff_utf8_paths(bar, quux), Some("../".into())); + /// + /// assert_eq!(diff_utf8_paths(&baz, &bar.to_string()), Some("baz".into())); + /// assert_eq!(diff_utf8_paths(Utf8Path::new(baz), Utf8Path::new(bar).to_path_buf()), Some("baz".into())); + /// ``` + #[cfg_attr(docsrs, doc(cfg(feature = "camino")))] + pub fn diff_utf8_paths<P, B>(path: P, base: B) -> Option<Utf8PathBuf> + where + P: AsRef<Utf8Path>, + B: AsRef<Utf8Path>, + { + let path = path.as_ref(); + let base = base.as_ref(); + + if path.is_absolute() != base.is_absolute() { + if path.is_absolute() { + Some(Utf8PathBuf::from(path)) + } else { + None + } + } else { + let mut ita = path.components(); + let mut itb = base.components(); + let mut comps: Vec<Utf8Component> = vec![]; + loop { + match (ita.next(), itb.next()) { + (None, None) => break, + (Some(a), None) => { + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + (None, _) => comps.push(Utf8Component::ParentDir), + (Some(a), Some(b)) if comps.is_empty() && a == b => (), + (Some(a), Some(b)) if b == Utf8Component::CurDir => comps.push(a), + (Some(_), Some(b)) if b == Utf8Component::ParentDir => return None, + (Some(a), Some(_)) => { + comps.push(Utf8Component::ParentDir); + for _ in itb { + comps.push(Utf8Component::ParentDir); + } + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + } + } + Some(comps.iter().map(|c| c.as_str()).collect()) + } + } +} + +#[cfg(feature = "camino")] +pub use crate::utf8_paths::*; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_absolute() { + assert_diff_paths("/foo", "/bar", Some("../foo")); + assert_diff_paths("/foo", "bar", Some("/foo")); + assert_diff_paths("foo", "/bar", None); + assert_diff_paths("foo", "bar", Some("../foo")); + } + + #[test] + fn test_identity() { + assert_diff_paths(".", ".", Some("")); + assert_diff_paths("../foo", "../foo", Some("")); + assert_diff_paths("./foo", "./foo", Some("")); + assert_diff_paths("/foo", "/foo", Some("")); + assert_diff_paths("foo", "foo", Some("")); + + assert_diff_paths("../foo/bar/baz", "../foo/bar/baz", Some("".into())); + assert_diff_paths("foo/bar/baz", "foo/bar/baz", Some("")); + } + + #[test] + fn test_subset() { + assert_diff_paths("foo", "fo", Some("../foo")); + assert_diff_paths("fo", "foo", Some("../fo")); + } + + #[test] + fn test_empty() { + assert_diff_paths("", "", Some("")); + assert_diff_paths("foo", "", Some("foo")); + assert_diff_paths("", "foo", Some("..")); + } + + #[test] + fn test_relative() { + assert_diff_paths("../foo", "../bar", Some("../foo")); + assert_diff_paths("../foo", "../foo/bar/baz", Some("../..")); + assert_diff_paths("../foo/bar/baz", "../foo", Some("bar/baz")); + + assert_diff_paths("foo/bar/baz", "foo", Some("bar/baz")); + assert_diff_paths("foo/bar/baz", "foo/bar", Some("baz")); + assert_diff_paths("foo/bar/baz", "foo/bar/baz", Some("")); + assert_diff_paths("foo/bar/baz", "foo/bar/baz/", Some("")); + + assert_diff_paths("foo/bar/baz/", "foo", Some("bar/baz")); + assert_diff_paths("foo/bar/baz/", "foo/bar", Some("baz")); + assert_diff_paths("foo/bar/baz/", "foo/bar/baz", Some("")); + assert_diff_paths("foo/bar/baz/", "foo/bar/baz/", Some("")); + + assert_diff_paths("foo/bar/baz", "foo/", Some("bar/baz")); + assert_diff_paths("foo/bar/baz", "foo/bar/", Some("baz")); + assert_diff_paths("foo/bar/baz", "foo/bar/baz", Some("")); + } + + #[test] + fn test_current_directory() { + assert_diff_paths(".", "foo", Some("../.")); + assert_diff_paths("foo", ".", Some("foo")); + assert_diff_paths("/foo", "/.", Some("foo")); + } + + fn assert_diff_paths(path: &str, base: &str, expected: Option<&str>) { + assert_eq!(diff_paths(path, base), expected.map(|s| s.into())); + #[cfg(feature = "camino")] + assert_eq!(diff_utf8_paths(path, base), expected.map(|s| s.into())); + } +} |