Compare commits

...

2 Commits

Author SHA1 Message Date
Zhengchao An 830055ba9c Merge branch 'main' into codex/backlog-1548-protocols-workspace-lints 2026-07-29 22:35:01 +08:00
overtrue a8c2e3e253 ci(protocols): inherit workspace lint policy 2026-07-29 21:45:10 +08:00
9 changed files with 20 additions and 24 deletions
+3
View File
@@ -25,6 +25,9 @@ description = "Protocol implementations for RustFS (FTPS, SFTP, etc.)"
keywords = ["ftp", "sftp", "protocol", "storage", "rustfs"] keywords = ["ftp", "sftp", "protocol", "storage", "rustfs"]
categories = ["network-programming", "filesystem"] categories = ["network-programming", "filesystem"]
[lints]
workspace = true
[features] [features]
default = [] default = []
ftps = ["dep:libunftp", "dep:unftp-core", "dep:rustls", "dep:rustfs-tls-runtime", "dep:subtle"] ftps = ["dep:libunftp", "dep:unftp-core", "dep:rustls", "dep:rustfs-tls-runtime", "dep:subtle"]
+5 -5
View File
@@ -608,7 +608,7 @@ impl StorageBackend for DummyBackend {
inner.put_object_calls.push(PutObjectCall { inner.put_object_calls.push(PutObjectCall {
bucket: input.bucket.to_string(), bucket: input.bucket.to_string(),
key: input.key.to_string(), key: input.key.to_string(),
metadata: input.metadata.clone(), metadata: input.metadata,
}); });
let stall = inner.stall_put_object; let stall = inner.stall_put_object;
let entered = inner.put_object_entered.clone(); let entered = inner.put_object_entered.clone();
@@ -731,7 +731,7 @@ impl StorageBackend for DummyBackend {
inner.create_multipart_calls.push(CreateMultipartCall { inner.create_multipart_calls.push(CreateMultipartCall {
bucket: input.bucket.to_string(), bucket: input.bucket.to_string(),
key: input.key.to_string(), key: input.key.to_string(),
metadata: input.metadata.clone(), metadata: input.metadata,
}); });
} }
match self.inner.lock().expect("lock").create_multipart_upload.pop_front() { match self.inner.lock().expect("lock").create_multipart_upload.pop_front() {
@@ -749,7 +749,7 @@ impl StorageBackend for DummyBackend {
inner.upload_part_calls.push(UploadPartCall { inner.upload_part_calls.push(UploadPartCall {
bucket: input.bucket.to_string(), bucket: input.bucket.to_string(),
key: input.key.to_string(), key: input.key.to_string(),
upload_id: input.upload_id.to_string(), upload_id: input.upload_id,
part_number: input.part_number, part_number: input.part_number,
content_length: input.content_length, content_length: input.content_length,
}); });
@@ -787,7 +787,7 @@ impl StorageBackend for DummyBackend {
inner.complete_multipart_calls.push(CompleteCall { inner.complete_multipart_calls.push(CompleteCall {
bucket: input.bucket.to_string(), bucket: input.bucket.to_string(),
key: input.key.to_string(), key: input.key.to_string(),
upload_id: input.upload_id.to_string(), upload_id: input.upload_id,
part_count, part_count,
}); });
} }
@@ -808,7 +808,7 @@ impl StorageBackend for DummyBackend {
inner.abort_multipart_calls.push(AbortCall { inner.abort_multipart_calls.push(AbortCall {
bucket: input.bucket.to_string(), bucket: input.bucket.to_string(),
key: input.key.to_string(), key: input.key.to_string(),
upload_id: input.upload_id.to_string(), upload_id: input.upload_id,
}); });
} }
match self.inner.lock().expect("lock").abort_multipart_upload.pop_front() { match self.inner.lock().expect("lock").abort_multipart_upload.pop_front() {
+1 -3
View File
@@ -379,9 +379,7 @@ where
.await .await
.map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?; .map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?;
let prefix_with_slash = prefix let prefix_with_slash = prefix.clone().map(|p| if p.ends_with('/') { p } else { format!("{}/", p) });
.clone()
.map(|p| if p.ends_with('/') { p.to_string() } else { format!("{}/", p) });
let list_input = ListObjectsV2Input::builder() let list_input = ListObjectsV2Input::builder()
.bucket(bucket) .bucket(bucket)
+1 -1
View File
@@ -371,7 +371,7 @@ impl UserDetailProvider for FtpsUserDetailProvider {
let ftps_user = FtpsUser { let ftps_user = FtpsUser {
username: principal.username.clone(), username: principal.username.clone(),
name: identity.credentials.name.clone(), name: identity.credentials.name,
session_context, session_context,
}; };
+2 -2
View File
@@ -1495,12 +1495,12 @@ mod tests {
let buffer_len_u64 = part_buffer_len as u64; let buffer_len_u64 = part_buffer_len as u64;
let phase = match phase_variant { let phase = match phase_variant {
0 => WritePhase::Buffering { 0 => WritePhase::Buffering {
part_buffer: part_buffer.clone(), part_buffer,
}, },
1 => WritePhase::Streaming { 1 => WritePhase::Streaming {
upload_id: "UP-proptest".to_string(), upload_id: "UP-proptest".to_string(),
abort_authorized: true, abort_authorized: true,
part_buffer: part_buffer.clone(), part_buffer,
uploaded_parts: Vec::new(), uploaded_parts: Vec::new(),
next_part_number, next_part_number,
}, },
+1 -3
View File
@@ -627,9 +627,7 @@ mod tests {
#[test] #[test]
fn test_parse_paths_with_empty_lines() { fn test_parse_paths_with_empty_lines() {
let body = "/container1/file1.txt\n\n/container2/file2.txt\n \n/container1/file3.txt"; let body = "/container1/file1.txt\n\n/container2/file2.txt\n \n/container1/file3.txt";
let paths: Vec<&str> = body.lines().filter(|line| !line.trim().is_empty()).collect(); assert_eq!(body.lines().filter(|line| !line.trim().is_empty()).count(), 3);
assert_eq!(paths.len(), 3);
} }
/// Tests for the `extract_tar_entries` async function. /// Tests for the `extract_tar_entries` async function.
+1 -2
View File
@@ -206,10 +206,9 @@ impl ObjectKeyMapper {
#[allow(dead_code)] // Used in: object operations #[allow(dead_code)] // Used in: object operations
pub fn normalize_path(object: &str) -> String { pub fn normalize_path(object: &str) -> String {
// Split by '/', filter out empty segments (except if it's the end) // Split by '/', filter out empty segments (except if it's the end)
let segments: Vec<&str> = object.split('/').collect();
let has_trailing_slash = object.ends_with('/'); let has_trailing_slash = object.ends_with('/');
let normalized_segments: Vec<&str> = segments.into_iter().filter(|s| !s.is_empty()).collect(); let normalized_segments: Vec<&str> = object.split('/').filter(|s| !s.is_empty()).collect();
let mut result = normalized_segments.join("/"); let mut result = normalized_segments.join("/");
+4 -4
View File
@@ -222,7 +222,7 @@ where
created: modified, created: modified,
is_dir: false, is_dir: false,
etag: output.e_tag.as_ref().map(etag_to_string), etag: output.e_tag.as_ref().map(etag_to_string),
content_type: output.content_type.map(|c| c.to_string()), content_type: output.content_type,
}) as Box<dyn DavMetaData>) }) as Box<dyn DavMetaData>)
} }
Err(e) => { Err(e) => {
@@ -1185,7 +1185,7 @@ where
created: modified, created: modified,
is_dir: false, is_dir: false,
etag: output.e_tag.as_ref().map(etag_to_string), etag: output.e_tag.as_ref().map(etag_to_string),
content_type: output.content_type.map(|c| c.to_string()), content_type: output.content_type,
}) as Box<dyn DavMetaData>) }) as Box<dyn DavMetaData>)
} }
ResolvedPath::Directory { metadata, .. } => { ResolvedPath::Directory { metadata, .. } => {
@@ -1204,7 +1204,7 @@ where
created: modified, created: modified,
is_dir: true, is_dir: true,
etag: metadata.as_ref().and_then(|output| output.e_tag.as_ref().map(etag_to_string)), etag: metadata.as_ref().and_then(|output| output.e_tag.as_ref().map(etag_to_string)),
content_type: metadata.and_then(|output| output.content_type.map(|c| c.to_string())), content_type: metadata.and_then(|output| output.content_type),
}) as Box<dyn DavMetaData>) }) as Box<dyn DavMetaData>)
} }
}; };
@@ -2035,7 +2035,7 @@ mod tests {
_access_key: &str, _access_key: &str,
_secret_key: &str, _secret_key: &str,
) -> Result<ListObjectsV2Output, Self::Error> { ) -> Result<ListObjectsV2Output, Self::Error> {
let prefix = input.prefix.map(|p| p.to_string()).unwrap_or_default(); let prefix = input.prefix.unwrap_or_default();
let mut keys: Vec<String> = self let mut keys: Vec<String> = self
.state .state
.lock() .lock()
@@ -436,12 +436,10 @@ fn test_symlink_to_nested_object() {
fn test_listing_empty_container() { fn test_listing_empty_container() {
let objects: Vec<&str> = vec![]; let objects: Vec<&str> = vec![];
let filtered: Vec<_> = objects.iter().collect(); assert!(objects.is_empty());
assert_eq!(filtered.len(), 0);
// With prefix // With prefix
let with_prefix: Vec<_> = objects.iter().filter(|o| o.starts_with("prefix/")).collect(); assert!(!objects.iter().any(|o| o.starts_with("prefix/")));
assert_eq!(with_prefix.len(), 0);
} }
/// Test listing lexicographic ordering /// Test listing lexicographic ordering