Skip to content

Commit

Permalink
Merge pull request #37944 from nextcloud/enh/allow-filescan-to-contin…
Browse files Browse the repository at this point in the history
…ue-on-error

Do not stop at the first PHP error/warning in files:scan
  • Loading branch information
come-nc authored May 9, 2023
2 parents 185fe53 + 88405d3 commit fc07627
Showing 1 changed file with 33 additions and 36 deletions.
69 changes: 33 additions & 36 deletions apps/files/lib/Command/Scan.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Scan extends Base {
protected float $execTime = 0;
protected int $foldersCounter = 0;
protected int $filesCounter = 0;
protected int $errorsCounter = 0;
private IRootFolder $root;
private MetadataManager $metadataManager;

Expand Down Expand Up @@ -148,10 +149,12 @@ protected function scanFiles(string $user, string $path, bool $scanMetadata, Out

$scanner->listen('\OC\Files\Utils\Scanner', 'StorageNotAvailable', function (StorageNotAvailableException $e) use ($output) {
$output->writeln('Error while scanning, storage not available (' . $e->getMessage() . ')', OutputInterface::VERBOSITY_VERBOSE);
++$this->errorsCounter;
});

$scanner->listen('\OC\Files\Utils\Scanner', 'normalizedNameMismatch', function ($fullPath) use ($output) {
$output->writeln("\t<error>Entry \"" . $fullPath . '" will not be accessible due to incompatible encoding</error>');
++$this->errorsCounter;
});

try {
Expand All @@ -164,14 +167,17 @@ protected function scanFiles(string $user, string $path, bool $scanMetadata, Out
$output->writeln("<error>Home storage for user $user not writable or 'files' subdirectory missing</error>");
$output->writeln(' ' . $e->getMessage());
$output->writeln('Make sure you\'re running the scan command only as the user the web server runs as');
++$this->errorsCounter;
} catch (InterruptedException $e) {
# exit the function if ctrl-c has been pressed
$output->writeln('Interrupted by user');
} catch (NotFoundException $e) {
$output->writeln('<error>Path not found: ' . $e->getMessage() . '</error>');
++$this->errorsCounter;
} catch (\Exception $e) {
$output->writeln('<error>Exception during scan: ' . $e->getMessage() . '</error>');
$output->writeln('<error>' . $e->getTraceAsString() . '</error>');
++$this->errorsCounter;
}
}

Expand All @@ -192,19 +198,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$users = $input->getArgument('user_id');
}

# restrict the verbosity level to VERBOSITY_VERBOSE
if ($output->getVerbosity() > OutputInterface::VERBOSITY_VERBOSE) {
$output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
}

# check quantity of users to be process and show it on the command line
$users_total = count($users);
if ($users_total === 0) {
$output->writeln('<error>Please specify the user id to scan, --all to scan for all users or --path=...</error>');
return 1;
}

$this->initTools();
$this->initTools($output);

$user_count = 0;
foreach ($users as $user) {
Expand Down Expand Up @@ -236,31 +237,37 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/**
* Initialises some useful tools for the Command
*/
protected function initTools() {
protected function initTools(OutputInterface $output) {
// Start the timer
$this->execTime = -microtime(true);
// Convert PHP errors to exceptions
set_error_handler([$this, 'exceptionErrorHandler'], E_ALL);
set_error_handler(
fn (int $severity, string $message, string $file, int $line): bool =>
$this->exceptionErrorHandler($output, $severity, $message, $file, $line),
E_ALL
);
}

/**
* Processes PHP errors as exceptions in order to be able to keep track of problems
* Processes PHP errors in order to be able to show them in the output
*
* @see https://www.php.net/manual/en/function.set-error-handler.php
*
* @param int $severity the level of the error raised
* @param string $message
* @param string $file the filename that the error was raised in
* @param int $line the line number the error was raised
*
* @throws \ErrorException
*/
public function exceptionErrorHandler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
public function exceptionErrorHandler(OutputInterface $output, int $severity, string $message, string $file, int $line): bool {
if (($severity === E_DEPRECATED) || ($severity === E_USER_DEPRECATED)) {
// Do not show deprecation warnings
return false;
}
throw new \ErrorException($message, 0, $severity, $file, $line);
$e = new \ErrorException($message, 0, $severity, $file, $line);
$output->writeln('<error>Error during scan: ' . $e->getMessage() . '</error>');
$output->writeln('<error>' . $e->getTraceAsString() . '</error>', OutputInterface::VERBOSITY_VERY_VERBOSE);
++$this->errorsCounter;
return true;
}

/**
Expand All @@ -271,28 +278,18 @@ protected function presentStats(OutputInterface $output) {
$this->execTime += microtime(true);

$headers = [
'Folders', 'Files', 'Elapsed time'
'Folders',
'Files',
'Errors',
'Elapsed time',
];

$this->showSummary($headers, null, $output);
}

/**
* Shows a summary of operations
*
* @param string[] $headers
* @param string[] $rows
* @param OutputInterface $output
*/
protected function showSummary($headers, $rows, OutputInterface $output) {
$niceDate = $this->formatExecTime();
if (!$rows) {
$rows = [
$this->foldersCounter,
$this->filesCounter,
$niceDate,
];
}
$rows = [
$this->foldersCounter,
$this->filesCounter,
$this->errorsCounter,
$niceDate,
];
$table = new Table($output);
$table
->setHeaders($headers)
Expand Down

0 comments on commit fc07627

Please sign in to comment.