Merge pull request #57298 from nextcloud/backport/52442/stable31

This commit is contained in:
Benjamin Gaussorgues 2026-01-08 11:03:23 +01:00 committed by GitHub
commit 5e3aea3326
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 78 additions and 7 deletions

View file

@ -7,8 +7,11 @@
*/
namespace OC\Files\Cache;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Cache\IScanner;
use OCP\Files\Cache\IWatcher;
use OCP\Files\Storage\IStorage;
/**
* check the storage backends for updates and change the cache accordingly
@ -19,27 +22,26 @@ class Watcher implements IWatcher {
protected $checkedPaths = [];
/**
* @var \OC\Files\Storage\Storage $storage
* @var IStorage $storage
*/
protected $storage;
/**
* @var Cache $cache
* @var ICache $cache
*/
protected $cache;
/**
* @var Scanner $scanner ;
* @var IScanner $scanner ;
*/
protected $scanner;
/** @var callable[] */
protected $onUpdate = [];
/**
* @param \OC\Files\Storage\Storage $storage
*/
public function __construct(\OC\Files\Storage\Storage $storage) {
protected ?string $checkFilter = null;
public function __construct(IStorage $storage) {
$this->storage = $storage;
$this->cache = $storage->getCache();
$this->scanner = $storage->getScanner();
@ -52,6 +54,10 @@ class Watcher implements IWatcher {
$this->watchPolicy = $policy;
}
public function setCheckFilter(?string $filter): void {
$this->checkFilter = $filter;
}
/**
* @return int either \OC\Files\Cache\Watcher::CHECK_NEVER, \OC\Files\Cache\Watcher::CHECK_ONCE, \OC\Files\Cache\Watcher::CHECK_ALWAYS
*/
@ -116,6 +122,12 @@ class Watcher implements IWatcher {
* @return bool
*/
public function needsUpdate($path, $cachedData) {
if ($this->checkFilter !== null) {
if (!preg_match($this->checkFilter, $path)) {
return false;
}
}
if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and !in_array($path, $this->checkedPaths))) {
$this->checkedPaths[] = $path;
return $cachedData['storage_mtime'] === null || $this->storage->hasUpdated($path, $cachedData['storage_mtime']);

View file

@ -329,6 +329,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage,
$this->watcher = new Watcher($storage);
$globalPolicy = Server::get(IConfig::class)->getSystemValueInt('filesystem_check_changes', Watcher::CHECK_NEVER);
$this->watcher->setPolicy((int)$this->getMountOption('filesystem_check_changes', $globalPolicy));
$this->watcher->setCheckFilter($this->getMountOption('filesystem_check_filter'));
}
return $this->watcher;
}

View file

@ -34,6 +34,17 @@ interface IWatcher {
*/
public function setPolicy($policy);
/**
* Set a filter regex, only paths matching the regex will be checked for updates.
*
* When set to `null`, every path will be checked for updates
*
* @param ?string $filter
* @return void
* @since 33.0.0
*/
public function setCheckFilter(?string $filter): void;
/**
* @return int either IWatcher::CHECK_NEVER, IWatcher::CHECK_ONCE, IWatcher::CHECK_ALWAYS
* @since 9.0.0

View file

@ -7,6 +7,12 @@
namespace Test\Files\Cache;
use OC\Files\Cache\CacheEntry;
use OC\Files\Cache\Watcher;
use OCP\Files\Cache\IWatcher;
use OCP\Files\Storage\IStorage;
use PHPUnit\Framework\Attributes\DataProvider;
/**
* Class WatcherTest
*
@ -191,4 +197,45 @@ class WatcherTest extends \Test\TestCase {
$this->storages[] = $storage;
return $storage;
}
public static function checkFilterProvider(): array {
return [
[null, [
'' => true,
'foo' => true,
'foo.txt' => true,
]],
['/^.+$/', [
'' => false,
'foo' => true,
'foo.txt' => true,
]],
['/^.+\..+$/', [
'' => false,
'foo' => false,
'foo.txt' => true,
]]
];
}
/**
* @dataProvider checkFilterProvider
*/
public function testCheckFilter($filter, $paths) {
$storage = $this->createMock(IStorage::class);
$storage->method('hasUpdated')
->willReturn(true);
$watcher = new Watcher($storage);
$watcher->setPolicy(IWatcher::CHECK_ALWAYS);
$watcher->setCheckFilter($filter);
$entry = new CacheEntry([
'storage_mtime' => 0,
]);
foreach ($paths as $patch => $shouldUpdate) {
$this->assertEquals($shouldUpdate, $watcher->needsUpdate($patch, $entry));
}
}
}