Skip to content

Commit

Permalink
adding packages.props and Directory.packages.props parser (#268)
Browse files Browse the repository at this point in the history
Co-authored-by: DmitriyLewen <[email protected]>
  • Loading branch information
yuriShafet and DmitriyLewen authored Nov 15, 2023
1 parent d61bf8b commit 89e3bab
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 0 deletions.
85 changes: 85 additions & 0 deletions pkg/nuget/packagesprops/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package packagesprops

import (
"encoding/xml"
"strings"

"golang.org/x/xerrors"

dio "github.com/aquasecurity/go-dep-parser/pkg/io"
"github.com/aquasecurity/go-dep-parser/pkg/types"
"github.com/aquasecurity/go-dep-parser/pkg/utils"
)

type pkg struct {
Version string `xml:"Version,attr"`
UpdatePackageName string `xml:"Update,attr"`
IncludePackageName string `xml:"Include,attr"`
}

// https://github.com/dotnet/roslyn-tools/blob/b4c5220f5dfc4278847b6d38eff91cc1188f8066/src/RoslynInsertionTool/RoslynInsertionTool/CoreXT.cs#L150
type itemGroup struct {
PackageReferenceEntry []pkg `xml:"PackageReference"`
PackageVersionEntry []pkg `xml:"PackageVersion"`
}

type project struct {
XMLName xml.Name `xml:"Project"`
ItemGroups []itemGroup `xml:"ItemGroup"`
}

type Parser struct{}

func NewParser() types.Parser {
return &Parser{}
}

func (p pkg) library() types.Library {
// Update attribute is considered legacy, so preferring Include
name := p.UpdatePackageName
if p.IncludePackageName != "" {
name = p.IncludePackageName
}

name = strings.TrimSpace(name)
version := strings.TrimSpace(p.Version)
return types.Library{
ID: utils.PackageID(name, version),
Name: name,
Version: version,
}
}

func shouldSkipLib(lib types.Library) bool {
if len(lib.Name) == 0 || len(lib.Version) == 0 {
return true
}
// *packages.props files don't contain variable resolution information.
// So we need to skip them.
if isVariable(lib.Name) || isVariable(lib.Version) {
return true
}
return false
}

func isVariable(s string) bool {
return strings.HasPrefix(s, "$(") && strings.HasSuffix(s, ")")
}

func (p *Parser) Parse(r dio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
var configData project
if err := xml.NewDecoder(r).Decode(&configData); err != nil {
return nil, nil, xerrors.Errorf("failed to decode '*.packages.props' file: %w", err)
}

var libs []types.Library
for _, item := range configData.ItemGroups {
for _, pkg := range append(item.PackageReferenceEntry, item.PackageVersionEntry...) {
lib := pkg.library()
if !shouldSkipLib(lib) {
libs = append(libs, lib)
}
}
}
return utils.UniqueLibraries(libs), nil, nil
}
82 changes: 82 additions & 0 deletions pkg/nuget/packagesprops/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package packagesprops_test

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

config "github.com/aquasecurity/go-dep-parser/pkg/nuget/packagesprops"
"github.com/aquasecurity/go-dep-parser/pkg/types"
)

func TestParse(t *testing.T) {
tests := []struct {
name string // Test input file
inputFile string
want []types.Library
wantErr string
}{
{
name: "PackagesProps",
inputFile: "testdata/packages.props",
want: []types.Library{
{Name: "Microsoft.Extensions.Configuration", Version: "2.1.1", ID: "[email protected]"},
{Name: "Microsoft.Extensions.DependencyInjection.Abstractions", Version: "2.2.1", ID: "[email protected]"},
{Name: "Microsoft.Extensions.Http", Version: "3.2.1", ID: "[email protected]"},
},
},
{
name: "DirectoryPackagesProps",
inputFile: "testdata/Directory.Packages.props",
want: []types.Library{
{Name: "PackageOne", Version: "6.2.3", ID: "[email protected]"},
{Name: "PackageThree", Version: "2.4.1", ID: "[email protected]"},
{Name: "PackageTwo", Version: "6.0.0", ID: "[email protected]"},
},
},
{
name: "SeveralItemGroupElements",
inputFile: "testdata/several_item_groups",
want: []types.Library{
{Name: "PackageOne", Version: "6.2.3", ID: "[email protected]"},
{Name: "PackageThree", Version: "2.4.1", ID: "[email protected]"},
{Name: "PackageTwo", Version: "6.0.0", ID: "[email protected]"},
},
},
{
name: "VariablesAsNamesOrVersion",
inputFile: "testdata/variables_and_empty",
want: []types.Library{
{Name: "PackageFour", Version: "2.4.1", ID: "[email protected]"},
},
},
{
name: "NoItemGroupInXMLStructure",
inputFile: "testdata/no_item_group.props",
want: []types.Library(nil),
},
{
name: "NoProject",
inputFile: "testdata/no_project.props",
wantErr: "failed to decode '*.packages.props' file",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := os.Open(tt.inputFile)
require.NoError(t, err)

got, _, err := config.NewParser().Parse(f)
if tt.wantErr != "" {
require.NotNil(t, err)
assert.Contains(t, err.Error(), tt.wantErr)
return
}

assert.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
7 changes: 7 additions & 0 deletions pkg/nuget/packagesprops/testdata/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project>
<ItemGroup>
<PackageReference Include="PackageOne" Version=" 6.2.3" />
<PackageReference Include="PackageTwo" Version="6.0.0" />
<PackageReference Include="PackageThree " Version="2.4.1" />
</ItemGroup>
</Project>
11 changes: 11 additions & 0 deletions pkg/nuget/packagesprops/testdata/no_item_group.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PackageReference Update="Microsoft.Extensions.Configuration" Version="2.1.1" />
<PackageReference Update="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.1" />
<PackageReference Update="Microsoft.Extensions.Http" Version="3.2.1" />
<PackageReference WrongAttribute="Package1" Version="3.2.1" />
<WrongEntry Update="Package2" Version="3.2.1" />
<PackageReference Update="Package3" />

</Project>
10 changes: 10 additions & 0 deletions pkg/nuget/packagesprops/testdata/no_project.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>

<ItemGroup Label="Microsoft Nugets">
<PackageReference Update="Microsoft.Extensions.Configuration" Version="2.1.1" />
<PackageReference Update="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.1" />
<PackageReference Update="Microsoft.Extensions.Http" Version="3.2.1" />
<PackageReference WrongAttribute="Package1" Version="3.2.1" />
<WrongEntry Update="Package2" Version="3.2.1" />
<PackageReference Update="Package3" />
</ItemGroup>
11 changes: 11 additions & 0 deletions pkg/nuget/packagesprops/testdata/packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="Microsoft Nugets">
<PackageReference Update="Microsoft.Extensions.Configuration" Version="2.1.1" />
<PackageReference Update="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.1" />
<PackageReference Update="Microsoft.Extensions.Http" Version="3.2.1" />
<PackageReference WrongAttribute="Package1" Version="3.2.1" />
<WrongEntry Update="Package2" Version="3.2.1" />
<PackageReference Update="Package3" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions pkg/nuget/packagesprops/testdata/several_item_groups
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project>
<ItemGroup>
<PackageReference Include="PackageOne" Version="6.2.3" />
<PackageReference Include="PackageTwo" Version="6.0.0" />

</ItemGroup>
<ItemGroup>
<PackageReference Include="PackageThree" Version="2.4.1" />
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions pkg/nuget/packagesprops/testdata/variables_and_empty
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>
<ItemGroup>
<PackageReference Include="PackageOne" Version="$(Variable1)" />
<PackageReference Include="$(variable2)" Version="6.0.0" />
<PackageReference Include="" Version="2.4.1" />
<PackageReference Include="package" Version="" />
<PackageReference Include="PackageFour" Version="2.4.1" />
</ItemGroup>
</Project>

0 comments on commit 89e3bab

Please sign in to comment.