Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ private void ProcessDependencyList(ISingleFileComponentRecorder singleFileCompon
{
var pnpmDependencyPath = this.pnpmParsingUtilities.ReconstructPnpmDependencyPath(name, dep.Version);
var (component, package) = components[pnpmDependencyPath];
var (_, packageVersion) = this.pnpmParsingUtilities.ExtractNameAndVersionFromPnpmPackagePath(pnpmDependencyPath);

// Lockfile v9 apparently removed the tagging of dev dependencies in the lockfile, so we revert to using the dependency tree to establish dev dependency state.
// At this point, the root dependencies are marked according to which dependency group they are declared in the lockfile itself.
// Ignore "file:" and "link:" as these are local packages.
var isFileOrLink = this.IsFileOrLink(dep.Version);
var isFileOrLink = this.IsFileOrLink(packageVersion);
if (!isFileOrLink)
{
singleFileComponentRecorder.RegisterUsage(component, isExplicitReferencedDependency: true, isDevelopmentDependency: isDevelopmentDependency);
Expand All @@ -102,7 +103,7 @@ private void ProcessIndirectDependencies(ISingleFileComponentRecorder singleFile
foreach (var (name, version) in dependencies ?? Enumerable.Empty<KeyValuePair<string, string>>())
{
// Ignore "file:" and "link:" as these are local packages.
if (version.StartsWith(PnpmConstants.PnpmLinkDependencyPath) || version.StartsWith(PnpmConstants.PnpmFileDependencyPath))
if (this.IsFileOrLink(version))
{
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public PnpmComponentDetectorFactory(

public override IEnumerable<ComponentType> SupportedComponentTypes { get; } = [ComponentType.Npm];

public override int Version { get; } = 7;
public override int Version { get; } = 8;

public override bool NeedsAutomaticRootDependencyCalculation => true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,77 @@ public async Task TestPnpmDetector_V9_GoodLockVersion_HttpDependenciesAreNotRegi
parentComponent => parentComponent.Name == "sampleDependency");
}

[TestMethod]
public async Task TestPnpmDetector_V9_GoodLockVersion_HttpsDependenciesAreNotRegistered()
{
var yamlFile = @"
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
sampleDependency:
specifier: ^1.1.1
version: 1.1.1
'@sample_dependency/sampleHttpDependency':
specifier: https://samplePackage/tar.gz/32f550d3b3bdb1b781aabe100683311cd982c98e
version: sample@https://samplePackage/tar.gz/32f550d3b3bdb1b781aabe100683311cd982c98e
SampleLinkDependency:
specifier: workspace:*
version: link:SampleLinkDependency
packages:
sampleDependency@1.1.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
sampleIndirectDependency2@2.2.2:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
sampleIndirectDependency@3.3.3:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
sample@https://samplePackage/tar.gz/32f550d3b3bdb1b781aabe100683311cd982c98e:
resolution: {tarball: https://samplePackage/tar.gz/32f550d3b3bdb1b781aabe100683311cd982c98e}
version: 1.3.3

snapshots:
sampleDependency@1.1.1:
dependencies:
sampleIndirectDependency: 3.3.3
sampleIndirectDependency2: 2.2.2
sampleIndirectDependency2@2.2.2: {}
sampleIndirectDependency@3.3.3: {}
sample@https://samplePackage/tar.gz/32f550d3b3bdb1b781aabe100683311cd982c98e': {}
";

var (scanResult, componentRecorder) = await this.DetectorTestUtility
.WithFile("pnpm-lock.yaml", yamlFile)
.ExecuteDetectorAsync();

scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);

var detectedComponents = componentRecorder.GetDetectedComponents();
detectedComponents.Should().HaveCount(3);
var npmComponents = detectedComponents.Select(x => new { Component = x.Component as NpmComponent, DetectedComponent = x });
npmComponents.Should().Contain(x => x.Component.Name == "sampleDependency" && x.Component.Version == "1.1.1");
npmComponents.Should().Contain(x => x.Component.Name == "sampleIndirectDependency2" && x.Component.Version == "2.2.2");
npmComponents.Should().Contain(x => x.Component.Name == "sampleIndirectDependency" && x.Component.Version == "3.3.3");

var noDevDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleDependency");
var indirectDependencyComponent2 = npmComponents.First(x => x.Component.Name == "sampleIndirectDependency2");
var indirectDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleIndirectDependency");

componentRecorder.GetEffectiveDevDependencyValue(noDevDependencyComponent.Component.Id).Should().BeFalse();
componentRecorder.GetEffectiveDevDependencyValue(indirectDependencyComponent2.Component.Id).Should().BeFalse();
componentRecorder.GetEffectiveDevDependencyValue(indirectDependencyComponent.Component.Id).Should().BeFalse();
componentRecorder.AssertAllExplicitlyReferencedComponents<NpmComponent>(
indirectDependencyComponent.Component.Id,
parentComponent => parentComponent.Name == "sampleDependency");
componentRecorder.AssertAllExplicitlyReferencedComponents<NpmComponent>(
indirectDependencyComponent2.Component.Id,
parentComponent => parentComponent.Name == "sampleDependency");
}

[TestMethod]
public async Task TestPnpmDetector_V9_GoodLockVersion_MissingSnapshotsSuccess()
{
Expand Down
Loading