Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix s3 doesDirectoryExist check for empty directories #22747

Merged
merged 2 commits into from
Sep 10, 2020

Conversation

icewind1991
Copy link
Member

if a directory is empty, only the 'marker' object / exists.

since not all s3 implementations return just the prefix when listing objects by prefix,
when listing objects by the folder prefix, nothing will be returned if the directory is empty.
by not including the trailing slash in the prefix, the folder marked will always be returned if it exists

Signed-off-by: Robin Appelman robin@icewind.nl

@icewind1991 icewind1991 added the 3. to review Waiting for reviews label Sep 9, 2020
@icewind1991 icewind1991 added this to the Nextcloud 20 milestone Sep 9, 2020
@kesselb
Copy link
Contributor

kesselb commented Sep 9, 2020

LGTM 👍

Which s3 implementation does not work correctly? As flysystem is using a similar approach I would like to port this fix.

Edit: Is the marker object something Nextcloud specific? Then a port is not necessary I guess. Empty folders may not exist in s3 world.

@juliushaertl
Copy link
Member

Unfortunately this doesn't yet work as expected. I've pushed another commit to basically only match directories, otherwise when uploading a file to an empty directory the new file would be detected as a folder.

Which s3 implementation does not work correctly? As flysystem is using a similar approach I would like to port this fix.

@icewind1991 and me reproduced this on minio.

Edit: Is the marker object something Nextcloud specific? Then a port is not necessary I guess. Empty folders may not exist in s3 world.

This actually still seems to be an issue, once you delete the last file in a directory the path will also be become unavailable on the storage of course, while it still is part of the filecache, but will get removed on the next check if it is a directory.

@juliushaertl
Copy link
Member

Ok this now seems to do the trick for the file upload part into an empty directory. Deletion are a separate topic I'd say.

@juliushaertl
Copy link
Member

Squashed my commits into one additional, mind to have another look if that makes sense to you as well @kesselb @icewind1991 ?

@icewind1991
Copy link
Member Author

👍

Copy link
Member

@rullzer rullzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐘

@rullzer rullzer mentioned this pull request Sep 9, 2020
13 tasks
icewind1991 and others added 2 commits September 10, 2020 08:11
if a directory is empty, only the 'marker' object `/` exists.

since not all s3 implementations return just the prefix when listing objects by prefix,
when listing objects by the folder prefix, nothing will be returned if the directory is empty.
by not including the trailing slash in the prefix, the folder marked will always be returned if it exists

Signed-off-by: Robin Appelman <robin@icewind.nl>
…ermined

Signed-off-by: Julius Härtl <jus@bitgrid.net>
@faily-bot
Copy link

faily-bot bot commented Sep 10, 2020

🤖 beep boop beep 🤖

Here are the logs for the failed build:

Status of 32917: failure

mysql8.0-php7.2

Show full log
There were 2 warnings:

1) Test\Files\ViewTest::testRenameFailDeleteTargetKeepSource
Trying to configure method "writeStream" which cannot be configured because it does not exist, has not been specified, is final, or is static

2) Test\Files\ViewTest::testCopyFailDeleteTargetKeepSource
Trying to configure method "writeStream" which cannot be configured because it does not exist, has not been specified, is final, or is static

--

There was 1 failure:

1) OCA\Files_Versions\Tests\VersioningTest::testRestoreMovedShare
File content has not changed
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'version 2'
+'version 1'

/drone/src/apps/files_versions/tests/VersioningTest.php:729

acceptance-app-files-sharing

  • tests/acceptance/features/app-files-sharing.feature:338
Show full log
  Scenario: sharee can revoke create permission from reshare after the sharer disabled it # /drone/src/tests/acceptance/features/app-files-sharing.feature:338
    Given I act as John                                                                   # ActorContext::iActAs()
    And I am logged in as the admin                                                       # LoginPageContext::iAmLoggedInAsTheAdmin()
    And I act as Jane                                                                     # ActorContext::iActAs()
    And I am logged in                                                                    # LoginPageContext::iAmLoggedIn()
    And I act as Jim                                                                      # ActorContext::iActAs()
    And I am logged in as "user1"                                                         # LoginPageContext::iAmLoggedInAs()
    And I act as John                                                                     # ActorContext::iActAs()
    And I create a new folder named "Shared folder"                                       # FileListContext::iCreateANewFolderNamed()
    And I see that the file list contains a file named "Shared folder"                    # FileListContext::iSeeThatTheFileListContainsAFileNamed()
    And I share "Shared folder" with "user0"                                              # FilesAppSharingContext::iShareWith()
    And I see that the file is shared with "user0"                                        # FilesAppSharingContext::iSeeThatTheFileIsSharedWith()
    And I act as Jane                                                                     # ActorContext::iActAs()
    And I open the Files app                                                              # FilesAppContext::iOpenTheFilesApp()
    And I share "Shared folder" with "user1"                                              # FilesAppSharingContext::iShareWith()
    And I see that the file is shared with "user1"                                        # FilesAppSharingContext::iSeeThatTheFileIsSharedWith()
    And I act as John                                                                     # ActorContext::iActAs()
    And I set the share with "user0" as not creatable                                     # FilesAppSharingContext::iSetTheShareWithAsNotCreatable()
    And I see that "user0" can not create in the share                                    # FilesAppSharingContext::iSeeThatCanNotCreateInTheShare()
    And I act as Jim                                                                      # ActorContext::iActAs()
    And I open the Files app                                                              # FilesAppContext::iOpenTheFilesApp()
    And I enter in the folder named "Shared folder"                                       # FileListContext::iEnterInTheFolderNamed()
    And I create a new folder named "Subfolder"                                           # FileListContext::iCreateANewFolderNamed()
    And I see that the file list contains a file named "Subfolder"                        # FileListContext::iSeeThatTheFileListContainsAFileNamed()
    When I act as Jane                                                                    # ActorContext::iActAs()
    And I open the Files app                                                              # FilesAppContext::iOpenTheFilesApp()
    And I open the details view for "Shared folder"                                       # FileListContext::iOpenTheDetailsViewFor()
    And I see that the details view is open                                               # FilesAppContext::iSeeThatTheDetailsViewIsOpen()
    And I open the "Sharing" tab in the details view                                      # FilesAppContext::iOpenTheTabInTheDetailsView()
    And I see that the "Sharing" tab in the details view is eventually loaded             # FilesAppContext::iSeeThatTheTabInTheDetailsViewIsEventuallyLoaded()
    And I set the share with "user1" as not creatable                                     # FilesAppSharingContext::iSetTheShareWithAsNotCreatable()
    Then I see that "user1" can not create in the share                                   # FilesAppSharingContext::iSeeThatCanNotCreateInTheShare()
    And I see that "user1" can not be allowed to create in the share                      # FilesAppSharingContext::iSeeThatCanNotBeAllowedToCreateInTheShare()
    And I act as Jim                                                                      # ActorContext::iActAs()
    And I open the Files app                                                              # FilesAppContext::iOpenTheFilesApp()
    And I enter in the folder named "Shared folder"                                       # FileListContext::iEnterInTheFolderNamed()
    And I see that it is not possible to create new files                                 # FileListContext::iSeeThatItIsNotPossibleToCreateNewFiles()
      Failed asserting that true is false.

Copy link
Member

@MorrisJobke MorrisJobke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐘

@MorrisJobke MorrisJobke merged commit 756254c into master Sep 10, 2020
@MorrisJobke MorrisJobke deleted the s3-isdir-empty branch September 10, 2020 10:48
@MorrisJobke
Copy link
Member

@icewind1991 @juliushaertl Backport?

@juliushaertl
Copy link
Member

/backport to stable19

@juliushaertl
Copy link
Member

/backport to stable18

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3. to review Waiting for reviews
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants