From e046ca6e16c95167c43bafda41b7aabe6a4c03d0 Mon Sep 17 00:00:00 2001 From: Tobias van Beek Date: Wed, 18 Aug 2021 17:29:22 +0200 Subject: [PATCH] First commit --- .gitattributes | 11 ++ .gitignore | 11 ++ .gitlab-ci.yml | 101 ++++++++++++++++++ CHANGELOG.md | 9 ++ CONTRIBUTING.md | 17 +++ LICENSE.md | 17 +++ README.md | 22 ++++ composer.json | 60 +++++++++++ docs/examples/basic.php | 21 ++++ phpcs.xml.dist | 15 +++ phpmd.xml.dist | 15 +++ phpstan.neon.dist | 7 ++ phpunit.xml.dist | 40 +++++++ src/Contracts/FinderFactory.php | 12 +++ src/Contracts/GitHashFinder.php | 22 ++++ src/Contracts/GitHashRetriever.php | 13 +++ src/Exceptions/FindHashException.php | 11 ++ src/Exceptions/GitHashException.php | 12 +++ src/Factories/GitHashFinderFactory.php | 37 +++++++ .../GitProcessCommandHashFinder.php | 37 +++++++ .../GitShellExecCommandHashFinder.php | 38 +++++++ src/Retriever/Retriever.php | 40 +++++++ src/Values/GitHash.php | 25 +++++ tests/TestCase.php | 13 +++ tests/Values/GitHashTest.php | 64 +++++++++++ 25 files changed, 670 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 docs/examples/basic.php create mode 100644 phpcs.xml.dist create mode 100644 phpmd.xml.dist create mode 100644 phpstan.neon.dist create mode 100644 phpunit.xml.dist create mode 100644 src/Contracts/FinderFactory.php create mode 100644 src/Contracts/GitHashFinder.php create mode 100644 src/Contracts/GitHashRetriever.php create mode 100644 src/Exceptions/FindHashException.php create mode 100644 src/Exceptions/GitHashException.php create mode 100644 src/Factories/GitHashFinderFactory.php create mode 100644 src/HashFinders/GitProcessCommandHashFinder.php create mode 100644 src/HashFinders/GitShellExecCommandHashFinder.php create mode 100644 src/Retriever/Retriever.php create mode 100644 src/Values/GitHash.php create mode 100644 tests/TestCase.php create mode 100644 tests/Values/GitHashTest.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..07d5b35 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +/.gitattributes export-ignore +/.gitlab-ci.yml export-ignore +/build export-ignore +/docs +/phpcs.xml.dist export-ignore +/phpmd.xml.dist export-ignore +/phpunit.xml.dist export-ignore +/phpstan.neon.dist export-ignore +/phpmd.xml.dist export-ignore +/tests export-ignore + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef97c38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/.phpunit.result.cache +/.phpunit.cache +/build/ +/vendor/ +/code-climate.json +/composer.lock +/phpcs.xml +/phpmd.xml +/phpstan.json +/phpstan.neon +/phpunit.xml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..5f8b234 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,101 @@ +# set the default docker image +image: registry.gitlab.com/tjvb/phpimages:php80 + +stages: + - prepare # prepare the cache + - check # check the codestyles + - test + +prepare_cache: + stage: prepare + script: + # Install composer + - curl -sS https://getcomposer.org/installer | php + - php composer.phar validate + - php composer.phar install + # we use this artifact for all the jobs + artifacts: + name: "vendor" + paths: + - vendor/* + +lint: + stage: check + script: + # lint recursive + - find src/ -type f -name '*.php' -exec php -l {} \; | (! grep -v "No syntax errors detected" ) + dependencies: [] + +phpcs: + stage: check + script: + - vendor/bin/phpcs + dependencies: + - prepare_cache + needs: + - prepare_cache + +phpmd: + stage: check + script: + - vendor/bin/phpmd src/ text phpmd.xml.dist + dependencies: + - prepare_cache + needs: + - prepare_cache + +phpstan: + stage: check + script: + # check for phpstan errors + - php -d memory_limit=500M vendor/bin/phpstan analyse --error-format=gitlab > phpstan.json + - cat phpstan.json + dependencies: + - prepare_cache + needs: + - prepare_cache + artifacts: + paths: + - phpstan.json + when: always + +test_lowest: + stage: test + script: + # Install composer + - rm -f composer.lock + - curl -sS https://getcomposer.org/installer | php + - php composer.phar update --prefer-lowest + - vendor/bin/phpunit --coverage-text --colors=never --log-junit=phpunitresult/junit.xml + artifacts: + reports: + junit: phpunitresult/junit.xml + dependencies: + - prepare_cache + needs: + - prepare_cache + +test_php80: + stage: test + script: + - vendor/bin/phpunit --coverage-text --colors=never --coverage-cobertura=phpunitresult/cobertura-coverage.xml --log-junit=phpunitresult/junit.xml + - sed -i 's~ filename="~ filename="src/~' phpunitresult/cobertura-coverage.xml + artifacts: + reports: + junit: phpunitresult/junit.xml + cobertura: phpunitresult/cobertura-coverage.xml + dependencies: + - prepare_cache + needs: + - prepare_cache + +CodeQuality: + stage: Code quality converter + dependencies: + - phpstan + script: + - vendor/bin/converter convert --phpstan --phpstan-json-file=phpstan.json + artifacts: + reports: + codequality: code-climate.json + when: always \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b4f6499 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + + +## [Unreleased] + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6e54558 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contributing +Contributions are allways very welcome. This file is a guideline about how to contribute. + +## How to contribute +All the contributes need to be done with a merge request. It is possible to create a merge request prefixed with WIP: to ask for feedback or if you didn't know how to match all requirements. +Please be sure to check all the [requirements](#requirements) before sending your merge request (except a WIP merge request) + +## Requirements +* All the code need to confirm to the [PSR-12](https://www.php-fig.org/psr/psr-12/). You can check this localy with `vendor/bin/phpcs` +* We use [PHPMD](https://phpmd.org) to validate the quality of the code. You can check it localy with `vendor/bin/phpmd src text phpmd.xml.dist` +* Add tests for code changes, we use [PHPUnit](https://phpunit.de/). You can run the test with `vendor/bin/phpunit` this wil also generate some reports in the build directory. +* We also use [PHPStan](https://phpstan.org/) to find possible bugs in the code. You can run it with `vendor/bin/phpstan`. +* Document the changes, any functional change or bug fix need to be writen in [CHANGELOG.md](CHANGELOG.md). Depending on your change you need to add some documentation to the [README.md](README.md) +* Respect [SemVer](http://semver.org/), we use Semanting Versioning so please respect it with the changes you want to add. +* A merge request for a change. Please don't mix multiple changes in one merge request. +* Ask questions, if you are not sure about something ask it. + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..a449b50 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,17 @@ +MIT License +Copyright (c) 2021 Tobias van Beek +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3d90341 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# GitHash + +This package is intended to give a usefull option + + +## Examples +See docs/examples for examples about how to use this package. + + +## Installation +You can install this package with composer by executing the command: `composer require tjvb/githash`. + + +## Changelog +We (try to) document all the changes in [CHANGELOG](CHANGELOG.md) so read it for more information. + +## Contributing +You are very welcome to contribute, read about it in [CONTRIBUTING](CONTRIBUTING.md) + +## License +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..5f43378 --- /dev/null +++ b/composer.json @@ -0,0 +1,60 @@ +{ + "name": "tjvb/githash", + "type": "library", + "description": "Get the current git hash from your project.", + "keywords": [ + "tjvb", + "githash" + ], + "license": "MIT", + "authors": [ + { + "name": "Tobias van Beek", + "email": "t.vanbeek@tjvb.nl", + "homepage": "https://www.tjvb.nl" + } + ], + "require": { + "php": "^8.0" + }, + "require-dev": { + "beechit/json-to-code-climate-subset-converter": "^1.6", + "fakerphp/faker": "^1.15", + "phpmd/phpmd": "^2.10", + "phpstan/phpstan": "^0.12.94", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.6", + "symfony/process": "^5.3" + }, + "suggest": { + "symfony/process": "Used rather than `shell_exec` if available (tested with ^5.3)." + }, + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { + "TJVB\\GitHash\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "TJVB\\GitHash\\Tests\\": "tests/" + } + }, + "scripts": { + "format": "vendor/bin/phpcbf", + "test": "vendor/bin/phpunit --no-coverage", + "test-coverage": "vendor/bin/phpunit --coverage-html coverage" + }, + "support": { + "issues": "https://gitlab.com/tjvb/githash/-/issues", + "source": "https://gitlab.com/tjvb/githash/-/tree/master" + }, + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/tvbeek" + } + ] +} diff --git a/docs/examples/basic.php b/docs/examples/basic.php new file mode 100644 index 0000000..5eb756a --- /dev/null +++ b/docs/examples/basic.php @@ -0,0 +1,21 @@ +getHash($path)->hash() . PHP_EOL; +} catch (GitHashException $exception) { + echo 'Failed to get the hash ' . $exception->getMessage() . PHP_EOL; +} diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..d04f9e7 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,15 @@ + + + The coding standard for GitHash. + ./src/ + ./tests/ + + + + + + + + + + diff --git a/phpmd.xml.dist b/phpmd.xml.dist new file mode 100644 index 0000000..5108429 --- /dev/null +++ b/phpmd.xml.dist @@ -0,0 +1,15 @@ + + + + GitHash ruleset + + + + + + + diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..d312b3d --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,7 @@ +parameters: + level: 5 + paths: + - src + - tests + + ignoreErrors: \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..b27a20f --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,40 @@ + + + + + tests + + + + + + + + + + + + + src + + + + + + + + + + + diff --git a/src/Contracts/FinderFactory.php b/src/Contracts/FinderFactory.php new file mode 100644 index 0000000..fe199a0 --- /dev/null +++ b/src/Contracts/FinderFactory.php @@ -0,0 +1,12 @@ +finders[] = $finder; + } + + public function registerDefaultFinders(): void + { + $this->register(new GitProcessCommandHashFinder()); + $this->register(new GitShellExecCommandHashFinder()); + } + + public function getRegisteredFinders(): array + { + return $this->finders; + } + + public static function withDefaultFinders(): GitHashFinderFactory + { + $factory = new self(); + $factory->registerDefaultFinders(); + return $factory; + } +} diff --git a/src/HashFinders/GitProcessCommandHashFinder.php b/src/HashFinders/GitProcessCommandHashFinder.php new file mode 100644 index 0000000..a4174a7 --- /dev/null +++ b/src/HashFinders/GitProcessCommandHashFinder.php @@ -0,0 +1,37 @@ +mustRun(); + $output = $process->getOutput(); + return new GitHash($output); + } catch (ProcessFailedException) { + throw new FindHashException('Failed to execute git command'); + } + } + + public function isAvailable(): bool + { + return class_exists('Symfony\Component\Process\Process') && + method_exists(Process::class, 'fromShellCommandline') + ; + } +} diff --git a/src/HashFinders/GitShellExecCommandHashFinder.php b/src/HashFinders/GitShellExecCommandHashFinder.php new file mode 100644 index 0000000..f7bb1fd --- /dev/null +++ b/src/HashFinders/GitShellExecCommandHashFinder.php @@ -0,0 +1,38 @@ +finderFactory = $finderFactory; + } + + public function getHash(string $path): GitHash + { + if ($this->finderFactory === null) { + throw new GitHashException('We can\'t find a hash if we didn\'t got a finder factory'); + } + foreach ($this->finderFactory->getRegisteredFinders() as $finder) { + if ($finder->isAvailable()) { + return $finder->findHash($path); + } + } + throw new GitHashException('No finder available'); + } + + public static function getWithFactory(FinderFactory $finderFactory): Retriever + { + $retriever = new self(); + $retriever->setFinderFactory($finderFactory); + return $retriever; + } +} diff --git a/src/Values/GitHash.php b/src/Values/GitHash.php new file mode 100644 index 0000000..f0bb856 --- /dev/null +++ b/src/Values/GitHash.php @@ -0,0 +1,25 @@ +hash = trim($hash); + } + + public function hash(): string + { + return $this->hash; + } + + public function short(int $size = 8): string + { + return substr($this->hash, 0, $size); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..d6bb5ee --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,13 @@ +sha1(); + + // run + $gitHash = new GitHash($hash); + + // verify/assert + $this->assertEquals($hash, $gitHash->hash()); + } + + /** + * @test + */ + public function weGetAShortForTheWantedLength(): void + { + // setup / mock + $faker = Factory::create(); + $hash = $faker->sha1(); + $size = mt_rand(6, 39); + + // run + $gitHash = new GitHash($hash); + $short = $gitHash->short($size); + + // verify/assert + $this->assertSame(strlen($short), $size); + $this->assertStringContainsString($short, $hash); + } + + /** + * @test + */ + public function weStripTheNewLinesFromTheHash(): void + { + // setup / mock + $faker = Factory::create(); + $hash = $faker->sha1(); + + // run + $gitHash = new GitHash($hash . "\n"); + + // verify/assert + $this->assertEquals($hash, $gitHash->hash()); + } +}