-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathPackageUtils.php
202 lines (185 loc) · 6.23 KB
/
PackageUtils.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\ComposerRootUpdatePlugin\Utils;
use Composer\Composer;
use Composer\Package\Link;
use Composer\Package\Locker;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
/**
* Common package-related utility functions
*/
class PackageUtils
{
public const OPEN_SOURCE_PKG_EDITION = 'community';
public const OPEN_SOURCE_METAPACKAGE = 'magento/product-community-edition';
public const COMMERCE_PKG_EDITION = 'enterprise';
public const COMMERCE_METAPACKAGE = 'magento/product-enterprise-edition';
public const CLOUD_PKG_EDITION = 'cloud';
public const CLOUD_METAPACKAGE = 'magento/magento-cloud-metapackage';
public const MAGENTO_CLOUD_DOCKER_PKG = 'magento/magento-cloud-docker';
/**
* @var Console $console
*/
protected $console;
/**
* @var Composer $composer
*/
protected $composer;
/**
* @param Console $console
* @param Composer|null $composer
*/
public function __construct(Console $console, ?Composer $composer = null)
{
$this->console = $console;
$this->composer = $composer;
}
/**
* Helper function to extract the edition from a package name if it is a magento/product or cloud metapackage
* For the purposes of this plugin, 'cloud' is treated as an edition
*
* @param string $packageName
* @return string|null CLOUD_PKG_EDITION, OPEN_SOURCE_PKG_EDITION, COMMERCE_PKG_EDITION, or null
*/
public function getMetapackageEdition(string $packageName): ?string
{
$packageName = strtolower($packageName);
if ($packageName == self::CLOUD_METAPACKAGE) {
return self::CLOUD_PKG_EDITION;
}
$regex = '/^magento\/product-(?<edition>' . self::OPEN_SOURCE_PKG_EDITION . '|' .
self::COMMERCE_PKG_EDITION . ')-edition$/';
if ($packageName && preg_match($regex, $packageName, $matches)) {
return $matches['edition'];
} else {
return null;
}
}
/**
* Helper function to construct the project package name from an edition
*
* @param string $edition
* @return string
*/
public function getProjectPackageName(string $edition): string
{
if (strtolower($edition) == self::CLOUD_PKG_EDITION) {
return 'magento/magento-cloud-template';
} else {
return strtolower("magento/project-$edition-edition");
}
}
/**
* Helper function to construct the product or cloud metapackage name from an edition
*
* @param string $edition
* @return string
*/
public function getMetapackageName(string $edition): string
{
if (strtolower($edition) == self::CLOUD_PKG_EDITION) {
return self::CLOUD_METAPACKAGE;
} else {
return strtolower("magento/product-$edition-edition");
}
}
/**
* Helper function to turn a package edition into the appropriate marketing edition label
*
* @param string $packageEdition
* @return string|null
*/
public function getEditionLabel(string $packageEdition): ?string
{
if ($packageEdition == self::OPEN_SOURCE_PKG_EDITION) {
return 'Magento Open Source';
} elseif ($packageEdition == self::COMMERCE_PKG_EDITION) {
return 'Adobe Commerce';
} elseif ($packageEdition == self::CLOUD_PKG_EDITION) {
return 'Adobe Commerce Cloud';
}
return null;
}
/**
* Returns the Link from the Composer require section matching the given package name or regex
*
* @param Composer $composer
* @param string $packageMatcher
* @return Link|bool
*/
public function findRequire(Composer $composer, string $packageMatcher)
{
$requires = array_values($composer->getPackage()->getRequires());
if (@preg_match($packageMatcher, '') === false) {
foreach ($requires as $link) {
if ($packageMatcher == $link->getTarget()) {
return $link;
}
}
} else {
foreach ($requires as $link) {
if (preg_match($packageMatcher, $link->getTarget())) {
return $link;
}
}
}
return false;
}
/**
* Is the given constraint strict or does it allow multiple versions
*
* @param string $constraint
* @return bool
*/
public function isConstraintStrict(string $constraint): bool
{
$versionParser = new VersionParser();
$parsedConstraint = $versionParser->parseConstraints($constraint);
return strpbrk($parsedConstraint->__toString(), '[]|<>!') === false;
}
/**
* Checks the composer.lock for the installed metapackage
*
* @return PackageInterface|null
*/
public function getLockedProduct(): ?PackageInterface
{
$locker = $this->getLocker();
$lockedMetapackage = null;
$lockedEdition = null;
if ($locker) {
$lockPackages = $locker->getLockedRepository()->getPackages();
foreach ($lockPackages as $lockedPackage) {
$pkgEdition = $this->getMetapackageEdition($lockedPackage->getName());
if ($pkgEdition == self::CLOUD_PKG_EDITION ||
$pkgEdition == self::COMMERCE_PKG_EDITION && $lockedEdition != self::CLOUD_PKG_EDITION ||
$pkgEdition == self::OPEN_SOURCE_PKG_EDITION && $lockedEdition == null
) {
$lockedMetapackage = $lockedPackage;
$lockedEdition = $pkgEdition;
}
}
}
return $lockedMetapackage;
}
/**
* Get the Locker for the current project
*
* @return Locker
*/
protected function getLocker(): Locker
{
$locker = $this->composer->getLocker();
if (!$locker || !$locker->isLocked()) {
$this->console->labeledVerbose(
'Unable to obtain the installed metapackage version: no composer.lock file found'
);
$locker = null;
}
return $locker;
}
}