Skip to content

Commit 46e8e80

Browse files
authored
Fixed pnpm detector failing parsing link dependencies (#129)
When the detector found a link dependency it failed the detection and the rest of components where not scanned. This change ignore the link dependencies and allow the dectector to continue parsing the rest of the file.
1 parent c5c4f9d commit 46e8e80

3 files changed

Lines changed: 71 additions & 3 deletions

File tree

docs/detectors/pnpm.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Pnpm detection
2+
3+
## Known limitations
4+
5+
The Pnpm detector doesn't support the resolution of local dependencies
6+
like:
7+
8+
- Link dependencies
9+
```
10+
dependencies:
11+
'@learningclient/common': link:../common
12+
```
13+
14+
- File dependencies
15+
```
16+
dependencies:
17+
file:./projects/gmc-bootstrapper.tgz
18+
```
19+
These kind of components are ignored by the Pnpm detector.
20+
21+
In the case of `link` dependencies that refer to a folder with a `package.json` file
22+
the component is then going to be detected by the `NpmComponentDetector`. This is going to happen
23+
only if the folder is inside the path that is been use for scanning.

src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmComponentDetector.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class PnpmComponentDetector : FileComponentDetector
2020

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

23-
public override int Version { get; } = 4;
23+
public override int Version { get; } = 5;
2424

2525
/// <inheritdoc />
2626
protected override IList<string> SkippedFolders => new List<string> { "node_modules", "pnpm-store" };
@@ -72,8 +72,8 @@ private void RecordDependencyGraphFromFile(PnpmYaml yaml, ISingleFileComponentRe
7272
{
7373
foreach (var dependency in packageKeyValue.Value.dependencies)
7474
{
75-
// Ignore file: as these are local packages.
76-
if (dependency.Key.StartsWith("file:"))
75+
// Ignore local packages.
76+
if (IsLocalDependency(dependency))
7777
{
7878
continue;
7979
}
@@ -98,6 +98,13 @@ private void RecordDependencyGraphFromFile(PnpmYaml yaml, ISingleFileComponentRe
9898
}
9999
}
100100

101+
private bool IsLocalDependency(KeyValuePair<string, string> dependency)
102+
{
103+
// Local dependencies are dependencies that live in the file system
104+
// this requires an extra parsing that is not supported yet
105+
return dependency.Key.StartsWith("file:") || dependency.Value.StartsWith("file:") || dependency.Value.StartsWith("link:");
106+
}
107+
101108
private string CreatePnpmPackagePathFromDependency(string dependencyName, string dependencyVersion)
102109
{
103110
return dependencyVersion.Contains('/') ? dependencyVersion : $"/{dependencyName}/{dependencyVersion}";

test/Microsoft.ComponentDetection.Detectors.Tests/PnpmDetectorTests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,5 +350,43 @@ public async Task TestPnpmDetector_DependencyGraphIsCreated()
350350
var testDependencies = dependencyGraph.GetDependenciesForComponent(testComponentId);
351351
Assert.AreEqual(0, testDependencies.Count());
352352
}
353+
354+
[TestMethod]
355+
public async Task TestPnpmDetector_DependenciesRefeToLocalPaths_DependenciesAreIgnored()
356+
{
357+
var yamlFile = @"
358+
dependencies:
359+
'query-string': 4.3.4,
360+
'@rush-temp/file-annotation-bar': file:projects/file-annotation-bar.tgz_node-sass@4.14.1
361+
362+
packages:
363+
file:projects/file-annotation-bar.tgz_node-sass@4.14.1:
364+
resolution: {integrity: sha1-G7T22scAcvwxPoyc0UF7UHTAoSU=}
365+
/query-string/4.3.4:
366+
dependencies:
367+
'@learningclient/common': link:../common
368+
nth-check: 2.0.0
369+
/nth-check/2.0.0:
370+
resolution: {integrity: sha1-G7T22scAcvwxPoyc0UF7UHTAoSU=} ";
371+
372+
var (scanResult, componentRecorder) = await detectorTestUtility
373+
.WithFile("shrinkwrap1.yaml", yamlFile)
374+
.ExecuteDetector();
375+
376+
scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
377+
componentRecorder.GetDetectedComponents().Should().HaveCount(2, "Components that comes from a file (file:* or link:*) should be ignored.");
378+
379+
var queryStringComponentId = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/query-string/4.3.4").Component.Id;
380+
var nthcheck = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/nth-check/2.0.0").Component.Id;
381+
382+
var dependencyGraph = componentRecorder.GetDependencyGraphsByLocation().Values.First();
383+
384+
var queryStringDependencies = dependencyGraph.GetDependenciesForComponent(queryStringComponentId);
385+
queryStringDependencies.Should().HaveCount(1);
386+
queryStringDependencies.Should().Contain(nthcheck);
387+
388+
var nthCheckDependencies = dependencyGraph.GetDependenciesForComponent(nthcheck);
389+
nthCheckDependencies.Should().HaveCount(0);
390+
}
353391
}
354392
}

0 commit comments

Comments
 (0)