Skip to content

Commit 58a02e6

Browse files
Merge pull request #10 from BytesCraftIO/feature/csproj
added support for csproj parsing
2 parents f0403bd + ab1da6c commit 58a02e6

File tree

6 files changed

+222
-0
lines changed

6 files changed

+222
-0
lines changed

pkg/nuget/csproj/parse.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package csproj
2+
3+
import (
4+
"encoding/xml"
5+
"strings"
6+
7+
"golang.org/x/xerrors"
8+
9+
dio "github.com/aquasecurity/go-dep-parser/pkg/io"
10+
"github.com/aquasecurity/go-dep-parser/pkg/types"
11+
"github.com/aquasecurity/go-dep-parser/pkg/utils"
12+
)
13+
14+
type Parser struct{}
15+
16+
func NewParser() types.Parser {
17+
return &Parser{}
18+
}
19+
20+
func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
21+
var cfgData csProject
22+
if err := xml.NewDecoder(r).Decode(&cfgData); err != nil {
23+
return nil, nil, xerrors.Errorf("failed to decode .csproj file: %w", err)
24+
}
25+
26+
libs := make([]types.Library, 0)
27+
for _, pkg := range cfgData.Packages {
28+
if pkg.Include == "" || isDevDependency(pkg) {
29+
continue
30+
}
31+
32+
var versionNotFloating = strings.TrimRight(pkg.Version, ".*")
33+
34+
lib := types.Library{
35+
Name: pkg.Include,
36+
Version: versionNotFloating,
37+
}
38+
39+
libs = append(libs, lib)
40+
}
41+
42+
return utils.UniqueLibraries(libs), nil, nil
43+
}
44+
45+
func isDevDependency(pkg packageReference) bool {
46+
var privateAssets = tagOrAttribute(pkg.PrivateAssetsTag, pkg.PrivateAssetsAttr)
47+
var excludeAssets = tagOrAttribute(pkg.ExcludeAssetsTag, pkg.ExcludeAssetsAttr)
48+
return assetListContains(privateAssets, "all") || assetListContains(excludeAssets, "all") || assetListContains(excludeAssets, "runtime")
49+
}
50+
51+
func assetListContains(assets []string, needle string) bool {
52+
for _, v := range assets {
53+
if strings.EqualFold(v, needle) {
54+
return true
55+
}
56+
}
57+
return false
58+
}
59+
60+
func tagOrAttribute(tag string, attr string) []string {
61+
var strvalue = ""
62+
if tag != "" {
63+
strvalue = tag
64+
} else {
65+
strvalue = attr
66+
}
67+
return strings.Split(strvalue, ";")
68+
}

pkg/nuget/csproj/parse_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package csproj_test
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/aquasecurity/go-dep-parser/pkg/nuget/csproj"
11+
"github.com/aquasecurity/go-dep-parser/pkg/types"
12+
)
13+
14+
func TestParse(t *testing.T) {
15+
tests := []struct {
16+
name string // Test input file
17+
inputFile string
18+
want []types.Library
19+
wantErr string
20+
}{
21+
{
22+
name: "csproj",
23+
inputFile: "testdata/packages.csproj",
24+
want: []types.Library{
25+
{Name: "Newtonsoft.Json", Version: "6.0.4"},
26+
{Name: "Microsoft.AspNet.WebApi", Version: "5.2.2"},
27+
{Name: "Floating.Version", Version: "1.2"},
28+
},
29+
},
30+
{
31+
name: "with development dependency",
32+
inputFile: "testdata/dev_dependency.csproj",
33+
want: []types.Library{
34+
{Name: "PrivateAssets.Tag.None", Version: "1.0.0"},
35+
{Name: "PrivateAssets.Conflicting.Tag.Attribute", Version: "1.0.0"},
36+
{Name: "ExcludeAssets.Tag.ContentFiles", Version: "1.0.0"},
37+
{Name: "ExcludeAssets.Tag.None", Version: "1.0.0"},
38+
{Name: "ExcludeAssets.Conflicting.Tag.Attribute", Version: "1.0.0"},
39+
{Name: "Newtonsoft.Json", Version: "8.0.3"},
40+
},
41+
},
42+
{
43+
name: "sad path",
44+
inputFile: "testdata/malformed_xml.csproj",
45+
wantErr: "failed to decode .csproj file: XML syntax error on line 10: unexpected EOF",
46+
},
47+
}
48+
for _, tt := range tests {
49+
t.Run(tt.name, func(t *testing.T) {
50+
f, err := os.Open(tt.inputFile)
51+
require.NoError(t, err)
52+
53+
got, _, err := csproj.NewParser().Parse(f)
54+
if tt.wantErr != "" {
55+
require.NotNil(t, err)
56+
assert.ErrorContains(t, err, tt.wantErr)
57+
return
58+
}
59+
60+
assert.NoError(t, err)
61+
assert.ElementsMatch(t, tt.want, got)
62+
})
63+
}
64+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<TargetFramework>net46</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<!-- PrivateAssets=all indicates a development dependency, and we exclude those -->
8+
<PackageReference Include="PrivateAssets.Tag.All" Version="1.0.0">
9+
<PrivateAssets>all</PrivateAssets>
10+
</PackageReference>
11+
<PackageReference Include="PrivateAssets.Tag.None" Version="1.0.0">
12+
<PrivateAssets>none</PrivateAssets>
13+
</PackageReference>
14+
<PackageReference Include="PrivateAssets.Attribute.All" Version="1.0.0" PrivateAssets="All" />
15+
<PackageReference Include="PrivateAssets.Conflicting.Tag.Attribute" Version="1.0.0"
16+
PrivateAssets="All">
17+
<PrivateAssets>None</PrivateAssets>
18+
</PackageReference>
19+
20+
<!-- ExcludeAssets=all / runtime indicates a compile-time dependency, and we exclude those -->
21+
<PackageReference Include="ExcludeAssets.Tag.All" Version="1.0.0">
22+
<ExcludeAssets>all</ExcludeAssets>
23+
</PackageReference>
24+
<PackageReference Include="ExcludeAssets.Tag.Runtime" Version="1.0.0">
25+
<ExcludeAssets>runtime</ExcludeAssets>
26+
</PackageReference>
27+
<PackageReference Include="ExcludeAssets.Tag.RuntimeAndMore" Version="1.0.0">
28+
<ExcludeAssets>contentFiles;runtime;native</ExcludeAssets>
29+
</PackageReference>
30+
<PackageReference Include="ExcludeAssets.Tag.ContentFiles" Version="1.0.0">
31+
<ExcludeAssets>contentFiles</ExcludeAssets>
32+
</PackageReference>
33+
<PackageReference Include="ExcludeAssets.Tag.None" Version="1.0.0">
34+
<ExcludeAssets>none</ExcludeAssets>
35+
</PackageReference>
36+
<PackageReference Include="ExcludeAssets.Attribute.All" Version="1.0.0" ExcludeAssets="All" />
37+
<PackageReference Include="ExcludeAssets.Conflicting.Tag.Attribute" Version="1.0.0"
38+
ExcludeAssets="All">
39+
<ExcludeAssets>None</ExcludeAssets>
40+
</PackageReference>
41+
42+
<!-- Normal dependency -->
43+
<PackageReference Include="Newtonsoft.Json" Version="8.0.3" />
44+
</ItemGroup>
45+
</Project>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<TargetFramework>net46</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="Microsoft.Net.Compilers" Version="1.0.0">
8+
<PrivateAssets>all</PrivateAssets>
9+
</PackageReference>
10+
<PackageReference Include="Newtonsoft.Json" Version="8.0.3" />
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<TargetFramework>net45</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<!-- other ItemGroup elements can lack PackageReference elements -->
8+
</ItemGroup>
9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.AspNet.WebApi" Version="5.2.2" />
11+
<PackageReference Include="Newtonsoft.Json" Version="6.0.4" />
12+
<PackageReference Include="Floating.Version" Version="1.2.*" />
13+
</ItemGroup>
14+
<ItemGroup>
15+
<!-- other ItemGroup elements can lack PackageReference elements -->
16+
</ItemGroup>
17+
</Project>

pkg/nuget/csproj/types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package csproj
2+
3+
import "encoding/xml"
4+
5+
type packageReference struct {
6+
XMLName xml.Name `xml:"PackageReference"`
7+
Version string `xml:"Version,attr"`
8+
Include string `xml:"Include,attr"`
9+
PrivateAssetsTag string `xml:"PrivateAssets"`
10+
PrivateAssetsAttr string `xml:"PrivateAssets,attr"`
11+
ExcludeAssetsTag string `xml:"ExcludeAssets"`
12+
ExcludeAssetsAttr string `xml:"ExcludeAssets,attr"`
13+
}
14+
15+
type csProject struct {
16+
XMLName xml.Name `xml:"Project"`
17+
Packages []packageReference `xml:"ItemGroup>PackageReference"`
18+
}

0 commit comments

Comments
 (0)