Skip to content

Commit

Permalink
added CLI switch --no-version-normalization
Browse files Browse the repository at this point in the history
is related to #102

Signed-off-by: Jan Kowalleck <[email protected]>
  • Loading branch information
jkowalleck committed Nov 10, 2021
1 parent e32e105 commit 93ccb8c
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 19 deletions.
11 changes: 11 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.

## unreleased

* Added
* CLI got a new switch `--no-version-normalization`. (via [#138])
That allows to omit component version-string normalization.
Per default this plugin will normalize version strings by stripping leading "v".
This is a compatibility-switch. The next major-version of this plugin will not modify component versions. (see [#102])

[#138]: https://github.com/CycloneDX/cyclonedx-php-composer/pull/138
[#102]: https://github.com/CycloneDX/cyclonedx-php-composer/issues/102



## 3.6.0 - 2021-10-15

* Added
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ Options:
--exclude-plugins Exclude composer plugins
--spec-version=SPEC-VERSION Which version of CycloneDX spec to use.
Values: "1.1", "1.2", "1.3" [default: "1.3"]
--no-validate Dont validate the resulting output
--no-validate Don't validate the resulting output
--mc-version=MC-VERSION Version of the main component.
This will override auto-detection.
--no-version-normalization Don't normalize component version strings.
Per default this plugin will normalize version strings by stripping leading "v".
This is a compatibility-switch. The next major-version of this plugin will not modify component versions.
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
Expand Down
38 changes: 26 additions & 12 deletions src/Builders/ComponentBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,17 @@ class ComponentBuilder
/** @var PackageUrlFactory */
private $packageUrlFactory;

/** @var bool */
private $enableVersionNormalization;

public function __construct(
LicenseFactory $licenseFactory,
PackageUrlFactory $packageUrlFactory
PackageUrlFactory $packageUrlFactory,
bool $enableVersionNormalization = true
) {
$this->licenseFactory = $licenseFactory;
$this->packageUrlFactory = $packageUrlFactory;
$this->enableVersionNormalization = $enableVersionNormalization;
}

public function getLicenseFactory(): LicenseFactory
Expand All @@ -66,6 +71,12 @@ public function getPackageUrlFactory(): PackageUrlFactory
return $this->packageUrlFactory;
}

public function setVersionNormalization(bool $enableVersionNormalization): self
{
$this->enableVersionNormalization = $enableVersionNormalization;
return $this;
}

/**
* @throws UnexpectedValueException if the given package does not provide a name or version
*/
Expand Down Expand Up @@ -144,17 +155,20 @@ private function getPackageVersion(PackageInterface $package): string
return $version;
}

// Versions of Composer packages may be prefixed with "v".
// * This prefix appears to be problematic for CPE and PURL matching and thus is removed here.
// *
// * See for example {@link https://ossindex.sonatype.org/component/pkg:composer/phpmailer/[email protected]}
// * vs {@link https://ossindex.sonatype.org/component/pkg:composer/phpmailer/[email protected]}.
//
// A _numeric_ version can be prefixed with 'v'.
// Strip leading 'v' must not be applied if the "version" is actually a branch name,
// which is totally fine in the composer ecosystem.
if (1 === preg_match('/^v\\d/', $version)) {
return substr($version, 1);
if ($this->enableVersionNormalization)
{
// Versions of Composer packages may be prefixed with "v".
// * This prefix appears to be problematic for CPE and PURL matching and thus is removed here.
// *
// * See for example {@link https://ossindex.sonatype.org/component/pkg:composer/phpmailer/[email protected]}
// * vs {@link https://ossindex.sonatype.org/component/pkg:composer/phpmailer/[email protected]}.
//
// A _numeric_ version can be prefixed with 'v'.
// Strip leading 'v' must not be applied if the "version" is actually a branch name,
// which is totally fine in the composer ecosystem.
if (1 === preg_match('/^v\\d/', $version)) {
return substr($version, 1);
}
}

return $version;
Expand Down
12 changes: 8 additions & 4 deletions src/MakeBom/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Command extends BaseCommand
/**
* @var \CycloneDX\Composer\Builders\BomBuilder
*/
private $bomFactory;
private $bomBuilder;

/**
* @var ToolUpdater|null
Expand All @@ -77,7 +77,7 @@ public function __construct(
) {
$this->options = $options;
$this->factory = $factory;
$this->bomFactory = $bomFactory;
$this->bomBuilder = $bomFactory;
$this->toolUpdater = $toolUpdater;
parent::__construct($name);
}
Expand Down Expand Up @@ -117,6 +117,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
$io->writeErrorRaw(__METHOD__.' Options: '.print_r($this->options, true), true, IOInterface::DEBUG);

$this->bomBuilder->getComponentBuilder()->setVersionNormalization(
$this->options->omitVersionNormalization
);

$this->updateTool();

$bomString = $this->makeBomString(
Expand Down Expand Up @@ -164,7 +168,7 @@ private function makeBom(Composer $composer): Bom
$components = $this->factory->makeLockerFromComposerForOptions($composer, $this->options);
$rootComponentVersionOverride = $this->options->mainComponentVersion;

$bom = $this->bomFactory->makeForPackageWithRequires($rootPackage, $components, $rootComponentVersionOverride);
$bom = $this->bomBuilder->makeForPackageWithRequires($rootPackage, $components, $rootComponentVersionOverride);

$io->writeErrorRaw('Bom: '.print_r($bom, true), true, IOInterface::DEBUG);

Expand Down Expand Up @@ -264,7 +268,7 @@ private function updateTool(): ?bool
$lockerRepo = $locker->getLockedRepository($withDevReqs);

// @TODO better use the installed-repo than the lockerRepo - as of milestone v4
return $updater->updateTool($this->bomFactory->getTool(), $lockerRepo);
return $updater->updateTool($this->bomBuilder->getTool(), $lockerRepo);
} catch (\Exception $exception) {
return false;
}
Expand Down
24 changes: 23 additions & 1 deletion src/MakeBom/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class Options
private const SWITCH_EXCLUDE_PLUGINS = 'exclude-plugins';
private const SWITCH_NO_VALIDATE = 'no-validate';

// added in preparation for https://github.com/CycloneDX/cyclonedx-php-composer/issues/102
// @TODO remove with next major version
private const SWITCH_NO_VERSION_NORMALIZATION = 'no-version-normalization';

private const ARGUMENT_COMPOSER_FILE = 'composer-file';

public const OUTPUT_FORMAT_XML = 'XML';
Expand Down Expand Up @@ -111,7 +115,7 @@ public function configureCommand(Command $command): void
self::SWITCH_NO_VALIDATE,
null,
InputOption::VALUE_NONE,
'Dont validate the resulting output'
'Don\'t validate the resulting output'
)
->addOption(
self::OPTION_MAIN_COMPONENT_VERSION,
Expand All @@ -121,6 +125,14 @@ public function configureCommand(Command $command): void
'This will override auto-detection.',
null
)
->addOption(
self::SWITCH_NO_VERSION_NORMALIZATION,
null,
InputOption::VALUE_NONE,
'Don\'t normalize component version strings.'.\PHP_EOL.
'Per default this plugin will normalize version strings by stripping leading "v".'.\PHP_EOL.
'This is a compatibility-switch. The next major-version of this plugin will not modify component versions.'
)
->addArgument(
self::ARGUMENT_COMPOSER_FILE,
InputArgument::OPTIONAL,
Expand Down Expand Up @@ -151,6 +163,13 @@ public function configureCommand(Command $command): void
*/
public $excludePlugins = false;

/**
* @var bool
* @readonly
* @psalm-allow-private-mutation
*/
public $omitVersionNormalization = false;

/**
* @var string
* @psalm-var Options::OUTPUT_FORMAT_*
Expand Down Expand Up @@ -214,13 +233,15 @@ public function setFromInput(InputInterface $input): self
$excludeDev = false !== $input->getOption(self::SWITCH_EXCLUDE_DEV);
$excludePlugins = false !== $input->getOption(self::SWITCH_EXCLUDE_PLUGINS);
$skipOutputValidation = false !== $input->getOption(self::SWITCH_NO_VALIDATE);
$omitVersionNormalization = false !== $input->getOption(self::SWITCH_NO_VERSION_NORMALIZATION);
$outputFile = $input->getOption(self::OPTION_OUTPUT_FILE);
\assert(null === $outputFile || \is_string($outputFile));
$composerFile = $input->getArgument(self::ARGUMENT_COMPOSER_FILE);
\assert(null === $composerFile || \is_string($composerFile));
$mainComponentVersion = $input->getOption(self::OPTION_MAIN_COMPONENT_VERSION);
\assert(null === $mainComponentVersion || \is_string($mainComponentVersion));


// endregion get from input

// those regions are split,
Expand All @@ -233,6 +254,7 @@ public function setFromInput(InputInterface $input): self
$this->excludePlugins = $excludePlugins;
$this->outputFormat = $outputFormat;
$this->skipOutputValidation = $skipOutputValidation;
$this->omitVersionNormalization = $omitVersionNormalization;
$this->outputFile = \is_string($outputFile) && '' !== $outputFile
? $outputFile
: self::OUTPUT_FILE_DEFAULT[$outputFormat];
Expand Down
30 changes: 29 additions & 1 deletion tests/Builders/ComponentBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,14 @@ public function testMakeFromPackageEmptPurlOnThrow(): void
public function testMakeFromPackage(
PackageInterface $package,
Component $expected,
bool $enableVersionNormalization = true,
?LicenseFactory $licenseFactory = null
): void {
$packageUrlFactory = $this->createMock(PackageUrlFactory::class);
$builder = new ComponentBuilder(
$licenseFactory ?? $this->createStub(LicenseFactory::class),
$packageUrlFactory
$packageUrlFactory,
$enableVersionNormalization
);

$purlMadeFromComponent = null;
Expand Down Expand Up @@ -172,6 +174,7 @@ public function dpMakeFromPackage(): \Generator
(new Component('library', 'some-library', '1.2.3'))
->setPackageUrl((new PackageUrl('composer', 'some-library'))->setVersion('1.2.3'))
->setBomRefValue('pkg:composer/[email protected]'),
true,
null,
];

Expand All @@ -187,6 +190,7 @@ public function dpMakeFromPackage(): \Generator
(new Component('application', 'some-project', '1.2.3'))
->setPackageUrl((new PackageUrl('composer', 'some-project'))->setVersion('1.2.3'))
->setBomRefValue('pkg:composer/[email protected]'),
true,
null,
];

Expand All @@ -202,6 +206,7 @@ public function dpMakeFromPackage(): \Generator
(new Component('application', 'some-composer-plugin', '1.2.3'))
->setPackageUrl((new PackageUrl('composer', 'some-composer-plugin'))->setVersion('1.2.3'))
->setBomRefValue('pkg:composer/[email protected]'),
true,
null,
];

Expand All @@ -218,6 +223,7 @@ public function dpMakeFromPackage(): \Generator
(new Component('library', 'some-inDev', 'dev-master'))
->setPackageUrl((new PackageUrl('composer', 'some-inDev'))->setVersion('dev-master'))
->setBomRefValue('pkg:composer/some-inDev@dev-master'),
true,
null,
];

Expand All @@ -233,6 +239,7 @@ public function dpMakeFromPackage(): \Generator
(new Component('library', 'some-noVersion', RootPackage::DEFAULT_PRETTY_VERSION))
->setPackageUrl((new PackageUrl('composer', 'some-noVersion'))->setVersion(null))
->setBomRefValue('pkg:composer/some-noVersion'),
true,
null,
];

Expand Down Expand Up @@ -266,7 +273,28 @@ public function dpMakeFromPackage(): \Generator
->setLicense($license)
->setHashRepository(new HashRepository([HashAlgorithm::SHA_1 => '12345678901234567890123456789012']))
->setBomRefValue('pkg:composer/my/[email protected]?checksum=sha1:12345678901234567890123456789012'),
true,
$licenseFactory,
];

yield 'library with non-normalized version' => [
$this->createConfiguredMock(
CompletePackageInterface::class,
[
'getPrettyName' => 'my/package',
'getPrettyVersion' => 'v1.2.3',
]
),
(new Component('library', 'package', 'v1.2.3'))
->setGroup('my')
->setPackageUrl(
(new PackageUrl('composer', 'package'))
->setNamespace('my')
->setVersion('v1.2.3')
)
->setBomRefValue('pkg:composer/my/[email protected]'),
false,
null,
];
}
}

0 comments on commit 93ccb8c

Please sign in to comment.