Skip to content

Commit 10b7cbf

Browse files
committed
wip PintPreCommitHook
1 parent be00927 commit 10b7cbf

File tree

6 files changed

+146
-3
lines changed

6 files changed

+146
-3
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Igorsgm\GitHooks\Console\Commands\Hooks;
4+
5+
use Closure;
6+
use Igorsgm\GitHooks\Contracts\PreCommitHook;
7+
use Igorsgm\GitHooks\Exceptions\HookFailException;
8+
use Igorsgm\GitHooks\Facades\GitHooks;
9+
use Igorsgm\GitHooks\Git\ChangedFiles;
10+
use Igorsgm\GitHooks\Traits\ConsoleHelper;
11+
12+
class PintPreCommitHook implements PreCommitHook
13+
{
14+
use ConsoleHelper;
15+
16+
public function getName(): ?string
17+
{
18+
return 'Laravel Pint';
19+
}
20+
21+
public function handle(ChangedFiles $files, Closure $next)
22+
{
23+
$stagedFilePaths = $files->getStaged()->map(function ($file) {
24+
return $file->getFilePath();
25+
})->toArray();
26+
27+
if (empty($stagedFilePaths) || GitHooks::isMergeInProgress()) {
28+
return $next($files);
29+
}
30+
31+
if (!$this->isPintInstalled()) {
32+
$this->newLine(2);
33+
$this->output->writeln(
34+
sprintf("<bg=red;fg=white> ERROR </> %s",
35+
'Pint is not installed. Please run <info>composer require laravel/pint --dev</info> to install it.')
36+
);
37+
$this->newLine();
38+
throw new HookFailException();
39+
}
40+
41+
$errorFiles = [];
42+
foreach ($stagedFilePaths as $stagedFilePath) {
43+
$isPintProperlyFormatted = $this->runCommands('./vendor/bin/pint --test --config ./pint.json ' . $stagedFilePath,
44+
[
45+
'cwd' => base_path(),
46+
])->isSuccessful();
47+
48+
if (!$isPintProperlyFormatted) {
49+
if (empty($errorFiles)) {
50+
$this->newLine();
51+
}
52+
53+
$this->output->writeln(
54+
sprintf("<fg=red> Pint Failed:</> %s", "$stagedFilePath")
55+
);
56+
$errorFiles[] = $stagedFilePath;
57+
}
58+
}
59+
60+
if (empty($errorFiles)) {
61+
return $next($files);
62+
}
63+
64+
$this->newLine();
65+
$this->output->writeln(
66+
sprintf("<bg=red;fg=white> COMMIT FAILED </> %s",
67+
'Your commit contains files that should pass Pint but do not. Please fix the Pint errors in the files above and try again.')
68+
);
69+
70+
if ($this->confirm("Would you like to attempt to correct files automagically?", false)) {
71+
$errorFilesString = implode(' ', $errorFiles);
72+
$this->runCommands(
73+
[
74+
'./vendor/bin/pint --config ./pint.json ' . $errorFilesString,
75+
'git add ' . $errorFilesString,
76+
],
77+
['cwd' => base_path()]
78+
);
79+
} else {
80+
throw new HookFailException();
81+
}
82+
}
83+
84+
public function isPintInstalled()
85+
{
86+
return file_exists(base_path('vendor/bin/pint'));
87+
}
88+
}

src/Contracts/Hook.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ interface Hook
99
*
1010
* @return string
1111
*/
12-
public function getName(): string;
12+
public function getName(): ?string;
1313
}

src/Traits/ConsoleHelper.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Igorsgm\GitHooks\Traits;
4+
5+
use Illuminate\Console\Concerns\InteractsWithIO;
6+
use Illuminate\Console\Concerns\InteractsWithSignals;
7+
use Illuminate\Console\OutputStyle;
8+
use Symfony\Component\Console\Input\StringInput;
9+
use Symfony\Component\Console\Output\ConsoleOutput;
10+
11+
trait ConsoleHelper
12+
{
13+
use ProcessHelper,
14+
InteractsWithIO,
15+
InteractsWithSignals;
16+
17+
/**
18+
* Holds an instance of the console output.
19+
*
20+
* @var \Symfony\Component\Console\Output\ConsoleOutput
21+
*/
22+
protected $consoleOutput;
23+
24+
/**
25+
* The output interface implementation.
26+
*
27+
* @var \Illuminate\Console\OutputStyle
28+
*/
29+
protected $output;
30+
31+
/**
32+
* Create a new console command instance.
33+
*
34+
* @return void
35+
*/
36+
public function __construct($argInput = "")
37+
{
38+
$this->input = new StringInput($argInput);
39+
$this->consoleOutput = new ConsoleOutput();
40+
$this->output = new OutputStyle($this->input, $this->consoleOutput);
41+
}
42+
}

src/Traits/GitHelper.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,16 @@ public function updateCommitMessageContentInFile(string $path, string $message):
6060
{
6161
file_put_contents($path, $message);
6262
}
63+
64+
/**
65+
* @read https://stackoverflow.com/questions/30733415/how-to-determine-if-git-merge-is-in-process#answer-30781568
66+
* @return bool
67+
*/
68+
public function isMergeInProgress()
69+
{
70+
$command = $this->runCommands('git merge HEAD &> /dev/null');
71+
72+
// If a merge is in progress, the process returns code 128
73+
return $command->getExitCode() === 128;
74+
}
6375
}

src/Traits/ProcessHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public function transformCommands($commands, $callback)
7878
}
7979

8080
return $callback($value);
81-
}, $commands);
81+
}, (array) $commands);
8282
}
8383

8484
/**

src/Traits/WithPipeline.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ protected function finishHookConsoleTask(): Closure
9797
*/
9898
public function getHookTaskTitle(Hook $hook): string
9999
{
100-
return sprintf(' <bg=blue;fg=white> HOOK </> %s', $hook->getName());
100+
$hookName = $hook->getName() ?? class_basename($hook);
101+
return sprintf(' <bg=blue;fg=white> HOOK </> %s', $hookName);
101102
}
102103
}

0 commit comments

Comments
 (0)