Skip to content

Commit

Permalink
Stripped down unix path
Browse files Browse the repository at this point in the history
  • Loading branch information
gsoltis committed May 3, 2023
1 parent 85cfc59 commit cf70e49
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 93 deletions.
40 changes: 29 additions & 11 deletions crates/turbopath/src/absolute_system_path_buf.rs
Expand Up @@ -17,6 +17,7 @@ use serde::Serialize;

use crate::{
AnchoredSystemPathBuf, IntoSystem, PathError, PathValidationError, RelativeSystemPathBuf,
RelativeUnixPath,
};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize)]
Expand Down Expand Up @@ -51,10 +52,10 @@ impl AbsoluteSystemPathBuf {
/// #[cfg(not(windows))]
/// assert_eq!(absolute_path.as_path(), Path::new("/Users/user"));
/// ```
pub fn new(unchecked_path: impl Into<PathBuf>) -> Result<Self, PathValidationError> {
pub fn new(unchecked_path: impl Into<PathBuf>) -> Result<Self, PathError> {
let unchecked_path = unchecked_path.into();
if !unchecked_path.is_absolute() {
return Err(PathValidationError::NotAbsolute(unchecked_path));
return Err(PathValidationError::NotAbsolute(unchecked_path).into());
}

let system_path = unchecked_path.into_system()?;
Expand Down Expand Up @@ -90,10 +91,7 @@ impl AbsoluteSystemPathBuf {
/// assert_eq!(anchored_path.as_path(), Path::new("Documents"));
/// }
/// ```
pub fn anchor(
&self,
path: &AbsoluteSystemPathBuf,
) -> Result<AnchoredSystemPathBuf, PathValidationError> {
pub fn anchor(&self, path: &AbsoluteSystemPathBuf) -> Result<AnchoredSystemPathBuf, PathError> {
AnchoredSystemPathBuf::new(self, path)
}

Expand Down Expand Up @@ -127,6 +125,14 @@ impl AbsoluteSystemPathBuf {
AbsoluteSystemPathBuf(self.0.join(path.as_path()))
}

pub fn join_unix_path(
&self,
unix_path: &RelativeUnixPath,
) -> Result<AbsoluteSystemPathBuf, PathError> {
let tail = unix_path.to_system_path()?;
Ok(AbsoluteSystemPathBuf(self.0.join(tail.as_path())))
}

pub fn as_path(&self) -> &Path {
self.0.as_path()
}
Expand Down Expand Up @@ -268,15 +274,21 @@ mod tests {
#[cfg(not(windows))]
#[test]
fn test_absolute_system_path_buf_on_unix() {
use crate::PathError;

assert!(AbsoluteSystemPathBuf::new("/Users/user").is_ok());
assert_matches!(
AbsoluteSystemPathBuf::new("./Users/user/"),
Err(PathValidationError::NotAbsolute(_))
Err(PathError::PathValidationError(
PathValidationError::NotAbsolute(_)
))
);

assert_matches!(
AbsoluteSystemPathBuf::new("Users"),
Err(PathValidationError::NotAbsolute(_))
Err(PathError::PathValidationError(
PathValidationError::NotAbsolute(_)
))
);
}

Expand All @@ -286,15 +298,21 @@ mod tests {
assert!(AbsoluteSystemPathBuf::new("C:\\Users\\user").is_ok());
assert_matches!(
AbsoluteSystemPathBuf::new(".\\Users\\user\\"),
Err(PathValidationError::NotAbsolute(_))
Err(PathError::PathValidationError(
PathValidationError::NotAbsolute(_)
))
);
assert_matches!(
AbsoluteSystemPathBuf::new("Users"),
Err(PathValidationError::NotAbsolute(_))
Err(PathError::PathValidationError(
PathValidationError::NotAbsolute(_)
))
);
assert_matches!(
AbsoluteSystemPathBuf::new("/Users/home"),
Err(PathValidationError::NotAbsolute(_))
Err(PathError::PathValidationError(
PathValidationError::NotAbsolute(_)
))
)
}
}
12 changes: 6 additions & 6 deletions crates/turbopath/src/anchored_system_path_buf.rs
Expand Up @@ -2,17 +2,17 @@ use std::path::{Path, PathBuf};

use serde::{Deserialize, Serialize};

use crate::{AbsoluteSystemPathBuf, IntoSystem, PathValidationError};
use crate::{AbsoluteSystemPathBuf, IntoSystem, PathError, PathValidationError};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
pub struct AnchoredSystemPathBuf(PathBuf);

impl TryFrom<&Path> for AnchoredSystemPathBuf {
type Error = PathValidationError;
type Error = PathError;

fn try_from(path: &Path) -> Result<Self, Self::Error> {
if path.is_absolute() {
return Err(PathValidationError::NotRelative(path.to_path_buf()));
return Err(PathValidationError::NotRelative(path.to_path_buf()).into());
}

Ok(AnchoredSystemPathBuf(path.into_system()?))
Expand All @@ -23,7 +23,7 @@ impl AnchoredSystemPathBuf {
pub fn new(
root: &AbsoluteSystemPathBuf,
path: &AbsoluteSystemPathBuf,
) -> Result<Self, PathValidationError> {
) -> Result<Self, PathError> {
let stripped_path = path
.as_path()
.strip_prefix(root.as_path())
Expand All @@ -37,10 +37,10 @@ impl AnchoredSystemPathBuf {
self.0.as_path()
}

pub fn to_str(&self) -> Result<&str, PathValidationError> {
pub fn to_str(&self) -> Result<&str, PathError> {
self.0
.to_str()
.ok_or_else(|| PathValidationError::InvalidUnicode(self.0.clone()))
.ok_or_else(|| PathValidationError::InvalidUnicode(self.0.clone()).into())
}
}

Expand Down
4 changes: 4 additions & 0 deletions crates/turbopath/src/lib.rs
Expand Up @@ -3,6 +3,7 @@
mod absolute_system_path_buf;
mod anchored_system_path_buf;
mod relative_system_path_buf;
mod relative_unix_path;
mod relative_unix_path_buf;

use std::{
Expand All @@ -14,6 +15,7 @@ pub use absolute_system_path_buf::AbsoluteSystemPathBuf;
pub use anchored_system_path_buf::AnchoredSystemPathBuf;
use path_slash::{PathBufExt, PathExt};
pub use relative_system_path_buf::RelativeSystemPathBuf;
pub use relative_unix_path::RelativeUnixPath;
pub use relative_unix_path_buf::RelativeUnixPathBuf;

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -44,6 +46,8 @@ pub enum PathValidationError {
NotRelative(PathBuf),
#[error("Path {0} is not parent of {1}")]
NotParent(String, String),
#[error("Path {0} is not a unix path")]
NotUnix(String),
}

trait IntoSystem {
Expand Down
4 changes: 4 additions & 0 deletions crates/turbopath/src/relative_system_path_buf.rs
Expand Up @@ -43,6 +43,10 @@ impl RelativeSystemPathBuf {
Ok(RelativeSystemPathBuf(system_path))
}

pub(crate) fn new_unchecked(unchecked_path: impl Into<PathBuf>) -> Self {
Self(unchecked_path.into())
}

pub fn as_path(&self) -> &Path {
&self.0
}
Expand Down
25 changes: 25 additions & 0 deletions crates/turbopath/src/relative_unix_path.rs
@@ -0,0 +1,25 @@
use std::path::Path;

use crate::{IntoSystem, PathError, PathValidationError, RelativeSystemPathBuf};

pub struct RelativeUnixPath {
inner: Path,
}

impl RelativeUnixPath {
pub fn new<P: AsRef<Path>>(value: &P) -> Result<&Self, PathError> {
let path = value.as_ref();
if path.is_absolute() {
return Err(PathValidationError::NotRelative(path.to_owned()).into());
}
// copied from stdlib path.rs: relies on the representation of
// RelativeUnixPath being just a Path, the same way Path relies on
// just being an OsStr
Ok(unsafe { &*(path as *const Path as *const Self) })
}

pub fn to_system_path(&self) -> Result<RelativeSystemPathBuf, PathError> {
let system_path = self.inner.into_system()?;
Ok(RelativeSystemPathBuf::new_unchecked(system_path))
}
}
59 changes: 1 addition & 58 deletions crates/turbopath/src/relative_unix_path_buf.rs
@@ -1,7 +1,4 @@
use std::{
ffi::OsStr,
path::{Components, Path, PathBuf},
};
use std::path::PathBuf;

use serde::Serialize;

Expand Down Expand Up @@ -36,49 +33,11 @@ impl RelativeUnixPathBuf {
Ok(RelativeUnixPathBuf(path.into_unix()?))
}

pub fn as_path(&self) -> &Path {
&self.0
}

pub fn components(&self) -> Components<'_> {
self.0.components()
}

pub fn parent(&self) -> Option<Self> {
self.0
.parent()
.map(|p| RelativeUnixPathBuf(p.to_path_buf()))
}

pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
self.0.starts_with(base.as_ref())
}

pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
self.0.ends_with(child.as_ref())
}

pub fn join<P: AsRef<Path>>(&self, path: P) -> RelativeUnixPathBuf {
RelativeUnixPathBuf(self.0.join(path))
}

pub fn to_str(&self) -> Result<&str, PathValidationError> {
self.0
.to_str()
.ok_or_else(|| PathValidationError::InvalidUnicode(self.0.clone()))
}

pub fn file_name(&self) -> Option<&OsStr> {
self.0.file_name()
}

pub fn extension(&self) -> Option<&OsStr> {
self.0.extension()
}

pub fn into_path_buf(self) -> PathBuf {
self.0
}
}

#[cfg(test)]
Expand All @@ -88,29 +47,13 @@ mod tests {
#[test]
fn test_relative_unix_path_buf() {
let path = RelativeUnixPathBuf::new(PathBuf::from("foo/bar")).unwrap();
assert_eq!(path.as_path(), Path::new("foo/bar"));
assert_eq!(path.components().count(), 2);
assert_eq!(path.parent().unwrap().as_path(), Path::new("foo"));
assert!(path.starts_with("foo"));
assert!(path.ends_with("bar"));
assert_eq!(path.join("baz").as_path(), Path::new("foo/bar/baz"));
assert_eq!(path.to_str().unwrap(), "foo/bar");
assert_eq!(path.file_name(), Some(OsStr::new("bar")));
assert_eq!(path.extension(), None);
}

#[test]
fn test_relative_unix_path_buf_with_extension() {
let path = RelativeUnixPathBuf::new(PathBuf::from("foo/bar.txt")).unwrap();
assert_eq!(path.as_path(), Path::new("foo/bar.txt"));
assert_eq!(path.components().count(), 2);
assert_eq!(path.parent().unwrap().as_path(), Path::new("foo"));
assert!(path.starts_with("foo"));
assert!(path.ends_with("bar.txt"));
assert_eq!(path.join("baz").as_path(), Path::new("foo/bar.txt/baz"));
assert_eq!(path.to_str().unwrap(), "foo/bar.txt");
assert_eq!(path.file_name(), Some(OsStr::new("bar.txt")));
assert_eq!(path.extension(), Some(OsStr::new("txt")));
}

#[test]
Expand Down
23 changes: 10 additions & 13 deletions crates/turborepo-scm/src/git.rs
@@ -1,11 +1,6 @@
use std::{
backtrace::Backtrace,
collections::HashSet,
path::{Path, PathBuf},
process::Command,
};
use std::{backtrace::Backtrace, collections::HashSet, path::PathBuf, process::Command};

use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf};
use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf, RelativeUnixPath};

use crate::Error;

Expand Down Expand Up @@ -102,7 +97,7 @@ fn add_files_from_stdout(
) {
let stdout = String::from_utf8(stdout).unwrap();
for line in stdout.lines() {
let path = Path::new(line);
let path = RelativeUnixPath::new(&line).unwrap();
let anchored_to_turbo_root_file_path =
reanchor_path_from_git_root_to_turbo_root(git_root, turbo_root, path).unwrap();
files.insert(
Expand All @@ -117,10 +112,9 @@ fn add_files_from_stdout(
fn reanchor_path_from_git_root_to_turbo_root(
git_root: &AbsoluteSystemPathBuf,
turbo_root: &AbsoluteSystemPathBuf,
path: &Path,
path: &RelativeUnixPath,
) -> Result<AnchoredSystemPathBuf, Error> {
let anchored_to_git_root_file_path: AnchoredSystemPathBuf = path.try_into()?;
let absolute_file_path = git_root.resolve(&anchored_to_git_root_file_path);
let absolute_file_path = git_root.join_unix_path(path)?;
let anchored_to_turbo_root_file_path = turbo_root.anchor(&absolute_file_path)?;
Ok(anchored_to_turbo_root_file_path)
}
Expand Down Expand Up @@ -185,7 +179,7 @@ mod tests {

use git2::{Oid, Repository};
use tempfile::TempDir;
use turbopath::PathValidationError;
use turbopath::{PathError, PathValidationError};

use super::previous_content;
use crate::{git::changed_files, Error};
Expand Down Expand Up @@ -615,7 +609,10 @@ mod tests {

assert_matches!(
turbo_root_is_not_subdir_of_git_root,
Err(Error::Path(PathValidationError::NotParent(_, _), _))
Err(Error::Path(
PathError::PathValidationError(PathValidationError::NotParent(_, _)),
_
))
);

Ok(())
Expand Down
7 changes: 2 additions & 5 deletions crates/turborepo-scm/src/lib.rs
Expand Up @@ -5,7 +5,7 @@
use std::backtrace;

use thiserror::Error;
use turbopath::PathValidationError;
use turbopath::PathError;

pub mod git;

Expand All @@ -18,8 +18,5 @@ pub enum Error {
#[error("io error: {0}")]
Io(#[from] std::io::Error, #[backtrace] backtrace::Backtrace),
#[error("path error: {0}")]
Path(
#[from] PathValidationError,
#[backtrace] backtrace::Backtrace,
),
Path(#[from] PathError, #[backtrace] backtrace::Backtrace),
}

0 comments on commit cf70e49

Please sign in to comment.