Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/fs-windows-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fs": patch
---

Fix can't use Windows paths like `C:/Users/UserName/file.txt`
23 changes: 20 additions & 3 deletions plugins/fs/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,26 @@ use crate::{scope::Entry, Error, FilePath, FsExt};
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum SafeFilePath {
#[serde(deserialize_with = "deserialize_url")]
Url(url::Url),
Path(SafePathBuf),
}

fn deserialize_url<'de, D>(deserializer: D) -> Result<url::Url, D::Error>
where
D: serde::Deserializer<'de>,
{
let url = url::Url::deserialize(deserializer)?;
let scheme = url.scheme();
if scheme.len() != 1 {
Ok(url)
} else {
Err(serde::de::Error::custom(format!(
"Single letter scheme \"{scheme}\" is not supported because it conflicts with Windows paths"
)))
}
}

impl From<SafeFilePath> for FilePath {
fn from(value: SafeFilePath) -> Self {
match value {
Expand All @@ -43,10 +59,11 @@ impl FromStr for SafeFilePath {
type Err = CommandError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(url) = url::Url::from_str(s) {
Ok(Self::Url(url))
} else {
Ok(Self::Path(SafePathBuf::new(s.into())?))
if url.scheme().len() != 1 {
return Ok(Self::Url(url));
}
}
Ok(Self::Path(SafePathBuf::new(s.into())?))
}
}

Expand Down
23 changes: 20 additions & 3 deletions plugins/fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,35 @@ type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum FilePath {
#[serde(deserialize_with = "deserialize_url")]
Url(url::Url),
Path(PathBuf),
}

fn deserialize_url<'de, D>(deserializer: D) -> std::result::Result<url::Url, D::Error>
where
D: serde::Deserializer<'de>,
{
let url: url::Url = Deserialize::deserialize::<D>(deserializer)?;
let scheme = url.scheme();
if scheme.len() != 1 {
Ok(url)
} else {
Err(serde::de::Error::custom(format!(
"Single letter scheme \"{scheme}\" is not supported because it conflicts with Windows paths"
)))
}
}

impl FromStr for FilePath {
type Err = Infallible;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
if let Ok(url) = url::Url::from_str(s) {
Ok(Self::Url(url))
} else {
Ok(Self::Path(PathBuf::from(s)))
if url.scheme().len() != 1 {
return Ok(Self::Url(url));
}
}
Ok(Self::Path(PathBuf::from(s)))
}
}

Expand Down