1
|
|
|
<?php |
2
|
|
|
#declare(strict_types = 1); |
|
|
|
|
3
|
|
|
namespace PurpleBooth\GitLintValidators\Composer; |
4
|
|
|
|
5
|
|
|
use Composer\IO\IOInterface; |
6
|
|
|
use Composer\Script\Event; |
7
|
|
|
|
8
|
|
|
class Scripts |
9
|
|
|
{ |
10
|
|
|
const BACKUP_EXTENSION = '.bak'; |
11
|
|
|
const GIT_PATH = '.git'; |
12
|
|
|
const HOOKS_PATH = 'hooks'; |
13
|
|
|
const HOOK_FILENAME = 'commit-msg'; |
14
|
|
|
const TEMPLATE_FILENAME = '.gitmessage'; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Default Permissions (Copied from example hooks) |
18
|
|
|
* |
19
|
|
|
* User: Read, Write, Execute |
20
|
|
|
* Group: Read, Execute |
21
|
|
|
* Other: Execute |
22
|
|
|
*/ |
23
|
|
|
const EXECUTABLE_PERMISSIONS = 0751; |
24
|
|
|
const HOOK_CONTENTS = <<<CONTENT |
25
|
|
|
#!/bin/sh |
26
|
|
|
|
27
|
|
|
vendor/bin/git-lint-validators git-lint-validator:hook $1 |
28
|
|
|
CONTENT; |
29
|
|
|
|
30
|
|
|
const TEMPLATE_CONTENTS = <<<CONTENT |
31
|
|
|
Subject line |
32
|
|
|
|
33
|
|
|
# - Capitalise the subject line and do not end it with a period |
34
|
|
|
# - Use the imperative mood in the subject line |
35
|
|
|
# - Summarise changes in around 50 (soft limit, hard limit at 69) |
36
|
|
|
# characters or less in the subject line |
37
|
|
|
# - Separate subject line from body with a blank line |
38
|
|
|
Subject body |
39
|
|
|
# - Use the subject body to explain what and why vs. how |
40
|
|
|
# - Wrap the subject body at 72 characters |
41
|
|
|
|
42
|
|
|
CONTENT; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Installs and activates the Git commit message |
46
|
|
|
* hook when confirmed by the user. An existing hook |
47
|
|
|
* is backed with the .bak extension. |
48
|
|
|
* |
49
|
|
|
* @param Event $event The script event. |
50
|
|
|
* |
51
|
|
|
* @return boolean |
52
|
|
|
*/ |
53
|
|
|
public static function installGitMessageHook(Event $event) |
54
|
|
|
{ |
55
|
|
|
$hookContent = self::HOOK_CONTENTS; |
56
|
|
|
$inputOutput = $event->getIO(); |
57
|
|
|
$question = "Do you want to install and activate the Git "; |
58
|
|
|
$question .= "commit message hook? "; |
59
|
|
|
|
60
|
|
|
if ($inputOutput->askConfirmation($question, false)) { |
61
|
|
|
$errorMessage = "Couldn't locate the .git directory. "; |
62
|
|
|
$errorMessage .= "Aborting the Git hook installation."; |
63
|
|
|
|
64
|
|
|
$gitDirectory = self::getGuardedGitDirectory($errorMessage, $inputOutput); |
65
|
|
|
|
66
|
|
|
if (!$gitDirectory) { |
|
|
|
|
67
|
|
|
return false; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
$hookFile = implode(DIRECTORY_SEPARATOR, [$gitDirectory, self::HOOKS_PATH, self::HOOK_FILENAME]); |
71
|
|
|
$existingHookFile = false; |
72
|
|
|
|
73
|
|
|
if (file_exists($hookFile)) { |
74
|
|
|
$existingHookFile = copy( |
75
|
|
|
$hookFile, |
76
|
|
|
$hookFile . self::BACKUP_EXTENSION |
77
|
|
|
); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
file_put_contents($hookFile, $hookContent); |
81
|
|
|
chmod($hookFile, self::EXECUTABLE_PERMISSIONS); |
82
|
|
|
|
83
|
|
|
$inputOutput->write("Installed and activated the Git commit message hook."); |
84
|
|
|
|
85
|
|
|
if ($existingHookFile) { |
86
|
|
|
$inputOutput->write("Backed previous Git commit message hook."); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
if ($inputOutput->isVerbose()) { |
90
|
|
|
$inputOutput->write("Wrote"); |
91
|
|
|
$inputOutput->write("<comment>$hookContent</comment>"); |
92
|
|
|
$inputOutput->write("into <info>$hookFile</info> and made it executable."); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
return true; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
$inputOutput->write("Aborted installation and activation of the Git commit message hook."); |
99
|
|
|
|
100
|
|
|
return false; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Installs and configures the Git commit message |
105
|
|
|
* template when confirmed by the user. |
106
|
|
|
* |
107
|
|
|
* @param Event $event The script event. |
108
|
|
|
* |
109
|
|
|
* @return boolean |
110
|
|
|
*/ |
111
|
|
|
public static function installGitCommitMessageTemplate(Event $event) |
112
|
|
|
{ |
113
|
|
|
$templateContent = self::TEMPLATE_CONTENTS; |
114
|
|
|
$inputOutput = $event->getIO(); |
115
|
|
|
$question = "Do you want to install and configure the Git "; |
116
|
|
|
$question .= "commit message template? "; |
117
|
|
|
|
118
|
|
|
if ($inputOutput->askConfirmation($question, false)) { |
119
|
|
|
$errorMessage = "Couldn't locate the .git directory. "; |
120
|
|
|
$errorMessage .= "Aborting the Git commit message template installation."; |
121
|
|
|
|
122
|
|
|
$gitDirectory = self::getGuardedGitDirectory($errorMessage, $inputOutput); |
123
|
|
|
|
124
|
|
|
if (!$gitDirectory) { |
|
|
|
|
125
|
|
|
return false; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$templateFile = implode(DIRECTORY_SEPARATOR, [$gitDirectory, self::TEMPLATE_FILENAME]); |
129
|
|
|
|
130
|
|
|
file_put_contents($templateFile, $templateContent); |
131
|
|
|
$gitConfigureCommand = "git config --add commit.template $templateFile"; |
132
|
|
|
exec($gitConfigureCommand); |
133
|
|
|
|
134
|
|
|
$inputOutput->write("Installed and configured the Git commit message template."); |
135
|
|
|
|
136
|
|
|
if ($inputOutput->isVerbose()) { |
137
|
|
|
$inputOutput->write("Wrote"); |
138
|
|
|
$inputOutput->write("<comment>$templateContent</comment>"); |
139
|
|
|
$inputOutput->write("into <info>$templateFile</info> and configured the Git commit message template "); |
140
|
|
|
$inputOutput->write("via <comment>$gitConfigureCommand</comment>."); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
return true; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
$inputOutput->write("Aborted installation and configuration of the Git commit message template."); |
147
|
|
|
|
148
|
|
|
return false; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Returns the .git directory if present. Errors the given |
153
|
|
|
* message if not. |
154
|
|
|
* |
155
|
|
|
* @param string $message The message to error. |
156
|
|
|
* @param IOInterface $io The Input/Output helper interface. |
157
|
|
|
* |
158
|
|
|
* @return mixed |
|
|
|
|
159
|
|
|
*/ |
160
|
|
|
private static function getGuardedGitDirectory($message, IOInterface $io) |
|
|
|
|
161
|
|
|
{ |
162
|
|
|
#$gitDirectory = implode(DIRECTORY_SEPARATOR, [dirname(__DIR__, 4), self::GIT_PATH]); |
|
|
|
|
163
|
|
|
$gitDirectory = implode(DIRECTORY_SEPARATOR, [dirname(dirname(dirname(dirname(__DIR__)))), self::GIT_PATH]); |
164
|
|
|
|
165
|
|
|
if (!is_dir($gitDirectory)) { |
166
|
|
|
$io->error($message); |
167
|
|
|
return false; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
return $gitDirectory; |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.