Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
],
"require": {
"php": "^8.0.0|^8.1.0|^8.2.0",
"captainhook/captainhook": "^5.12.0"
"captainhook/captainhook": "^5.12.0",
"sebastianfeldmann/git": "^3.14.0"
},
"require-dev": {
"bitexpert/captainhook-infection": "^0.7.0",
Expand Down
45 changes: 45 additions & 0 deletions src/bitExpert/CaptainHook/ValidateAuthor/GitIdentity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
* This file is part of the Captain Hook Validate Author plugin package.
*
* (c) bitExpert AG
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace bitExpert\CaptainHook\ValidateAuthor;

final class GitIdentity
{
public function __construct(private string $name, private string $email)
{
}

public function getName(): string
{
return $this->name;
}

public function getEmail(): string
{
return $this->email;
}

/**
* Parses a git identity from an ident string as returned by e.g.
* `git var GIT_AUTHOR_IDENT` or `git var GIT_COMMITTER_IDENT`.
*
* @param string $ident
* @return self
*/
public static function fromIdentString(string $ident): self
{
if (!(bool)preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) {

Check warning on line 39 in src/bitExpert/CaptainHook/ValidateAuthor/GitIdentity.php

View workflow job for this annotation

GitHub Actions / run (ubuntu-latest, 8.2, false)

Escaped Mutant for Mutator "CastBool": --- Original +++ New @@ @@ */ public static function fromIdentString(string $ident) : self { - if (!(bool) preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { + if (!preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { throw new \RuntimeException('Could not parse git ident string'); } return new self($matches[1], $matches[2]); } }

Check warning on line 39 in src/bitExpert/CaptainHook/ValidateAuthor/GitIdentity.php

View workflow job for this annotation

GitHub Actions / run (ubuntu-latest, 8.1, false)

Escaped Mutant for Mutator "CastBool": --- Original +++ New @@ @@ */ public static function fromIdentString(string $ident) : self { - if (!(bool) preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { + if (!preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { throw new \RuntimeException('Could not parse git ident string'); } return new self($matches[1], $matches[2]); } }

Check warning on line 39 in src/bitExpert/CaptainHook/ValidateAuthor/GitIdentity.php

View workflow job for this annotation

GitHub Actions / run (ubuntu-latest, 8.0, false)

Escaped Mutant for Mutator "CastBool": --- Original +++ New @@ @@ */ public static function fromIdentString(string $ident) : self { - if (!(bool) preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { + if (!preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { throw new \RuntimeException('Could not parse git ident string'); } return new self($matches[1], $matches[2]); } }

Check warning on line 39 in src/bitExpert/CaptainHook/ValidateAuthor/GitIdentity.php

View workflow job for this annotation

GitHub Actions / run (ubuntu-latest, 8.2, true, false)

Escaped Mutant for Mutator "CastBool": --- Original +++ New @@ @@ */ public static function fromIdentString(string $ident) : self { - if (!(bool) preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { + if (!preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) { throw new \RuntimeException('Could not parse git ident string'); } return new self($matches[1], $matches[2]); } }
throw new \RuntimeException('Could not parse git ident string');
}

return new self($matches[1], $matches[2]);
}
}
34 changes: 7 additions & 27 deletions src/bitExpert/CaptainHook/ValidateAuthor/ValidateAuthorAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,15 @@
use CaptainHook\App\Config;
use CaptainHook\App\Console\IO;
use CaptainHook\App\Hook\Action;
use SebastianFeldmann\Cli\Command\Runner\Simple;
use SebastianFeldmann\Cli\Processor\ProcOpen as Processor;
use SebastianFeldmann\Git\Command\Config\Get;
use SebastianFeldmann\Git\Command\Config\ListSettings\MapSettings;
use SebastianFeldmann\Git\Repository;

class ValidateAuthorAction implements Action
{
/**
* @var Simple
*/
private $runner;

/**
* Creates new {@link \bitExpert\CaptainHook\ValidateAuthor\ValidateAuthorAction}.
*/
public function __construct()
{
$this->runner = new Simple(new Processor());
}

/**
Expand All @@ -52,8 +42,10 @@ public function execute(Config $config, IO $io, Repository $repository, Config\A
return;
}

$authorIdentity = $this->getGitAuthorIdentity($repository);

if (isset($options['name'])) {
$userName = $this->getConfig($repository, 'user.name');
$userName = $authorIdentity->getName();
if (!(bool)preg_match($options['name'], $userName)) {
throw new \RuntimeException(
sprintf(
Expand All @@ -66,7 +58,7 @@ public function execute(Config $config, IO $io, Repository $repository, Config\A
}

if (isset($options['email'])) {
$userEmail = $this->getConfig($repository, 'user.email');
$userEmail = $authorIdentity->getEmail();
if (!(bool)preg_match($options['email'], $userEmail)) {
throw new \RuntimeException(
sprintf(
Expand All @@ -79,21 +71,9 @@ public function execute(Config $config, IO $io, Repository $repository, Config\A
}
}

/**
* Returns the given config $setting for given $repository.
*
* @param Repository $repository
* @param string $setting
* @return string
*/
protected function getConfig(Repository $repository, string $setting): string
protected function getGitAuthorIdentity(Repository $repository): GitIdentity
{
$cmd = (new Get($repository->getRoot()))
->name($setting);

$result = $this->runner->run($cmd, new MapSettings());
/** @var array<String> $output */
$output =$result->getFormattedOutput();
return (string) key($output);
$gitAuthorIdentString = $repository->getConfigOperator()->getVar('GIT_AUTHOR_IDENT');
return GitIdentity::fromIdentString($gitAuthorIdentString);
}
}
28 changes: 28 additions & 0 deletions tests/bitExpert/CaptainHook/ValidateAuthor/GitIdentityUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* This file is part of the Captain Hook Validate Author plugin package.
*
* (c) bitExpert AG
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace bitExpert\CaptainHook\ValidateAuthor;

use PHPUnit\Framework\TestCase;

class GitIdentityUnitTest extends TestCase
{
/**
* @test
* @see https://git-scm.com/docs/git-var#_examples
*/
public function parsesGitIdentStringToNameAndEmail(): void
{
$ident = GitIdentity::fromIdentString('Eric W. Biederman <ebiederm@lnxi.com> 1121223278 -0600');
self::assertSame('Eric W. Biederman', $ident->getName());
self::assertSame('ebiederm@lnxi.com', $ident->getEmail());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function setUp(): void
$this->io = $this->createMock(IO::class);
$this->repository = $this->createMock(Repository::class);
$this->action = $this->createMock(Action::class);
$this->hook = $this->createPartialMock(ValidateAuthorAction::class, ['getConfig']);
$this->hook = $this->createPartialMock(ValidateAuthorAction::class, ['getGitAuthorIdentity']);
}

/**
Expand All @@ -71,7 +71,7 @@ public function missingConfigurationStopsExecution(): void
->willReturn(new Options([]));

$this->hook->expects(self::never())
->method('getConfig');
->method('getGitAuthorIdentity');

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand All @@ -86,9 +86,9 @@ public function configuredNameRegexWillTriggerValidation(): void
->willReturn(new Options(['name' => '/Some author name/']));

$this->hook->expects(self::once())
->method('getConfig')
->with($this->repository, 'user.name')
->willReturn('Some author name');
->method('getGitAuthorIdentity')
->with($this->repository)
->willReturn(new GitIdentity('Some author name', 'test@test.loc'));

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand All @@ -103,9 +103,9 @@ public function nameValidationWillNotThrowExceptionIfMatches(): void
->willReturn(new Options(['name' => '/[A-F]+/']));

$this->hook->expects(self::once())
->method('getConfig')
->with($this->repository, 'user.name')
->willReturn('ABCDEF');
->method('getGitAuthorIdentity')
->with($this->repository)
->willReturn(new GitIdentity('ABCDEF', 'test@test.loc'));

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand All @@ -122,9 +122,9 @@ public function nameValidationWillThrowExceptionIfNotMatches(): void
->willReturn(new Options(['name' => '/^[1-9]+$/']));

$this->hook->expects(self::once())
->method('getConfig')
->with($this->repository, 'user.name')
->willReturn('ABCDEF');
->method('getGitAuthorIdentity')
->with($this->repository)
->willReturn(new GitIdentity('ABCDEF', 'test@test.loc'));

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand All @@ -139,9 +139,9 @@ public function configuredEmailRegexWillTriggerValidation(): void
->willReturn(new Options(['email' => '/test@test.loc/']));

$this->hook->expects(self::once())
->method('getConfig')
->with($this->repository, 'user.email')
->willReturn('test@test.loc');
->method('getGitAuthorIdentity')
->with($this->repository)
->willReturn(new GitIdentity('Some author name', 'test@test.loc'));

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand All @@ -156,9 +156,9 @@ public function emailValidationWillNotThrowExceptionIfMatches(): void
->willReturn(new Options(['email' => '/@/']));

$this->hook->expects(self::once())
->method('getConfig')
->with($this->repository, 'user.email')
->willReturn('test@test.loc');
->method('getGitAuthorIdentity')
->with($this->repository)
->willReturn(new GitIdentity('Some author name', 'test@test.loc'));

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand All @@ -175,9 +175,9 @@ public function emailValidationWillThrowExceptionIfNotMatches(): void
->willReturn(new Options(['email' => '/^[1-9]+$/']));

$this->hook->expects(self::once())
->method('getConfig')
->with($this->repository, 'user.email')
->willReturn('test@test.loc');
->method('getGitAuthorIdentity')
->with($this->repository)
->willReturn(new GitIdentity('Some author name', 'test@test.loc'));

$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
}
Expand Down