diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 16ca44b..6289153 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,3 +30,6 @@ jobs: - name: Check coding styles run: composer run-script cs-lint + + - name: Check leanness of package + run: composer run-script validate-gitattributes diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml new file mode 100644 index 0000000..34990c8 --- /dev/null +++ b/.github/workflows/test-macos.yml @@ -0,0 +1,31 @@ +name: test-macos + +on: push + +jobs: + build: + name: "PHPUnit (PHP ${{ matrix.php }}) macOS" + runs-on: macos-latest + + strategy: + matrix: + php: + - "8.4" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install difftastic + run: brew install difftastic + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Run tests + run: composer run-script test diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml new file mode 100644 index 0000000..98f7d70 --- /dev/null +++ b/.github/workflows/test-windows.yml @@ -0,0 +1,31 @@ +name: test-windows + +on: push + +jobs: + build: + name: "PHPUnit (PHP ${{ matrix.php }})" + runs-on: "windows-latest" + + strategy: + matrix: + php: + - "8.1" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install difftastic + run: choco install difftastic + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Run tests + run: composer run-script test diff --git a/README.md b/README.md index 26d755b..c73a7b6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ # Difftastic PHP +![Test Status](https://github.com/raphaelstolt/difftastic-php/workflows/test/badge.svg) +[![Version](http://img.shields.io/packagist/v/stolt/difftastic-php.svg?style=flat)](https://packagist.org/packages/stolt/difftastic-php) +![PHP Version](https://img.shields.io/badge/php-8.1+-ff69b4.svg) +[![PDS Skeleton](https://img.shields.io/badge/pds-skeleton-blue.svg?style=flat)](https://github.com/php-pds/skeleton) + This Composer package provides a wrapper around [difftastic](https://github.com/Wilfred/difftastic) -for usage in PHP based projects; therefor it requires `difftastic` to be [installed](https://difftastic.wilfred.me.uk/installation.html). +for usage in PHP based projects; therefor it requires `difftastic` to be [installed](https://difftastic.wilfred.me.uk/installation.html). +Which can be done on macOS via a simple `brew install difftastic`. ## Installation @@ -20,6 +26,15 @@ $difftastic = new Difftastic(); $diff = $difftastic->diff('[1, 2, 3]', '[3, 2, 1]'); ``` +With options differing from the default: + +```php +use Stolt\Difftastic; + +$difftastic = new Difftastic(background: 'light', color: 'never'); +$diff = $difftastic->diff('[1, 2, 3]', '[3, 2, 1]'); +``` + ### Running tests ``` bash diff --git a/composer.json b/composer.json index 6250b14..6a8b67b 100644 --- a/composer.json +++ b/composer.json @@ -26,13 +26,15 @@ "scripts": { "test": "phpunit", "test-with-coverage": "export XDEBUG_MODE=coverage && phpunit --coverage-html coverage-reports", + "validate-gitattributes": "lean-package-validator validate", "cs-fix": "php-cs-fixer --allow-risky=yes fix . -vv || true", "cs-lint": "php-cs-fixer fix --diff --stop-on-violation --verbose --dry-run --allow-risky=yes", "static-analyse": "phpstan analyse --configuration phpstan.neon.dist", "pre-commit-check": [ "@test", "@cs-lint", - "@static-analyse" + "@static-analyse", + "@validate-gitattributes" ] }, "config": { @@ -43,6 +45,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.0", "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^11.4.4||^10.5.25" + "phpunit/phpunit": "^11.4.4||^10.5.25", + "stolt/lean-package-validator": "^4.1" } } diff --git a/src/Difftastic.php b/src/Difftastic.php index c53aeae..2547aa9 100644 --- a/src/Difftastic.php +++ b/src/Difftastic.php @@ -10,6 +10,10 @@ final class Difftastic { private string $difftasticBinaryCommand; + private string $background = 'dark'; + + private string $color = 'auto'; + /** * @throws RuntimeException */ @@ -26,9 +30,6 @@ public function __construct(string $background = 'dark', string $color = 'auto') if ($this->isDifftasticCommandAvailable() === false) { throw new RuntimeException('Difftastic CLI not available'); } - // is difftastic binary installed [x] - // set config/option values [x] (see https://github.com/joeldrapper/difftastic-ruby/blob/main/lib/difftastic/differ.rb) - // determine which difftastic binary to use, difftastic or difft [x] } private function isDifftasticCommandAvailable(): bool @@ -48,18 +49,37 @@ private function getDifftasticBinaryByOs(): string return match (\strtolower(PHP_OS_FAMILY)) { 'darwin' => 'difft', 'linux' => 'difftastic', - 'windows' => 'difftastic', + 'windows' => 'difft', default => throw new RuntimeException( 'Unsupported operating system ' . PHP_OS_FAMILY ) }; } + + private function getDifftasticOptions(): string + { + $options = ''; + + if ($this->background !== 'dark') { + $options .= ' --background ' . $this->background; + } + + if ($this->color !== 'auto') { + $options .= ' --color ' . $this->color; + } + + return $options; + } + private function createTemporaryFile(string $name, string $content): string { - $file = DIRECTORY_SEPARATOR . - \trim(\sys_get_temp_dir(), DIRECTORY_SEPARATOR) . - DIRECTORY_SEPARATOR . - \ltrim($name, DIRECTORY_SEPARATOR); + $file = DIRECTORY_SEPARATOR . \trim(\sys_get_temp_dir(), DIRECTORY_SEPARATOR) + . DIRECTORY_SEPARATOR . \ltrim($name, DIRECTORY_SEPARATOR); + + if ($this->isWindows()) { + $file = \trim(\sys_get_temp_dir(), DIRECTORY_SEPARATOR) + . DIRECTORY_SEPARATOR . \ltrim($name, DIRECTORY_SEPARATOR); + } file_put_contents($file, $content); @@ -84,11 +104,9 @@ public function diff(string $a, string $b): string $aFile = $this->createTemporaryFile('a', $a); $bFile = $this->createTemporaryFile('b', $b); - \exec( - $this->difftasticBinaryCommand . ' ' . $aFile . ' ' . $bFile . ' 2>&1', - $output, - $returnValue - ); + $command = $this->difftasticBinaryCommand . $this->getDifftasticOptions() . ' ' . $aFile . ' ' . $bFile . ' 2>&1'; + + \exec($command, $output, $returnValue); return \implode(PHP_EOL, $output); } diff --git a/tests/DifftasticTest.php b/tests/DifftasticTest.php index e5f79ec..9936d70 100644 --- a/tests/DifftasticTest.php +++ b/tests/DifftasticTest.php @@ -4,6 +4,7 @@ namespace Stolt\Tests; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\Ticket; use PHPUnit\Framework\TestCase; @@ -23,7 +24,7 @@ public function getsExpectedDifftasticBinary(): void $expectedBinary = 'difftastic'; - if (\strtolower(PHP_OS_FAMILY) === 'darwin') { + if (\strtolower(PHP_OS_FAMILY) === 'darwin' || \strtolower(PHP_OS_FAMILY) === 'windows') { $expectedBinary = 'difft'; } @@ -42,6 +43,7 @@ public function throwsExpectedExceptionOnMisconfiguration(): void #[Test] #[Ticket('https://github.com/Wilfred/difftastic/issues/809')] + #[RunInSeparateProcess] public function returnsExpectedDiff(): void { $difftastic = new Difftastic(); @@ -52,6 +54,23 @@ public function returnsExpectedDiff(): void No such file: /tmp/b DIFF; - $this->assertEquals($diff, $expectedDifftasticOutput); + if (\strtolower(PHP_OS_FAMILY) === 'darwin') { + $expectedDifftasticOutput = <<assertEquals($this->removeFirstOutputLine($diff), $this->removeFirstOutputLine($expectedDifftasticOutput)); + } + + private function removeFirstOutputLine(string $output): string + { + $parts = \explode(PHP_EOL, $output); + + \array_shift($parts); + + return \implode(PHP_EOL, $parts); } }