mirror of
https://github.com/openai/codex.git
synced 2026-04-27 16:15:09 +00:00
fix: introduce AbsolutePathBuf as part of sandbox config (#7856)
Changes the `writable_roots` field of the `WorkspaceWrite` variant of the `SandboxPolicy` enum from `Vec<PathBuf>` to `Vec<AbsolutePathBuf>`. This is helpful because now callers can be sure the value is an absolute path rather than a relative one. (Though when using an absolute path in a Seatbelt config policy, we still have to _canonicalize_ it first.) Because `writable_roots` can be read from a config file, it is important that we are able to resolve relative paths properly using the parent folder of the config file as the base path.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use path_absolutize::Absolutize;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Deserializer;
|
||||
use serde::Serialize;
|
||||
@@ -7,6 +8,7 @@ use std::cell::RefCell;
|
||||
use std::path::Display;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use ts_rs::TS;
|
||||
|
||||
/// A path that is guaranteed to be absolute and normalized (though it is not
|
||||
/// guaranteed to be canonicalized or exist on the filesystem).
|
||||
@@ -15,27 +17,27 @@ use std::path::PathBuf;
|
||||
/// using `AbsolutePathBufGuard::new(base_path)`. If no base path is set, the
|
||||
/// deserialization will fail unless the path being deserialized is already
|
||||
/// absolute.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, JsonSchema, TS)]
|
||||
pub struct AbsolutePathBuf(PathBuf);
|
||||
|
||||
impl AbsolutePathBuf {
|
||||
pub fn resolve_path_against_base<P, B>(path: P, base_path: B) -> std::io::Result<Self>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
B: AsRef<Path>,
|
||||
{
|
||||
pub fn resolve_path_against_base<P: AsRef<Path>, B: AsRef<Path>>(
|
||||
path: P,
|
||||
base_path: B,
|
||||
) -> std::io::Result<Self> {
|
||||
let absolute_path = path.as_ref().absolutize_from(base_path.as_ref())?;
|
||||
Ok(Self(absolute_path.into_owned()))
|
||||
}
|
||||
|
||||
pub fn from_absolute_path<P>(path: P) -> std::io::Result<Self>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
pub fn from_absolute_path<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
|
||||
let absolute_path = path.as_ref().absolutize()?;
|
||||
Ok(Self(absolute_path.into_owned()))
|
||||
}
|
||||
|
||||
pub fn join<P: AsRef<Path>>(&self, path: P) -> std::io::Result<Self> {
|
||||
Self::resolve_path_against_base(path, &self.0)
|
||||
}
|
||||
|
||||
pub fn as_path(&self) -> &Path {
|
||||
&self.0
|
||||
}
|
||||
@@ -48,11 +50,59 @@ impl AbsolutePathBuf {
|
||||
self.0.clone()
|
||||
}
|
||||
|
||||
pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
|
||||
self.0.to_string_lossy()
|
||||
}
|
||||
|
||||
pub fn display(&self) -> Display<'_> {
|
||||
self.0.display()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for AbsolutePathBuf {
|
||||
fn as_ref(&self) -> &Path {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AbsolutePathBuf> for PathBuf {
|
||||
fn from(path: AbsolutePathBuf) -> Self {
|
||||
path.into_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Path> for AbsolutePathBuf {
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(value: &Path) -> Result<Self, Self::Error> {
|
||||
Self::from_absolute_path(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PathBuf> for AbsolutePathBuf {
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
|
||||
Self::from_absolute_path(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for AbsolutePathBuf {
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
Self::from_absolute_path(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for AbsolutePathBuf {
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
Self::from_absolute_path(value)
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static ABSOLUTE_PATH_BASE: RefCell<Option<PathBuf>> = const { RefCell::new(None) };
|
||||
}
|
||||
@@ -96,18 +146,6 @@ impl<'de> Deserialize<'de> for AbsolutePathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for AbsolutePathBuf {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.as_path()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AbsolutePathBuf> for PathBuf {
|
||||
fn from(path: AbsolutePathBuf) -> Self {
|
||||
path.into_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user