From 62d86470d12d61ccb41a1d1282c49ee15bdfde5f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 6 Sep 2023 19:33:01 -0700 Subject: [PATCH] Add wrappers around std::fs::metadata This adds wrappers around std::fs::metadata and std::fs::symlink_metadata which provide better error messages indicating the path that caused the error. --- crates/cargo-util/src/paths.rs | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crates/cargo-util/src/paths.rs b/crates/cargo-util/src/paths.rs index ce675585979..888ca1af564 100644 --- a/crates/cargo-util/src/paths.rs +++ b/crates/cargo-util/src/paths.rs @@ -4,7 +4,7 @@ use anyhow::{Context, Result}; use filetime::FileTime; use std::env; use std::ffi::{OsStr, OsString}; -use std::fs::{self, File, OpenOptions}; +use std::fs::{self, File, Metadata, OpenOptions}; use std::io; use std::io::prelude::*; use std::iter; @@ -136,6 +136,24 @@ pub fn resolve_executable(exec: &Path) -> Result { } } +/// Returns metadata for a file (follows symlinks). +/// +/// Equivalent to [`std::fs::metadata`] with better error messages. +pub fn metadata>(path: P) -> Result { + let path = path.as_ref(); + std::fs::metadata(path) + .with_context(|| format!("failed to load metadata for path `{}`", path.display())) +} + +/// Returns metadata for a file without following symlinks. +/// +/// Equivalent to [`std::fs::metadata`] with better error messages. +pub fn symlink_metadata>(path: P) -> Result { + let path = path.as_ref(); + std::fs::symlink_metadata(path) + .with_context(|| format!("failed to load metadata for path `{}`", path.display())) +} + /// Reads a file to a string. /// /// Equivalent to [`std::fs::read_to_string`] with better error messages. @@ -216,16 +234,14 @@ pub fn open>(path: P) -> Result { /// Returns the last modification time of a file. pub fn mtime(path: &Path) -> Result { - let meta = - fs::metadata(path).with_context(|| format!("failed to stat `{}`", path.display()))?; + let meta = metadata(path)?; Ok(FileTime::from_last_modification_time(&meta)) } /// Returns the maximum mtime of the given path, recursing into /// subdirectories, and following symlinks. pub fn mtime_recursive(path: &Path) -> Result { - let meta = - fs::metadata(path).with_context(|| format!("failed to stat `{}`", path.display()))?; + let meta = metadata(path)?; if !meta.is_dir() { return Ok(FileTime::from_last_modification_time(&meta)); } @@ -432,10 +448,7 @@ pub fn remove_dir_all>(p: P) -> Result<()> { } fn _remove_dir_all(p: &Path) -> Result<()> { - if p.symlink_metadata() - .with_context(|| format!("could not get metadata for `{}` to remove", p.display()))? - .is_symlink() - { + if symlink_metadata(p)?.is_symlink() { return remove_file(p); } let entries = p