From 393a435f7b49354ae0720f7541196606d6475e2c Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 7 Feb 2022 21:40:55 -0500 Subject: [PATCH] Repository skeleton --- .gitattributes | 7 ++ .gitignore | 27 ++++++ .php_cs.dist | 80 +++++++++++++++++ RoboFile.php | 147 +++++++++++++++++++++++++++++++ composer.json | 38 ++++++++ robo | 14 +++ robo.bat | 21 +++++ tests/bootstrap.php | 18 ++++ tests/phpunit.dist.xml | 23 +++++ vendor-bin/csfixer/composer.json | 5 ++ vendor-bin/phpunit/composer.json | 6 ++ vendor-bin/robo/composer.json | 5 ++ 12 files changed, 391 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .php_cs.dist create mode 100644 RoboFile.php create mode 100644 composer.json create mode 100755 robo create mode 100644 robo.bat create mode 100644 tests/bootstrap.php create mode 100644 tests/phpunit.dist.xml create mode 100644 vendor-bin/csfixer/composer.json create mode 100644 vendor-bin/phpunit/composer.json create mode 100644 vendor-bin/robo/composer.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..aaa63b7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto encoding=utf-8 + +*.html diff=html +*.php diff=php +*.bat eol=crlf +*.cmd eol=crlf +.gitignore -eol diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bbb94f --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Temporary files + +/tests/coverage/ +/.php_cs.cache +/tests/.phpunit.result.cache + +# Dependencies + +/vendor/ +/vendor-bin/*/vendor + +# Windows files + +Thumbs.db +ehthumbs.db +Desktop.ini +$RECYCLE.BIN/ + + +# macOS files + +.DS_Store +.AppleDouble +.LSOverride +._* +.Spotlight-V100 +.Trashes diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..8cb299a --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,80 @@ + ['comment_type' => "phpdocs_only"], + 'array_syntax' => ['syntax' => "short"], + 'binary_operator_spaces' => [ + 'default' => "single_space", + 'operators' => ['=>' => "align_single_space"], + ], + 'cast_spaces' => ['space' => "single"], + 'concat_space' => ['spacing' => "none"], + 'list_syntax' => ['syntax' => "short"], + 'magic_constant_casing' => true, + 'magic_method_casing' => true, + 'modernize_types_casting' => true, + 'native_function_casing' => true, + 'native_function_type_declaration_casing' => true, + 'no_binary_string' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_extra_blank_lines' => true, // this could probably use more configuration + 'no_mixed_echo_print' => ['use' => "echo"], + 'no_short_bool_cast' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_curly_braces' => true, + 'no_unused_imports' => true, + 'no_whitespace_before_comma_in_array' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'pow_to_exponentiation' => true, + 'set_type_to_cast' => true, + 'standardize_not_equals' => true, + 'trailing_comma_in_multiline_array' => true, + 'unary_operator_spaces' => true, + 'yoda_style' => false, + // PSR standard to apply + '@PSR2' => true, + // PSR-12 rules; php-cs-fixer does not yet support PSR-12 natively + 'compact_nullable_typehint' => true, + 'declare_equal_normalize' => ['space' => "none"], + 'function_typehint_space' => true, + 'lowercase_cast' => true, + 'lowercase_static_reference' => true, + 'no_alternative_syntax' => true, + 'no_empty_statement' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_whitespace_in_blank_line' => true, + 'return_type_declaration' => ['space_before' => "none"], + 'single_trait_insert_per_statement' => true, + 'short_scalar_cast' => true, + 'visibility_required' => ['elements' => ["const", "property", "method"]], + // house exceptions to PSR rules + 'braces' => ['position_after_functions_and_oop_constructs' => "same"], + 'function_declaration' => ['closure_function_spacing' => "none"], + 'new_with_braces' => false, // no option to specify absence of braces + ]; + +$finder = \PhpCsFixer\Finder::create(); +foreach ($paths as $path) { + if (is_file($path)) { + $finder = $finder->append([$path]); + } else { + $finder = $finder->in($path); + } +} +return \PhpCsFixer\Config::create()->setRiskyAllowed(true)->setRules($rules)->setFinder($finder); diff --git a/RoboFile.php b/RoboFile.php new file mode 100644 index 0000000..e33013f --- /dev/null +++ b/RoboFile.php @@ -0,0 +1,147 @@ +runTests(escapeshellarg(\PHP_BINARY), "typical", $args); + } + + /** Runs the full test suite + * + * This includes pedantic tests which may help to identify problems. + * See help for the "test" task for more details. + */ + public function testFull(array $args): Result { + return $this->runTests(escapeshellarg(\PHP_BINARY), "full", $args); + } + + /** + * Runs a quick subset of the test suite + * + * See help for the "test" task for more details. + */ + public function testQuick(array $args): Result { + return $this->runTests(escapeshellarg(\PHP_BINARY), "quick", $args); + } + + /** Produces a code coverage report + * + * By default this task produces an HTML-format coverage report in + * tests/coverage/. Additional reports may be produced by passing + * arguments to this task as one would to PHPUnit. + * + * Robo first tries to use pcov and will fall back first to xdebug then + * phpdbg. Neither pcov nor xdebug need to be enabled to be used; they + * only need to be present in the extension load path to be used. + */ + public function coverage(array $args): Result { + // run tests with code coverage reporting enabled + $exec = $this->findCoverageEngine(); + return $this->runTests($exec, "coverage", array_merge(["--coverage-html", BASE_TEST."coverage"], $args)); + } + + /** Produces a code coverage report, with redundant tests + * + * Depending on the environment, some tests that normally provide + * coverage may be skipped, while working alternatives are normally + * suppressed for reasons of time. This coverage report will try to + * run all tests which may cover code. + * + * See also help for the "coverage" task for more details. + */ + public function coverageFull(array $args): Result { + // run tests with code coverage reporting enabled + $exec = $this->findCoverageEngine(); + return $this->runTests($exec, "typical", array_merge(["--coverage-html", BASE_TEST."coverage"], $args)); + } + + /** Runs the coding standards fixer */ + public function clean($opts = ['demo|d' => false]): Result { + $t = $this->taskExec(norm(BASE."vendor/bin/php-cs-fixer")); + $t->arg("fix"); + if ($opts['demo']) { + $t->args("--dry-run", "--diff")->option("--diff-format", "udiff"); + } + return $t->run(); + } + + protected function findCoverageEngine(): string { + $dir = rtrim(ini_get("extension_dir"), "/").\DIRECTORY_SEPARATOR; + $ext = IS_WIN ? "dll" : "so"; + $php = escapeshellarg(\PHP_BINARY); + $code = escapeshellarg(BASE."lib"); + if (extension_loaded("pcov")) { + return "$php -d pcov.enabled=1 -d pcov.directory=$code"; + } elseif (extension_loaded("xdebug")) { + return "$php -d xdebug.mode=coverage"; + } elseif (file_exists($dir."pcov.$ext")) { + return "$php -d extension=pcov.$ext -d pcov.enabled=1 -d pcov.directory=$code"; + } elseif (file_exists($dir."xdebug.$ext")) { + return "$php -d zend_extension=xdebug.$ext -d xdebug.mode=coverage"; + } else { + if (IS_WIN) { + $dbg = dirname(\PHP_BINARY)."\\phpdbg.exe"; + $dbg = file_exists($dbg) ? $dbg : ""; + } else { + $dbg = trim(`which phpdbg 2>/dev/null`); + } + if ($dbg) { + return escapeshellarg($dbg)." -qrr"; + } else { + return $php; + } + } + } + + protected function blackhole(bool $all = false): string { + $hole = IS_WIN ? "nul" : "/dev/null"; + return $all ? ">$hole 2>&1" : "2>$hole"; + } + + protected function runTests(string $executor, string $set, array $args): Result { + switch ($set) { + case "typical": + $set = ["--exclude-group", "optional"]; + break; + case "quick": + $set = ["--exclude-group", "optional,slow"]; + break; + case "coverage": + $set = ["--exclude-group", "optional,coverageOptional"]; + break; + case "full": + $set = []; + break; + default: + throw new \Exception; + } + $execpath = norm(BASE."vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit"); + $confpath = realpath(BASE_TEST."phpunit.dist.xml") ?: norm(BASE_TEST."phpunit.xml"); + return $this->taskExec($executor)->option("-d", "zend.assertions=1")->arg($execpath)->option("-c", $confpath)->args(array_merge($set, $args))->run(); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4d4f1b0 --- /dev/null +++ b/composer.json @@ -0,0 +1,38 @@ +{ + "name": "mensbeam/docopt-ng", + "type": "library", + "description": "A PHP port of Docopt-ng", + "license": "MIT", + "authors": [ + { + "name": "J. King", + "email": "jking@jkingweb.ca", + "homepage": "https://jkingweb.ca/" + } + + ], + "require": { + "php": ">=7.1" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "*" + }, + "config": { + "allow-plugins": { + "bamarni/composer-bin-plugin": true + } + }, + "scripts": { + "post-install-cmd": ["@composer bin all install"], + "post-update-cmd": ["@composer bin all update"] + }, + "autoload": { + "classmap": ["lib/Docopt.php"] + }, + "autoload-dev": { + "psr-4": { + "MensBeam\\Docopt\\Test\\": "tests/lib/", + "MensBeam\\Docopt\\TestCase\\": "tests/cases/" + } + } +} diff --git a/robo b/robo new file mode 100755 index 0000000..e096c36 --- /dev/null +++ b/robo @@ -0,0 +1,14 @@ +#! /bin/sh +base=`dirname "$0"` +roboCommand="$1" +if [ $# -eq 0 ]; then + "$base/vendor/bin/robo" +else + shift + ulimit -n 2048 + if [ "$1" = "clean" ]; then + "$base/vendor/bin/robo" "$roboCommand" "$@" + else + "$base/vendor/bin/robo" "$roboCommand" -- "$@" + fi +fi diff --git a/robo.bat b/robo.bat new file mode 100644 index 0000000..297f954 --- /dev/null +++ b/robo.bat @@ -0,0 +1,21 @@ +@echo off +setlocal +set base=%~dp0 +set roboCommand=%1 + +rem get all arguments except the first +shift +set "args=" +:parse +if "%~1" neq "" ( + set args=%args% %1 + shift + goto :parse +) +if defined args set args=%args:~1% + +if "%1"=="clean" ( + call "%base%vendor\bin\robo" "%roboCommand%" %args% +) else ( + call "%base%vendor\bin\robo" "%roboCommand%" -- %args% +) diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..9726367 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,18 @@ + + + + + + ../lib + + + + + + diff --git a/vendor-bin/csfixer/composer.json b/vendor-bin/csfixer/composer.json new file mode 100644 index 0000000..c49c075 --- /dev/null +++ b/vendor-bin/csfixer/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.8" + } +} diff --git a/vendor-bin/phpunit/composer.json b/vendor-bin/phpunit/composer.json new file mode 100644 index 0000000..1959b22 --- /dev/null +++ b/vendor-bin/phpunit/composer.json @@ -0,0 +1,6 @@ +{ + "require-dev": { + "phpunit/phpunit": "^9.0", + "clue/arguments": "^2.0" + } +} diff --git a/vendor-bin/robo/composer.json b/vendor-bin/robo/composer.json new file mode 100644 index 0000000..1052c54 --- /dev/null +++ b/vendor-bin/robo/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "consolidation/robo": "^3.0" + } +}