-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathHook.php
199 lines (165 loc) · 5.05 KB
/
Hook.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<?php
namespace ProjektGopher\Whisky;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use SplFileInfo;
class Hook
{
const FROM_CONFIG = 1;
const FROM_GIT = 2;
const ALL = 3;
public string $name;
public string $bin;
public function __construct(
public string $hook,
) {
$this->name = $hook;
$this->bin = Whisky::bin_path();
}
public function uninstall(): bool
{
$path = Platform::git_path("hooks/{$this->hook}");
if ($this->fileIsMissing()) {
// This should be unreachable.
throw new FileNotFoundException("Could not find {$path}");
}
$contents = File::get($path);
$commands = $this->getSnippets()
->map(fn (string $snippet): string => $snippet.PHP_EOL)
->toArray();
if (! Str::contains($contents, $commands)) {
return false;
}
File::put($path, str_replace($commands, '', $contents));
return true;
}
// use ensureFileExists instead?
public function fileExists(): bool
{
return File::exists(Platform::git_path("hooks/{$this->hook}"));
}
public function fileIsMissing(): bool
{
return ! $this->fileExists();
}
/**
* Checks if the hook is enabled **in git**.
*/
public function isEnabled(): bool
{
return $this->fileExists();
}
/**
* Checks if the hook is not enabled **in git**.
*/
public function isNotEnabled(): bool
{
return ! $this->isEnabled();
}
/**
* Creates the git hook file.
*/
public function enable(): void
{
File::put(Platform::git_path("hooks/{$this->hook}"), '#!/bin/sh'.PHP_EOL);
}
/**
* Ensure the hook is executable.
*/
public function ensureExecutable(): void
{
if ((new Platform)->isNotWindows()) {
exec('chmod +x '.Platform::cwd(".git/hooks/{$this->hook}"));
}
}
/**
* Checks if the hook uses Whisky.
*/
public function isInstalled(): bool
{
return Str::contains(
File::get(Platform::git_path("hooks/{$this->hook}")),
$this->getSnippets()->toArray(),
);
}
/**
* Adds snippet for calling Whisky to the git hook file.
*/
public function install(): void
{
File::append(
Platform::git_path("hooks/{$this->hook}"),
$this->getSnippets()->first().PHP_EOL,
);
}
/**
* Checks if the hook is disabled in `whisky.json`.
*/
public function isDisabled(): bool
{
return in_array($this->hook, Whisky::readConfig('hooks.disabled'));
}
public function getScripts(): Collection
{
return collect(Whisky::readConfig("hooks.{$this->hook}"));
}
/**
* Collect the bash snippet history for calling the Whisky bin.
* The current version of the snippet should always be first.
* We keep this history to make updating our hooks easier.
*
* @return Collection<int, string>
*/
public function getSnippets(): Collection
{
$cwd = Platform::cwd();
return collect([
"pushd {$cwd} && {$this->bin} run {$this->hook} \"$1\" && popd",
// Legacy Snippets.
"{$this->bin} run {$this->hook} \"$1\"",
"{$this->bin} run {$this->hook}",
"eval \"$({$this->bin} get-run-cmd {$this->hook})\"",
"eval \"$(./vendor/bin/whisky get-run-cmd {$this->hook})\"",
]);
}
////////////////////////////////////////
//// Static methods ////
////////////////////////////////////////
/**
* Static Constructor.
*/
public static function make(string $hook): Hook
{
return new Hook($hook);
}
/**
* Get a collection of hooks.
*
* Passing `Hook::FROM_CONFIG` flag will return hooks that are listed in `whisky.json` config.
* Passing `Hook::FROM_GIT` flag will return hooks that are enabled in `.git/hooks` folder.
* Passing `Hook::ALL`, or `Hook::FROM_CONFIG | Hook::FROM_GIT` to flag will return all hooks.
*/
public static function all(int $flags = self::FROM_CONFIG): Collection
{
$result = collect();
if ($flags & self::FROM_GIT) {
$result->push(...collect(File::files(Platform::git_path('hooks')))
->map(fn (SplFileInfo $file) => $file->getFilename())
->filter(fn (string $filename) => ! str_ends_with($filename, 'sample'))
);
}
if ($flags & self::FROM_CONFIG) {
$result->push(...array_keys(Whisky::readConfig('hooks')));
}
// dd($result->unique());
return $result->unique()->map(
fn (string $hook) => new Hook($hook),
);
}
public static function each(callable $callable, int $flags = self::FROM_CONFIG): Collection
{
return self::all($flags)->each($callable);
}
}