Skip to content

Commit ac9c17c

Browse files
hweihwangicewind1991
authored andcommitted
fix: keep trashbin cache and db in sync
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
1 parent bb1ad1c commit ac9c17c

2 files changed

Lines changed: 80 additions & 16 deletions

File tree

apps/files_trashbin/lib/Trashbin.php

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ public static function move2trash($file_path, $ownerOnly = false) {
309309
$trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
310310
if ($inCache) {
311311
$trashStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
312+
} else {
313+
$trashStorage->getUpdater()->update($trashInternalPath);
312314
}
313315
} catch (CopyRecursiveException $e) {
314316
$moveSuccessful = false;
@@ -345,18 +347,51 @@ public static function move2trash($file_path, $ownerOnly = false) {
345347
->setValue('location', $query->createNamedParameter($location))
346348
->setValue('user', $query->createNamedParameter($owner))
347349
->setValue('deleted_by', $query->createNamedParameter($deletedBy));
348-
$result = $query->executeStatement();
349-
if (!$result) {
350-
Server::get(LoggerInterface::class)->error('trash bin database couldn\'t be updated', ['app' => 'files_trashbin']);
350+
$inserted = false;
351+
try {
352+
$inserted = ($query->executeStatement() === 1);
353+
} catch (\Throwable $e) {
354+
Server::get(LoggerInterface::class)->error(
355+
'trash bin database insert failed',
356+
[
357+
'app' => 'files_trashbin',
358+
'exception' => $e,
359+
'user' => $owner,
360+
'filename' => $filename,
361+
'timestamp' => $timestamp,
362+
]
363+
);
364+
}
365+
if (!$inserted) {
366+
Server::get(LoggerInterface::class)->error(
367+
'trash bin database couldn\'t be updated, removing trash payload',
368+
[
369+
'app' => 'files_trashbin',
370+
'user' => $owner,
371+
'filename' => $filename,
372+
'timestamp' => $timestamp,
373+
]
374+
);
375+
if ($trashStorage->file_exists($trashInternalPath)) {
376+
if ($trashStorage->is_dir($trashInternalPath)) {
377+
$trashStorage->rmdir($trashInternalPath);
378+
} else {
379+
$trashStorage->unlink($trashInternalPath);
380+
}
381+
}
382+
$trashStorage->getUpdater()->remove($trashInternalPath);
383+
$moveSuccessful = false;
351384
}
352-
Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path),
353-
'trashPath' => Filesystem::normalizePath(static::getTrashFilename($filename, $timestamp))]);
385+
if ($inserted) {
386+
Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path),
387+
'trashPath' => Filesystem::normalizePath(static::getTrashFilename($filename, $timestamp))]);
354388

355-
self::retainVersions($filename, $owner, $ownerPath, $timestamp);
389+
self::retainVersions($filename, $owner, $ownerPath, $timestamp);
356390

357-
// if owner !== user we need to also add a copy to the users trash
358-
if ($user !== $owner && $ownerOnly === false) {
359-
self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
391+
// if owner !== user we need to also add a copy to the users trash
392+
if ($user !== $owner && $ownerOnly === false) {
393+
self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
394+
}
360395
}
361396
}
362397

@@ -689,13 +724,6 @@ public static function delete($filename, $user, $timestamp = null) {
689724
$size = 0;
690725

691726
if ($timestamp) {
692-
$query = Server::get(IDBConnection::class)->getQueryBuilder();
693-
$query->delete('files_trash')
694-
->where($query->expr()->eq('user', $query->createNamedParameter($user)))
695-
->andWhere($query->expr()->eq('id', $query->createNamedParameter($filename)))
696-
->andWhere($query->expr()->eq('timestamp', $query->createNamedParameter($timestamp)));
697-
$query->executeStatement();
698-
699727
$file = static::getTrashFilename($filename, $timestamp);
700728
} else {
701729
$file = $filename;
@@ -706,6 +734,14 @@ public static function delete($filename, $user, $timestamp = null) {
706734
try {
707735
$node = $userRoot->get('/files_trashbin/files/' . $file);
708736
} catch (NotFoundException $e) {
737+
if ($timestamp) {
738+
$query = Server::get(IDBConnection::class)->getQueryBuilder();
739+
$query->delete('files_trash')
740+
->where($query->expr()->eq('user', $query->createNamedParameter($user)))
741+
->andWhere($query->expr()->eq('id', $query->createNamedParameter($filename)))
742+
->andWhere($query->expr()->eq('timestamp', $query->createNamedParameter($timestamp)));
743+
$query->executeStatement();
744+
}
709745
return $size;
710746
}
711747

@@ -719,6 +755,15 @@ public static function delete($filename, $user, $timestamp = null) {
719755
$node->delete();
720756
self::emitTrashbinPostDelete('/files_trashbin/files/' . $file);
721757

758+
if ($timestamp) {
759+
$query = Server::get(IDBConnection::class)->getQueryBuilder();
760+
$query->delete('files_trash')
761+
->where($query->expr()->eq('user', $query->createNamedParameter($user)))
762+
->andWhere($query->expr()->eq('id', $query->createNamedParameter($filename)))
763+
->andWhere($query->expr()->eq('timestamp', $query->createNamedParameter($timestamp)));
764+
$query->executeStatement();
765+
}
766+
722767
return $size;
723768
}
724769

apps/files_trashbin/tests/StorageTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,25 @@ public function testSingleStorageDeleteFile(): void {
118118
$this->assertEquals('test.txt', substr($name, 0, strrpos($name, '.')));
119119
}
120120

121+
public function testTrashEntryCreatedWhenSourceNotInCache(): void {
122+
$this->userView->file_put_contents('uncached.txt', 'foo');
123+
124+
[$storage, $internalPath] = $this->userView->resolvePath('uncached.txt');
125+
$cache = $storage->getCache();
126+
$cache->remove($internalPath);
127+
$this->assertFalse($cache->inCache($internalPath));
128+
129+
$this->userView->unlink('uncached.txt');
130+
131+
$results = $this->rootView->getDirectoryContent($this->user . '/files_trashbin/files/');
132+
$this->assertCount(1, $results);
133+
$name = $results[0]->getName();
134+
$this->assertEquals('uncached.txt', substr($name, 0, strrpos($name, '.')));
135+
136+
[$trashStorage, $trashInternalPath] = $this->rootView->resolvePath('/' . $this->user . '/files_trashbin/files/' . $name);
137+
$this->assertTrue($trashStorage->getCache()->inCache($trashInternalPath));
138+
}
139+
121140
/**
122141
* Test that deleting a folder puts it into the trashbin.
123142
*/

0 commit comments

Comments
 (0)