From c9c46db77e44380f76b247dd6fde34dae5f719fe Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 4 Feb 2026 14:33:46 -0800 Subject: [PATCH] s3api: fix ListObjectVersions inconsistency with delimiters (#8210) * s3api: fix ListObjectVersions inconsistency with delimiters (fixes #8206) Prioritize handling of .versions and .uploads directories before delimiter processing in collectVersions. This ensures .versions directories are processed as version containers instead of being incorrectly rolled up into CommonPrefixes when a delimiter is used. * s3api: refactor processDirectory to remove redundant special directory checks These checks are now handled in the main collectVersions loop. --- weed/s3api/s3api_object_versioning.go | 28 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/weed/s3api/s3api_object_versioning.go b/weed/s3api/s3api_object_versioning.go index 1b8ae333f..9147ebbdf 100644 --- a/weed/s3api/s3api_object_versioning.go +++ b/weed/s3api/s3api_object_versioning.go @@ -640,6 +640,24 @@ func (vc *versionCollector) collectVersions(currentPath, relativePath string) er continue } + // Handle special directories that should bypass delimiter logic + // This ensures .versions directories are processed as version containers + // rather than being rolled up into CommonPrefixes when a delimiter is used + if entry.IsDirectory { + // Skip .uploads directory + if strings.HasPrefix(entry.Name, s3_constants.MultipartUploadsFolder) { + continue + } + + // Handle .versions directory + if strings.HasSuffix(entry.Name, s3_constants.VersionsFolder) { + if err := vc.processVersionsDirectory(entryPath); err != nil { + return err + } + continue + } + } + // Group into common prefixes if delimiter is found after the prefix if vc.delimiter != "" { fullKey := entryPath @@ -688,16 +706,6 @@ func (vc *versionCollector) collectVersions(currentPath, relativePath string) er // processDirectory handles directory entries func (vc *versionCollector) processDirectory(currentPath, entryPath string, entry *filer_pb.Entry) error { - // Skip .uploads directory - if strings.HasPrefix(entry.Name, ".uploads") { - return nil - } - - // Handle .versions directory - if strings.HasSuffix(entry.Name, s3_constants.VersionsFolder) { - return vc.processVersionsDirectory(entryPath) - } - // Handle explicit S3 directory object if entry.Attributes.Mime == s3_constants.FolderMimeType { vc.processExplicitDirectory(entryPath, entry)