Skip to content

Commit d7074b9

Browse files
authored
fix: adding support for .csproj as root when manifest is custom file (#12)
1 parent 838877b commit d7074b9

File tree

5 files changed

+300
-4
lines changed

5 files changed

+300
-4
lines changed

lib/dependency.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
var debug = require('debug')('snyk');
2+
13
function Dependency(name, version) {
24
this.name = name;
35
this.version = version;
@@ -24,6 +26,7 @@ Dependency.extractFromDotVersionNotation = function (expression) {
2426

2527
Dependency.from = {
2628
folderName: function (folderName) {
29+
debug('Extracting by folder name ' + folderName);
2730
var info = Dependency.extractFromDotVersionNotation(folderName);
2831
var result = new Dependency(
2932
info.name,
@@ -32,13 +35,17 @@ Dependency.from = {
3235
return result;
3336
},
3437
packgesConfigEntry: function (manifest) {
38+
debug('Extracting by packages.config entry:' +
39+
' name = ' + manifest.$.id +
40+
' version = ' + manifest.$.version);
3541
var result = new Dependency(
3642
manifest.$.id,
3743
manifest.$.version);
3844
result.versionSpec = manifest.$.version;
3945
return result;
4046
},
4147
csprojEntry: function (referenceItem) {
48+
debug('Extracting by hintPath ' + referenceItem.HintPath[0]);
4249
var sep = (
4350
/\//.exec(referenceItem.HintPath[0]) ||
4451
/\\/.exec(referenceItem.HintPath[0]))[0];

lib/index.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var Dependecy = require('./dependency');
55
var findFolder = require('./find-folder');
66
var path = require('path');
77
var parseNuspec = require('./nuspec-parser');
8+
var jsonManifestParest = require('./json-manifest-parser');
89
var debug = require('debug')('snyk');
910

1011
function determineManifestType (filename) {
@@ -43,6 +44,7 @@ module.exports = {
4344
try {
4445
manifestType = determineManifestType(path.basename(targetFile || root));
4546
fileContent = fs.readFileSync(targetFile).toString();
47+
debug('Loaded ' + targetFile + ' with manifest type ' + manifestType);
4648
}
4749
catch (error) {
4850
return Promise.reject(error);
@@ -66,8 +68,10 @@ module.exports = {
6668
var installedPackages = [];
6769
switch (manifestType) {
6870
case 'project.json': {
69-
debug('Trying to parse project.json manifest');
70-
var rawDependencies = JSON.parse(fileContent).dependencies;
71+
debug('Trying to parse project.json format manifest');
72+
var projectData = jsonManifestParest.parse(fileContent);
73+
var rawDependencies = projectData.dependencies;
74+
debug(rawDependencies);
7175
if (rawDependencies) {
7276
for (var name in rawDependencies) {
7377
// Array<{ "libraryName": "version" }>
@@ -78,6 +82,10 @@ module.exports = {
7882
}
7983
}
8084
}
85+
if (projectData.project) {
86+
packageTree.package.name = projectData.project.name;
87+
packageTree.package.version = projectData.project.version;
88+
}
8189
resolve(installedPackages);
8290
break;
8391
}

lib/json-manifest-parser.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
function scanForDependencies(obj, deps) {
2+
deps = deps || {};
3+
if (typeof obj !== 'object') {
4+
return deps;
5+
}
6+
Object.keys(obj).forEach(function (key) {
7+
if (key === 'dependencies') {
8+
var dependencies = obj.dependencies;
9+
Object.keys(dependencies).forEach(function (key) {
10+
var depName = key;
11+
var version = dependencies[key];
12+
if (typeof version === 'object') {
13+
version = version.version;
14+
}
15+
if (typeof version === 'undefined') {
16+
version = 'unknown';
17+
} else {
18+
version = version.toString();
19+
}
20+
deps[depName] = version;
21+
})
22+
} else {
23+
scanForDependencies(obj[key], deps);
24+
}
25+
});
26+
return deps;
27+
}
28+
29+
module.exports = {
30+
parse: function parseJsonManifest(fileContent) {
31+
var rawContent = JSON.parse(fileContent);
32+
var result = {};
33+
result.dependencies = scanForDependencies(rawContent, {});
34+
if (typeof rawContent.project === 'object') {
35+
var pData = rawContent.project
36+
var name = (pData.restore && pData.restore.projectName)
37+
result.project = {
38+
version: pData.version || '0.0.0',
39+
};
40+
if (name) {
41+
result.project.name = name;
42+
}
43+
}
44+
return result;
45+
},
46+
};

test/parse-with-traverse.test.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,42 @@ var alternatePackagesFolder =
99
stubProjectLocation + 'alternate_packages';
1010
var targetCSProjFile =
1111
stubProjectLocation + 'dummy_project_1/WebApplication1.csproj';
12+
var targetJSONManifest =
13+
'./test/stubs/_2_project.json';
14+
var targetJSONManifestData =
15+
require('./stubs/_2_project.json');
16+
17+
18+
test('parse assets.project.json and traverse packages', function (t) {
19+
var expectedTreeFile =
20+
fs.readFileSync(
21+
stubProjectLocation + 'dummy_project_1/expected_csproj.json');
22+
var expectedTree = JSON.parse(expectedTreeFile.toString());
23+
// NUnit can be referenced in .nuspec files.
24+
// In this test the manifest file has no NUnit reference,
25+
// therefor it is not expected to be in the result.
26+
delete expectedTree.package.dependencies.NUnit;
27+
plugin.inspect(stubProjectLocation, targetJSONManifest, {
28+
packagesFolder: stubProjectLocation + '/packages',
29+
}).then(function (result) {
30+
// In case project details are included in manifest file,
31+
// it's expected to be included in the 'package' section
32+
t.equal(
33+
result.package.name,
34+
targetJSONManifestData.project.restore.projectName,
35+
'expects extraction of project\'s name from manifest');
36+
t.equal(
37+
result.package.version,
38+
targetJSONManifestData.project.version,
39+
'expects extraction of project\'s version from manifest');
40+
t.deepEqual(
41+
result.package.dependencies,
42+
expectedTree.package.dependencies,
43+
'expects dependency tree to be correct');
44+
t.ok(result.plugin);
45+
t.end();
46+
});
47+
});
1248

1349

1450
test('parse .csproj and traverse packages', function (t) {
@@ -22,8 +58,13 @@ test('parse .csproj and traverse packages', function (t) {
2258
t.test('traversing', function (t) {
2359
t.deepEqual(
2460
result.package.dependencies,
25-
expectedTree.package.dependencies);
26-
t.ok(result.plugin);
61+
expectedTree.package.dependencies,
62+
'expects dependency tree to be correct');
63+
t.ok(result.plugin, 'plugin details exists in result');
64+
t.equal(result.plugin.name, 'snyk-nuget-plugin',
65+
'plugin\'s name is snyk-nuget-plugin');
66+
t.equal(result.plugin.targetFile, targetCSProjFile,
67+
'plugin shows correct targetFile');
2768
t.end();
2869
})
2970
return result;

test/stubs/_2_project.json

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
{
2+
"version": 3,
3+
"targets": {
4+
"Target_1": {
5+
"Microsoft.NETCore.App/2.0.0": {
6+
"type": "package",
7+
"dependencies": {
8+
"Antlr": "3.4.1.9004",
9+
"bootstrap": "3.0.0",
10+
"EntityFramework": "6.1.3",
11+
"jQuery": "1.10.2",
12+
"Knockout.Validation": "1.0.1",
13+
"knockoutjs": "2.3.0",
14+
"Microsoft.ApplicationInsights": "2.2.0",
15+
"Microsoft.ApplicationInsights.Agent.Intercept": "2.0.6",
16+
"Microsoft.ApplicationInsights.DependencyCollector": "2.2.0",
17+
"Microsoft.ApplicationInsights.PerfCounterCollector": "2.2.0",
18+
"Microsoft.ApplicationInsights.Web": "2.2.0",
19+
"Microsoft.ApplicationInsights.WindowsServer": "2.2.0",
20+
"Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel": "2.2.0",
21+
"Microsoft.AspNet.Identity.Core": "2.2.1",
22+
"Microsoft.AspNet.Identity.EntityFramework": "2.2.1",
23+
"Microsoft.AspNet.Identity.Owin": "2.2.1",
24+
"Microsoft.AspNet.Mvc": "5.2.3",
25+
"Microsoft.AspNet.Razor": "3.2.3",
26+
"Microsoft.AspNet.Web.Optimization": "1.1.3",
27+
"Microsoft.AspNet.WebApi": "5.2.3",
28+
"Microsoft.AspNet.WebApi.Client": "5.2.3",
29+
"Microsoft.AspNet.WebApi.Core": "5.2.3",
30+
"Microsoft.AspNet.WebApi.HelpPage": "5.2.3",
31+
"Microsoft.AspNet.WebApi.Owin": "5.2.3",
32+
"Microsoft.AspNet.WebApi.WebHost": "5.2.3",
33+
"Microsoft.AspNet.WebPages": "3.2.3",
34+
"Microsoft.CodeAnalysis.Analyzers": "1.1.0",
35+
"Microsoft.CodeAnalysis.Common": "1.3.2",
36+
"Microsoft.CodeAnalysis.CSharp": "1.3.2",
37+
"Microsoft.CodeDom.Providers.DotNetCompilerPlatform": "1.0.5",
38+
"Microsoft.Net.Compilers": "2.1.0",
39+
"Microsoft.Orleans.Core": "1.4.0",
40+
"Microsoft.Orleans.OrleansCodeGenerator": "1.4.0",
41+
"Microsoft.Owin": "3.0.1",
42+
"Microsoft.Owin.Host.SystemWeb": "3.0.1",
43+
"Microsoft.Owin.Security": "3.0.1",
44+
"Microsoft.Owin.Security.Cookies": "3.0.1",
45+
"Microsoft.Owin.Security.Facebook": "3.0.1",
46+
"Microsoft.Owin.Security.Google": "3.0.1",
47+
"Microsoft.Owin.Security.MicrosoftAccount": "3.0.1",
48+
"Microsoft.Owin.Security.OAuth": "3.0.1",
49+
"Microsoft.Owin.Security.Twitter": "3.0.1",
50+
"Microsoft.Web.Infrastructure": "1.0.0.0",
51+
"Modernizr": "2.6.2",
52+
"Newtonsoft.Json": "10.0.3",
53+
"Owin": "1.0",
54+
"Respond": "1.2.0",
55+
"Sammy.js": "0.7.4",
56+
"System.AppContext": "4.1.0",
57+
"System.Collections": "4.0.11",
58+
"System.Collections.Concurrent": "4.0.12",
59+
"System.Collections.Immutable": "1.2.0",
60+
"System.Console": "4.0.0",
61+
"System.Diagnostics.Debug": "4.0.11",
62+
"System.Diagnostics.FileVersionInfo": "4.0.0",
63+
"System.Diagnostics.StackTrace": "4.0.1",
64+
"System.Diagnostics.Tools": "4.0.1",
65+
"System.Dynamic.Runtime": "4.0.11",
66+
"System.Globalization": "4.0.11",
67+
"System.IO.FileSystem": "4.0.1",
68+
"System.IO.FileSystem.Primitives": "4.0.1",
69+
"System.Linq": "4.1.0",
70+
"System.Linq.Expressions": "4.1.0",
71+
"System.Reflection": "4.1.0",
72+
"System.Reflection.Metadata": "1.3.0",
73+
"System.Reflection.Primitives": "4.0.1",
74+
"System.Resources.ResourceManager": "4.0.1",
75+
"System.Runtime": "4.1.0",
76+
"System.Runtime.Extensions": "4.1.0",
77+
"System.Runtime.Handles": "4.0.1",
78+
"System.Runtime.InteropServices": "4.1.0",
79+
"System.Runtime.Numerics": "4.0.1",
80+
"System.Security.Cryptography.Algorithms": "4.2.0",
81+
"System.Security.Cryptography.Encoding": "4.0.0",
82+
"System.Security.Cryptography.Primitives": "4.0.0",
83+
"System.Security.Cryptography.X509Certificates": "4.1.0",
84+
"System.Text.Encoding": "4.0.11",
85+
"System.Text.Encoding.CodePages": "4.0.1"
86+
},
87+
"compile": {
88+
"ignored": "ignored"
89+
},
90+
"build": {
91+
"ignored": "ignored"
92+
}
93+
}
94+
},
95+
"Target_2": {
96+
"Microsoft.NETCore.App/2.0.0": {
97+
"type": "package",
98+
"dependencies": {
99+
"System.Text.Encoding.Extensions": "4.0.11",
100+
"System.Threading": "4.0.11",
101+
"System.Threading.Tasks": "4.0.11",
102+
"System.Threading.Tasks.Parallel": "4.0.1",
103+
"System.Threading.Thread": "4.0.0",
104+
"System.Xml.ReaderWriter": "4.0.11",
105+
"System.Xml.XDocument": "4.0.11",
106+
"System.Xml.XmlDocument": "4.0.1",
107+
"System.Xml.XPath": "4.0.1",
108+
"System.Xml.XPath.XDocument": "4.0.1",
109+
"WebGrease": "1.5.2"
110+
},
111+
"compile": {
112+
"ignored": "ignored"
113+
},
114+
"build": {
115+
"ignored": "ignored"
116+
}
117+
},
118+
"NETStandard.Library/2.0.0": {
119+
"type": "package",
120+
"dependencies": {
121+
"System.Xml.XDocument": "4.0.11",
122+
"System.Xml.XmlDocument": "4.0.1",
123+
"System.Xml.XPath": "4.0.1",
124+
"System.Xml.XPath.XDocument": "4.0.1",
125+
"WebGrease": "1.5.2"
126+
},
127+
"compile": {
128+
"ignored": "ignored"
129+
},
130+
"runtime": {
131+
"ignored": "ignored"
132+
},
133+
"build": {
134+
"ignored": "ignored"
135+
}
136+
}
137+
}
138+
},
139+
"projectFileDependencyGroups": {
140+
"NOTE_TO_DEVELOPERS": "This is for the resolver",
141+
".NETCoreApp,Version=v2.0": [
142+
"Microsoft.NETCore.App >= 2.0.0"
143+
]
144+
},
145+
"packageFolders": {
146+
"/path/to/.nuget/packages/": {}
147+
},
148+
"project": {
149+
"NOTE_TO_DEVELOPERS": "This could be a source of data to add to the snyk manifest",
150+
"version": "1.0.0",
151+
"restore": {
152+
"projectUniqueName": "/path/to/project/testapp.csproj",
153+
"projectName": "project-name",
154+
"projectPath": "/path/to/project/project-manifest.csproj",
155+
"packagesPath": "/path/to/packages",
156+
"outputPath": "/path/to/project/obj",
157+
"projectStyle": "PackageReference",
158+
"configFilePaths": [
159+
"/path/to/nuget/.config/NuGet/NuGet.Config"
160+
],
161+
"originalTargetFrameworks": [
162+
"netcoreapp2.0"
163+
],
164+
"sources": {
165+
"https://api.nuget.org/v3/index.json": {}
166+
},
167+
"frameworks": {
168+
"netcoreapp2.0": {
169+
"projectReferences": {}
170+
}
171+
},
172+
"warningProperties": {
173+
"warnAsError": [
174+
"NU1605"
175+
]
176+
}
177+
},
178+
"frameworks": {
179+
"NOTE_TO_DEVELOPERS": "We may want to include these as dependencies",
180+
"netcoreapp2.0": {
181+
"dependencies": {
182+
},
183+
"imports": [
184+
"net461"
185+
],
186+
"assetTargetFallback": true,
187+
"warn": true
188+
}
189+
},
190+
"runtimes": {
191+
"ignored": "ignored"
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)