Skip to content

Commit 589d44e

Browse files
committed
refactor(deps): remove composer/composer package dependency
The composer/composer package dependency was only used to read the contents of the extra section of a project's composer.json file. This commit replaces this logic by standard PHP functions. As a result, the composer/composer dependency has been removed which results in potentially 21 less dependencies when installing this package as a dependency. Closes: #103
1 parent 1911eb2 commit 589d44e

File tree

3 files changed

+77
-113
lines changed

3 files changed

+77
-113
lines changed

composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
"php": "^8.1",
2525
"ext-json": "*",
2626
"composer-runtime-api": "^2.0",
27-
"composer/composer": "^2.4",
2827
"jawira/case-converter": "^3.5",
2928
"opis/json-schema": "^2.3",
3029
"symfony/console": "^6.0 || ^7.0",

src/ConventionalCommits/Configuration/FinderTool.php

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121

2222
namespace Ramsey\ConventionalCommits\Configuration;
2323

24-
use Composer\Composer;
25-
use Composer\Factory;
26-
use Composer\IO\ConsoleIO;
2724
use JsonException;
2825
use Opis\JsonSchema\Errors\ErrorFormatter;
2926
use Opis\JsonSchema\Errors\ValidationError;
@@ -32,7 +29,7 @@
3229
use Ramsey\ConventionalCommits\Exception\ComposerNotFound;
3330
use Ramsey\ConventionalCommits\Exception\InvalidArgument;
3431
use Ramsey\ConventionalCommits\Exception\InvalidValue;
35-
use Symfony\Component\Console\Helper\HelperSet;
32+
use RuntimeException;
3633
use Symfony\Component\Console\Input\InputInterface;
3734
use Symfony\Component\Console\Output\OutputInterface;
3835
use Symfony\Component\Filesystem\Filesystem;
@@ -43,6 +40,7 @@
4340
use function gettype;
4441
use function implode;
4542
use function is_array;
43+
use function is_readable;
4644
use function json_decode;
4745
use function realpath;
4846
use function sprintf;
@@ -84,23 +82,6 @@ public function findConfiguration(
8482
return new DefaultConfiguration($this->loadConfigFromComposer($input, $output));
8583
}
8684

87-
/**
88-
* Returns the Composer instance for the current project
89-
*/
90-
public function getComposer(
91-
InputInterface $input,
92-
OutputInterface $output,
93-
Filesystem $filesystem,
94-
): Composer {
95-
$composerJson = $this->findComposerJson($filesystem);
96-
97-
$composerIO = new ConsoleIO($input, $output, new HelperSet());
98-
$composerFactory = new Factory();
99-
100-
/** @var Composer */
101-
return $composerFactory->createComposer($composerIO, $composerJson, true, null, true);
102-
}
103-
10485
/**
10586
* @return array{typeCase?: string | null, types?: string[], scopeRequired?: bool, scopeCase?: string | null, scopes?: string[], descriptionCase?: string | null, descriptionEndMark?: string | null, bodyRequired?: bool, bodyWrapWidth?: int | null, requiredFooters?: string[]}
10687
*
@@ -137,10 +118,17 @@ private function loadConfigFromFile(string $file): array
137118
*/
138119
private function loadConfigFromComposer(InputInterface $input, OutputInterface $output): array
139120
{
140-
$composer = $this->getComposer($input, $output, new Filesystem());
141-
121+
$composerJsonPath = $this->findComposerJson(new Filesystem());
122+
if (!is_readable($composerJsonPath)) {
123+
throw new RuntimeException(sprintf('The file "%s" is not readable.', $composerJsonPath));
124+
}
125+
$contents = @file_get_contents($composerJsonPath);
126+
if ($contents === false) {
127+
throw new RuntimeException(sprintf('Could not read file "%s"', $composerJsonPath));
128+
}
129+
$composerData = json_decode($contents, true, flags: JSON_THROW_ON_ERROR);
142130
/** @var array{"ramsey/conventional-commits"?: array{config?: scalar | array{typeCase?: string | null, types?: string[], scopeRequired?: bool, scopeCase?: string | null, scopes?: string[], descriptionCase?: string | null, descriptionEndMark?: string | null, bodyRequired?: bool, bodyWrapWidth?: int | null, requiredFooters?: string[]}, configFile?: scalar}} | null $extra */
143-
$extra = $composer->getPackage()->getExtra();
131+
$extra = is_array($composerData) ? ($composerData['extra'] ?? null) : null;
144132

145133
$config = $extra['ramsey/conventional-commits']['config'] ?? null;
146134
$configFile = $extra['ramsey/conventional-commits']['configFile'] ?? null;

tests/ConventionalCommits/Configuration/FinderToolTest.php

Lines changed: 65 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,25 @@
44

55
namespace Ramsey\Test\ConventionalCommits\Configuration;
66

7-
use Composer\Composer;
87
use JsonException;
98
use Mockery\MockInterface;
109
use Ramsey\ConventionalCommits\Configuration\Configuration;
1110
use Ramsey\ConventionalCommits\Configuration\FinderTool;
12-
use Ramsey\ConventionalCommits\Exception\ComposerNotFound;
1311
use Ramsey\ConventionalCommits\Exception\InvalidArgument;
1412
use Ramsey\ConventionalCommits\Exception\InvalidValue;
1513
use Ramsey\Test\SnapshotsTool;
1614
use Ramsey\Test\TestCase;
1715
use Ramsey\Test\WindowsSafeTextDriver;
16+
use RuntimeException;
1817
use Symfony\Component\Console\Input\InputInterface;
1918
use Symfony\Component\Console\Output\OutputInterface;
2019
use Symfony\Component\Filesystem\Filesystem;
2120

21+
use function file_put_contents;
2222
use function json_encode;
2323
use function realpath;
24+
use function sys_get_temp_dir;
25+
use function unlink;
2426

2527
use const DIRECTORY_SEPARATOR;
2628

@@ -34,6 +36,8 @@ class FinderToolTest extends TestCase
3436

3537
private OutputInterface & MockInterface $output;
3638

39+
private Filesystem $fileSystem;
40+
3741
protected function setUp(): void
3842
{
3943
parent::setUp();
@@ -43,6 +47,7 @@ protected function setUp(): void
4347
$this->finderTool = new class () {
4448
use FinderTool;
4549
};
50+
$this->fileSystem = new Filesystem();
4651
}
4752

4853
/**
@@ -168,79 +173,52 @@ public function testFindConfigurationThrowsExceptionWhenConfigIsInvalid(): void
168173
]);
169174
}
170175

171-
public function testGetComposerFindsComposerJsonForCurrentProject(): void
172-
{
173-
$this->output->shouldReceive('isDebug');
174-
$this->output->allows()->getVerbosity()->andReturn(OutputInterface::VERBOSITY_QUIET);
175-
$this->output->allows()->isDebug()->andReturnFalse();
176-
177-
$filesystem = new Filesystem();
178-
179-
// @phpstan-ignore-next-line
180-
$composer = $this->finderTool->getComposer($this->input, $this->output, $filesystem);
181-
182-
$this->assertInstanceOf(Composer::class, $composer);
183-
$this->assertSame('ramsey/conventional-commits', $composer->getPackage()->getName());
184-
}
185-
186-
public function testGetComposerThrowsExceptionWhenAutoloaderDoesNotExist(): void
176+
public function testFindConfigurationThrowsExceptionWhenComposerJsonDoesNotExist(): void
187177
{
188-
$this->output->allows()->getVerbosity()->andReturn(OutputInterface::VERBOSITY_QUIET);
189-
190-
/** @var Filesystem & MockInterface $filesystem */
191-
$filesystem = $this->mockery(Filesystem::class);
192-
$filesystem->shouldReceive('exists')->twice()->andReturnFalse();
178+
$composerJsonPath = 'path/to/nonexistent/composer.json';
193179

194-
$this->expectException(ComposerNotFound::class);
195-
$this->expectExceptionMessage(
196-
'Could not find the autoloader. Did you run composer install or composer update?',
197-
);
180+
$finderTool = new class () {
181+
use FinderTool;
198182

199-
// @phpstan-ignore-next-line
200-
$this->finderTool->getComposer($this->input, $this->output, $filesystem);
201-
}
183+
public string $composerJsonPath;
202184

203-
public function testGetComposerThrowsExceptionWhenComposerJsonDoesNotExist(): void
204-
{
205-
$this->output->allows()->getVerbosity()->andReturn(OutputInterface::VERBOSITY_QUIET);
185+
public function findComposerJson(Filesystem $filesystem): string
186+
{
187+
return $this->composerJsonPath;
188+
}
189+
};
206190

207-
/** @var Filesystem & MockInterface $filesystem */
208-
$filesystem = $this->mockery(Filesystem::class);
209-
$filesystem->shouldReceive('exists')->andReturn(false, true, false);
191+
$finderTool->composerJsonPath = $composerJsonPath;
210192

211-
$this->expectException(ComposerNotFound::class);
212-
$this->expectExceptionMessage('Could not find composer.json.');
193+
$this->expectException(RuntimeException::class);
194+
$this->expectExceptionMessage("The file \"{$composerJsonPath}\" is not readable.");
213195

214-
// @phpstan-ignore-next-line
215-
$this->finderTool->getComposer($this->input, $this->output, $filesystem);
196+
$finderTool->findConfiguration($this->input, $this->output);
216197
}
217198

218199
public function testFindConfigurationThrowsExceptionWhenComposerHasInvalidValue(): void
219200
{
220-
/** @var Composer & MockInterface $composer */
221-
$composer = $this->mockery(Composer::class, [
222-
'getPackage->getExtra' => [
201+
$composerJsonPath = $this->fileSystem->tempnam(sys_get_temp_dir(), 'cc_', '.json');
202+
file_put_contents($composerJsonPath, json_encode([
203+
'extra' => [
223204
'ramsey/conventional-commits' => [
224205
'config' => 'invalid value',
225206
],
226207
],
227-
]);
208+
]));
228209

229210
$finderTool = new class () {
230211
use FinderTool;
231212

232-
public Composer $composer;
213+
public string $composerJsonPath;
233214

234-
public function getComposer(
235-
InputInterface $input,
236-
OutputInterface $output,
237-
Filesystem $filesystem,
238-
): Composer {
239-
return $this->composer;
215+
public function findComposerJson(Filesystem $filesystem): string
216+
{
217+
return $this->composerJsonPath;
240218
}
241219
};
242220

243-
$finderTool->composer = $composer;
221+
$finderTool->composerJsonPath = $composerJsonPath;
244222

245223
$this->expectException(InvalidValue::class);
246224
$this->expectExceptionMessage(
@@ -249,103 +227,102 @@ public function getComposer(
249227
);
250228

251229
$finderTool->findConfiguration($this->input, $this->output);
230+
231+
@unlink($composerJsonPath);
252232
}
253233

254234
public function testFindConfigurationReturnsConfigurationUsingComposerConfig(): void
255235
{
256-
/** @var Composer & MockInterface $composer */
257-
$composer = $this->mockery(Composer::class, [
258-
'getPackage->getExtra' => [
236+
$composerJsonPath = $this->fileSystem->tempnam(sys_get_temp_dir(), 'cc_', '.json');
237+
file_put_contents($composerJsonPath, json_encode([
238+
'extra' => [
259239
'ramsey/conventional-commits' => [
260240
'configFile' => (string) realpath(__DIR__ . '/../../configs/config-03.json'),
261241
'config' => [
262242
'typeCase' => 'pascal',
263243
],
264244
],
265245
],
266-
]);
246+
]));
267247

268248
$finderTool = new class () {
269249
use FinderTool;
270250

271-
public Composer $composer;
251+
public string $composerJsonPath;
272252

273-
public function getComposer(
274-
InputInterface $input,
275-
OutputInterface $output,
276-
Filesystem $filesystem,
277-
): Composer {
278-
return $this->composer;
253+
public function findComposerJson(Filesystem $filesystem): string
254+
{
255+
return $this->composerJsonPath;
279256
}
280257
};
281258

282-
$finderTool->composer = $composer;
259+
$finderTool->composerJsonPath = $composerJsonPath;
283260

284261
/** @var Configuration $configuration */
285262
$configuration = $finderTool->findConfiguration($this->input, $this->output);
286263

287264
$this->assertMatchesSnapshot(json_encode($configuration), new WindowsSafeTextDriver());
265+
266+
@unlink($composerJsonPath);
288267
}
289268

290269
public function testFindConfigurationReturnsConfigurationUsingComposerConfigFile(): void
291270
{
292-
/** @var Composer & MockInterface $composer */
293-
$composer = $this->mockery(Composer::class, [
294-
'getPackage->getExtra' => [
271+
$composerJsonPath = $this->fileSystem->tempnam(sys_get_temp_dir(), 'cc_', '.json');
272+
file_put_contents($composerJsonPath, json_encode([
273+
'extra' => [
295274
'ramsey/conventional-commits' => [
296275
'configFile' => (string) realpath(__DIR__ . '/../../configs/config-03.json'),
297276
],
298277
],
299-
]);
278+
]));
300279

301280
$finderTool = new class () {
302281
use FinderTool;
303282

304-
public Composer $composer;
283+
public string $composerJsonPath;
305284

306-
public function getComposer(
307-
InputInterface $input,
308-
OutputInterface $output,
309-
Filesystem $filesystem,
310-
): Composer {
311-
return $this->composer;
285+
public function findComposerJson(Filesystem $filesystem): string
286+
{
287+
return $this->composerJsonPath;
312288
}
313289
};
314290

315-
$finderTool->composer = $composer;
291+
$finderTool->composerJsonPath = $composerJsonPath;
316292

317293
/** @var Configuration $configuration */
318294
$configuration = $finderTool->findConfiguration($this->input, $this->output);
319295

320296
$this->assertMatchesSnapshot(json_encode($configuration), new WindowsSafeTextDriver());
297+
298+
@unlink($composerJsonPath);
321299
}
322300

323301
public function testFindConfigurationReturnsDefaultConfigurationWhenComposerHasNone(): void
324302
{
325-
/** @var Composer & MockInterface $composer */
326-
$composer = $this->mockery(Composer::class, [
327-
'getPackage->getExtra' => [],
328-
]);
303+
$composerJsonPath = $this->fileSystem->tempnam(sys_get_temp_dir(), 'cc_', '.json');
304+
file_put_contents($composerJsonPath, json_encode([
305+
'extra' => [],
306+
]));
329307

330308
$finderTool = new class () {
331309
use FinderTool;
332310

333-
public Composer $composer;
311+
public string $composerJsonPath;
334312

335-
public function getComposer(
336-
InputInterface $input,
337-
OutputInterface $output,
338-
Filesystem $filesystem,
339-
): Composer {
340-
return $this->composer;
313+
public function findComposerJson(Filesystem $filesystem): string
314+
{
315+
return $this->composerJsonPath;
341316
}
342317
};
343318

344-
$finderTool->composer = $composer;
319+
$finderTool->composerJsonPath = $composerJsonPath;
345320

346321
/** @var Configuration $configuration */
347322
$configuration = $finderTool->findConfiguration($this->input, $this->output);
348323

349324
$this->assertMatchesSnapshot(json_encode($configuration), new WindowsSafeTextDriver());
325+
326+
@unlink($composerJsonPath);
350327
}
351328
}

0 commit comments

Comments
 (0)