From 28705bce22eb273bf6dccfadf00446631df69ccc Mon Sep 17 00:00:00 2001 From: s1syph0s <34000276+s1syph0s@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:00:40 +0100 Subject: [PATCH] chore(package): vendor common_path (#3780) * vendoring common_path * add original license to common_path * Clarify license scope * refactor: remove rand dependency --------- Co-authored-by: Aram Drevekenin --- Cargo.lock | 7 -- zellij-utils/Cargo.toml | 1 - zellij-utils/src/common_path.rs | 137 ++++++++++++++++++++++++++++++++ zellij-utils/src/lib.rs | 8 +- 4 files changed, 142 insertions(+), 11 deletions(-) create mode 100644 zellij-utils/src/common_path.rs diff --git a/Cargo.lock b/Cargo.lock index 72bad136..6a8109ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,12 +636,6 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dfdf9179d546b55ff3f88c9d93ecfaa3e9760163da5a1080af5243230dbbb70" -[[package]] -name = "common-path" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" - [[package]] name = "compact-bar" version = "0.1.0" @@ -5126,7 +5120,6 @@ dependencies = [ "clap_complete", "colored", "colorsys", - "common-path", "crossbeam", "curl-sys", "directories", diff --git a/zellij-utils/Cargo.toml b/zellij-utils/Cargo.toml index 1f2c535e..6e51c27d 100644 --- a/zellij-utils/Cargo.toml +++ b/zellij-utils/Cargo.toml @@ -17,7 +17,6 @@ clap = { version = "3.2.2", features = ["derive", "env"] } clap_complete = "3.2.1" colored = "2.0.0" colorsys = "0.6.5" -common-path = "1.0.0" crossbeam = "0.8.1" directories = "5.0" include_dir = "0.7.3" diff --git a/zellij-utils/src/common_path.rs b/zellij-utils/src/common_path.rs new file mode 100644 index 00000000..e163f0e0 --- /dev/null +++ b/zellij-utils/src/common_path.rs @@ -0,0 +1,137 @@ +// The following license refers to code in this file and this file only. +// We chose to vendor this dependency rather than depend on it through crates.io in order to facilitate +// packaging. This license was copied verbatim from: https://docs.rs/crate/common-path/1.0.0/source/LICENSE-MIT +// +// MIT License +// +// Copyright 2018 Paul Woolcock +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +use std::path::{Path, PathBuf}; + +/// Find the common prefix, if any, between any number of paths +/// +/// # Example +/// +/// ```rust +/// use std::path::{PathBuf, Path}; +/// use zellij_utils::common_path::common_path_all; +/// +/// # fn main() { +/// let baz = Path::new("/foo/bar/baz"); +/// let quux = Path::new("/foo/bar/quux"); +/// let foo = Path::new("/foo/bar/foo"); +/// let prefix = common_path_all(vec![baz, quux, foo]).unwrap(); +/// assert_eq!(prefix, Path::new("/foo/bar").to_path_buf()); +/// # } +/// ``` +pub fn common_path_all<'a>(paths: impl IntoIterator) -> Option { + let mut path_iter = paths.into_iter(); + let mut result = path_iter.next()?.to_path_buf(); + for path in path_iter { + if let Some(r) = common_path(&result, &path) { + result = r; + } else { + return None; + } + } + Some(result.to_path_buf()) +} + +/// Find the common prefix, if any, between 2 paths +/// +/// # Example +/// +/// ```rust +/// use std::path::{PathBuf, Path}; +/// use zellij_utils::common_path::common_path; +/// +/// # fn main() { +/// let baz = Path::new("/foo/bar/baz"); +/// let quux = Path::new("/foo/bar/quux"); +/// let prefix = common_path(baz, quux).unwrap(); +/// assert_eq!(prefix, Path::new("/foo/bar").to_path_buf()); +/// # } +/// ``` +pub fn common_path(one: P, two: Q) -> Option +where + P: AsRef, + Q: AsRef, +{ + let one = one.as_ref(); + let two = two.as_ref(); + let one = one.components(); + let two = two.components(); + let mut final_path = PathBuf::new(); + let mut found = false; + let paths = one.zip(two); + for (l, r) in paths { + if l == r { + final_path.push(l.as_os_str()); + found = true; + } else { + break; + } + } + if found { + Some(final_path) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn compare_all_paths() { + let one = Path::new("/foo/bar/baz/one.txt"); + let two = Path::new("/foo/bar/quux/quuux/two.txt"); + let three = Path::new("/foo/bar/baz/foo/bar"); + let result = Path::new("/foo/bar"); + let path_permutations = vec![ + vec![one, two, three], + vec![one, three, two], + vec![two, one, three], + vec![two, three, one], + vec![three, one, two], + vec![three, two, one], + ]; + for all in path_permutations { + assert_eq!(common_path_all(all).unwrap(), result.to_path_buf()) + } + } + + #[test] + fn compare_paths() { + let one = Path::new("/foo/bar/baz/one.txt"); + let two = Path::new("/foo/bar/quux/quuux/two.txt"); + let result = Path::new("/foo/bar"); + assert_eq!(common_path(&one, &two).unwrap(), result.to_path_buf()) + } + + #[test] + fn no_common_path() { + let one = Path::new("/foo/bar"); + let two = Path::new("./baz/quux"); + assert!(common_path(&one, &two).is_none()); + } +} diff --git a/zellij-utils/src/lib.rs b/zellij-utils/src/lib.rs index 44d48a5d..2085473f 100644 --- a/zellij-utils/src/lib.rs +++ b/zellij-utils/src/lib.rs @@ -17,6 +17,8 @@ pub mod shared; #[cfg(not(target_family = "wasm"))] pub mod channels; // Requires async_std #[cfg(not(target_family = "wasm"))] +pub mod common_path; +#[cfg(not(target_family = "wasm"))] pub mod downloader; // Requires async_std #[cfg(not(target_family = "wasm"))] pub mod ipc; // Requires interprocess @@ -25,9 +27,9 @@ pub mod logging; // Requires log4rs #[cfg(not(target_family = "wasm"))] pub use ::{ - anyhow, async_channel, async_std, clap, common_path, humantime, interprocess, isahc, - lazy_static, libc, miette, nix, notify_debouncer_full, regex, serde, signal_hook, tempfile, - termwiz, url, uuid, vte, + anyhow, async_channel, async_std, clap, humantime, interprocess, isahc, lazy_static, libc, + miette, nix, notify_debouncer_full, regex, serde, signal_hook, tempfile, termwiz, url, uuid, + vte, }; pub use ::prost;