diff --git a/src/ComplianceValidator.php b/src/ComplianceValidator.php index b739deb..d7d27cb 100644 --- a/src/ComplianceValidator.php +++ b/src/ComplianceValidator.php @@ -14,8 +14,12 @@ class ComplianceValidator public function execute($root = null) { $lines = $this->getFiles($root); - $results = $this->validate($lines); - $this->outputResults($results); + try { + $results = $this->validate($lines); + $this->outputResults($results); + } catch (\Exception $e) { + echo $e->getMessage(); + } return $this->getCompliant(); } @@ -68,6 +72,10 @@ public function getFiles($root = null) $root = $root ?: __DIR__ . '/../../../../'; $root = realpath($root); + if (!is_dir($root)) { + throw new GeneratorException("Specified directory does not exist. Remember to use an absolute path."); + } + if ($this->files == null) { $files = scandir($root); foreach ($files as $i => $file) { diff --git a/src/GeneratorException.php b/src/GeneratorException.php new file mode 100644 index 0000000..5bad9c7 --- /dev/null +++ b/src/GeneratorException.php @@ -0,0 +1,8 @@ +getFiles($root); - $validatorResults = $validator->validate($lines); - $files = $this->createFiles($validatorResults, $root); - $this->outputResults($files); + try { + $lines = $validator->getFiles($root); + $validatorResults = $validator->validate($lines); + $files = $this->createFiles($validatorResults, $root); + $this->outputResults($files); + } catch (\Exception $e) { + echo $e->getMessage(); + } return true; } @@ -18,6 +22,14 @@ public function createFiles($validatorResults, $root = null) $root = $root ?: __DIR__ . '/../../../../'; $root = realpath($root); + if (!is_dir($root)) { + throw new GeneratorException("Specified directory does not exist. Create it first."); + } + + if (!is_writable($root) || !is_executable($root)) { + throw new GeneratorException("Cannot write into specified directory. Please check folder permissions for {$root}"); + } + $files = $this->createFileList($validatorResults); $createdFiles = []; @@ -26,13 +38,15 @@ public function createFiles($validatorResults, $root = null) if ($isDir) { $path = $root . '/' . substr($file, 0, -1); $createdFiles[$file] = $path; - mkdir($path, 0755); + !is_dir($path) && !mkdir($path, 0755) && !is_dir($path); continue; } $path = $root . '/' . $file . '.md'; - $createdFiles[$file] = $file . '.md'; - file_put_contents($path, ''); - chmod($path, 0644); + $createdFiles[$file] = $path; + if (!file_exists($path)) { + file_put_contents($path, ''); + chmod($path, 0644); + } } return $createdFiles; diff --git a/tests/PackageGeneratorTest.php b/tests/PackageGeneratorTest.php index 7c1fd25..2140e10 100644 --- a/tests/PackageGeneratorTest.php +++ b/tests/PackageGeneratorTest.php @@ -7,8 +7,15 @@ class PackageGeneratorTest public static function run() { + set_error_handler(function ($severity, $message, $file, $line) { + throw new \ErrorException($message, $severity, $severity, $file, $line); + }); + $tester = new PackageGeneratorTest(); $tester->testGenerate_WithMissingBin_ReturnsBin(); + $tester->testGenerate_WithExistingDir_SkipsDir(); + $tester->testGenerate_WithExistingFile_SkipsFile(); + $tester->testGenerate_WithBadPermissions_SkipsDirAndThrowsException(); echo __CLASS__ . " errors: {$tester->numErrors}" . PHP_EOL; } @@ -25,8 +32,7 @@ public function testGenerate_WithMissingBin_ReturnsBin() ], ]; - $generator = new PackageGenerator(); - $files = $generator->createFileList($validatorResults); + $files = (new PackageGenerator())->createFileList($validatorResults); if (!array_key_exists('bin/', $files)) { $this->numErrors++; @@ -38,4 +44,108 @@ public function testGenerate_WithMissingBin_ReturnsBin() echo __FUNCTION__ . ": Expected config/ to be absent" . PHP_EOL; } } + + public function testGenerate_WithExistingDir_SkipsDir() + { + $validatorResults = [ + 'bin/' => [ + 'state' => ComplianceValidator::STATE_OPTIONAL_NOT_PRESENT, + 'expected' => 'bin/', + ], + ]; + + $tmp = __DIR__.'/tmp_allowed'; + $bin = $tmp.'/bin'; + if (!is_dir($tmp)) { + mkdir($tmp, 0755); + } + if (!is_dir($bin)) { + mkdir($bin, 0755); + } + + try { + $createdFiles = (new PackageGenerator())->createFiles($validatorResults, $tmp); + } catch (GeneratorException $e) { + $this->numErrors++; + echo __FUNCTION__ . ": Unexpected exception" . PHP_EOL; + } + + if (!array_key_exists('bin/', $createdFiles)) { + $this->numErrors++; + echo __FUNCTION__ . ": Expected to return bin/" . PHP_EOL; + } + + rmdir($tmp.'/bin'); + rmdir($tmp); + } + + public function testGenerate_WithExistingFile_SkipsFile() + { + $validatorResults = [ + 'LICENSE' => [ + 'state' => ComplianceValidator::STATE_RECOMMENDED_NOT_PRESENT, + 'expected' => 'LICENSE', + ], + ]; + + $tmp = __DIR__.'/tmp_allowed'; + $file = $tmp.'/LICENSE.md'; + if (!is_dir($tmp)) { + mkdir($tmp, 0755); + } + touch($file); + file_put_contents($file, 'Original content'); + + try { + $createdFiles = (new PackageGenerator())->createFiles($validatorResults, $tmp); + } catch (GeneratorException $e) { + $this->numErrors++; + echo __FUNCTION__ . ': Unexpected exception' . PHP_EOL; + } + + if (!array_key_exists('LICENSE', $createdFiles)) { + $this->numErrors++; + echo __FUNCTION__ . ': Expected to return file' . PHP_EOL; + } + + if (file_get_contents($file) !== 'Original content') { + $this->numErrors++; + echo __FUNCTION__ . ': Expected to preserve original content' . PHP_EOL; + } + + unlink($file); + rmdir($tmp); + } + + public function testGenerate_WithBadPermissions_SkipsDirAndThrowsException() + { + $validatorResults = [ + 'bin/' => [ + 'state' => ComplianceValidator::STATE_OPTIONAL_NOT_PRESENT, + 'expected' => 'bin/', + ], + ]; + + $tmp = __DIR__.'/tmp_forbidden'; + if (!is_dir($tmp)) { + mkdir($tmp, 0644); + } + + try { + (new PackageGenerator())->createFiles($validatorResults, $tmp); + } catch (GeneratorException $e) { + rmdir($tmp); + return; + } + + $this->numErrors++; + echo __FUNCTION__ . ": Expected exception, but none was thrown" . PHP_EOL; + + if (!is_dir($tmp.'/bin')) { + $this->numErrors++; + echo __FUNCTION__ . ": Expected to not create a directory, but bin/ was created" . PHP_EOL; + } + + rmdir($tmp); + } } \ No newline at end of file