Scripts::installGitMessageHook()   B
last analyzed

Complexity

Conditions 6
Paths 10

Size

Total Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

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