Skip to content

Commit

Permalink
1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
eldertek committed Jul 9, 2024
1 parent 01d5408 commit 6469681
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 44 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0 - 2024-07-09
### Fixed
- File locking when interupting the scan

## 1.1.11 - 2024-07-05
### Added
- Multi-select feature for duplicates
Expand Down
2 changes: 1 addition & 1 deletion js/duplicatefinder-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/duplicatefinder-settings.js

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions lib/Command/FindDuplicates.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -111,6 +113,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$users = (array)$input->getOption('user');
$paths = (array)$input->getOption('path');

// Set up signal handler for SIGINT (Ctrl+C)
pcntl_signal(SIGINT, function () {
$this->output->writeln("\n<comment>Scan aborted by user.</comment>");
exit(1);
});

return (!empty($users)) ? $this->findDuplicatesForUsers($users, $paths) : $this->findAllDuplicates($paths);
}

Expand Down Expand Up @@ -164,7 +172,8 @@ private function findAllDuplicates(array $paths): int
private function findDuplicates(string $user, array $paths): void
{
$callback = function () {
// Handle interruption if needed
pcntl_signal_dispatch();
return false; // Continue scanning
};

if (empty($paths)) {
Expand All @@ -177,4 +186,4 @@ private function findDuplicates(string $user, array $paths): void

CMDUtils::showDuplicates($this->fileDuplicateService, $this->output, $callback, $user);
}
}
}
9 changes: 6 additions & 3 deletions lib/Command/ListDuplicates.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,11 @@ private function listDuplicatesForUsers(array $users): int
*/
private function listAllDuplicates(): int
{
CMDUtils::showDuplicates($this->fileDuplicateService, $this->output, function() {});
// Assuming you want to list duplicates for all users, you might need to iterate over all users
$users = $this->userManager->search('');
foreach ($users as $user) {
CMDUtils::showDuplicates($this->fileDuplicateService, $this->output, function() {}, $user->getUID());
}
return 0;
}
}

}
26 changes: 12 additions & 14 deletions lib/Service/FileDuplicateService.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public function findAll(
$entities = $this->mapper->findAll($user, $pageSize, $offset, $orderBy);

foreach ($entities as $entity) {
$entity = $this->stripFilesWithoutAccessRights($entity, $user);
if ($user !== null) {
$entity = $this->stripFilesWithoutAccessRights($entity, $user);
}
if ($enrich) {
$entity = $this->enrich($entity);
}
Expand Down Expand Up @@ -112,22 +114,18 @@ public function findAll(

private function stripFilesWithoutAccessRights(
FileDuplicate $duplicate,
?string $user
string $user
): FileDuplicate {
$files = $this->fileInfoService->findByHash($duplicate->getHash(), $duplicate->getType());
$duplicate->setFiles($files);
if (is_null($user)) {
return $duplicate;
}
foreach ($duplicate->getFiles() as $fileId => $fileInfo) {
if (is_string($fileInfo)) {
continue;
}
if (!$this->fileInfoService->hasAccessRight($fileInfo, $user)) {
$duplicate->removeDuplicate($fileId);
$accessibleFiles = [];

foreach ($files as $fileInfo) {
if ($this->fileInfoService->hasAccessRight($fileInfo, $user)) {
$accessibleFiles[] = $fileInfo;
}
}
unset($fileInfo);

$duplicate->setFiles($accessibleFiles);
return $duplicate;
}

Expand Down Expand Up @@ -180,4 +178,4 @@ public function getTotalCount(string $type = 'unacknowledged'): int
{
return $this->mapper->getTotalCount($type);
}
}
}
111 changes: 93 additions & 18 deletions lib/Service/FileInfoService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use Symfony\Component\Console\Output\OutputInterface;
use OCP\Lock\ILockingProvider;
use OCP\Files\Storage\IStorage;
use OCP\Files\IRootFolder;
use OCP\IDBConnection;

use OCA\DuplicateFinder\AppInfo\Application;
use OCA\DuplicateFinder\Db\FileInfo;
Expand Down Expand Up @@ -35,6 +39,9 @@ class FileInfoService
private $scannerUtil;
/** @var FilterService */
private $filterService;
private $lockingProvider;
private $rootFolder;
private $connection;

public function __construct(
FileInfoMapper $mapper,
Expand All @@ -43,7 +50,10 @@ public function __construct(
ShareService $shareService,
FilterService $filterService,
FolderService $folderService,
ScannerUtil $scannerUtil
ScannerUtil $scannerUtil,
ILockingProvider $lockingProvider,
IRootFolder $rootFolder,
IDBConnection $connection
) {
$this->mapper = $mapper;
$this->eventDispatcher = $eventDispatcher;
Expand All @@ -52,6 +62,9 @@ public function __construct(
$this->filterService = $filterService;
$this->folderService = $folderService;
$this->scannerUtil = $scannerUtil;
$this->lockingProvider = $lockingProvider;
$this->rootFolder = $rootFolder;
$this->connection = $connection;
}

/**
Expand Down Expand Up @@ -269,6 +282,8 @@ public function scanFiles(
try {
$this->scannerUtil->setHandles($this, $output, $abortIfInterrupted);
$this->scannerUtil->scan($user, $scanPath);
} catch (\OCP\Lock\LockedException $e) {
$this->handleLockedFile($e->getPath(), $output);
} catch (NotFoundException $e) {
$this->logger->error('The given scan path doesn\'t exists.', ['app' => Application::ID, 'exception' => $e]);
CMDUtils::showIfOutputIsPresent(
Expand All @@ -284,26 +299,86 @@ public function scanFiles(
}
}

public function hasAccessRight(FileInfo $fileInfo, string $user): ?FileInfo
private function handleLockedFile(string $path, ?OutputInterface $output): void
{
$result = null;
if ($fileInfo->getOwner() === $user) {
$result = $fileInfo;
} else {
try {
$path = $this->shareService->hasAccessRight(
$this->folderService->getNodeByFileInfo($fileInfo, $user),
$user
try {
// Get the file node
$node = $this->rootFolder->get($path);
$storage = $node->getStorage();

if ($storage instanceof IStorage) {
// Try to release the lock at the storage level
$storage->unlockFile($path, ILockingProvider::LOCK_SHARED);
CMDUtils::showIfOutputIsPresent(
"Released storage-level lock for file: $path",
$output
);
if (!is_null($path)) {
$fileInfo->setPath($path);
$result = $fileInfo;
}
} catch (NotFoundException $e) {
$result = null;
}

// Try to release the lock at the application level
$this->lockingProvider->releaseAll($path, ILockingProvider::LOCK_SHARED);
CMDUtils::showIfOutputIsPresent(
"Released application-level lock for file: $path",
$output
);

// Check if the file is still locked
if ($this->lockingProvider->isLocked($path, ILockingProvider::LOCK_SHARED)) {
CMDUtils::showIfOutputIsPresent(
"<error>File is still locked after release attempt: $path</error>",
$output
);
// Call the method to disable all locks
$this->disableAllLocks($output);
} else {
CMDUtils::showIfOutputIsPresent(
"<info>Successfully released all locks for file: $path</info>",
$output
);
}
} catch (\Exception $e) {
CMDUtils::showIfOutputIsPresent(
"<error>Failed to release lock for file: $path - " . $e->getMessage() . "</error>",
$output
);
$this->logger->error("Failed to release lock for file: $path", ['exception' => $e]);
// Call the method to disable all locks
$this->disableAllLocks($output);
}
}

private function disableAllLocks(?OutputInterface $output): void
{
try {
$query = $this->connection->prepare('DELETE FROM oc_file_locks WHERE true');
$query->execute();
CMDUtils::showIfOutputIsPresent(
"<info>All locks have been disabled by emptying the oc_file_locks table.</info>",
$output
);
} catch (\Exception $e) {
CMDUtils::showIfOutputIsPresent(
"<error>Failed to disable all locks: " . $e->getMessage() . "</error>",
$output
);
$this->logger->error("Failed to disable all locks", ['exception' => $e]);
}
}

public function hasAccessRight(FileInfo $fileInfo, string $user): bool
{
if ($fileInfo->getOwner() === $user) {
return true;
}

return $result;
try {
$path = $this->shareService->hasAccessRight(
$this->folderService->getNodeByFileInfo($fileInfo, $user),
$user
);
return !is_null($path);
} catch (NotFoundException $e) {
return false;
}
}
}
}
10 changes: 8 additions & 2 deletions lib/Utils/ScannerUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use OCP\IDBConnection;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\NotFoundException;
use OCP\Lock\LockedException;

use OCA\DuplicateFinder\AppInfo\Application;
use OCA\DuplicateFinder\Exception\ForcedToIgnoreFileException;
Expand Down Expand Up @@ -67,6 +68,9 @@ public function scan(string $user, string $path, bool $isShared = false) : void
$this->scanSharedFiles($user, $path);
$this->showOutput('Finished searching files');
}
} catch (LockedException $e) {
$this->showOutput('<error>File locked, attempting to release: ' . $e->getPath() . '</error>');
throw $e; // Rethrow to be handled in FileInfoService
} catch (\Exception $e) {
$errorMessage = 'An error occurred during scanning: ' . $e->getMessage();
$this->logger->error($errorMessage, ['app' => Application::ID, 'exception' => $e]);
Expand Down Expand Up @@ -106,7 +110,9 @@ private function saveScannedFile(
}
if ($this->abortIfInterrupted) {
$abort = $this->abortIfInterrupted;
$abort();
if ($abort()) {
throw new \Exception('Scan aborted by user');
}
}
}

Expand Down Expand Up @@ -138,4 +144,4 @@ private function showOutput(string $message, bool $isVerbose = false) : void
);
}

}
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "duplicatefinder",
"description": "Save some space by finding your duplicate files",
"version": "1.1.11",
"version": "1.2.0",
"author": "André Théo LAURET <andrelauret@eclipse-technology.eu>",
"contributors": [],
"bugs": {
Expand Down

0 comments on commit 6469681

Please sign in to comment.