Skip to content

Commit fcbb99a

Browse files
committed
PR ajeetdsouza#609: Normalize drive letters when resolving paths on Windows
1 parent 7bc5e2b commit fcbb99a

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

src/cmd/add.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ impl Run for Add {
1919
let mut db = Database::open()?;
2020

2121
for path in &self.paths {
22-
let path =
23-
if config::resolve_symlinks() { util::canonicalize } else { util::resolve_path }(
24-
path,
25-
)?;
22+
let path = util::patch_path(if config::resolve_symlinks() {
23+
util::canonicalize
24+
} else {
25+
util::resolve_path
26+
}(path)?);
2627
let path = util::path_to_str(&path)?;
2728

2829
// Ignore path if it contains unsupported characters, or if it's in the exclude

src/util.rs

+41-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::ffi::OsStr;
22
use std::fs::{self, File, OpenOptions};
33
use std::io::{self, Read, Write};
4-
use std::path::{Component, Path, PathBuf};
4+
use std::path::{Component, Path, PathBuf, Prefix};
55
use std::process::{Child, Command, Stdio};
66
use std::time::SystemTime;
77
use std::{env, mem};
@@ -263,6 +263,37 @@ pub fn path_to_str(path: &impl AsRef<Path>) -> Result<&str> {
263263
path.to_str().with_context(|| format!("invalid unicode in path: {}", path.display()))
264264
}
265265

266+
pub fn patch_path(path: PathBuf) -> PathBuf {
267+
if cfg!(windows) {
268+
fn patch_drive(drive_letter: u8) -> char {
269+
drive_letter.to_ascii_uppercase() as char
270+
}
271+
272+
let mut components = path.components();
273+
match components.next() {
274+
Some(Component::Prefix(prefix)) => {
275+
let prefix = match prefix.kind() {
276+
Prefix::Disk(drive_letter) => {
277+
format!(r"{}:", patch_drive(drive_letter))
278+
}
279+
Prefix::VerbatimDisk(drive_letter) => {
280+
format!(r"\\?\{}:", patch_drive(drive_letter))
281+
}
282+
_ => return path,
283+
};
284+
285+
let mut path = PathBuf::default();
286+
path.push(prefix);
287+
path.extend(components);
288+
path
289+
}
290+
_ => path,
291+
}
292+
} else {
293+
path
294+
}
295+
}
296+
266297
/// Returns the absolute version of a path. Like
267298
/// [`std::path::Path::canonicalize`], but doesn't resolve symlinks.
268299
pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
@@ -274,8 +305,6 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
274305

275306
// initialize root
276307
if cfg!(windows) {
277-
use std::path::Prefix;
278-
279308
fn get_drive_letter(path: impl AsRef<Path>) -> Option<u8> {
280309
let path = path.as_ref();
281310
let mut components = path.components();
@@ -292,7 +321,7 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
292321
}
293322

294323
fn get_drive_path(drive_letter: u8) -> PathBuf {
295-
format!(r"{}:\", drive_letter as char).into()
324+
format!(r"{}:\", drive_letter.to_ascii_uppercase() as char).into()
296325
}
297326

298327
fn get_drive_relative(drive_letter: u8) -> Result<PathBuf> {
@@ -312,23 +341,25 @@ pub fn resolve_path(path: impl AsRef<Path>) -> Result<PathBuf> {
312341
match components.peek() {
313342
Some(Component::Prefix(prefix)) => match prefix.kind() {
314343
Prefix::Disk(drive_letter) => {
315-
let disk = components.next().unwrap();
344+
components.next();
316345
if components.peek() == Some(&Component::RootDir) {
317-
let root = components.next().unwrap();
318-
stack.push(disk);
319-
stack.push(root);
346+
components.next();
347+
base_path = get_drive_path(drive_letter);
320348
} else {
321349
base_path = get_drive_relative(drive_letter)?;
322-
stack.extend(base_path.components());
323350
}
351+
352+
stack.extend(base_path.components());
324353
}
325354
Prefix::VerbatimDisk(drive_letter) => {
326355
components.next();
327356
if components.peek() == Some(&Component::RootDir) {
328357
components.next();
358+
base_path = get_drive_path(drive_letter);
359+
} else {
360+
bail!("illegal path: {}", path.display());
329361
}
330362

331-
base_path = get_drive_path(drive_letter);
332363
stack.extend(base_path.components());
333364
}
334365
_ => bail!("invalid path: {}", path.display()),

0 commit comments

Comments
 (0)