Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable26] Do not stop at the first PHP error/warning in files:scan #38154

Merged
merged 3 commits into from
May 11, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -163,14 +166,17 @@ protected function scanFiles(string $user, string $path, bool $scanMetadata, Out
} catch (ForbiddenException $e) {
$output->writeln("<error>Home storage for user $user not writable or 'files' subdirectory missing</error>");
$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 @@ -191,19 +197,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 @@ -235,31 +236,37 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/**
* Initialises some useful tools for the Command
*/
protected function initTools() {
protected function initTools(OutputInterface $output) {

Check notice

Code scanning / Psalm

MissingReturnType

Method OCA\Files\Command\Scan::initTools does not have a return type, expecting void
// 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 @@ -270,28 +277,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