diff --git a/README.md b/README.md
index d95ae27..79dff5d 100644
--- a/README.md
+++ b/README.md
@@ -146,7 +146,7 @@ The ``ec`` binary supports the following options:
| ``--uncovered`` | ``-u`` | Lists all files which are not covered by .editorconfig. |
| ``--verbose`` | ``-v`` | Shows additional informations, like detailed info about internal time tracking and which binary files have been skipped. |
| ``--no-interaction`` | ``-n`` | Do not ask for confirmation, if more than 500 files found and continue scanning. |
-| ``--no-error-on-exit`` | | By default ``ec`` returns code 2 when issues occurred. With this option set return code is always 0. |
+| ``--no-error-on-exit`` | | By default ``ec`` returns code 2 when issues or code 1 when warnings occurred. With this option set return code is always 0. |
**Tip:** The "usage" section on ``ec``'s help page shows some examples.
diff --git a/src/Application.php b/src/Application.php
index cc6ce83..609bb88 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -193,6 +193,22 @@ protected function executing(Input $input, Output $output): int
? $this->scan($finder, $count, $io, (bool)$input->getOption('strict'), (bool)$input->getOption('no-progress'), (bool)$input->getOption('compact'), (bool)$input->getOption('uncovered'))
: $this->fix($finder, $io, (bool)$input->getOption('strict'));
+ if (!empty($this->scanner->getUnavailableFiles())) {
+ $amountUnavailableFiles = count($this->scanner->getUnavailableFiles());
+ $io->warning('Found ' . $amountUnavailableFiles . ' unavailable ' . StringFormatUtility::pluralizeFiles($amountUnavailableFiles) . ' not being scanned!');
+ $filePaths = [];
+ foreach ($this->scanner->getUnavailableFiles() as $unavailableFile) {
+ $filePaths[] = $unavailableFile->getPathname();
+ }
+ $io->listing($filePaths);
+ if ($gitOnlyEnabled) {
+ $io->writeln('The files listed by the "' . $gitOnlyCommand . '" command are not physically present.');
+ $io->writeln('This typically occurs when files are deleted without being staged in Git. To verify, check "git status".');
+ $io->newLine();
+ }
+ $returnValue = 1;
+ }
+
if ($this->isVerbose) {
if (!empty($this->scanner->getSkippedBinaryFiles())) {
$amountBinaryFiles = count($this->scanner->getSkippedBinaryFiles());
diff --git a/src/EditorConfig/Rules/FileUnavailableException.php b/src/EditorConfig/Rules/FileUnavailableException.php
new file mode 100644
index 0000000..d1808a7
--- /dev/null
+++ b/src/EditorConfig/Rules/FileUnavailableException.php
@@ -0,0 +1,24 @@
+unavailableFile;
+ }
+
+ public function setUnavailableFile(SplFileInfo $unavailableFile): self
+ {
+ $this->unavailableFile = $unavailableFile;
+
+ return $this;
+ }
+}
diff --git a/src/EditorConfig/Rules/Validator.php b/src/EditorConfig/Rules/Validator.php
index 42d3ba1..a84830d 100644
--- a/src/EditorConfig/Rules/Validator.php
+++ b/src/EditorConfig/Rules/Validator.php
@@ -34,6 +34,11 @@ public function createValidatedFileResult(SplFileInfo $file, array $editorConfig
$this->skippingRules = $skippingRules;
$filePath = (string)$file->getRealPath();
+
+ if (empty($filePath)) {
+ throw (new FileUnavailableException())->setUnavailableFile($file);
+ }
+
$rules = [];
if (!MimeTypeUtility::isCommonTextType($filePath) && (MimeTypeUtility::isCommonBinaryType($filePath) || MimeTypeUtility::isBinaryFileType($filePath))) {
diff --git a/src/EditorConfig/Scanner.php b/src/EditorConfig/Scanner.php
index 327bfce..741b3ab 100644
--- a/src/EditorConfig/Scanner.php
+++ b/src/EditorConfig/Scanner.php
@@ -5,11 +5,13 @@
namespace Armin\EditorconfigCli\EditorConfig;
use Armin\EditorconfigCli\EditorConfig\Rules\FileResult;
+use Armin\EditorconfigCli\EditorConfig\Rules\FileUnavailableException;
use Armin\EditorconfigCli\EditorConfig\Rules\Validator;
use Armin\EditorconfigCli\EditorConfig\Utility\MimeTypeUtility;
use Armin\EditorconfigCli\EditorConfig\Utility\TimeTrackingUtility;
use Idiosyncratic\EditorConfig\EditorConfig;
use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\SplFileInfo;
class Scanner
{
@@ -38,6 +40,11 @@ class Scanner
*/
private $skippedBinaryFiles = [];
+ /**
+ * @var array|SplFileInfo[]
+ */
+ private $unavailableFiles = [];
+
public function __construct(?EditorConfig $editorConfig = null, ?Validator $validator = null, string $rootPath = null, array $skippingRules = [])
{
$this->editorConfig = $editorConfig ?? new EditorConfig();
@@ -71,6 +78,14 @@ public function getSkippedBinaryFiles(): array
return $this->skippedBinaryFiles;
}
+ /**
+ * @return array|SplFileInfo[]
+ */
+ public function getUnavailableFiles(): array
+ {
+ return $this->unavailableFiles;
+ }
+
/**
* @param bool $strict when true, any difference of indention size is spotted
*
@@ -82,7 +97,13 @@ public function scan(Finder $finderInstance, bool $strict = false, callable $tic
foreach ($finderInstance as $file) {
$config = $this->editorConfig->getConfigForPath((string)$file->getRealPath());
- $fileResult = $this->validator->createValidatedFileResult($file, $config, $strict, $this->skippingRules);
+ try {
+ $fileResult = $this->validator->createValidatedFileResult($file, $config, $strict, $this->skippingRules);
+ } catch (FileUnavailableException $e) {
+ $this->unavailableFiles[] = $e->getUnavailableFile();
+ continue;
+ }
+
$filePath = $fileResult->getFilePath();
if (!empty($this->rootPath)) {
$filePath = substr($filePath, strlen($this->rootPath));
diff --git a/tests/Functional/EditorConfig/CommandGitUnavailableFilesTest.php b/tests/Functional/EditorConfig/CommandGitUnavailableFilesTest.php
new file mode 100644
index 0000000..7f412f0
--- /dev/null
+++ b/tests/Functional/EditorConfig/CommandGitUnavailableFilesTest.php
@@ -0,0 +1,58 @@
+workspacePath = sys_get_temp_dir() . '/current_editorconfig_cli_test';
+
+ parent::setUp();
+
+ // Copy test files
+ copy(__DIR__ . '/../../Fixtures/image.jpg', $this->workspacePath . '/' . 'image.jpg');
+ copy(__DIR__ . '/../../Fixtures/document.pdf', $this->workspacePath . '/' . 'document.pdf');
+ copy(__DIR__ . '/../../Fixtures/kreis-weiß.svg', $this->workspacePath . '/' . 'kreis-weiß.svg');
+
+ // Set up Git repository for testing
+ exec('cd ' . $this->workspacePath . ' && ' . self::GIT_BINARY . ' init', $result, $returnCode);
+ if ($returnCode !== 0) {
+ throw new \RuntimeException('Unable to create test git repository!');
+ }
+
+ // Add files to git stage
+ exec('cd ' . $this->workspacePath . ' && ' . self::GIT_BINARY . ' add image.jpg');
+ exec('cd ' . $this->workspacePath . ' && ' . self::GIT_BINARY . ' add document.pdf');
+ exec('cd ' . $this->workspacePath . ' && ' . self::GIT_BINARY . ' add kreis-weiß.svg');
+
+ // Remove files physically
+ exec('rm -f ' . $this->workspacePath . '/image.jpg');
+ exec('rm -f ' . $this->workspacePath . '/document.pdf');
+ }
+
+ public function testUnavailableFiles()
+ {
+ $command = new Application();
+ $command->setAutoExit(false);
+ $commandTester = new CommandTester($command);
+ $commandTester->execute(['-d' => $this->workspacePath, '--no-progress' => true, '--git-only' => true]);
+
+ self::assertSame(1, $commandTester->getStatusCode());
+ self::assertStringContainsString('[WARNING] Found 2 unavailable files not being scanned!', $commandTester->getDisplay());
+ self::assertStringContainsString('* ' . $this->workspacePath . '/document.pdf', $commandTester->getDisplay());
+ self::assertStringContainsString('* ' . $this->workspacePath . '/image.jpg', $commandTester->getDisplay());
+ }
+}