Skip to content

Commit c117590

Browse files
authored
Merge pull request #58 from aboks/issue57
Derive author from `git var GIT_AUTHOR_IDENT`
2 parents 715cd0c + be8e803 commit c117590

File tree

5 files changed

+102
-48
lines changed

5 files changed

+102
-48
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
],
1313
"require": {
1414
"php": "^8.0.0|^8.1.0|^8.2.0",
15-
"captainhook/captainhook": "^5.12.0"
15+
"captainhook/captainhook": "^5.12.0",
16+
"sebastianfeldmann/git": "^3.14.0"
1617
},
1718
"require-dev": {
1819
"bitexpert/captainhook-infection": "^0.7.0",
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Captain Hook Validate Author plugin package.
5+
*
6+
* (c) bitExpert AG
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace bitExpert\CaptainHook\ValidateAuthor;
13+
14+
final class GitIdentity
15+
{
16+
public function __construct(private string $name, private string $email)
17+
{
18+
}
19+
20+
public function getName(): string
21+
{
22+
return $this->name;
23+
}
24+
25+
public function getEmail(): string
26+
{
27+
return $this->email;
28+
}
29+
30+
/**
31+
* Parses a git identity from an ident string as returned by e.g.
32+
* `git var GIT_AUTHOR_IDENT` or `git var GIT_COMMITTER_IDENT`.
33+
*
34+
* @param string $ident
35+
* @return self
36+
*/
37+
public static function fromIdentString(string $ident): self
38+
{
39+
if (!(bool)preg_match('/^([^<]+) <([^>]+)>/', $ident, $matches)) {
40+
throw new \RuntimeException('Could not parse git ident string');
41+
}
42+
43+
return new self($matches[1], $matches[2]);
44+
}
45+
}

src/bitExpert/CaptainHook/ValidateAuthor/ValidateAuthorAction.php

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,15 @@
1414
use CaptainHook\App\Config;
1515
use CaptainHook\App\Console\IO;
1616
use CaptainHook\App\Hook\Action;
17-
use SebastianFeldmann\Cli\Command\Runner\Simple;
18-
use SebastianFeldmann\Cli\Processor\ProcOpen as Processor;
19-
use SebastianFeldmann\Git\Command\Config\Get;
20-
use SebastianFeldmann\Git\Command\Config\ListSettings\MapSettings;
2117
use SebastianFeldmann\Git\Repository;
2218

2319
class ValidateAuthorAction implements Action
2420
{
25-
/**
26-
* @var Simple
27-
*/
28-
private $runner;
29-
3021
/**
3122
* Creates new {@link \bitExpert\CaptainHook\ValidateAuthor\ValidateAuthorAction}.
3223
*/
3324
public function __construct()
3425
{
35-
$this->runner = new Simple(new Processor());
3626
}
3727

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

45+
$authorIdentity = $this->getGitAuthorIdentity($repository);
46+
5547
if (isset($options['name'])) {
56-
$userName = $this->getConfig($repository, 'user.name');
48+
$userName = $authorIdentity->getName();
5749
if (!(bool)preg_match($options['name'], $userName)) {
5850
throw new \RuntimeException(
5951
sprintf(
@@ -66,7 +58,7 @@ public function execute(Config $config, IO $io, Repository $repository, Config\A
6658
}
6759

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

82-
/**
83-
* Returns the given config $setting for given $repository.
84-
*
85-
* @param Repository $repository
86-
* @param string $setting
87-
* @return string
88-
*/
89-
protected function getConfig(Repository $repository, string $setting): string
74+
protected function getGitAuthorIdentity(Repository $repository): GitIdentity
9075
{
91-
$cmd = (new Get($repository->getRoot()))
92-
->name($setting);
93-
94-
$result = $this->runner->run($cmd, new MapSettings());
95-
/** @var array<String> $output */
96-
$output =$result->getFormattedOutput();
97-
return (string) key($output);
76+
$gitAuthorIdentString = $repository->getConfigOperator()->getVar('GIT_AUTHOR_IDENT');
77+
return GitIdentity::fromIdentString($gitAuthorIdentString);
9878
}
9979
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Captain Hook Validate Author plugin package.
5+
*
6+
* (c) bitExpert AG
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace bitExpert\CaptainHook\ValidateAuthor;
13+
14+
use PHPUnit\Framework\TestCase;
15+
16+
class GitIdentityUnitTest extends TestCase
17+
{
18+
/**
19+
* @test
20+
* @see https://git-scm.com/docs/git-var#_examples
21+
*/
22+
public function parsesGitIdentStringToNameAndEmail(): void
23+
{
24+
$ident = GitIdentity::fromIdentString('Eric W. Biederman <[email protected]> 1121223278 -0600');
25+
self::assertSame('Eric W. Biederman', $ident->getName());
26+
self::assertSame('[email protected]', $ident->getEmail());
27+
}
28+
}

tests/bitExpert/CaptainHook/ValidateAuthor/ValidateAuthorActionUnitTest.php

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function setUp(): void
5858
$this->io = $this->createMock(IO::class);
5959
$this->repository = $this->createMock(Repository::class);
6060
$this->action = $this->createMock(Action::class);
61-
$this->hook = $this->createPartialMock(ValidateAuthorAction::class, ['getConfig']);
61+
$this->hook = $this->createPartialMock(ValidateAuthorAction::class, ['getGitAuthorIdentity']);
6262
}
6363

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

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

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

8888
$this->hook->expects(self::once())
89-
->method('getConfig')
90-
->with($this->repository, 'user.name')
91-
->willReturn('Some author name');
89+
->method('getGitAuthorIdentity')
90+
->with($this->repository)
91+
->willReturn(new GitIdentity('Some author name', '[email protected]'));
9292

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

105105
$this->hook->expects(self::once())
106-
->method('getConfig')
107-
->with($this->repository, 'user.name')
108-
->willReturn('ABCDEF');
106+
->method('getGitAuthorIdentity')
107+
->with($this->repository)
108+
->willReturn(new GitIdentity('ABCDEF', '[email protected]'));
109109

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

124124
$this->hook->expects(self::once())
125-
->method('getConfig')
126-
->with($this->repository, 'user.name')
127-
->willReturn('ABCDEF');
125+
->method('getGitAuthorIdentity')
126+
->with($this->repository)
127+
->willReturn(new GitIdentity('ABCDEF', '[email protected]'));
128128

129129
$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
130130
}
@@ -139,9 +139,9 @@ public function configuredEmailRegexWillTriggerValidation(): void
139139
->willReturn(new Options(['email' => '/[email protected]/']));
140140

141141
$this->hook->expects(self::once())
142-
->method('getConfig')
143-
->with($this->repository, 'user.email')
144-
->willReturn('[email protected]');
142+
->method('getGitAuthorIdentity')
143+
->with($this->repository)
144+
->willReturn(new GitIdentity('Some author name', '[email protected]'));
145145

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

158158
$this->hook->expects(self::once())
159-
->method('getConfig')
160-
->with($this->repository, 'user.email')
161-
->willReturn('[email protected]');
159+
->method('getGitAuthorIdentity')
160+
->with($this->repository)
161+
->willReturn(new GitIdentity('Some author name', '[email protected]'));
162162

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

177177
$this->hook->expects(self::once())
178-
->method('getConfig')
179-
->with($this->repository, 'user.email')
180-
->willReturn('[email protected]');
178+
->method('getGitAuthorIdentity')
179+
->with($this->repository)
180+
->willReturn(new GitIdentity('Some author name', '[email protected]'));
181181

182182
$this->hook->execute($this->config, $this->io, $this->repository, $this->action);
183183
}

0 commit comments

Comments
 (0)