@@ -221,6 +221,11 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
221221
222222 // Only update metadata that has changed
223223 $ newData = array_diff_assoc ($ data , $ cacheData ->getData ());
224+
225+ // make it known to the caller that etag has been changed and needs propagation
226+ if (isset ($ newData ['etag ' ])) {
227+ $ data ['etag_changed ' ] = true ;
228+ }
224229 } else {
225230 // we only updated unencrypted_size if it's already set
226231 unset($ data ['unencrypted_size ' ]);
@@ -389,16 +394,20 @@ protected function getExistingChildren($folderId) {
389394 * @param int|float $oldSize the size of the folder before (re)scanning the children
390395 * @return int|float the size of the scanned folder or -1 if the size is unknown at this stage
391396 */
392- protected function scanChildren (string $ path , $ recursive , int $ reuse , int $ folderId , bool $ lock , int |float $ oldSize ) {
397+ protected function scanChildren (string $ path , $ recursive , int $ reuse , int $ folderId , bool $ lock , int |float $ oldSize, & $ etagChanged = false ) {
393398 if ($ reuse === -1 ) {
394399 $ reuse = ($ recursive === self ::SCAN_SHALLOW ) ? self ::REUSE_ETAG | self ::REUSE_SIZE : self ::REUSE_ETAG ;
395400 }
396401 $ this ->emit ('\OC\Files\Cache\Scanner ' , 'scanFolder ' , [$ path , $ this ->storageId ]);
397402 $ size = 0 ;
398- $ childQueue = $ this ->handleChildren ($ path , $ recursive , $ reuse , $ folderId , $ lock , $ size );
403+ $ childQueue = $ this ->handleChildren ($ path , $ recursive , $ reuse , $ folderId , $ lock , $ size, $ etagChanged );
399404
400405 foreach ($ childQueue as $ child => [$ childId , $ childSize ]) {
401- $ childSize = $ this ->scanChildren ($ child , $ recursive , $ reuse , $ childId , $ lock , $ childSize );
406+ // "etag changed" propagates up, but not down, so we pass `false` to the children even if we already know that the etag of the current folder changed
407+ $ childEtagChanged = false ;
408+ $ childSize = $ this ->scanChildren ($ child , $ recursive , $ reuse , $ childId , $ lock , $ childSize , $ childEtagChanged );
409+ $ etagChanged |= $ childEtagChanged ;
410+
402411 if ($ childSize === -1 ) {
403412 $ size = -1 ;
404413 } elseif ($ size !== -1 ) {
@@ -411,8 +420,17 @@ protected function scanChildren(string $path, $recursive, int $reuse, int $folde
411420 if ($ this ->storage ->instanceOfStorage (Encryption::class)) {
412421 $ this ->cache ->calculateFolderSize ($ path );
413422 } else {
414- if ($ this ->cacheActive && $ oldSize !== $ size ) {
415- $ this ->cache ->update ($ folderId , ['size ' => $ size ]);
423+ if ($ this ->cacheActive ) {
424+ $ updatedData = [];
425+ if ($ oldSize !== $ size ) {
426+ $ updatedData ['size ' ] = $ size ;
427+ }
428+ if ($ etagChanged ) {
429+ $ updatedData ['etag ' ] = uniqid ();;
430+ }
431+ if ($ updatedData ) {
432+ $ this ->cache ->update ($ folderId , $ updatedData );
433+ }
416434 }
417435 }
418436 $ this ->emit ('\OC\Files\Cache\Scanner ' , 'postScanFolder ' , [$ path , $ this ->storageId ]);
@@ -422,7 +440,7 @@ protected function scanChildren(string $path, $recursive, int $reuse, int $folde
422440 /**
423441 * @param bool|IScanner::SCAN_RECURSIVE_INCOMPLETE $recursive
424442 */
425- private function handleChildren (string $ path , $ recursive , int $ reuse , int $ folderId , bool $ lock , int |float &$ size ): array {
443+ private function handleChildren (string $ path , $ recursive , int $ reuse , int $ folderId , bool $ lock , int |float &$ size, bool & $ etagChanged ): array {
426444 // we put this in it's own function so it cleans up the memory before we start recursing
427445 $ existingChildren = $ this ->getExistingChildren ($ folderId );
428446 $ newChildren = iterator_to_array ($ this ->storage ->getDirectoryContent ($ path ));
@@ -470,6 +488,10 @@ private function handleChildren(string $path, $recursive, int $reuse, int $folde
470488 } elseif ($ size !== -1 ) {
471489 $ size += $ data ['size ' ];
472490 }
491+
492+ if (isset ($ data ['etag_changed ' ]) && $ data ['etag_changed ' ]) {
493+ $ etagChanged = true ;
494+ }
473495 }
474496 } catch (Exception $ ex ) {
475497 // might happen if inserting duplicate while a scanning
0 commit comments