[codex] Make AbsolutePathBuf joins infallible (#16981)

Having to check for errors every time join is called is painful and
unnecessary.
This commit is contained in:
pakrym-oai
2026-04-07 10:52:08 -07:00
committed by GitHub
parent 0b9e42f6f7
commit f1a2b920f9
40 changed files with 361 additions and 315 deletions

View File

@@ -1,5 +1,4 @@
use dirs::home_dir;
use path_absolutize::Absolutize;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Deserializer;
@@ -11,6 +10,8 @@ use std::path::Path;
use std::path::PathBuf;
use ts_rs::TS;
mod absolutize;
/// A path that is guaranteed to be absolute and normalized (though it is not
/// guaranteed to be canonicalized or exist on the filesystem).
///
@@ -43,30 +44,34 @@ impl AbsolutePathBuf {
pub fn resolve_path_against_base<P: AsRef<Path>, B: AsRef<Path>>(
path: P,
base_path: B,
) -> std::io::Result<Self> {
) -> Self {
let expanded = Self::maybe_expand_home_directory(path.as_ref());
let absolute_path = expanded.absolutize_from(base_path.as_ref())?;
Ok(Self(absolute_path.into_owned()))
Self(absolutize::absolutize_from(&expanded, base_path.as_ref()))
}
pub fn from_absolute_path<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
let expanded = Self::maybe_expand_home_directory(path.as_ref());
let absolute_path = expanded.absolutize()?;
Ok(Self(absolute_path.into_owned()))
Ok(Self(absolutize::absolutize(&expanded)?))
}
pub fn current_dir() -> std::io::Result<Self> {
let current_dir = std::env::current_dir()?;
Self::from_absolute_path(current_dir)
Ok(Self(absolutize::absolutize_from(
&current_dir,
&current_dir,
)))
}
/// Construct an absolute path from `path`, resolving relative paths against
/// the process current working directory.
pub fn relative_to_current_dir<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
Self::resolve_path_against_base(path, std::env::current_dir()?)
Ok(Self::resolve_path_against_base(
path,
std::env::current_dir()?,
))
}
pub fn join<P: AsRef<Path>>(&self, path: P) -> std::io::Result<Self> {
pub fn join<P: AsRef<Path>>(&self, path: P) -> Self {
Self::resolve_path_against_base(path, &self.0)
}
@@ -187,9 +192,7 @@ impl<'de> Deserialize<'de> for AbsolutePathBuf {
{
let path = PathBuf::deserialize(deserializer)?;
ABSOLUTE_PATH_BASE.with(|cell| match cell.borrow().as_deref() {
Some(base) => {
Ok(Self::resolve_path_against_base(path, base).map_err(SerdeError::custom)?)
}
Some(base) => Ok(Self::resolve_path_against_base(path, base)),
None if path.is_absolute() => {
Self::from_absolute_path(path).map_err(SerdeError::custom)
}
@@ -213,8 +216,7 @@ mod tests {
let base_path = base_dir.path();
let absolute_path = absolute_dir.path().join("file.txt");
let abs_path_buf =
AbsolutePathBuf::resolve_path_against_base(absolute_path.clone(), base_path)
.expect("failed to create");
AbsolutePathBuf::resolve_path_against_base(absolute_path.clone(), base_path);
assert_eq!(abs_path_buf.as_path(), absolute_path.as_path());
}
@@ -222,8 +224,16 @@ mod tests {
fn relative_path_is_resolved_against_base_path() {
let temp_dir = tempdir().expect("base dir");
let base_dir = temp_dir.path();
let abs_path_buf = AbsolutePathBuf::resolve_path_against_base("file.txt", base_dir)
.expect("failed to create");
let abs_path_buf = AbsolutePathBuf::resolve_path_against_base("file.txt", base_dir);
assert_eq!(abs_path_buf.as_path(), base_dir.join("file.txt").as_path());
}
#[test]
fn relative_path_dots_are_normalized_against_base_path() {
let temp_dir = tempdir().expect("base dir");
let base_dir = temp_dir.path();
let abs_path_buf =
AbsolutePathBuf::resolve_path_against_base("./nested/../file.txt", base_dir);
assert_eq!(abs_path_buf.as_path(), base_dir.join("file.txt").as_path());
}