From 8379405bb6f95d22719df2fb3c90eb64c3e32d8e Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sat, 31 Oct 2020 20:13:15 -0500 Subject: [PATCH] Don't have a duplicate slash in root dir. --- src/dir.rs | 6 ++++-- src/info.rs | 3 ++- src/main.rs | 5 +++-- src/ops/put.rs | 3 ++- src/utils.rs | 23 ++++++++++++++++++----- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/dir.rs b/src/dir.rs index 94d971c..0892ada 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -25,7 +25,8 @@ impl TrashDir { /// /// > For every user2 a “home trash” directory MUST be available. /// > Its name and location are $XDG_DATA_HOME/Trash - /// > $XDG_DATA_HOME is the base directory for user-specific data, as defined in the Desktop Base Directory Specification. + /// > $XDG_DATA_HOME is the base directory for user-specific data, as + /// defined in the Desktop Base Directory Specification. pub fn get_home_trash() -> Self { TrashDir::from(XDG.get_data_home().join("Trash")) } @@ -38,7 +39,8 @@ impl TrashDir { .unwrap_or_else(|| TrashDir::get_home_trash()) } - /// Actually create the directory on disk corresponding to this trash directory + /// Actually create the directory on disk corresponding to this trash + /// directory pub fn create(&self) -> Result<(), Error> { let path = &self.0; if !path.exists() { diff --git a/src/info.rs b/src/info.rs index 8bfee41..1a46d21 100644 --- a/src/info.rs +++ b/src/info.rs @@ -41,7 +41,8 @@ pub struct TrashInfo { } impl TrashInfo { - /// Create a new TrashInfo based on the .trashinfo path and the deleted file path + /// Create a new TrashInfo based on the .trashinfo path and the deleted file + /// path /// /// This is useful for reading files from the Trash. pub fn from_files( diff --git a/src/main.rs b/src/main.rs index dedbd73..e1edb9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,8 +21,9 @@ enum Command { /// Puts files into the trash. /// /// If a trash directory isn't specified, the best strategy is picked - /// for each file that's deleted (after shell glob expansion). The algorithm - /// for deciding a strategy is specified in the FreeDesktop Trash spec. + /// for each file that's deleted (after shell glob expansion). The + /// algorithm for deciding a strategy is specified in the FreeDesktop + /// Trash spec. #[structopt(name = "put")] Put(PutOptions), diff --git a/src/ops/put.rs b/src/ops/put.rs index 2311515..49032a7 100644 --- a/src/ops/put.rs +++ b/src/ops/put.rs @@ -98,7 +98,8 @@ enum DeletionStrategy { Fixed(TrashDir), /// move the candidate files/directories to the trash directory - /// (this requires that both the candidate and the trash directories be on the same filesystem) + /// (this requires that both the candidate and the trash directories be on + /// the same filesystem) MoveTo(TrashDir), /// recursively copy the candidate files/directories to the trash directory diff --git a/src/utils.rs b/src/utils.rs index 48c514a..560d612 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,7 @@ use std::env; use std::ffi::{OsStr, OsString}; use std::fs; use std::os::unix::ffi::OsStrExt; -use std::path::{Path, PathBuf, MAIN_SEPARATOR}; +use std::path::{Component, Path, PathBuf, MAIN_SEPARATOR}; use anyhow::Result; use percent_encoding::AsciiSet; @@ -61,10 +61,23 @@ pub fn recursive_copy( /// Percent-encodes a path, but only the file names, not the separators. pub fn percent_encode(path: impl AsRef) -> String { let path = path.as_ref(); - path.iter() - .map(|segment| { - percent_encoding::percent_encode(segment.as_bytes(), MASK) - .to_string() + path.components() + .filter_map(|segment| { + match segment { + Component::RootDir => Some(String::new()), + Component::Prefix(_) => unreachable!("windows"), + + // TODO: separate type for normalized path + Component::ParentDir => { + unreachable!("path should be normalized") + } + Component::CurDir => unreachable!("path should be normalized"), + + Component::Normal(s) => Some( + percent_encoding::percent_encode(s.as_bytes(), MASK) + .to_string(), + ), + } }) .collect::>() .join(&MAIN_SEPARATOR.to_string())