This commit is contained in:
/dev/mataha 2024-08-12 01:30:47 -07:00 committed by GitHub
commit 76ea1a6095
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 14 deletions

View File

@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- zsh: better cd completions. - zsh: better cd completions.
- elvish: `z -` now work as expected. - elvish: `z -` now work as expected.
- Lazily delete excluded directories from the database. - Lazily delete excluded directories from the database.
- Normalize drive letters when resolving paths on Windows.
## [0.9.4] - 2024-02-21 ## [0.9.4] - 2024-02-21

View File

@ -19,10 +19,11 @@ impl Run for Add {
let mut db = Database::open()?; let mut db = Database::open()?;
for path in &self.paths { for path in &self.paths {
let path = let path = util::patch_path(if config::resolve_symlinks() {
if config::resolve_symlinks() { util::canonicalize } else { util::resolve_path }( util::canonicalize
path, } else {
)?; util::resolve_path
}(path)?);
let path = util::path_to_str(&path)?; let path = util::path_to_str(&path)?;
// Ignore path if it contains unsupported characters, or if it's in the exclude // Ignore path if it contains unsupported characters, or if it's in the exclude

View File

@ -1,7 +1,7 @@
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs::{self, File, OpenOptions}; use std::fs::{self, File, OpenOptions};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf, Prefix};
use std::process::{Child, Command, Stdio}; use std::process::{Child, Command, Stdio};
use std::time::SystemTime; use std::time::SystemTime;
use std::{env, mem}; use std::{env, mem};
@ -263,6 +263,37 @@ pub fn path_to_str(path: &impl AsRef<Path>) -> Result<&str> {
path.to_str().with_context(|| format!("invalid unicode in path: {}", path.display())) path.to_str().with_context(|| format!("invalid unicode in path: {}", path.display()))
} }
pub fn patch_path(path: PathBuf) -> PathBuf {
if cfg!(windows) {
fn patch_drive(drive_letter: u8) -> char {
drive_letter.to_ascii_uppercase() as char
}
let mut components = path.components();
match components.next() {
Some(Component::Prefix(prefix)) => {
let prefix = match prefix.kind() {
Prefix::Disk(drive_letter) => {
format!(r"{}:", patch_drive(drive_letter))
}
Prefix::VerbatimDisk(drive_letter) => {
format!(r"\\?\{}:", patch_drive(drive_letter))
}
_ => return path,
};
let mut path = PathBuf::default();
path.push(prefix);
path.extend(components);
path
}
_ => path,
}
} else {
path
}
}
/// Returns the absolute version of a path. Like /// Returns the absolute version of a path. Like
/// [`std::path::Path::canonicalize`], but doesn't resolve symlinks. /// [`std::path::Path::canonicalize`], but doesn't resolve symlinks.
pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> { pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
@ -274,8 +305,6 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
// initialize root // initialize root
if cfg!(windows) { if cfg!(windows) {
use std::path::Prefix;
fn get_drive_letter(path: impl AsRef<Path>) -> Option<u8> { fn get_drive_letter(path: impl AsRef<Path>) -> Option<u8> {
let path = path.as_ref(); let path = path.as_ref();
let mut components = path.components(); let mut components = path.components();
@ -292,7 +321,7 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
} }
fn get_drive_path(drive_letter: u8) -> PathBuf { fn get_drive_path(drive_letter: u8) -> PathBuf {
format!(r"{}:\", drive_letter as char).into() format!(r"{}:\", drive_letter.to_ascii_uppercase() as char).into()
} }
fn get_drive_relative(drive_letter: u8) -> Result<PathBuf> { fn get_drive_relative(drive_letter: u8) -> Result<PathBuf> {
@ -312,23 +341,25 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
match components.peek() { match components.peek() {
Some(Component::Prefix(prefix)) => match prefix.kind() { Some(Component::Prefix(prefix)) => match prefix.kind() {
Prefix::Disk(drive_letter) => { Prefix::Disk(drive_letter) => {
let disk = components.next().unwrap(); components.next();
if components.peek() == Some(&Component::RootDir) { if components.peek() == Some(&Component::RootDir) {
let root = components.next().unwrap(); components.next();
stack.push(disk); base_path = get_drive_path(drive_letter);
stack.push(root);
} else { } else {
base_path = get_drive_relative(drive_letter)?; base_path = get_drive_relative(drive_letter)?;
stack.extend(base_path.components());
} }
stack.extend(base_path.components());
} }
Prefix::VerbatimDisk(drive_letter) => { Prefix::VerbatimDisk(drive_letter) => {
components.next(); components.next();
if components.peek() == Some(&Component::RootDir) { if components.peek() == Some(&Component::RootDir) {
components.next(); components.next();
base_path = get_drive_path(drive_letter);
} else {
bail!("illegal path: {}", path.display());
} }
base_path = get_drive_path(drive_letter);
stack.extend(base_path.components()); stack.extend(base_path.components());
} }
_ => bail!("invalid path: {}", path.display()), _ => bail!("invalid path: {}", path.display()),