11
11
use Magento \MagentoCloud \Filesystem \Driver \File ;
12
12
use Magento \MagentoCloud \Filesystem \FileSystemException ;
13
13
use Magento \MagentoCloud \Package \MagentoVersion ;
14
- use Magento \MagentoCloud \Package \UndefinedPackageException ;
15
14
16
15
/**
17
16
* Generates composer.json data for installation from git.
18
17
*/
19
18
class ComposerGenerator
20
19
{
21
- public const REPO_TYPE_SINGLE_PACKAGE = 'single-package ' ;
22
-
23
- /**
24
- * Type for packages with modules in the root directory such as Inventory
25
- */
26
- public const REPO_TYPE_FLAT_STRUCTURE = 'flat-structure ' ;
27
-
28
20
/**
29
21
* @var DirectoryList
30
22
*/
@@ -40,29 +32,35 @@ class ComposerGenerator
40
32
*/
41
33
private $ file ;
42
34
35
+ /**
36
+ * @var string
37
+ */
38
+ private $ excludeRepoPathsPattern ;
39
+
43
40
/**
44
41
* @param DirectoryList $directoryList
45
42
* @param MagentoVersion $magentoVersion
46
43
* @param File $file
44
+ * @param string $excludeRepoPathsPattern
47
45
*/
48
46
public function __construct (
49
47
DirectoryList $ directoryList ,
50
48
MagentoVersion $ magentoVersion ,
51
- File $ file
49
+ File $ file ,
50
+ $ excludeRepoPathsPattern = '/^((?!test|Test|dev).)*$/ '
52
51
) {
53
52
$ this ->directoryList = $ directoryList ;
54
53
$ this ->magentoVersion = $ magentoVersion ;
55
54
$ this ->file = $ file ;
55
+ $ this ->excludeRepoPathsPattern = $ excludeRepoPathsPattern ;
56
56
}
57
57
58
58
/**
59
59
* Generates composer.json data for installation from git.
60
60
*
61
61
* @param array $repoOptions
62
62
* @return array
63
- * @throws UndefinedPackageException
64
63
* @throws FileSystemException
65
- *
66
64
* @codeCoverageIgnore
67
65
*/
68
66
public function generate (array $ repoOptions ): array
@@ -78,26 +76,38 @@ public function generate(array $repoOptions): array
78
76
$ composer ['require ' ] += ['magento/ece-tools ' => '2002.0.* ' ];
79
77
}
80
78
81
- foreach (array_keys ($ repoOptions ) as $ repoName ) {
82
- $ repoComposerJsonPath = $ this ->directoryList ->getMagentoRoot () . '/ ' . $ repoName . '/composer.json ' ;
83
- if (!$ this ->file ->isExists ($ repoComposerJsonPath )) {
84
- continue ;
79
+ $ preparePackagesScripts = [];
80
+ foreach (array_keys ($ repoOptions ) as $ repoDir ) {
81
+ $ baseRepoFolder = $ this ->directoryList ->getMagentoRoot () . '/ ' . $ repoDir ;
82
+
83
+ $ dirComposerJson = $ baseRepoFolder . '/composer.json ' ;
84
+ if ($ this ->file ->isExists ($ dirComposerJson )) {
85
+ $ dirPackageInfo = json_decode ($ this ->file ->fileGetContents ($ dirComposerJson ), true );
86
+ if (isset ($ dirPackageInfo ['type ' ]) && $ dirPackageInfo ['type ' ] == 'project ' ) {
87
+ $ composer ['require ' ] = array_merge ($ composer ['require ' ], $ dirPackageInfo ['require ' ]);
88
+ }
85
89
}
86
90
87
- $ repoComposer = $ this ->file -> fileGetContents ( $ repoComposerJsonPath );
88
- $ composer [ ' require ' ] = array_merge (
89
- $ composer ['require ' ],
90
- json_decode ( $ repoComposer , true )[ ' require ' ]
91
- );
92
- }
93
-
94
- foreach ( array_keys ( $ composer [ ' require ' ]) as $ packageName ) {
95
- if ( preg_match ( ' /magento\/framework|magento\/module/ ' , $ packageName )) {
96
- $ composer ['require ' ][$ packageName ] = '* ' ;
91
+ $ repoPackages = $ this ->findPackages ( $ baseRepoFolder );
92
+ foreach ( $ repoPackages as $ packageName => $ packagePath ) {
93
+ $ composer ['repositories ' ][ $ packageName ] = [
94
+ ' type ' => ' path ' ,
95
+ ' url ' => $ repoDir . ' / ' . $ packagePath ,
96
+ ' options ' => [
97
+ ' symlink ' => false ,
98
+ ]
99
+ ];
100
+ $ composer ['require ' ][$ packageName ] = '*@dev ' ;
97
101
}
102
+ $ excludeRepoStr = empty ($ repoPackages ) ? '' : "--exclude=' " . join ("' --exclude=' " , $ repoPackages ) . "' " ;
103
+ $ preparePackagesScripts [] = sprintf (
104
+ "rsync -azhm --stats $ excludeRepoStr--exclude='dev/tests' --exclude='.git' " .
105
+ "--exclude='composer.json' --exclude='composer.lock' ./%s/ ./ " ,
106
+ $ repoDir
107
+ );
98
108
}
99
-
100
- $ composer = $ this -> addModules ( $ repoOptions , $ composer ) ;
109
+ $ composer [ ' scripts ' ][ ' prepare-packages ' ] = $ preparePackagesScripts ;
110
+ $ composer[ ' scripts ' ][ ' post-install-cmd ' ] = [ ' @prepare-packages ' ] ;
101
111
102
112
return $ composer ;
103
113
}
@@ -112,13 +122,14 @@ public function getInstallFromGitScripts(array $repoOptions): array
112
122
$ installFromGitScripts [] = 'rm -rf ' . implode (' ' , array_keys ($ repoOptions ));
113
123
114
124
foreach ($ repoOptions as $ repoName => $ gitOption ) {
115
- $ gitCloneCommand = 'git clone -b %s --single-branch --depth 1 %s %s ' ;
116
-
125
+ $ gitRef = $ gitOption ['ref ' ] ?? $ gitOption ['branch ' ];
117
126
$ installFromGitScripts [] = sprintf (
118
- $ gitCloneCommand ,
119
- $ gitOption ['branch ' ],
127
+ 'git clone %s "%s" && git --git-dir="%s/.git" --work-tree="%s" checkout %s ' ,
120
128
$ gitOption ['repo ' ],
121
- $ repoName
129
+ $ repoName ,
130
+ $ repoName ,
131
+ $ repoName ,
132
+ $ gitRef
122
133
);
123
134
}
124
135
@@ -130,26 +141,10 @@ public function getInstallFromGitScripts(array $repoOptions): array
130
141
*
131
142
* @param array $repoOptions
132
143
* @return array
133
- * @throws UndefinedPackageException
134
144
*/
135
145
private function getBaseComposer (array $ repoOptions ): array
136
146
{
137
147
$ installFromGitScripts = $ this ->getInstallFromGitScripts ($ repoOptions );
138
-
139
- $ preparePackagesScripts = [];
140
-
141
- foreach ($ repoOptions as $ repoName => $ gitOption ) {
142
- if ($ this ->isSinglePackage ($ gitOption ) || $ this ->isFlatStructurePackage ($ gitOption )) {
143
- continue ;
144
- }
145
-
146
- $ preparePackagesScripts [] = sprintf (
147
- "rsync -azh --stats --exclude='app/code/Magento/' --exclude='app/i18n/' --exclude='app/design/' "
148
- . "--exclude='dev/tests' --exclude='lib/internal/Magento' --exclude='.git' ./%s/ ./ " ,
149
- $ repoName
150
- );
151
- }
152
-
153
148
$ composer = [
154
149
'name ' => 'magento/cloud-dev ' ,
155
150
'description ' => 'eCommerce Platform for Growth ' ,
@@ -162,16 +157,6 @@ private function getBaseComposer(array $repoOptions): array
162
157
'ce/bin/magento ' ,
163
158
],
164
159
'repositories ' => [
165
- 'magento/framework ' => [
166
- 'type ' => 'path ' ,
167
- 'url ' => './ce/lib/internal/Magento/Framework/ ' ,
168
- 'transport-options ' => [
169
- 'symlink ' => false ,
170
- ],
171
- 'options ' => [
172
- 'symlink ' => false ,
173
- ],
174
- ],
175
160
],
176
161
'require ' => [
177
162
],
@@ -192,111 +177,44 @@ private function getBaseComposer(array $repoOptions): array
192
177
],
193
178
'scripts ' => [
194
179
'install-from-git ' => $ installFromGitScripts ,
195
- 'prepare-packages ' => $ preparePackagesScripts ,
196
180
'pre-install-cmd ' => [
197
181
'@install-from-git ' ,
198
182
],
199
183
'pre-update-cmd ' => [
200
184
'@install-from-git ' ,
201
185
],
202
- 'post-install-cmd ' => [
203
- '@prepare-packages ' ,
204
- ],
205
186
],
206
187
];
207
188
208
189
return $ composer ;
209
190
}
210
191
211
192
/**
212
- * Adds modules and repositories to composer.json.
193
+ * Find Composer packages in the folder (recursively)
213
194
*
214
- * @param array $repoOptions
215
- * @param array $composer
195
+ * @param string $path
216
196
* @return array
217
197
* @throws FileSystemException
218
- *
219
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
220
- *
221
- * @codeCoverageIgnore
222
198
*/
223
- private function addModules ( array $ repoOptions , array $ composer ): array
199
+ private function findPackages ( string $ path )
224
200
{
225
- foreach ($ repoOptions as $ repoName => $ gitOption ) {
226
- $ baseRepoFolder = $ this ->directoryList ->getMagentoRoot () . '/ ' . $ repoName ;
227
- if ($ this ->isSinglePackage ($ gitOption )) {
228
- $ this ->addModule ($ baseRepoFolder , $ composer , '* ' );
229
- continue ;
230
- }
231
-
232
- if ($ this ->isFlatStructurePackage ($ gitOption )) {
233
- foreach (glob ($ baseRepoFolder . '/* ' ) as $ dir ) {
234
- $ this ->addModule ($ dir , $ composer );
235
- }
236
- continue ;
237
- }
238
-
239
- foreach (glob ($ baseRepoFolder . '/app/code/Magento/* ' ) as $ dir ) {
240
- $ this ->addModule ($ dir , $ composer );
241
- }
242
- foreach (glob ($ baseRepoFolder . '/app/design/*/Magento/*/ ' ) as $ dir ) {
243
- $ this ->addModule ($ dir , $ composer );
244
- }
245
- foreach (glob ($ baseRepoFolder . '/app/design/*/Magento/*/ ' ) as $ dir ) {
246
- $ this ->addModule ($ dir , $ composer );
247
- }
248
- if ($ this ->file ->isDirectory ($ baseRepoFolder . '/lib/internal/Magento/Framework/ ' )) {
249
- foreach (glob ($ baseRepoFolder . '/lib/internal/Magento/Framework/* ' ) as $ dir ) {
250
- $ this ->addModule ($ dir , $ composer );
251
- }
201
+ $ path = rtrim ($ path , '\\/ ' );
202
+ $ packageTypes = ['magento2-module ' , 'magento2-theme ' , 'magento2-language ' , 'magento2-library ' ];
203
+ $ pathLength = strlen ($ path . '/ ' );
204
+
205
+ $ dirIterator = $ this ->file ->getRecursiveFileIterator (
206
+ $ path ,
207
+ '/composer.json$/ ' ,
208
+ $ this ->excludeRepoPathsPattern
209
+ );
210
+ $ packages = [];
211
+ foreach ($ dirIterator as $ currentFileInfo ) {
212
+ $ packageInfo = json_decode ($ this ->file ->fileGetContents ($ currentFileInfo ->getPathName ()), true );
213
+ if (isset ($ packageInfo ['type ' ]) && in_array ($ packageInfo ['type ' ], $ packageTypes )) {
214
+ $ packages [$ packageInfo ['name ' ]] = substr ($ currentFileInfo ->getPath (), $ pathLength );
252
215
}
253
216
}
254
217
255
- return $ composer ;
256
- }
257
-
258
- /**
259
- * Add single module to composer json
260
- *
261
- * @param string $dir
262
- * @param array $composer
263
- * @param string|null $version
264
- * @throws FileSystemException
265
- */
266
- private function addModule (string $ dir , array &$ composer , string $ version = null ): void
267
- {
268
- if (!$ this ->file ->isExists ($ dir . '/composer.json ' )) {
269
- return ;
270
- }
271
-
272
- $ dirComposer = json_decode ($ this ->file ->fileGetContents ($ dir . '/composer.json ' ), true );
273
- $ composer ['repositories ' ][$ dirComposer ['name ' ]] = [
274
- 'type ' => 'path ' ,
275
- 'url ' => ltrim (str_replace ($ this ->directoryList ->getMagentoRoot (), '' , $ dir ), '/ ' ),
276
- 'options ' => [
277
- 'symlink ' => false ,
278
- ],
279
- ];
280
- $ composer ['require ' ][$ dirComposer ['name ' ]] = $ version ?? $ dirComposer ['version ' ] ?? '* ' ;
281
- }
282
-
283
- /**
284
- * @param array $repoOptions
285
- * @return bool
286
- */
287
- private function isSinglePackage (array $ repoOptions ): bool
288
- {
289
- return isset ($ repoOptions ['type ' ]) && $ repoOptions ['type ' ] === self ::REPO_TYPE_SINGLE_PACKAGE ;
290
- }
291
-
292
- /**
293
- * Checks that package has option type and it equal to @see ComposerGenerator::REPO_TYPE_FLAT_STRUCTURE
294
- *
295
- * @param array $repoOptions
296
- * @return bool
297
- */
298
- private function isFlatStructurePackage (array $ repoOptions ): bool
299
- {
300
- return isset ($ repoOptions ['type ' ]) && $ repoOptions ['type ' ] === self ::REPO_TYPE_FLAT_STRUCTURE ;
218
+ return $ packages ;
301
219
}
302
220
}
0 commit comments