|
15 | 15 | use Composer\Semver\Semver; |
16 | 16 | use Deviantintegral\ComposerGavel\Exception\ConstraintException; |
17 | 17 |
|
18 | | -class ComposerVersionRequirement implements PluginInterface, EventSubscriberInterface { |
19 | | - |
20 | | - /** |
21 | | - * @var \Composer\Composer |
22 | | - */ |
23 | | - protected $composer; |
24 | | - |
25 | | - /** |
26 | | - * @var \Composer\IO\IOInterface |
27 | | - */ |
28 | | - protected $io; |
29 | | - |
30 | | - /** |
31 | | - * {@inheritdoc} |
32 | | - */ |
33 | | - public function activate(Composer $composer, IOInterface $io) { |
34 | | - $this->composer = $composer; |
35 | | - $this->io = $io; |
36 | | - } |
37 | | - |
38 | | - /** |
39 | | - * {@inheritdoc} |
40 | | - */ |
41 | | - public function deactivate(Composer $composer, IOInterface $io) { |
42 | | - } |
43 | | - |
44 | | - /** |
45 | | - * {@inheritdoc} |
46 | | - */ |
47 | | - public function uninstall(Composer $composer, IOInterface $io) { |
48 | | - } |
49 | | - |
50 | | - /** |
51 | | - * {@inheritdoc} |
52 | | - */ |
53 | | - public static function getSubscribedEvents() { |
54 | | - return [ |
55 | | - ScriptEvents::PRE_INSTALL_CMD => 'checkComposerVersion', |
56 | | - ScriptEvents::PRE_UPDATE_CMD => 'checkComposerVersion', |
57 | | - ]; |
58 | | - } |
59 | | - |
60 | | - /** |
61 | | - * Check currently running composer version, and offer to set a constraint. |
62 | | - * |
63 | | - * @param \Composer\Script\Event $event |
64 | | - */ |
65 | | - public function checkComposerVersion(Event $event) { |
66 | | - $class_name = get_class($this->composer); |
67 | | - $version = $class_name::VERSION; |
68 | | - |
69 | | - // Handle git checkouts of composer for debugging. |
70 | | - if ($version === '@package_version@' || $version === '@package_branch_alias_version@') { |
71 | | - $this->io->writeError('<warning>You are running a development version of Composer. The Composer version will not be enforced.</warning>'); |
72 | | - return; |
| 18 | +class ComposerVersionRequirement implements PluginInterface, EventSubscriberInterface |
| 19 | +{ |
| 20 | + /** |
| 21 | + * @var Composer |
| 22 | + */ |
| 23 | + protected $composer; |
| 24 | + |
| 25 | + /** |
| 26 | + * @var IOInterface |
| 27 | + */ |
| 28 | + protected $io; |
| 29 | + |
| 30 | + public function activate(Composer $composer, IOInterface $io) |
| 31 | + { |
| 32 | + $this->composer = $composer; |
| 33 | + $this->io = $io; |
73 | 34 | } |
74 | 35 |
|
75 | | - $extra = $this->composer->getPackage()->getExtra(); |
76 | | - |
77 | | - // No composer version is currently defined, offer to add it if we are |
78 | | - // running composer update. |
79 | | - if (empty($extra['composer-version'])) { |
80 | | - $this->io->writeError('<error>composer-version is not defined in extra in composer.json.</error>'); |
81 | | - // Don't offer to update composer.json when running composer update, |
82 | | - // otherwise the content-hash will become invalid. |
83 | | - if ($event->getName() == ScriptEvents::PRE_INSTALL_CMD |
84 | | - || !($this->io->askAndValidate(sprintf('Set the Composer version constraint to %s? [Y/n] ', "^$version"), $this->validate(), null, true))) { |
85 | | - return; |
86 | | - } |
87 | | - |
88 | | - $extra['composer-version'] = "^$version"; |
89 | | - $this->composer->getPackage()->setExtra($extra); |
90 | | - $this->writeConstraint($extra['composer-version']); |
| 36 | + public function deactivate(Composer $composer, IOInterface $io) |
| 37 | + { |
91 | 38 | } |
92 | 39 |
|
93 | | - $constraint = $extra['composer-version']; |
94 | | - if (!Semver::satisfies($version, $constraint)) { |
95 | | - throw new ConstraintException(sprintf('Composer %s is in use but this project requires Composer %s. Upgrade composer by running composer self-update.', $version, $constraint)); |
| 40 | + public function uninstall(Composer $composer, IOInterface $io) |
| 41 | + { |
96 | 42 | } |
97 | 43 |
|
98 | | - $this->io->writeError(sprintf('<info>Composer %s satisfies composer-version %s.</info>', $version, $constraint)); |
99 | | - } |
100 | | - |
101 | | - /** |
102 | | - * Write a composer version constraint to composer.json. |
103 | | - * |
104 | | - * @param string $constraint The semantic version of composer to require. |
105 | | - * |
106 | | - * @throws \RuntimeException Thrown when composer.json is not readable. |
107 | | - */ |
108 | | - protected function writeConstraint($constraint) { |
109 | | - $file = Factory::getComposerFile(); |
110 | | - if (!is_readable($file)) { |
111 | | - throw new \RuntimeException(sprintf('%s is not readable.', $file)); |
| 44 | + public static function getSubscribedEvents() |
| 45 | + { |
| 46 | + return [ |
| 47 | + ScriptEvents::PRE_INSTALL_CMD => 'checkComposerVersion', |
| 48 | + ScriptEvents::PRE_UPDATE_CMD => 'checkComposerVersion', |
| 49 | + ]; |
112 | 50 | } |
113 | | - if (!is_writable($file)) { |
114 | | - throw new \RuntimeException(sprintf('%s is not writable.', $file)); |
115 | | - } |
116 | | - |
117 | | - // Load composer.json and save the constraint. |
118 | | - $json = new JsonFile($file); |
119 | | - $manipulator = new JsonManipulator(file_get_contents($json->getPath())); |
120 | | - $manipulator->addProperty('extra.composer-version', $constraint); |
121 | | - $contents = $manipulator->getContents(); |
122 | | - file_put_contents($json->getPath(), $contents); |
123 | | - |
124 | | - // Update the lockfile's content-hash property. |
125 | | - $lockFile = "json" === pathinfo($file, PATHINFO_EXTENSION) |
126 | | - ? substr($file, 0, -4).'lock' |
127 | | - : $file . '.lock'; |
128 | 51 |
|
129 | | - if (version_compare(PluginInterface::PLUGIN_API_VERSION, '2.0.0', '<')) { |
130 | | - $locker = new Locker($this->io, new JsonFile($lockFile, null, $this->io), $this->composer->getRepositoryManager(), $this->composer->getInstallationManager(), $contents); |
131 | | - } |
132 | | - else { |
133 | | - $locker = new Locker($this->io, new JsonFile($lockFile, null, $this->io), $this->composer->getInstallationManager(), $contents); |
| 52 | + /** |
| 53 | + * Check currently running composer version, and offer to set a constraint. |
| 54 | + */ |
| 55 | + public function checkComposerVersion(Event $event) |
| 56 | + { |
| 57 | + $class_name = \get_class($this->composer); |
| 58 | + $version = $class_name::VERSION; |
| 59 | + |
| 60 | + // Handle git checkouts of composer for debugging. |
| 61 | + if ('@package_version@' === $version || '@package_branch_alias_version@' === $version) { |
| 62 | + $this->io->writeError('<warning>You are running a development version of Composer. The Composer version will not be enforced.</warning>'); |
| 63 | + |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + $extra = $this->composer->getPackage()->getExtra(); |
| 68 | + |
| 69 | + // No composer version is currently defined, offer to add it if we are |
| 70 | + // running composer update. |
| 71 | + if (empty($extra['composer-version'])) { |
| 72 | + $this->io->writeError('<error>composer-version is not defined in extra in composer.json.</error>'); |
| 73 | + // Don't offer to update composer.json when running composer update, |
| 74 | + // otherwise the content-hash will become invalid. |
| 75 | + if (ScriptEvents::PRE_INSTALL_CMD == $event->getName() |
| 76 | + || !$this->io->askAndValidate(\sprintf('Set the Composer version constraint to %s? [Y/n] ', "^$version"), $this->validate(), null, true)) { |
| 77 | + return; |
| 78 | + } |
| 79 | + |
| 80 | + $extra['composer-version'] = "^$version"; |
| 81 | + $this->composer->getPackage()->setExtra($extra); |
| 82 | + $this->writeConstraint($extra['composer-version']); |
| 83 | + } |
| 84 | + |
| 85 | + $constraint = $extra['composer-version']; |
| 86 | + if (!Semver::satisfies($version, $constraint)) { |
| 87 | + throw new ConstraintException(\sprintf('Composer %s is in use but this project requires Composer %s. Upgrade composer by running composer self-update.', $version, $constraint)); |
| 88 | + } |
| 89 | + |
| 90 | + $this->io->writeError(\sprintf('<info>Composer %s satisfies composer-version %s.</info>', $version, $constraint)); |
134 | 91 | } |
135 | 92 |
|
136 | | - $this->composer->setLocker($locker); |
137 | | - |
138 | | - $this->io->writeError(sprintf('<info>Composer requirement set to %s.</info>', $constraint)); |
139 | | - } |
140 | | - |
141 | | - /** |
142 | | - * Validate y, n, and a newline (mapped to '1') as Y. |
143 | | - * |
144 | | - * @internal |
145 | | - * |
146 | | - * @return \Closure |
147 | | - */ |
148 | | - public function validate() { |
149 | | - return function ($answer) { |
150 | | - $normalized = strtolower($answer); |
151 | | - if (!in_array($normalized, ['y', 'n', '1'], true)) { |
152 | | - throw new \RuntimeException("Enter 'y' or 'n'"); |
153 | | - } |
154 | | - |
155 | | - return ($normalized == 'y' || $normalized) && $normalized != 'n'; |
156 | | - }; |
157 | | - } |
| 93 | + /** |
| 94 | + * Write a composer version constraint to composer.json. |
| 95 | + * |
| 96 | + * @param string $constraint The semantic version of composer to require. |
| 97 | + * |
| 98 | + * @throws \RuntimeException Thrown when composer.json is not readable. |
| 99 | + */ |
| 100 | + protected function writeConstraint($constraint) |
| 101 | + { |
| 102 | + $file = Factory::getComposerFile(); |
| 103 | + if (!is_readable($file)) { |
| 104 | + throw new \RuntimeException(\sprintf('%s is not readable.', $file)); |
| 105 | + } |
| 106 | + if (!is_writable($file)) { |
| 107 | + throw new \RuntimeException(\sprintf('%s is not writable.', $file)); |
| 108 | + } |
| 109 | + |
| 110 | + // Load composer.json and save the constraint. |
| 111 | + $json = new JsonFile($file); |
| 112 | + $manipulator = new JsonManipulator(file_get_contents($json->getPath())); |
| 113 | + $manipulator->addProperty('extra.composer-version', $constraint); |
| 114 | + $contents = $manipulator->getContents(); |
| 115 | + file_put_contents($json->getPath(), $contents); |
| 116 | + |
| 117 | + // Update the lockfile's content-hash property. |
| 118 | + $lockFile = 'json' === pathinfo($file, \PATHINFO_EXTENSION) |
| 119 | + ? substr($file, 0, -4).'lock' |
| 120 | + : $file.'.lock'; |
| 121 | + |
| 122 | + if (version_compare(PluginInterface::PLUGIN_API_VERSION, '2.0.0', '<')) { |
| 123 | + $locker = new Locker($this->io, new JsonFile($lockFile, null, $this->io), $this->composer->getRepositoryManager(), $this->composer->getInstallationManager(), $contents); |
| 124 | + } else { |
| 125 | + $locker = new Locker($this->io, new JsonFile($lockFile, null, $this->io), $this->composer->getInstallationManager(), $contents); |
| 126 | + } |
| 127 | + |
| 128 | + $this->composer->setLocker($locker); |
| 129 | + |
| 130 | + $this->io->writeError(\sprintf('<info>Composer requirement set to %s.</info>', $constraint)); |
| 131 | + } |
158 | 132 |
|
| 133 | + /** |
| 134 | + * Validate y, n, and a newline (mapped to '1') as Y. |
| 135 | + * |
| 136 | + * @internal |
| 137 | + * |
| 138 | + * @return \Closure |
| 139 | + */ |
| 140 | + public function validate() |
| 141 | + { |
| 142 | + return function ($answer) { |
| 143 | + $normalized = strtolower($answer); |
| 144 | + if (!\in_array($normalized, ['y', 'n', '1'], true)) { |
| 145 | + throw new \RuntimeException("Enter 'y' or 'n'"); |
| 146 | + } |
| 147 | + |
| 148 | + return ('y' == $normalized || $normalized) && 'n' != $normalized; |
| 149 | + }; |
| 150 | + } |
159 | 151 | } |
0 commit comments