mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: make the SFTP VFS provider's create_dir() and create_new() correctly report "file exists" errors (#3495)
This commit is contained in:
parent
81c66a645f
commit
e611de5284
6 changed files with 65 additions and 32 deletions
36
Cargo.lock
generated
36
Cargo.lock
generated
|
|
@ -599,9 +599,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.53"
|
||||
version = "4.5.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
|
||||
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -609,9 +609,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.53"
|
||||
version = "4.5.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
|
||||
checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -2106,9 +2106,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
version = "0.2.179"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f"
|
||||
|
||||
[[package]]
|
||||
name = "libcrux-intrinsics"
|
||||
|
|
@ -2889,9 +2889,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
|||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.8.4"
|
||||
version = "2.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22"
|
||||
checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"ucd-trie",
|
||||
|
|
@ -2899,9 +2899,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.8.4"
|
||||
version = "2.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f"
|
||||
checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
|
|
@ -2909,9 +2909,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.8.4"
|
||||
version = "2.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625"
|
||||
checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
|
|
@ -2922,9 +2922,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.8.4"
|
||||
version = "2.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82"
|
||||
checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"sha2 0.10.9",
|
||||
|
|
@ -4412,9 +4412,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.48.0"
|
||||
version = "1.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
|
||||
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
|
|
@ -5933,9 +5933,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de9211a9f64b825911bdf0240f58b7a8dac217fe260fc61f080a07f61372fbd5"
|
||||
checksum = "317f17ff091ac4515f17cc7a190d2769a8c9a96d227de5d64b500b01cda8f2cd"
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ ansi-to-tui = "8.0.0"
|
|||
anyhow = "1.0.100"
|
||||
base64 = "0.22.1"
|
||||
bitflags = { version = "2.10.0", features = [ "serde" ] }
|
||||
clap = { version = "4.5.53", features = [ "derive" ] }
|
||||
clap = { version = "4.5.54", features = [ "derive" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
|
||||
dirs = "6.0.0"
|
||||
|
|
@ -39,7 +39,7 @@ futures = "0.3.31"
|
|||
globset = "0.4.18"
|
||||
hashbrown = { version = "0.16.1", features = [ "serde" ] }
|
||||
indexmap = { version = "2.12.1", features = [ "serde" ] }
|
||||
libc = "0.2.178"
|
||||
libc = "0.2.179"
|
||||
lru = "0.16.2"
|
||||
mlua = { version = "0.11.5", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serde" ] }
|
||||
objc2 = "0.6.3"
|
||||
|
|
@ -56,7 +56,7 @@ serde = { version = "1.0.228", features = [ "derive" ] }
|
|||
serde_json = "1.0.148"
|
||||
syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
thiserror = "2.0.17"
|
||||
tokio = { version = "1.48.0", features = [ "full" ] }
|
||||
tokio = { version = "1.49.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-util = "0.7.17"
|
||||
toml = { version = "0.9.10" }
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ impl From<Error> for std::io::Error {
|
|||
responses::StatusCode::NoConnection => Self::from(std::io::ErrorKind::NotConnected),
|
||||
responses::StatusCode::ConnectionLost => Self::from(std::io::ErrorKind::ConnectionReset),
|
||||
responses::StatusCode::OpUnsupported => Self::from(std::io::ErrorKind::Unsupported),
|
||||
responses::StatusCode::InvalidHandle => Self::from(std::io::ErrorKind::InvalidInput),
|
||||
responses::StatusCode::NoSuchPath => Self::from(std::io::ErrorKind::NotFound),
|
||||
responses::StatusCode::FileAlreadyExists => Self::from(std::io::ErrorKind::AlreadyExists),
|
||||
responses::StatusCode::WriteProtect => Self::from(std::io::ErrorKind::PermissionDenied),
|
||||
responses::StatusCode::NoMedia => Self::from(std::io::ErrorKind::Other),
|
||||
},
|
||||
Error::Packet(e) => Self::new(std::io::ErrorKind::InvalidData, e),
|
||||
Error::Timeout => Self::from(std::io::ErrorKind::TimedOut),
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ impl Status {
|
|||
|
||||
pub fn is_eof(&self) -> bool { self.code == StatusCode::Eof }
|
||||
|
||||
pub fn is_failure(&self) -> bool { self.code == StatusCode::Failure }
|
||||
|
||||
pub(crate) fn connection_lost(id: u32) -> Self {
|
||||
Self {
|
||||
id,
|
||||
|
|
@ -40,13 +42,18 @@ impl Status {
|
|||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
|
||||
pub enum StatusCode {
|
||||
Ok = 0,
|
||||
Eof = 1,
|
||||
NoSuchFile = 2,
|
||||
PermissionDenied = 3,
|
||||
Failure = 4,
|
||||
BadMessage = 5,
|
||||
NoConnection = 6,
|
||||
ConnectionLost = 7,
|
||||
OpUnsupported = 8,
|
||||
Ok = 0,
|
||||
Eof = 1,
|
||||
NoSuchFile = 2,
|
||||
PermissionDenied = 3,
|
||||
Failure = 4,
|
||||
BadMessage = 5,
|
||||
NoConnection = 6,
|
||||
ConnectionLost = 7,
|
||||
OpUnsupported = 8,
|
||||
InvalidHandle = 9,
|
||||
NoSuchPath = 10,
|
||||
FileAlreadyExists = 11,
|
||||
WriteProtect = 12,
|
||||
NoMedia = 13,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,9 +68,20 @@ impl FileBuilder for Gate {
|
|||
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, format!("Not an SFTP URL: {url:?}")))?,
|
||||
};
|
||||
|
||||
let conn = Conn { name, config }.roll().await?;
|
||||
let flags = Flags::from(*self);
|
||||
let attrs = super::Attrs(self.0.attrs).try_into().unwrap_or_default();
|
||||
Ok(Conn { name, config }.roll().await?.open(path, flags, &attrs).await?)
|
||||
|
||||
let result = conn.open(path, flags, &attrs).await;
|
||||
if self.0.create_new
|
||||
&& let Err(yazi_sftp::Error::Status(status)) = &result
|
||||
&& status.is_failure()
|
||||
&& conn.lstat(path).await.is_ok()
|
||||
{
|
||||
return Err(io::Error::from(io::ErrorKind::AlreadyExists));
|
||||
}
|
||||
|
||||
Ok(result?)
|
||||
}
|
||||
|
||||
fn read(&mut self, read: bool) -> &mut Self {
|
||||
|
|
|
|||
|
|
@ -117,7 +117,17 @@ impl<'a> Provider for Sftp<'a> {
|
|||
}
|
||||
|
||||
async fn create_dir(&self) -> io::Result<()> {
|
||||
Ok(self.op().await?.mkdir(self.path, Attrs::default()).await?)
|
||||
let op = self.op().await?;
|
||||
let result = op.mkdir(self.path, Attrs::default()).await;
|
||||
|
||||
if let Err(yazi_sftp::Error::Status(status)) = &result
|
||||
&& status.is_failure()
|
||||
&& op.lstat(self.path).await.is_ok()
|
||||
{
|
||||
return Err(io::Error::from(io::ErrorKind::AlreadyExists));
|
||||
}
|
||||
|
||||
Ok(result?)
|
||||
}
|
||||
|
||||
async fn hard_link<P>(&self, to: P) -> io::Result<()>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue