mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-29 17:48:58 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 830055ba9c | |||
| a8c2e3e253 |
@@ -25,6 +25,9 @@ description = "Protocol implementations for RustFS (FTPS, SFTP, etc.)"
|
||||
keywords = ["ftp", "sftp", "protocol", "storage", "rustfs"]
|
||||
categories = ["network-programming", "filesystem"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
ftps = ["dep:libunftp", "dep:unftp-core", "dep:rustls", "dep:rustfs-tls-runtime", "dep:subtle"]
|
||||
|
||||
@@ -608,7 +608,7 @@ impl StorageBackend for DummyBackend {
|
||||
inner.put_object_calls.push(PutObjectCall {
|
||||
bucket: input.bucket.to_string(),
|
||||
key: input.key.to_string(),
|
||||
metadata: input.metadata.clone(),
|
||||
metadata: input.metadata,
|
||||
});
|
||||
let stall = inner.stall_put_object;
|
||||
let entered = inner.put_object_entered.clone();
|
||||
@@ -731,7 +731,7 @@ impl StorageBackend for DummyBackend {
|
||||
inner.create_multipart_calls.push(CreateMultipartCall {
|
||||
bucket: input.bucket.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() {
|
||||
@@ -749,7 +749,7 @@ impl StorageBackend for DummyBackend {
|
||||
inner.upload_part_calls.push(UploadPartCall {
|
||||
bucket: input.bucket.to_string(),
|
||||
key: input.key.to_string(),
|
||||
upload_id: input.upload_id.to_string(),
|
||||
upload_id: input.upload_id,
|
||||
part_number: input.part_number,
|
||||
content_length: input.content_length,
|
||||
});
|
||||
@@ -787,7 +787,7 @@ impl StorageBackend for DummyBackend {
|
||||
inner.complete_multipart_calls.push(CompleteCall {
|
||||
bucket: input.bucket.to_string(),
|
||||
key: input.key.to_string(),
|
||||
upload_id: input.upload_id.to_string(),
|
||||
upload_id: input.upload_id,
|
||||
part_count,
|
||||
});
|
||||
}
|
||||
@@ -808,7 +808,7 @@ impl StorageBackend for DummyBackend {
|
||||
inner.abort_multipart_calls.push(AbortCall {
|
||||
bucket: input.bucket.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() {
|
||||
|
||||
@@ -379,9 +379,7 @@ where
|
||||
.await
|
||||
.map_err(|_| Error::new(ErrorKind::PermanentFileNotAvailable, "Access denied"))?;
|
||||
|
||||
let prefix_with_slash = prefix
|
||||
.clone()
|
||||
.map(|p| if p.ends_with('/') { p.to_string() } else { format!("{}/", p) });
|
||||
let prefix_with_slash = prefix.clone().map(|p| if p.ends_with('/') { p } else { format!("{}/", p) });
|
||||
|
||||
let list_input = ListObjectsV2Input::builder()
|
||||
.bucket(bucket)
|
||||
|
||||
@@ -371,7 +371,7 @@ impl UserDetailProvider for FtpsUserDetailProvider {
|
||||
|
||||
let ftps_user = FtpsUser {
|
||||
username: principal.username.clone(),
|
||||
name: identity.credentials.name.clone(),
|
||||
name: identity.credentials.name,
|
||||
session_context,
|
||||
};
|
||||
|
||||
|
||||
@@ -1495,12 +1495,12 @@ mod tests {
|
||||
let buffer_len_u64 = part_buffer_len as u64;
|
||||
let phase = match phase_variant {
|
||||
0 => WritePhase::Buffering {
|
||||
part_buffer: part_buffer.clone(),
|
||||
part_buffer,
|
||||
},
|
||||
1 => WritePhase::Streaming {
|
||||
upload_id: "UP-proptest".to_string(),
|
||||
abort_authorized: true,
|
||||
part_buffer: part_buffer.clone(),
|
||||
part_buffer,
|
||||
uploaded_parts: Vec::new(),
|
||||
next_part_number,
|
||||
},
|
||||
|
||||
@@ -627,9 +627,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_parse_paths_with_empty_lines() {
|
||||
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!(paths.len(), 3);
|
||||
assert_eq!(body.lines().filter(|line| !line.trim().is_empty()).count(), 3);
|
||||
}
|
||||
|
||||
/// Tests for the `extract_tar_entries` async function.
|
||||
|
||||
@@ -206,10 +206,9 @@ impl ObjectKeyMapper {
|
||||
#[allow(dead_code)] // Used in: object operations
|
||||
pub fn normalize_path(object: &str) -> String {
|
||||
// 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 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("/");
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ where
|
||||
created: modified,
|
||||
is_dir: false,
|
||||
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>)
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -1185,7 +1185,7 @@ where
|
||||
created: modified,
|
||||
is_dir: false,
|
||||
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>)
|
||||
}
|
||||
ResolvedPath::Directory { metadata, .. } => {
|
||||
@@ -1204,7 +1204,7 @@ where
|
||||
created: modified,
|
||||
is_dir: true,
|
||||
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>)
|
||||
}
|
||||
};
|
||||
@@ -2035,7 +2035,7 @@ mod tests {
|
||||
_access_key: &str,
|
||||
_secret_key: &str,
|
||||
) -> 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
|
||||
.state
|
||||
.lock()
|
||||
|
||||
@@ -436,12 +436,10 @@ fn test_symlink_to_nested_object() {
|
||||
fn test_listing_empty_container() {
|
||||
let objects: Vec<&str> = vec![];
|
||||
|
||||
let filtered: Vec<_> = objects.iter().collect();
|
||||
assert_eq!(filtered.len(), 0);
|
||||
assert!(objects.is_empty());
|
||||
|
||||
// With prefix
|
||||
let with_prefix: Vec<_> = objects.iter().filter(|o| o.starts_with("prefix/")).collect();
|
||||
assert_eq!(with_prefix.len(), 0);
|
||||
assert!(!objects.iter().any(|o| o.starts_with("prefix/")));
|
||||
}
|
||||
|
||||
/// Test listing lexicographic ordering
|
||||
|
||||
Reference in New Issue
Block a user