Skip to content

Commit 205b7fe

Browse files
committed
refactor: rename the "provider" term in VFS config to "service" (#3403)
1 parent dccc9b2 commit 205b7fe

File tree

15 files changed

+118
-131
lines changed

15 files changed

+118
-131
lines changed

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

yazi-config/src/vfs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
yazi_macro::mod_flat!(provider vfs);
1+
yazi_macro::mod_flat!(service vfs);

yazi-config/src/vfs/provider.rs renamed to yazi-config/src/vfs/service.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ use yazi_fs::path::expand_url;
55

66
#[derive(Deserialize, Serialize)]
77
#[serde(tag = "type", rename_all = "kebab-case")]
8-
pub enum Provider {
9-
Sftp(ProviderSftp),
8+
pub enum Service {
9+
Sftp(ServiceSftp),
1010
}
1111

12-
impl TryFrom<&'static Provider> for &'static ProviderSftp {
12+
impl TryFrom<&'static Service> for &'static ServiceSftp {
1313
type Error = &'static str;
1414

15-
fn try_from(value: &'static Provider) -> Result<Self, Self::Error> {
15+
fn try_from(value: &'static Service) -> Result<Self, Self::Error> {
1616
match value {
17-
Provider::Sftp(p) => Ok(p),
17+
Service::Sftp(p) => Ok(p),
1818
}
1919
}
2020
}
2121

22-
impl Provider {
22+
impl Service {
2323
pub(super) fn reshape(&mut self) -> io::Result<()> {
2424
match self {
2525
Self::Sftp(p) => p.reshape(),
@@ -29,7 +29,7 @@ impl Provider {
2929

3030
// --- SFTP
3131
#[derive(Deserialize, Eq, Hash, PartialEq, Serialize)]
32-
pub struct ProviderSftp {
32+
pub struct ServiceSftp {
3333
pub host: String,
3434
pub user: String,
3535
pub port: u16,
@@ -41,7 +41,7 @@ pub struct ProviderSftp {
4141
pub identity_agent: PathBuf,
4242
}
4343

44-
impl ProviderSftp {
44+
impl ServiceSftp {
4545
fn reshape(&mut self) -> io::Result<()> {
4646
if !self.key_file.as_os_str().is_empty() {
4747
self.key_file = expand_url(&self.key_file)

yazi-config/src/vfs/vfs.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ use tokio::sync::OnceCell;
66
use yazi_fs::Xdg;
77
use yazi_macro::ok_or_not_found;
88

9-
use super::Provider;
9+
use super::Service;
1010

1111
#[derive(Deserialize, Serialize)]
1212
pub struct Vfs {
13-
pub providers: HashMap<String, Provider>,
13+
pub services: HashMap<String, Service>,
1414
}
1515

1616
impl Vfs {
@@ -27,16 +27,16 @@ impl Vfs {
2727
LOADED.get_or_try_init(init).await
2828
}
2929

30-
pub async fn provider<'a, P>(name: &str) -> io::Result<(&'a str, P)>
30+
pub async fn service<'a, P>(name: &str) -> io::Result<(&'a str, P)>
3131
where
32-
P: TryFrom<&'a Provider, Error = &'static str>,
32+
P: TryFrom<&'a Service, Error = &'static str>,
3333
{
34-
let Some((key, value)) = Self::load().await?.providers.get_key_value(name) else {
35-
return Err(io::Error::other(format!("No such VFS provider: {name}")));
34+
let Some((key, value)) = Self::load().await?.services.get_key_value(name) else {
35+
return Err(io::Error::other(format!("No such VFS service: {name}")));
3636
};
3737
match value.try_into() {
3838
Ok(p) => Ok((key.as_str(), p)),
39-
Err(e) => Err(io::Error::other(format!("VFS provider `{key}` has wrong type: {e}"))),
39+
Err(e) => Err(io::Error::other(format!("VFS service `{key}` has wrong type: {e}"))),
4040
}
4141
}
4242

@@ -48,14 +48,14 @@ impl Vfs {
4848
}
4949

5050
fn reshape(mut self) -> io::Result<Self> {
51-
for (name, provider) in &mut self.providers {
51+
for (name, service) in &mut self.services {
5252
if name.is_empty() || name.len() > 20 {
5353
Err(io::Error::other(format!("VFS name `{name}` must be between 1 and 20 characters")))?;
5454
} else if !name.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'z' | b'-')) {
5555
Err(io::Error::other(format!("VFS name `{name}` must be in kebab-case")))?;
5656
}
5757

58-
provider.reshape()?;
58+
service.reshape()?;
5959
}
6060

6161
Ok(self)

yazi-fs/src/path/path.rs

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,59 +9,3 @@ pub fn skip_url(url: &UrlBuf, n: usize) -> StrandCow<'_> {
99
}
1010
it.strand()
1111
}
12-
13-
#[cfg(test)]
14-
mod tests {
15-
use yazi_shared::url::{AsUrl, UrlCow};
16-
17-
use crate::path::url_relative_to;
18-
19-
#[test]
20-
fn test_url_relative_to() {
21-
yazi_shared::init_tests();
22-
23-
#[cfg(unix)]
24-
let cases = [
25-
// Same urls
26-
("", "", "."),
27-
(".", ".", "."),
28-
("/a", "/a", "."),
29-
("regular:///", "/", "."),
30-
("regular://", "regular://", "."),
31-
("regular://", "search://kw/", "search://kw/."),
32-
("regular:///b", "search://kw//b", "search://kw/."),
33-
// Relative urls
34-
("foo", "bar", "../bar"),
35-
// Absolute urls
36-
("/a/b/c", "/a/b", ".."),
37-
("/a/b", "/a/b/c", "c"),
38-
("/a/b/d", "/a/b/c", "../c"),
39-
("/a/b/c", "/a", "../.."),
40-
("/a/b/b", "/a/a/b", "../../a/b"),
41-
("regular:///a/b", "regular:///a/b/c", "c"),
42-
("/a/b/c/", "search://kw//a/d/", "search://kw/../../d"),
43-
("search://kw//a/b/c", "search://kw//a/b", "search://kw/.."),
44-
// Different schemes
45-
("", "sftp://test/", "sftp://test/"),
46-
("a", "sftp://test/", "sftp://test/"),
47-
("a", "sftp://test/b", "sftp://test/b"),
48-
("/a", "sftp://test//b", "sftp://test//b"),
49-
("sftp://test//a/b", "sftp://test//a/d", "sftp://test:0:0/../d"),
50-
];
51-
52-
#[cfg(windows)]
53-
let cases = [
54-
(r"C:\a\b\c", r"C:\a\b", r".."),
55-
(r"C:\a\b", r"C:\a\b\c", "c"),
56-
(r"C:\a\b\d", r"C:\a\b\c", r"..\c"),
57-
(r"C:\a\b\c", r"C:\a", r"..\.."),
58-
(r"C:\a\b\b", r"C:\a\a\b", r"..\..\a\b"),
59-
];
60-
61-
for (from, to, expected) in cases {
62-
let from: UrlCow = from.try_into().unwrap();
63-
let to: UrlCow = to.try_into().unwrap();
64-
assert_eq!(format!("{:?}", url_relative_to(from, to).unwrap().as_url()), expected);
65-
}
66-
}
67-
}

yazi-fs/src/path/relative.rs

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,35 @@
11
use anyhow::{Result, bail};
2-
use yazi_shared::{path::PathBufDyn, url::{UrlCow, UrlLike}};
2+
use yazi_shared::path::{PathBufDyn, PathCow, PathDyn, PathLike};
33

4-
pub fn url_relative_to<'a, 'b, U, V>(from: U, to: V) -> Result<UrlCow<'b>>
4+
pub fn path_relative_to<'a, 'b, P, Q>(from: P, to: Q) -> Result<PathCow<'b>>
55
where
6-
U: Into<UrlCow<'a>>,
7-
V: Into<UrlCow<'b>>,
6+
P: Into<PathCow<'a>>,
7+
Q: Into<PathCow<'b>>,
88
{
9-
url_relative_to_(from.into(), to.into())
9+
path_relative_to_impl(from.into(), to.into())
1010
}
1111

12-
fn url_relative_to_<'a>(from: UrlCow<'_>, to: UrlCow<'a>) -> Result<UrlCow<'a>> {
13-
use yazi_shared::url::Component::*;
12+
fn path_relative_to_impl<'a>(from: PathCow<'_>, to: PathCow<'a>) -> Result<PathCow<'a>> {
13+
use yazi_shared::path::Component::*;
1414

1515
if from.is_absolute() != to.is_absolute() {
1616
return if to.is_absolute() {
1717
Ok(to)
1818
} else {
19-
bail!("Urls must be both absolute or both relative: {from:?} and {to:?}");
19+
bail!("Paths must be both absolute or both relative: {from:?} and {to:?}");
2020
};
2121
}
2222

23-
if from.covariant(&to) {
24-
return UrlCow::try_from((
25-
to.scheme().zeroed().to_owned(),
26-
PathBufDyn::with_str(to.kind(), "."),
27-
));
23+
if from == to {
24+
return Ok(PathDyn::with_str(to.kind(), ".").into());
2825
}
2926

3027
let (mut f_it, mut t_it) = (from.components(), to.components());
3128
let (f_head, t_head) = loop {
3229
match (f_it.next(), t_it.next()) {
33-
(Some(Scheme(a)), Some(Scheme(b))) if a.covariant(b) => {}
3430
(Some(RootDir), Some(RootDir)) => {}
3531
(Some(Prefix(a)), Some(Prefix(b))) if a == b => {}
36-
(Some(Scheme(_) | Prefix(_) | RootDir), _) | (_, Some(Scheme(_) | Prefix(_) | RootDir)) => {
32+
(Some(Prefix(_) | RootDir), _) | (_, Some(Prefix(_) | RootDir)) => {
3733
return Ok(to);
3834
}
3935
(None, None) => break (None, None),
@@ -45,8 +41,51 @@ fn url_relative_to_<'a>(from: UrlCow<'_>, to: UrlCow<'a>) -> Result<UrlCow<'a>>
4541
let dots = f_head.into_iter().chain(f_it).map(|_| ParentDir);
4642
let rest = t_head.into_iter().chain(t_it);
4743

48-
let iter = dots.chain(rest).map(|c| c.downgrade().expect("path component from dot or normal"));
49-
let buf = PathBufDyn::from_components(to.kind(), iter)?;
44+
let buf = PathBufDyn::from_components(to.kind(), dots.chain(rest))?;
45+
Ok(buf.into())
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
use yazi_shared::path::PathDyn;
51+
52+
use super::*;
53+
54+
#[test]
55+
fn test_path_relative_to() {
56+
yazi_shared::init_tests();
5057

51-
UrlCow::try_from((to.scheme().zeroed().to_owned(), buf))
58+
#[cfg(unix)]
59+
let cases = [
60+
// Same paths
61+
("", "", "."),
62+
(".", ".", "."),
63+
("/", "/", "."),
64+
("/a", "/a", "."),
65+
// Relative paths
66+
("foo", "bar", "../bar"),
67+
// Absolute paths
68+
("/a/b", "/a/b/c", "c"),
69+
("/a/b/c", "/a/b", ".."),
70+
("/a/b/d", "/a/b/c", "../c"),
71+
("/a/b/c", "/a", "../.."),
72+
("/a/b/c/", "/a/d/", "../../d"),
73+
("/a/b/b", "/a/a/b", "../../a/b"),
74+
];
75+
76+
#[cfg(windows)]
77+
let cases = [
78+
(r"C:\a\b", r"C:\a\b\c", "c"),
79+
(r"C:\a\b\c", r"C:\a\b", r".."),
80+
(r"C:\a\b\d", r"C:\a\b\c", r"..\c"),
81+
(r"C:\a\b\c", r"C:\a", r"..\.."),
82+
(r"C:\a\b\b", r"C:\a\a\b", r"..\..\a\b"),
83+
];
84+
85+
for (from, to, expected) in cases {
86+
let from = PathDyn::Os(from.as_ref());
87+
let to = PathDyn::Os(to.as_ref());
88+
assert_eq!(path_relative_to(from, to).unwrap().to_str().unwrap(), expected);
89+
}
90+
}
5291
}

yazi-plugin/preset/plugins/fzf.lua

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ end)
1111
function M:entry()
1212
ya.emit("escape", { visual = true })
1313

14-
local _permit = ui.hide()
1514
local cwd, selected = state()
15+
if cwd.scheme.is_virtual then
16+
return ya.notify { title = "Fzf", content = "Not supported under virtual filesystems", timeout = 5, level = "warn" }
17+
end
1618

19+
local _permit = ui.hide()
1720
local output, err = M.run_with(cwd, selected)
1821
if not output then
1922
return ya.notify { title = "Fzf", content = tostring(err), timeout = 5, level = "error" }

yazi-plugin/preset/plugins/mime-remote.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ end
1717
function M:fetch(job)
1818
local updates, unknown, state = {}, {}, {}
1919
for i, file in ipairs(job.files) do
20-
if not file.cache then
20+
if file.cha.is_dummy then
21+
-- Skip dummy files
22+
elseif not file.cache then
2123
unknown[#unknown + 1] = file
2224
elseif not fs.cha(file.cache) then
2325
updates[file.url], state[i] = "vfs/absent", true

yazi-scheduler/src/file/file.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use std::{collections::VecDeque, hash::{BuildHasher, Hash, Hasher}};
1+
use std::{collections::VecDeque, hash::{BuildHasher, Hash, Hasher}, time::Duration};
22

33
use anyhow::{Context, Result, anyhow};
44
use tokio::{io::{self, ErrorKind::{AlreadyExists, NotFound}}, sync::mpsc};
55
use tracing::warn;
66
use yazi_config::YAZI;
7-
use yazi_fs::{Cwd, FsHash128, FsUrl, cha::Cha, ok_or_not_found, path::{skip_url, url_relative_to}, provider::{Attrs, DirReader, FileHolder, Provider, local::Local}};
7+
use yazi_fs::{Cwd, FsHash128, FsUrl, cha::Cha, ok_or_not_found, path::{path_relative_to, skip_url}, provider::{Attrs, DirReader, FileHolder, Provider, local::Local}};
88
use yazi_macro::ok_or_not_found;
99
use yazi_shared::{path::PathCow, timestamp_us, url::{AsUrl, UrlBuf, UrlCow, UrlLike}};
1010
use yazi_vfs::{VfsCha, maybe_exists, provider::{self, DirEntry}, unique_name};
@@ -132,27 +132,27 @@ impl File {
132132
}
133133

134134
pub(crate) async fn link_do(&self, task: FileInLink) -> Result<(), FileOutLink> {
135-
let src: PathCow = if task.resolve {
135+
if !task.from.scheme().covariant(task.to.scheme()) {
136+
Err(anyhow!("Source and target must be on the same filesystem: {task:?}"))?
137+
}
138+
139+
let mut src: PathCow = if task.resolve {
136140
ok_or_not_found!(
137141
provider::read_link(&task.from).await,
138142
return Ok(self.ops.out(task.id, FileOutLink::Succ))
139143
)
140144
.into()
141-
} else if task.from.scheme().covariant(task.to.scheme()) {
142-
task.from.loc().into()
143145
} else {
144-
Err(anyhow!("Source and target must be on the same filesystem: {task:?}"))?
146+
task.from.loc().into()
145147
};
146148

147-
let src = UrlCow::try_from((task.from.scheme(), src))?;
148-
let src = if task.relative {
149-
url_relative_to(provider::canonicalize(task.to.parent().unwrap()).await?, &src)?
150-
} else {
151-
src
152-
};
149+
if task.relative {
150+
let canon = provider::canonicalize(task.to.parent().unwrap()).await?;
151+
src = path_relative_to(canon.loc(), src)?;
152+
}
153153

154154
ok_or_not_found!(provider::remove_file(&task.to).await);
155-
provider::symlink(&src, &task.to, async || {
155+
provider::symlink(task.to, src, async || {
156156
Ok(match task.cha {
157157
Some(cha) => cha.is_dir(),
158158
None => Self::cha(&task.from, task.resolve, None).await?.is_dir(),

yazi-shared/src/path/cow.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ impl From<PathCow<'_>> for PathBufDyn {
2727
fn from(value: PathCow<'_>) -> Self { value.into_owned() }
2828
}
2929

30+
impl PartialEq for PathCow<'_> {
31+
fn eq(&self, other: &Self) -> bool { self.as_path() == other.as_path() }
32+
}
33+
3034
impl PartialEq<&str> for PathCow<'_> {
3135
fn eq(&self, other: &&str) -> bool {
3236
match self {

0 commit comments

Comments
 (0)