-
Notifications
You must be signed in to change notification settings - Fork 1
/
ChangelogsPlugin.php
154 lines (138 loc) · 5.42 KB
/
ChangelogsPlugin.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
namespace Kewlar\Composer;
use Composer\Composer;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallerEvent;
use Composer\Installer\InstallerEvents;
use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Plugin\PluginInterface;
use Kewlar\Composer\Exception;
/**
* Class ChangelogsPlugin
*
* A composer plugin for `composer update` that prints links to updated packages' GitHub compare pages
* for easier access to package changelogs.
*
* @author Mindaugas Pelionis <[email protected]>
*/
class ChangelogsPlugin implements PluginInterface, EventSubscriberInterface
{
const PAD_STR = ' ';
/** @var Composer */
protected $composer;
/** @var IOInterface */
protected $io;
/**
* {@inheritdoc}
*/
public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->io = $io;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
// Only here because it actually fires when doing `composer update --dry-run`.
InstallerEvents::POST_DEPENDENCIES_SOLVING => 'onPostDependenciesSolving',
// POST_PACKAGE_UPDATE event would be perfect, but, sadly, it does not fire when doing `--dry-run`.
PackageEvents::POST_PACKAGE_UPDATE => 'onPostPackageUpdate',
];
}
/**
* Prints a list of links to package changelogs on the post-dependencies-solving event.
*
* @param InstallerEvent $event
*/
public function onPostDependenciesSolving(InstallerEvent $event)
{
$changelogs = [];
$operations = $event->getOperations();
foreach ($operations as $operation) {
if ($operation instanceof UpdateOperation) {
try {
$changelogs[] = self::getChangelog($operation->getInitialPackage(), $operation->getTargetPackage());
} catch (Exception\CouldNotCalculateChangelog $e) {
$changelogs[] = $e->getMessage();
}
}
}
if (!empty($changelogs)) {
$this->io->write(self::PAD_STR . 'CHANGELOGS:');
foreach ($changelogs as $changelog) {
$this->io->write(self::PAD_STR . self::PAD_STR . $changelog);
}
}
}
/**
* Prints a links to package changelog on the post-package-update event.
*
* @param PackageEvent $event
*/
public function onPostPackageUpdate(PackageEvent $event)
{
$operation = $event->getOperation();
if ($operation instanceof UpdateOperation) {
try {
$changelog = self::getChangelog($operation->getInitialPackage(), $operation->getTargetPackage());
} catch (Exception\CouldNotCalculateChangelog $e) {
$changelog = $e->getMessage();
}
$this->io->write(self::PAD_STR . 'CHANGELOG: ' . $changelog);
}
}
/**
* Returns a GitHub "Comparing changes" URL for provided package versions.
*
* @param PackageInterface $initialPackage
* @param PackageInterface $targetPackage
*
* @throws Exception\CouldNotCalculateChangelog
*
* @return string
*/
public static function getChangelog(PackageInterface $initialPackage, PackageInterface $targetPackage)
{
if ($initialPackage->getSourceUrl() === $targetPackage->getSourceUrl()) {
$repositoryUrl = $initialPackage->getSourceUrl();
// [email protected]:doctrine/instantiator.git -> https://github.com/doctrine/instantiator.git
$repositoryUrl = preg_replace('/^git@github\.com:/', 'https://github.com/', $repositoryUrl);
$reGithubUrl = '/^https?:\\/\\/github\\.com\\/[^\\/]+\\/[^\\/]+\\.git$/';
if (preg_match($reGithubUrl, $repositoryUrl)) {
/*
Example:
PackageInterface::sourceUrl: https://github.com/sonata-project/SonataCoreBundle.git
PackageInterface::prettyVersion: 2.2 (or 2.4, or master)
Result: https://github.com/sonata-project/SonataCoreBundle/compare/2.2...master
*/
$initialVersion = $initialPackage->getPrettyVersion();
$targetVersion = $targetPackage->getPrettyVersion();
if ($initialVersion === $targetVersion) {
$initialVersion = $initialPackage->getSourceReference();
$targetVersion = $targetPackage->getSourceReference();
}
return preg_replace(
'/\\.git$/',
"/compare/{$initialVersion}...{$targetVersion}",
$repositoryUrl
);
}
throw new Exception\CouldNotCalculateChangelog(
'Unknown changelog; not a GitHub URL: ' .$repositoryUrl,
Exception\CouldNotCalculateChangelog::CODE_SOURCEURL_UNSUPPORTED
);
}
throw new Exception\CouldNotCalculateChangelog(
'Unknown changelog; source URLs don\'t match: ' .
$initialPackage->getSourceUrl() . ', ' . $targetPackage->getSourceUrl(),
Exception\CouldNotCalculateChangelog::CODE_SOURCEURL_MISMATCH
);
}
}