1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Ams\Composer\GitHooks\Installer; |
4
|
|
|
|
5
|
|
|
use Ams\Composer\GitHooks\Config; |
6
|
|
|
use Ams\Composer\GitHooks\GitHooks; |
7
|
|
|
use Ams\Composer\GitHooks\Plugin; |
8
|
|
|
use Composer\Installer\LibraryInstaller; |
9
|
|
|
use Composer\Package\PackageInterface; |
10
|
|
|
use Composer\Repository\InstalledRepositoryInterface; |
11
|
|
|
use Composer\Util\Silencer; |
12
|
|
|
|
13
|
|
|
class GitHooksInstaller extends LibraryInstaller |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* @inheritdoc |
17
|
|
|
*/ |
18
|
2 |
|
public function supports($packageType) |
19
|
|
|
{ |
20
|
2 |
|
return $packageType == Plugin::PACKAGE_TYPE; |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* {@inheritDoc} |
25
|
|
|
*/ |
26
|
|
View Code Duplication |
public function install(InstalledRepositoryInterface $repo, PackageInterface $package) |
|
|
|
|
27
|
|
|
{ |
28
|
|
|
parent::install($repo, $package); |
29
|
|
|
|
30
|
|
|
$gitRootPath = realpath($this->getGitRootPath()); |
31
|
|
|
if (!is_dir($gitRootPath) || !file_exists($gitRootPath)) { |
32
|
|
|
$this->io->writeError(sprintf(' <warning>Skipped installation of %s: Not a git repository found on "git-root" path %s</warning>', $package->getName(), $gitRootPath)); |
33
|
|
|
return; |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
$originPath = $this->getInstallPath($package); |
37
|
|
|
$targetPath = $this->getGitHooksInstallPath(); |
38
|
|
|
|
39
|
|
|
if ($this->io->isVerbose()) { |
40
|
|
|
$this->io->write(sprintf(' Installing git hooks from %s into %s', $originPath, $targetPath)); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
// throws exception if one of both paths doesn't exists or couldn't be created |
44
|
|
|
$this->filesystem->ensureDirectoryExists($originPath); |
45
|
|
|
$this->filesystem->ensureDirectoryExists($targetPath); |
46
|
|
|
|
47
|
|
|
$this->copyGitHooks($originPath, $targetPath); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* {@inheritDoc} |
52
|
|
|
*/ |
53
|
|
View Code Duplication |
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) |
|
|
|
|
54
|
|
|
{ |
55
|
|
|
parent::update($repo, $initial, $target); |
56
|
|
|
|
57
|
|
|
$gitRootPath = realpath($this->getGitRootPath()); |
58
|
|
|
if (!is_dir($gitRootPath)) { |
59
|
|
|
$this->io->writeError(sprintf(' <warning>Skipped update of %s: Not a git repository found on "git-root" path %s</warning>', $target->getName(), $gitRootPath)); |
60
|
|
|
return; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
$originPath = $this->getInstallPath($initial); |
64
|
|
|
$targetPath = $this->getGitHooksInstallPath(); |
65
|
|
|
|
66
|
|
|
if ($this->io->isVerbose()) { |
67
|
|
|
$this->io->write(sprintf(' Updating git hooks from %s into %s', $originPath, $targetPath)); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
// throws exception if one of both paths doesn't exists or couldn't be created |
71
|
|
|
$this->filesystem->ensureDirectoryExists($originPath); |
72
|
|
|
$this->filesystem->ensureDirectoryExists($targetPath); |
73
|
|
|
|
74
|
|
|
$this->copyGitHooks($originPath, $targetPath, true); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* {@inheritDoc} |
79
|
|
|
*/ |
80
|
|
|
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) |
81
|
|
|
{ |
82
|
|
|
parent::uninstall($repo, $package); |
83
|
|
|
|
84
|
|
|
$gitRootPath = realpath($this->getGitRootPath()); |
85
|
|
|
if (!is_dir($gitRootPath)) { |
86
|
|
|
$this->io->writeError(sprintf(' Skipped update of %s: Not a git repository found on "git-root" path %s', $package->getName(), $gitRootPath)); |
87
|
|
|
return; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
$originPath = $this->getInstallPath($package); |
91
|
|
|
$targetPath = $this->getGitHooksInstallPath(); |
92
|
|
|
|
93
|
|
|
if ($this->io->isVerbose()) { |
94
|
|
|
$this->io->write(sprintf(' Uninstalling git hooks from %s into %s', $originPath, $targetPath)); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
$this->removeGitHooks($originPath, $targetPath); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @param string $sourcePath |
102
|
|
|
* @param string $targetPath |
103
|
|
|
* @param bool $isUpdate |
104
|
|
|
*/ |
105
|
|
|
private function copyGitHooks($sourcePath, $targetPath, $isUpdate = false) |
106
|
|
|
{ |
107
|
|
|
$i = new \FilesystemIterator($sourcePath); |
108
|
|
|
|
109
|
|
|
foreach ($i as $githook) { |
110
|
|
|
// ignore all files not matching a git hook name |
111
|
|
|
if (!array_search($githook->getFilename(), GitHooks::$hookFilename)) { |
112
|
|
|
continue; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
$newPath = $targetPath . '/' . $githook->getFilename(); |
116
|
|
|
|
117
|
|
|
// check if .sample version exists in that case rename it |
118
|
|
|
if (file_exists($newPath . GitHooks::SAMPLE)) { |
119
|
|
|
rename($newPath . GitHooks::SAMPLE, $newPath . GitHooks::SAMPLE . '.bk'); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
// check if there is already a git hook with same name do nothing |
123
|
|
|
if (file_exists($newPath) && !$isUpdate) { |
124
|
|
|
$this->io->write(sprintf(' Found already existing %s git hook. Doing nothing.', $githook->getFilename())); |
125
|
|
|
continue; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
// if hook already exist but anything changed update it |
129
|
|
|
if (file_exists($newPath) && $isUpdate && sha1_file($githook->getPathname()) === sha1_file($newPath)) { |
130
|
|
|
continue; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$this->io->write(sprintf(' Installing git hook %s', $githook->getFilename())); |
134
|
|
|
$this->filesystem->relativeSymlink($githook->getPathname(), $newPath); |
135
|
|
|
Silencer::call('chmod', $newPath, 0777 & ~umask()); |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @param string $sourcePath |
141
|
|
|
* @param string $targetPath |
142
|
|
|
*/ |
143
|
|
|
private function removeGitHooks($sourcePath, $targetPath) |
144
|
|
|
{ |
145
|
|
|
$i = new \FilesystemIterator($sourcePath); |
146
|
|
|
|
147
|
|
|
foreach ($i as $githook) { |
148
|
|
|
// ignore all files not matching a git hook name |
149
|
|
|
if (!array_search($githook->getFilename(), GitHooks::$hookFilename)) { |
150
|
|
|
continue; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
$newPath = $targetPath . '/' . $githook->getFilename(); |
154
|
|
|
if (file_exists($newPath)) { |
155
|
|
|
$this->io->write(sprintf(' Removing git hook %s', $githook->getFilename())); |
156
|
|
|
unlink($newPath); |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Returns the installation path of the Git hooks |
163
|
|
|
* |
164
|
|
|
* @return string |
165
|
|
|
*/ |
166
|
|
|
private function getGitHooksInstallPath() |
167
|
|
|
{ |
168
|
|
|
return $this->getGitRootPath() . '/hooks'; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Returns the git root path |
173
|
|
|
* |
174
|
|
|
* @return string |
175
|
|
|
*/ |
176
|
|
|
private function getGitRootPath() |
177
|
|
|
{ |
178
|
|
|
$config = $this->composer->getPackage()->getExtra(); |
179
|
|
|
$relPath = array_key_exists(Config::GIT_ROOT_DIR_KEY, $config) ? ('/' . $config[Config::GIT_ROOT_DIR_KEY]) : ''; |
180
|
|
|
|
181
|
|
|
return $this->vendorDir . $relPath . '/../.git'; |
182
|
|
|
} |
183
|
|
|
} |
184
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.