Merge pull request #1184 from versity/sis/deleteobject-non-empty-dir-obj

fix: Fixes non empty directory objects deletion
This commit is contained in:
Ben McClelland
2025-04-02 13:09:48 -07:00
committed by GitHub
3 changed files with 58 additions and 1 deletions

View File

@@ -3224,7 +3224,22 @@ func (p *Posix) DeleteObject(ctx context.Context, input *s3.DeleteObjectInput) (
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENOTEMPTY) {
return nil, s3err.GetAPIError(s3err.ErrDirectoryNotEmpty)
// If the directory object has been uploaded explicitly
// remove the directory object (remove the ETag)
_, err = p.meta.RetrieveAttribute(nil, objpath, "", etagkey)
if err != nil && !errors.Is(err, meta.ErrNoSuchKey) {
return nil, fmt.Errorf("get object etag: %w", err)
}
if errors.Is(err, meta.ErrNoSuchKey) {
return nil, s3err.GetAPIError(s3err.ErrDirectoryNotEmpty)
}
err = p.meta.DeleteAttribute(objpath, "", etagkey)
if err != nil {
return nil, fmt.Errorf("delete object etag: %w", err)
}
return &s3.DeleteObjectOutput{}, nil
}
if err != nil {
return nil, fmt.Errorf("delete object: %w", err)

View File

@@ -254,6 +254,7 @@ func TestDeleteObject(s *S3Conf) {
DeleteObject_directory_object_noslash(s)
DeleteObject_non_existing_dir_object(s)
DeleteObject_directory_object(s)
DeleteObject_non_empty_dir_obj(s)
DeleteObject_success(s)
DeleteObject_success_status_code(s)
}
@@ -917,6 +918,7 @@ func GetIntTests() IntTests {
"ListObjectVersions_VD_success": ListObjectVersions_VD_success,
"DeleteObject_non_existing_object": DeleteObject_non_existing_object,
"DeleteObject_directory_object_noslash": DeleteObject_directory_object_noslash,
"DeleteObject_non_empty_dir_obj": DeleteObject_non_empty_dir_obj,
"DeleteObject_name_too_long": DeleteObject_name_too_long,
"CopyObject_overwrite_same_dir_object": CopyObject_overwrite_same_dir_object,
"CopyObject_overwrite_same_file_object": CopyObject_overwrite_same_file_object,

View File

@@ -5532,6 +5532,46 @@ func DeleteObject_directory_object_noslash(s *S3Conf) error {
})
}
func DeleteObject_non_empty_dir_obj(s *S3Conf) error {
testName := "DeleteObject_non_empty_dir_obj"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
objToDel := "foo/"
nestedObj := objToDel + "bar"
_, err := putObjects(s3client, []string{nestedObj, objToDel}, bucket)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.DeleteObject(ctx, &s3.DeleteObjectInput{
Bucket: &bucket,
Key: &objToDel,
})
cancel()
if err != nil {
return err
}
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
res, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if len(res.Contents) != 1 {
return fmt.Errorf("expected the object list length to be 1, instead got %v", len(res.Contents))
}
if *res.Contents[0].Key != nestedObj {
return fmt.Errorf("expected the object key to be %v, instead got %v", nestedObj, *res.Contents[0].Key)
}
return nil
})
}
func DeleteObject_directory_not_empty(s *S3Conf) error {
testName := "DeleteObject_directory_not_empty"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {