├── .github
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
└── src
├── DiffPlugin.php
└── IO.php
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Please read the CLA carefully before submitting your contribution to Mercari.
2 | Under any circumstances, by submitting your contribution, you are deemed to accept and agree to be bound by the terms and conditions of the CLA.
3 |
4 | https://www.mercari.com/cla/
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Mercari, Inc
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | composer-diff-plugin
2 | ==================
3 |
4 | composer plugin to show library version diff at "composer update".
5 |
6 | 
7 |
8 | feature
9 | -----------------
10 |
11 | * print upgrade/downgrade/add/remove of libraries.
12 | * output `composer.list` file
13 |
14 |
15 | Install
16 | -----------------
17 |
18 | ```bash
19 | $ composer global require mercari/composer-diff-plugin
20 | ```
21 |
22 | Uninstall
23 | ----------------
24 |
25 | ```bash
26 | $ composer global remove mercari/composer-diff-plugin
27 | ```
28 |
29 | License
30 | ---------------
31 |
32 | Copyright 2016 Mercari, Inc.
33 |
34 | Licensed under the MIT License
35 |
36 | Contribution
37 | --------------
38 |
39 | Fork the project, create a feature branch, and send us a pull request.
40 |
41 | Please read the CLA carefully before submitting your contribution to Mercari.
42 |
43 | https://www.mercari.com/cla/
44 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mercari/composer-diff-plugin",
3 | "description": "composer plugin to show library version diff at \"composer update\"",
4 | "type": "composer-plugin",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Hiraku NAKANO",
9 | "email": "hiraku@mercari.com"
10 | }
11 | ],
12 | "require": {
13 | "composer-plugin-api": ">=1.0.0-alpha10"
14 | },
15 | "require-dev": {
16 | "composer/composer": "1.0.0-alpha10"
17 | },
18 | "autoload": {
19 | "psr-4": {
20 | "Mercari\\ComposerDiffPlugin\\": "src/"
21 | }
22 | },
23 | "extra": {
24 | "class": "Mercari\\ComposerDiffPlugin\\DiffPlugin"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "hash": "dc34ca1049e690532f851699385bf351",
8 | "content-hash": "6255cbcd06460c5cfa83ef5776a612b1",
9 | "packages": [],
10 | "packages-dev": [
11 | {
12 | "name": "composer/composer",
13 | "version": "1.0.0-alpha10",
14 | "source": {
15 | "type": "git",
16 | "url": "https://github.com/composer/composer.git",
17 | "reference": "775f6cd5c633facf2e7b99611fdcaa900b58ddb7"
18 | },
19 | "dist": {
20 | "type": "zip",
21 | "url": "https://api.github.com/repos/composer/composer/zipball/775f6cd5c633facf2e7b99611fdcaa900b58ddb7",
22 | "reference": "775f6cd5c633facf2e7b99611fdcaa900b58ddb7",
23 | "shasum": ""
24 | },
25 | "require": {
26 | "justinrainbow/json-schema": "~1.4",
27 | "php": ">=5.3.2",
28 | "seld/jsonlint": "~1.0",
29 | "symfony/console": "~2.5",
30 | "symfony/finder": "~2.2",
31 | "symfony/process": "~2.1"
32 | },
33 | "require-dev": {
34 | "phpunit/phpunit": "~4.5"
35 | },
36 | "suggest": {
37 | "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
38 | "ext-zip": "Enabling the zip extension allows you to unzip archives, and allows gzip compression of all internet traffic"
39 | },
40 | "bin": [
41 | "bin/composer"
42 | ],
43 | "type": "library",
44 | "extra": {
45 | "branch-alias": {
46 | "dev-master": "1.0-dev"
47 | }
48 | },
49 | "autoload": {
50 | "psr-0": {
51 | "Composer": "src/"
52 | }
53 | },
54 | "notification-url": "https://packagist.org/downloads/",
55 | "license": [
56 | "MIT"
57 | ],
58 | "authors": [
59 | {
60 | "name": "Nils Adermann",
61 | "email": "naderman@naderman.de",
62 | "homepage": "http://www.naderman.de"
63 | },
64 | {
65 | "name": "Jordi Boggiano",
66 | "email": "j.boggiano@seld.be",
67 | "homepage": "http://seld.be"
68 | }
69 | ],
70 | "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.",
71 | "homepage": "http://getcomposer.org/",
72 | "keywords": [
73 | "autoload",
74 | "dependency",
75 | "package"
76 | ],
77 | "time": "2015-04-14 21:18:51"
78 | },
79 | {
80 | "name": "justinrainbow/json-schema",
81 | "version": "1.6.1",
82 | "source": {
83 | "type": "git",
84 | "url": "https://github.com/justinrainbow/json-schema.git",
85 | "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341"
86 | },
87 | "dist": {
88 | "type": "zip",
89 | "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/cc84765fb7317f6b07bd8ac78364747f95b86341",
90 | "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341",
91 | "shasum": ""
92 | },
93 | "require": {
94 | "php": ">=5.3.29"
95 | },
96 | "require-dev": {
97 | "json-schema/json-schema-test-suite": "1.1.0",
98 | "phpdocumentor/phpdocumentor": "~2",
99 | "phpunit/phpunit": "~3.7"
100 | },
101 | "bin": [
102 | "bin/validate-json"
103 | ],
104 | "type": "library",
105 | "extra": {
106 | "branch-alias": {
107 | "dev-master": "1.6.x-dev"
108 | }
109 | },
110 | "autoload": {
111 | "psr-4": {
112 | "JsonSchema\\": "src/JsonSchema/"
113 | }
114 | },
115 | "notification-url": "https://packagist.org/downloads/",
116 | "license": [
117 | "BSD-3-Clause"
118 | ],
119 | "authors": [
120 | {
121 | "name": "Bruno Prieto Reis",
122 | "email": "bruno.p.reis@gmail.com"
123 | },
124 | {
125 | "name": "Justin Rainbow",
126 | "email": "justin.rainbow@gmail.com"
127 | },
128 | {
129 | "name": "Igor Wiedler",
130 | "email": "igor@wiedler.ch"
131 | },
132 | {
133 | "name": "Robert Schönthal",
134 | "email": "seroscho@googlemail.com"
135 | }
136 | ],
137 | "description": "A library to validate a json schema.",
138 | "homepage": "https://github.com/justinrainbow/json-schema",
139 | "keywords": [
140 | "json",
141 | "schema"
142 | ],
143 | "time": "2016-01-25 15:43:01"
144 | },
145 | {
146 | "name": "seld/jsonlint",
147 | "version": "1.4.0",
148 | "source": {
149 | "type": "git",
150 | "url": "https://github.com/Seldaek/jsonlint.git",
151 | "reference": "66834d3e3566bb5798db7294619388786ae99394"
152 | },
153 | "dist": {
154 | "type": "zip",
155 | "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394",
156 | "reference": "66834d3e3566bb5798db7294619388786ae99394",
157 | "shasum": ""
158 | },
159 | "require": {
160 | "php": "^5.3 || ^7.0"
161 | },
162 | "bin": [
163 | "bin/jsonlint"
164 | ],
165 | "type": "library",
166 | "autoload": {
167 | "psr-4": {
168 | "Seld\\JsonLint\\": "src/Seld/JsonLint/"
169 | }
170 | },
171 | "notification-url": "https://packagist.org/downloads/",
172 | "license": [
173 | "MIT"
174 | ],
175 | "authors": [
176 | {
177 | "name": "Jordi Boggiano",
178 | "email": "j.boggiano@seld.be",
179 | "homepage": "http://seld.be"
180 | }
181 | ],
182 | "description": "JSON Linter",
183 | "keywords": [
184 | "json",
185 | "linter",
186 | "parser",
187 | "validator"
188 | ],
189 | "time": "2015-11-21 02:21:41"
190 | },
191 | {
192 | "name": "symfony/console",
193 | "version": "v2.8.2",
194 | "source": {
195 | "type": "git",
196 | "url": "https://github.com/symfony/console.git",
197 | "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d"
198 | },
199 | "dist": {
200 | "type": "zip",
201 | "url": "https://api.github.com/repos/symfony/console/zipball/d0239fb42f98dd02e7d342f793c5d2cdee0c478d",
202 | "reference": "d0239fb42f98dd02e7d342f793c5d2cdee0c478d",
203 | "shasum": ""
204 | },
205 | "require": {
206 | "php": ">=5.3.9",
207 | "symfony/polyfill-mbstring": "~1.0"
208 | },
209 | "require-dev": {
210 | "psr/log": "~1.0",
211 | "symfony/event-dispatcher": "~2.1|~3.0.0",
212 | "symfony/process": "~2.1|~3.0.0"
213 | },
214 | "suggest": {
215 | "psr/log": "For using the console logger",
216 | "symfony/event-dispatcher": "",
217 | "symfony/process": ""
218 | },
219 | "type": "library",
220 | "extra": {
221 | "branch-alias": {
222 | "dev-master": "2.8-dev"
223 | }
224 | },
225 | "autoload": {
226 | "psr-4": {
227 | "Symfony\\Component\\Console\\": ""
228 | },
229 | "exclude-from-classmap": [
230 | "/Tests/"
231 | ]
232 | },
233 | "notification-url": "https://packagist.org/downloads/",
234 | "license": [
235 | "MIT"
236 | ],
237 | "authors": [
238 | {
239 | "name": "Fabien Potencier",
240 | "email": "fabien@symfony.com"
241 | },
242 | {
243 | "name": "Symfony Community",
244 | "homepage": "https://symfony.com/contributors"
245 | }
246 | ],
247 | "description": "Symfony Console Component",
248 | "homepage": "https://symfony.com",
249 | "time": "2016-01-14 08:33:16"
250 | },
251 | {
252 | "name": "symfony/finder",
253 | "version": "v2.8.2",
254 | "source": {
255 | "type": "git",
256 | "url": "https://github.com/symfony/finder.git",
257 | "reference": "c90fabdd97e431ee19b6383999cf35334dff27da"
258 | },
259 | "dist": {
260 | "type": "zip",
261 | "url": "https://api.github.com/repos/symfony/finder/zipball/c90fabdd97e431ee19b6383999cf35334dff27da",
262 | "reference": "c90fabdd97e431ee19b6383999cf35334dff27da",
263 | "shasum": ""
264 | },
265 | "require": {
266 | "php": ">=5.3.9"
267 | },
268 | "type": "library",
269 | "extra": {
270 | "branch-alias": {
271 | "dev-master": "2.8-dev"
272 | }
273 | },
274 | "autoload": {
275 | "psr-4": {
276 | "Symfony\\Component\\Finder\\": ""
277 | },
278 | "exclude-from-classmap": [
279 | "/Tests/"
280 | ]
281 | },
282 | "notification-url": "https://packagist.org/downloads/",
283 | "license": [
284 | "MIT"
285 | ],
286 | "authors": [
287 | {
288 | "name": "Fabien Potencier",
289 | "email": "fabien@symfony.com"
290 | },
291 | {
292 | "name": "Symfony Community",
293 | "homepage": "https://symfony.com/contributors"
294 | }
295 | ],
296 | "description": "Symfony Finder Component",
297 | "homepage": "https://symfony.com",
298 | "time": "2016-01-14 08:26:52"
299 | },
300 | {
301 | "name": "symfony/polyfill-mbstring",
302 | "version": "v1.1.0",
303 | "source": {
304 | "type": "git",
305 | "url": "https://github.com/symfony/polyfill-mbstring.git",
306 | "reference": "1289d16209491b584839022f29257ad859b8532d"
307 | },
308 | "dist": {
309 | "type": "zip",
310 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d",
311 | "reference": "1289d16209491b584839022f29257ad859b8532d",
312 | "shasum": ""
313 | },
314 | "require": {
315 | "php": ">=5.3.3"
316 | },
317 | "suggest": {
318 | "ext-mbstring": "For best performance"
319 | },
320 | "type": "library",
321 | "extra": {
322 | "branch-alias": {
323 | "dev-master": "1.1-dev"
324 | }
325 | },
326 | "autoload": {
327 | "psr-4": {
328 | "Symfony\\Polyfill\\Mbstring\\": ""
329 | },
330 | "files": [
331 | "bootstrap.php"
332 | ]
333 | },
334 | "notification-url": "https://packagist.org/downloads/",
335 | "license": [
336 | "MIT"
337 | ],
338 | "authors": [
339 | {
340 | "name": "Nicolas Grekas",
341 | "email": "p@tchwork.com"
342 | },
343 | {
344 | "name": "Symfony Community",
345 | "homepage": "https://symfony.com/contributors"
346 | }
347 | ],
348 | "description": "Symfony polyfill for the Mbstring extension",
349 | "homepage": "https://symfony.com",
350 | "keywords": [
351 | "compatibility",
352 | "mbstring",
353 | "polyfill",
354 | "portable",
355 | "shim"
356 | ],
357 | "time": "2016-01-20 09:13:37"
358 | },
359 | {
360 | "name": "symfony/process",
361 | "version": "v2.8.2",
362 | "source": {
363 | "type": "git",
364 | "url": "https://github.com/symfony/process.git",
365 | "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac"
366 | },
367 | "dist": {
368 | "type": "zip",
369 | "url": "https://api.github.com/repos/symfony/process/zipball/6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac",
370 | "reference": "6f1979c3b0f4c22c77a8a8971afaa7dd07f082ac",
371 | "shasum": ""
372 | },
373 | "require": {
374 | "php": ">=5.3.9"
375 | },
376 | "type": "library",
377 | "extra": {
378 | "branch-alias": {
379 | "dev-master": "2.8-dev"
380 | }
381 | },
382 | "autoload": {
383 | "psr-4": {
384 | "Symfony\\Component\\Process\\": ""
385 | },
386 | "exclude-from-classmap": [
387 | "/Tests/"
388 | ]
389 | },
390 | "notification-url": "https://packagist.org/downloads/",
391 | "license": [
392 | "MIT"
393 | ],
394 | "authors": [
395 | {
396 | "name": "Fabien Potencier",
397 | "email": "fabien@symfony.com"
398 | },
399 | {
400 | "name": "Symfony Community",
401 | "homepage": "https://symfony.com/contributors"
402 | }
403 | ],
404 | "description": "Symfony Process Component",
405 | "homepage": "https://symfony.com",
406 | "time": "2016-01-06 09:59:23"
407 | }
408 | ],
409 | "aliases": [],
410 | "minimum-stability": "stable",
411 | "stability-flags": {
412 | "composer-plugin-api": 15,
413 | "composer/composer": 15
414 | },
415 | "prefer-stable": false,
416 | "prefer-lowest": false,
417 | "platform": [],
418 | "platform-dev": []
419 | }
420 |
--------------------------------------------------------------------------------
/src/DiffPlugin.php:
--------------------------------------------------------------------------------
1 | composer = $composer;
33 | $this->io = $io;
34 | }
35 |
36 | public static function getSubscribedEvents()
37 | {
38 | return array(
39 | ScriptEvents::PRE_UPDATE_CMD => array(
40 | 'onPreUpdate',
41 | ),
42 | ScriptEvents::POST_UPDATE_CMD => array(
43 | 'onPostUpdate',
44 | ),
45 | );
46 | }
47 |
48 | public function onPreUpdate(Event $arg)
49 | {
50 | $this->before = $this->licenses();
51 | }
52 |
53 | public function onPostUpdate(Event $arg)
54 | {
55 | $this->after = $this->licenses();
56 | $io = $this->io;
57 |
58 | $before = $this->before;
59 | $after = $this->after;
60 |
61 | $io->write("\n" . '[[[ library version information ]]]');
62 | if ($before == $after) {
63 | $io->write('no change!');
64 | return;
65 | }
66 | $output = IO::getSymfonyOutput($io);
67 |
68 | $table = new Table($output);
69 | $table->setStyle('compact');
70 | $table->getStyle()->setVerticalBorderChar('');
71 | $table->getStyle()->setCellRowContentFormat('%s ');
72 |
73 | // deleted packages
74 | $minus = array_diff_key($before, $after);
75 | if ($minus) {
76 | foreach ($minus as $name => $val) {
77 | $table->addRow(array(
78 | '[-]>',
79 | $name,
80 | $val['version'],
81 | implode(', ', $val['license']) ?: 'none',
82 | ));
83 |
84 | unset($before[$name]);
85 | }
86 | }
87 |
88 | // added packages
89 | $plus = array_diff_key($after, $before);
90 | if ($plus) {
91 | foreach ($plus as $name => $val) {
92 | $table->addRow(array(
93 | '[+]>',
94 | $name,
95 | $val['version'],
96 | implode(', ', $val['license']) ?: 'none',
97 | ));
98 |
99 | unset($after[$name]);
100 | }
101 | }
102 |
103 | // changed packages
104 | $diff = array();
105 | foreach ($before as $name => $val) {
106 | if ($val == $after[$name]) {
107 | continue; //no change
108 | }
109 | $diff[$name] = array($val, $after[$name]);
110 | }
111 | if ($diff) {
112 | foreach ($diff as $name => $val) {
113 | $a = $val[0]['version'];
114 | $b = $val[1]['version'];
115 | $vd = version_compare($a, $b);
116 | switch ($vd) {
117 | case 1:
118 | $change = '[d]>';
119 | break;
120 | case -1:
121 | $change = '[u]>';
122 | break;
123 | case 0:
124 | $change = '[?]';
125 | break;
126 | }
127 | $table->addRow(array($change, $name, "$a=>$b", ''));
128 | }
129 | }
130 | $table->render();
131 |
132 | $this->writeLibraryList($this->after);
133 | }
134 |
135 | /**
136 | * to array composer licenses
137 | */
138 | protected function licenses()
139 | {
140 | $composer = $this->composer;
141 |
142 | $root = $composer->getPackage();
143 | $repo = $composer->getRepositoryManager()->getLocalRepository();
144 |
145 | $packages = array();
146 | foreach ($repo->getPackages() as $p) {
147 | $packages[$p->getName()] = $p;
148 | }
149 |
150 | ksort($packages);
151 |
152 | $libs = array();
153 | foreach ($packages as $p) {
154 | $libs[$p->getPrettyName()] = array(
155 | 'version' => $p->getFullPrettyVersion(),
156 | 'license' => $p->getLicense(),
157 | );
158 | }
159 |
160 | return $libs;
161 | }
162 |
163 | /**
164 | * write composer.list
165 | */
166 | protected function writeLibraryList($packages)
167 | {
168 | $fp = fopen('composer.list', 'wb');
169 |
170 | $output = new \Symfony\Component\Console\Output\StreamOutput($fp);
171 | $table = new Table($output);
172 | $table->setStyle('compact');
173 | $table->getStyle()->setVerticalBorderChar('');
174 | $table->getStyle()->setCellRowContentFormat('%s ');
175 | $table->setHeaders(array('Name', 'Version', 'License'));
176 | foreach ($packages as $name => $p) {
177 | $table->addRow(array(
178 | $name,
179 | $p['version'],
180 | implode(', ', $p['license']) ?: 'none',
181 | ));
182 | }
183 | $table->render();
184 |
185 | unset($table);
186 | fclose($fp);
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/src/IO.php:
--------------------------------------------------------------------------------
1 | input;
13 | }
14 |
15 | public static function getSymfonyOutput(\Composer\IO\ConsoleIO $io)
16 | {
17 | return $io->output;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------