From a2a44c07ad75b6499927c8a05f272959268efb28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:09:52 +0000 Subject: [PATCH 1/3] Deps: Bump AWSSDK.S3 from 3.7.504.1 to 4.0.11.2 --- updated-dependencies: - dependency-name: AWSSDK.S3 dependency-version: 4.0.11.2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- src/SharpSync/SharpSync.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpSync/SharpSync.csproj b/src/SharpSync/SharpSync.csproj index b9a39ac..b310d87 100644 --- a/src/SharpSync/SharpSync.csproj +++ b/src/SharpSync/SharpSync.csproj @@ -39,7 +39,7 @@ - + From 05a52c3837965c75520ed363f01e32ddc2e0a6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Polykanine?= Date: Thu, 13 Nov 2025 22:17:43 +0100 Subject: [PATCH 2/3] Fix new types after update --- src/SharpSync/Storage/S3Storage.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SharpSync/Storage/S3Storage.cs b/src/SharpSync/Storage/S3Storage.cs index bbe6892..da7b6d0 100644 --- a/src/SharpSync/Storage/S3Storage.cs +++ b/src/SharpSync/Storage/S3Storage.cs @@ -220,8 +220,8 @@ public async Task> ListItemsAsync(string path, Cancellatio items.Add(new SyncItem { Path = relativePath, IsDirectory = false, - Size = s3Object.Size, - LastModified = s3Object.LastModified.ToUniversalTime(), + Size = s3Object.Size ?? 0, + LastModified = s3Object.LastModified?.ToUniversalTime() ?? DateTime.UtcNow, ETag = s3Object.ETag?.Trim('"'), MimeType = GetMimeType(s3Object.Key), Metadata = new Dictionary { @@ -250,7 +250,7 @@ public async Task> ListItemsAsync(string path, Cancellatio } request.ContinuationToken = response.NextContinuationToken; - } while (response.IsTruncated); + } while (response is not null && response.IsTruncated.GetValueOrDefault()); return (IEnumerable)items; }, cancellationToken); @@ -279,7 +279,7 @@ public async Task> ListItemsAsync(string path, Cancellatio Path = path, IsDirectory = false, Size = response.ContentLength, - LastModified = response.LastModified.ToUniversalTime(), + LastModified = response.LastModified?.ToUniversalTime() ?? DateTime.UtcNow, ETag = response.ETag?.Trim('"'), MimeType = response.Headers.ContentType, Metadata = new Dictionary { @@ -526,7 +526,7 @@ private async Task DeleteDirectoryRecursive(string prefix, CancellationToken can } listRequest.ContinuationToken = response.NextContinuationToken; - } while (response.IsTruncated); + } while (response is not null && response.IsTruncated.GetValueOrDefault()); // Also delete the directory marker if it exists try { From b44fdf821363be715d90027df84ce6e3a5a7e718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Polykanine?= Date: Thu, 13 Nov 2025 22:40:59 +0100 Subject: [PATCH 3/3] Fix more nullability issues --- src/SharpSync/Storage/S3Storage.cs | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/SharpSync/Storage/S3Storage.cs b/src/SharpSync/Storage/S3Storage.cs index da7b6d0..6e562c3 100644 --- a/src/SharpSync/Storage/S3Storage.cs +++ b/src/SharpSync/Storage/S3Storage.cs @@ -207,15 +207,16 @@ public async Task> ListItemsAsync(string path, Cancellatio response = await _client.ListObjectsV2Async(request, cancellationToken); // Add files (objects) - foreach (var s3Object in response.S3Objects) { + var s3Objects = response?.S3Objects ?? Enumerable.Empty(); + foreach (var s3Object in s3Objects) { cancellationToken.ThrowIfCancellationRequested(); // Skip directory marker objects (keys ending with '/') - if (s3Object.Key.EndsWith('/')) { + if (s3Object.Key is not null && s3Object.Key.EndsWith('/')) { continue; } - var relativePath = GetRelativePath(s3Object.Key); + var relativePath = GetRelativePath(s3Object.Key ?? string.Empty); items.Add(new SyncItem { Path = relativePath, @@ -223,7 +224,7 @@ public async Task> ListItemsAsync(string path, Cancellatio Size = s3Object.Size ?? 0, LastModified = s3Object.LastModified?.ToUniversalTime() ?? DateTime.UtcNow, ETag = s3Object.ETag?.Trim('"'), - MimeType = GetMimeType(s3Object.Key), + MimeType = GetMimeType(s3Object.Key ?? string.Empty), Metadata = new Dictionary { ["StorageClass"] = s3Object.StorageClass?.Value ?? "STANDARD" } @@ -231,25 +232,25 @@ public async Task> ListItemsAsync(string path, Cancellatio } // Add directories (common prefixes) - foreach (var commonPrefix in response.CommonPrefixes) { + var commonPrefixes = response?.CommonPrefixes ?? Enumerable.Empty(); + foreach (var commonPrefix in commonPrefixes) { cancellationToken.ThrowIfCancellationRequested(); // CommonPrefix includes trailing slash, remove it for relative path var relativePath = GetRelativePath(commonPrefix.TrimEnd('/')); - // Avoid duplicates using HashSet.Add's return value (CA1868) if (directories.Add(relativePath)) { items.Add(new SyncItem { Path = relativePath, IsDirectory = true, Size = 0, - LastModified = DateTime.UtcNow, // S3 doesn't track directory timestamps + LastModified = DateTime.UtcNow, MimeType = null }); } } - request.ContinuationToken = response.NextContinuationToken; + request.ContinuationToken = response?.NextContinuationToken; } while (response is not null && response.IsTruncated.GetValueOrDefault()); return (IEnumerable)items; @@ -296,7 +297,10 @@ public async Task> ListItemsAsync(string path, Cancellatio var listResponse = await _client.ListObjectsV2Async(listRequest, cancellationToken); - if (listResponse.S3Objects.Count > 0 || listResponse.CommonPrefixes.Count > 0) { + var hasObjects = listResponse?.S3Objects is not null && listResponse.S3Objects.Count > 0; + var hasPrefixes = listResponse?.CommonPrefixes is not null && listResponse.CommonPrefixes.Count > 0; + + if (hasObjects || hasPrefixes) { return new SyncItem { Path = path, IsDirectory = true, @@ -479,7 +483,7 @@ await ExecuteWithRetry(async () => { // First, try to get the item to determine if it's a file or directory var item = await GetItemAsync(path, cancellationToken); - if (item == null) { + if (item is null) { return true; // Already deleted } @@ -514,18 +518,17 @@ private async Task DeleteDirectoryRecursive(string prefix, CancellationToken can ListObjectsV2Response? response; do { response = await _client.ListObjectsV2Async(listRequest, cancellationToken); - - if (response.S3Objects.Count > 0) { - // Delete objects in batches (S3 allows up to 1000 objects per request) + var objectsToDelete = response?.S3Objects ?? Enumerable.Empty(); + if (objectsToDelete.Any()) { var deleteRequest = new DeleteObjectsRequest { BucketName = _bucketName, - Objects = response.S3Objects.Select(obj => new KeyVersion { Key = obj.Key }).ToList() + Objects = objectsToDelete.Select(obj => new KeyVersion { Key = obj.Key }).ToList() }; await _client.DeleteObjectsAsync(deleteRequest, cancellationToken); } - listRequest.ContinuationToken = response.NextContinuationToken; + listRequest.ContinuationToken = response?.NextContinuationToken; } while (response is not null && response.IsTruncated.GetValueOrDefault()); // Also delete the directory marker if it exists