From 6954f7afac9de0e961b94b718f5aadc0a44a34ad Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 18 Sep 2024 16:35:35 +0600 Subject: [PATCH 01/16] test: add test --- pkg/dependency/parser/java/pom/parse_test.go | 37 ++++++++++++++++++ .../parent/pom.xml | 28 ++++++++++++++ .../pom.xml | 38 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 9fa97ffd3672..7e6c451a9f37 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1595,6 +1595,43 @@ func TestPom_Parse(t *testing.T) { }, }, }, + // [INFO] com.example:child-depManagement-in-parent:jar:1.0.0 + // [INFO] +- org.example:example-api:jar:1.0.1:compile + // [INFO] \- org.example:example-api2:jar:1.0.2:runtime + { + name: "dependency from parent uses version from child(scanned) pom depManagement", + inputFile: filepath.Join("testdata", "use-child-dep-management-in-parent", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:child-depManagement-in-parent:1.0.0", + Name: "com.example:child-depManagement-in-parent", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "org.example:example-api:1.0.1", + Name: "org.example:example-api", + Version: "1.0.1", + Relationship: ftypes.RelationshipDirect, // TODO change this!!! + }, + { + ID: "org.example:example-api2:1.0.2", + Name: "org.example:example-api2", + Version: "1.0.2", + Relationship: ftypes.RelationshipDirect, // TODO change this!!! + }, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:child-depManagement-in-parent:1.0.0", + DependsOn: []string{ + "org.example:example-api2:1.0.2", + "org.example:example-api:1.0.1", + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml new file mode 100644 index 000000000000..73e4de2814c7 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml @@ -0,0 +1,28 @@ + + + + 4.0.0 + + org.example + example-parent + 4.0.0 + pom + + + 4.0.1 + + + + + org.example + example-api + ${api.version} + compile + + + org.example + example-api2 + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml new file mode 100644 index 000000000000..0e9ac955a942 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml @@ -0,0 +1,38 @@ + + 4.0.0 + + + org.example + example-parent + 4.0.0 + ./parent/pom.xml + + + com.example + child-depManagement-in-parent + 1.0.0 + + + + 1.0.1 + 1.0.2 + + + + + + org.example + example-api + ${api.version} + runtime + + + org.example + example-api2 + ${api2.version} + runtime + + + + From 25da2945e1a447a67203747aa6130ec0ad7119ce Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 18 Sep 2024 16:35:44 +0600 Subject: [PATCH 02/16] fix(pom): fix version and scope resolve for root depManagement --- pkg/dependency/parser/java/pom/pom.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index 889d107c3c6c..f6a7622d5975 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -239,10 +239,10 @@ func (d pomDependency) Resolve(props map[string]string, depManagement, rootDepMa // If this dependency is managed in the root POM, // we need to overwrite fields according to the managed dependency. if managed, found := findDep(d.Name(), rootDepManagement); found { // dependencyManagement from the root POM - if managed.Version != "" { - dep.Version = evaluateVariable(managed.Version, props, nil) - } - if managed.Scope != "" { + // We always need to use version from root POM + dep.Version = evaluateVariable(managed.Version, props, nil) + + if managed.Scope == "" { dep.Scope = evaluateVariable(managed.Scope, props, nil) } if managed.Optional { From 8103758681389bc573739547b3e749d19a401986 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 18 Sep 2024 16:35:51 +0600 Subject: [PATCH 03/16] fix(parse): resolve depManagement of current pom for parent --- pkg/dependency/parser/java/pom/parse.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 76ca37f2dd05..37e67edfdee9 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -340,9 +340,15 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) // For better understanding see the following tests: // - `dependency from parent uses version from child pom depManagement` // - `dependency from parent uses version from root pom depManagement` + // - `dependency from parent uses version from scanned pom depManagement` // // depManagements from root pom has higher priority than depManagements from current pom. - depManagementForParent := lo.UniqBy(append(opts.depManagement, pom.content.DependencyManagement.Dependencies.Dependency...), + + var resolvedPomDepManagent []pomDependency + for _, dep := range pom.content.DependencyManagement.Dependencies.Dependency { + resolvedPomDepManagent = append(resolvedPomDepManagent, dep.Resolve(pom.content.Properties, nil, nil)) + } + depManagementForParent := lo.UniqBy(append(opts.depManagement, resolvedPomDepManagent...), func(dep pomDependency) string { return dep.Name() }) From e592bdb94e8b8513a833b57df14bc7250a2b2471 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 13:18:49 +0600 Subject: [PATCH 04/16] test: add scope tests --- pkg/dependency/parser/java/pom/parse_test.go | 308 ++++++++++++++++++ .../pom.xml | 29 ++ .../pom.xml | 64 ++++ .../parent/pom.xml | 65 ++++ .../pom.xml | 16 + .../example-nested-scope-compile-1.0.0.pom | 41 +++ .../1.0.0/parent/pom.xml | 21 ++ .../example-nested-scope-empty-1.0.0.pom | 40 +++ .../1.0.0/parent/pom.xml | 21 ++ .../example-nested-scope-runtime-1.0.0.pom | 41 +++ .../1.0.0/parent/pom.xml | 21 ++ .../2.0.0/example-scope-compile-2.0.0.pom | 23 ++ .../2.0.0/example-scope-empty-2.0.0.pom | 22 ++ .../2.0.0/example-scope-runtime-2.0.0.pom | 23 ++ 14 files changed, 735 insertions(+) create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom create mode 100644 pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 7e6c451a9f37..dd5d96a2e6d3 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -14,6 +14,100 @@ import ( ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ) +var ( + exampleNestedScopeCompile = func(start, end int) ftypes.Package { + var location ftypes.Locations + if start != 0 && end != 0 { + location = append(location, ftypes.Location{ + StartLine: start, + EndLine: end, + }) + } + return ftypes.Package{ + ID: "org.example:example-nested-scope-compile:1.0.0", + Name: "org.example:example-nested-scope-compile", + Version: "1.0.0", + Relationship: ftypes.RelationshipDirect, + Locations: location, + } + } + + exampleNestedScopeEmpty = func(start, end int) ftypes.Package { + var location ftypes.Locations + if start != 0 && end != 0 { + location = append(location, ftypes.Location{ + StartLine: start, + EndLine: end, + }) + } + return ftypes.Package{ + ID: "org.example:example-nested-scope-empty:1.0.0", + Name: "org.example:example-nested-scope-empty", + Version: "1.0.0", + Relationship: ftypes.RelationshipDirect, + Locations: location, + } + } + + exampleNestedScopeRuntime = func(start, end int) ftypes.Package { + var location ftypes.Locations + if start != 0 && end != 0 { + location = append(location, ftypes.Location{ + StartLine: start, + EndLine: end, + }) + } + return ftypes.Package{ + ID: "org.example:example-nested-scope-runtime:1.0.0", + Name: "org.example:example-nested-scope-runtime", + Version: "1.0.0", + Relationship: ftypes.RelationshipDirect, + Locations: location, + } + } + + exampleScopeCompile = ftypes.Package{ + ID: "org.example:example-scope-compile:2.0.0", + Name: "org.example:example-scope-compile", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleScopeEmpty = ftypes.Package{ + ID: "org.example:example-scope-empty:2.0.0", + Name: "org.example:example-scope-empty", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleScopeRuntime = ftypes.Package{ + ID: "org.example:example-scope-runtime:2.0.0", + Name: "org.example:example-scope-runtime", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } + exampleApiCompile = ftypes.Package{ + ID: "org.example:example-api-compile:3.0.0", + Name: "org.example:example-api-compile", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleApiEmpty = ftypes.Package{ + ID: "org.example:example-api-empty:3.0.0", + Name: "org.example:example-api-empty", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } + + exampleApiRuntime = ftypes.Package{ + ID: "org.example:example-api-runtime:3.0.0", + Name: "org.example:example-api-runtime", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } +) + func TestPom_Parse(t *testing.T) { tests := []struct { name string @@ -1632,6 +1726,220 @@ func TestPom_Parse(t *testing.T) { }, }, }, + // [INFO] com.example:inherit-scopes-in-child-deps:jar:1.0.0 + // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:test + // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:runtime + // [INFO] \- org.example:example-api-empty:jar:3.0.0:test + // + // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes + { + name: "inherit scopes from child dependencies and their parents", + inputFile: filepath.Join("testdata", "inherit-scopes-from-child-deps-and-their-parents", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:inherit-scopes-from-child-deps-and-their-parents:0.0.1", + Name: "com.example:inherit-scopes-from-child-deps-and-their-parents", + Version: "0.0.1", + Relationship: ftypes.RelationshipRoot, + }, + exampleNestedScopeCompile(16, 21), + exampleNestedScopeEmpty(22, 26), + exampleNestedScopeRuntime(10, 15), + exampleApiCompile, + exampleApiEmpty, + exampleApiRuntime, + exampleScopeCompile, + exampleScopeEmpty, + exampleScopeRuntime, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:inherit-scopes-for-child-deps-and-parents:0.0.1", + DependsOn: []string{ + "org.example:example-nested-scope-compile:1.0.0", + "org.example:example-nested-scope-empty:1.0.0", + "org.example:example-nested-scope-runtime:1.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-compile:1.0.0", + DependsOn: []string{ + "org.example:example-scope-compile:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-empty:1.0.0", + DependsOn: []string{ + "org.example:example-scope-empty:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-runtime:1.0.0", + DependsOn: []string{ + "org.example:example-scope-runtime:2.0.0", + }, + }, + { + ID: "org.example:example-scope-compile:2.0.0", + DependsOn: []string{ + "org.example:example-api-compile:3.0.0", + }, + }, + { + ID: "org.example:example-scope-empty:2.0.0", + DependsOn: []string{ + "org.example:example-api-empty:3.0.0", + }, + }, + { + ID: "org.example:example-scope-runtime:2.0.0", + DependsOn: []string{ + "org.example:example-api-runtime:3.0.0", + }, + }, + }, + }, + // [INFO] com.example:inherit-scopes-in-children-from-root:jar:0.0.1 + // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime + // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:runtime + // [INFO] \- org.example:example-api-empty:jar:3.0.0:test + // + // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes + // scopes from `dependencyManagement` of root pom are used + { + name: "inherit scopes in children from root pom", + inputFile: filepath.Join("testdata", "inherit-scopes-in-children-from-root", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:inherit-scopes-in-children-from-root:0.0.1", + Name: "com.example:inherit-scopes-in-children-from-root", + Version: "0.0.1", + Relationship: ftypes.RelationshipRoot, + }, + exampleNestedScopeCompile(51, 56), + exampleNestedScopeEmpty(57, 61), + exampleNestedScopeRuntime(45, 50), + exampleApiRuntime, + exampleScopeCompile, + exampleScopeEmpty, + exampleScopeRuntime, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:inherit-scopes-for-child-deps-and-parents:0.0.1", + DependsOn: []string{ + "org.example:example-nested-scope-compile:1.0.0", + "org.example:example-nested-scope-empty:1.0.0", + "org.example:example-nested-scope-runtime:1.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-compile:1.0.0", + DependsOn: []string{ + "org.example:example-scope-compile:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-empty:1.0.0", + DependsOn: []string{ + "org.example:example-scope-empty:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-runtime:1.0.0", + DependsOn: []string{ + "org.example:example-scope-runtime:2.0.0", + }, + }, + { + ID: "org.example:example-scope-runtime:2.0.0", + DependsOn: []string{ + "org.example:example-api-runtime:3.0.0", + }, + }, + }, + }, + // [INFO] com.example:inherit-scopes-in-parents-of-children-from-root:jar:0.1.0 + // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime + // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:runtime + // [INFO] \- org.example:example-api-empty:jar:3.0.0:test + // + // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes + // scopes from `dependencyManagement` of root pom are used in parent dependencies + { + name: "inherit scopes in children from root pom", + inputFile: filepath.Join("testdata", "inherit-scopes-in-parents-of-children-from-root", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "com.example:inherit-scopes-in-parents-of-children-from-root:0.1.0", + Name: "com.example:inherit-scopes-in-parents-of-children-from-root", + Version: "0.1.0", + Relationship: ftypes.RelationshipRoot, + }, + exampleNestedScopeCompile(0, 0), + exampleNestedScopeEmpty(0, 0), + exampleNestedScopeRuntime(0, 0), + exampleApiRuntime, + exampleScopeCompile, + exampleScopeEmpty, + exampleScopeRuntime, + }, + wantDeps: []ftypes.Dependency{ + { + ID: "com.example:inherit-scopes-for-child-deps-and-parents:0.0.1", + DependsOn: []string{ + "org.example:example-nested-scope-compile:1.0.0", + "org.example:example-nested-scope-empty:1.0.0", + "org.example:example-nested-scope-runtime:1.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-compile:1.0.0", + DependsOn: []string{ + "org.example:example-scope-compile:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-empty:1.0.0", + DependsOn: []string{ + "org.example:example-scope-empty:2.0.0", + }, + }, + { + ID: "org.example:example-nested-scope-runtime:1.0.0", + DependsOn: []string{ + "org.example:example-scope-runtime:2.0.0", + }, + }, + { + ID: "org.example:example-scope-runtime:2.0.0", + DependsOn: []string{ + "org.example:example-api-runtime:3.0.0", + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml new file mode 100644 index 000000000000..17e6c55de090 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-from-child-deps-and-their-parents/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + + com.example + inherit-scopes-from-child-deps-and-their-parents + 0.0.1 + + + + org.example + example-nested-scope-runtime + 1.0.0 + runtime + + + org.example + example-nested-scope-compile + 1.0.0 + compile + + + org.example + example-nested-scope-empty + 1.0.0 + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml new file mode 100644 index 000000000000..26bdb25621d7 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-children-from-root/pom.xml @@ -0,0 +1,64 @@ + + 4.0.0 + + com.example + inherit-scopes-in-children-from-root + 0.0.1 + + + + + org.example + example-scope-runtime + 2.0.0 + compile + + + org.example + example-scope-compile + 2.0.0 + runtime + + + org.example + example-api-compile + 3.0.0 + test + + + org.example + example-scope-empty + 2.0.0 + runtime + + + org.example + example-api-empty + 3.0.0 + test + + + + + + + org.example + example-nested-scope-runtime + 1.0.0 + runtime + + + org.example + example-nested-scope-compile + 1.0.0 + compile + + + org.example + example-nested-scope-empty + 1.0.0 + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml new file mode 100644 index 000000000000..392737e8309c --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml @@ -0,0 +1,65 @@ + + 4.0.0 + + com.example + inherit-scopes-in-parents-of-children-from-root-parent + 0.0.1 + pom + + + + + org.example + example-scope-runtime + 2.0.0 + compile + + + org.example + example-scope-compile + 2.0.0 + runtime + + + org.example + example-api-compile + 3.0.0 + test + + + org.example + example-scope-empty + 2.0.0 + runtime + + + org.example + example-api-empty + 3.0.0 + test + + + + + + + org.example + example-nested-scope-runtime + 1.0.0 + runtime + + + org.example + example-nested-scope-compile + 1.0.0 + compile + + + org.example + example-nested-scope-empty + 1.0.0 + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml new file mode 100644 index 000000000000..13ae9686fb91 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml @@ -0,0 +1,16 @@ + + 4.0.0 + + com.example + inherit-scopes-in-parents-of-children-from-root + 0.1.0 + + + com.example + inherit-scopes-in-parents-of-children-from-root-parent + 0.0.1 + ./parent + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom new file mode 100644 index 000000000000..43ca478a88cd --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/example-nested-scope-compile-1.0.0.pom @@ -0,0 +1,41 @@ + + + + 4.0.0 + + + com.example + example-nested-parent-scope-compile + 1.0.1 + ./parent + + + org.example + example-nested-scope-compile + 1.0.0 + + jar + Example pom with example-scope-compile 2.0.0 + + + + + org.example + example-api-compile + 3.0.0 + runtime + + + + + + + org.example + example-scope-compile + 2.0.0 + compile + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml new file mode 100644 index 000000000000..5fe41b350df1 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-compile/1.0.0/parent/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + com.example + example-nested-parent-scope-compile + 1.0.1 + pom + + + + + org.example + example-scope-compile + 2.0.0 + test + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom new file mode 100644 index 000000000000..b1def2383f79 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/example-nested-scope-empty-1.0.0.pom @@ -0,0 +1,40 @@ + + + + 4.0.0 + + + com.example + example-nested-parent-scope-empty + 1.0.1 + ./parent + + + org.example + example-nested-scope-empty + 1.0.0 + + jar + Example pom with example-scope-empty 2.0.0 + + + + + org.example + example-api-empty + 3.0.0 + test + + + + + + + org.example + example-scope-empty + 2.0.0 + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml new file mode 100644 index 000000000000..6ca0232f4fc3 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-empty/1.0.0/parent/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + com.example + example-nested-parent-scope-empty + 1.0.1 + pom + + + + + org.example + example-scope-empty + 2.0.0 + compile + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom new file mode 100644 index 000000000000..8e48dcd812c3 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/example-nested-scope-runtime-1.0.0.pom @@ -0,0 +1,41 @@ + + + + 4.0.0 + + + com.example + example-nested-parent-scope-runtime + 1.0.1 + ./parent + + + org.example + example-nested-scope-runtime + 1.0.0 + + jar + Example pom with example-scope-runtime 2.0.0 + + + + + org.example + example-api-runtime + 3.0.0 + test + + + + + + + org.example + example-scope-runtime + 2.0.0 + runtime + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml new file mode 100644 index 000000000000..f59df7902390 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-nested-scope-runtime/1.0.0/parent/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + com.example + example-nested-parent-scope-runtime + 1.0.1 + pom + + + + + org.example + example-scope-runtime + 2.0.0 + test + + + + + diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom new file mode 100644 index 000000000000..1d5bc02ff3b9 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-compile/2.0.0/example-scope-compile-2.0.0.pom @@ -0,0 +1,23 @@ + + + + 4.0.0 + + org.example + example-scope-compile + 2.0.0 + + jar + Example pom with example-api-compile 3.0.0 + + + + org.example + example-api-compile + 3.0.0 + compile + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom new file mode 100644 index 000000000000..82ce31008fc3 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-empty/2.0.0/example-scope-empty-2.0.0.pom @@ -0,0 +1,22 @@ + + + + 4.0.0 + + org.example + example-scope-empty + 2.0.0 + + jar + Example pom with example-api-empty 3.0.0 + + + + org.example + example-api-empty + 3.0.0 + + + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom new file mode 100644 index 000000000000..90bf973def80 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/repository/org/example/example-scope-runtime/2.0.0/example-scope-runtime-2.0.0.pom @@ -0,0 +1,23 @@ + + + + 4.0.0 + + org.example + example-scope-runtime + 2.0.0 + + jar + Example pom with example-api-runtime 3.0.0 + + + + org.example + example-api-runtime + 3.0.0 + runtime + + + \ No newline at end of file From abe23c91f7859d59b1ec69b531e8242df4488dcd Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 13:21:00 +0600 Subject: [PATCH 05/16] test: refactor inherit-scopes-in-parents-from-root test --- pkg/dependency/parser/java/pom/parse_test.go | 11 ++++++----- .../parent/pom.xml | 2 +- .../pom.xml | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) rename pkg/dependency/parser/java/pom/testdata/{inherit-scopes-in-parents-of-children-from-root => inherit-scopes-in-parents-from-root}/parent/pom.xml (96%) rename pkg/dependency/parser/java/pom/testdata/{inherit-scopes-in-parents-of-children-from-root => inherit-scopes-in-parents-from-root}/pom.xml (74%) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index dd5d96a2e6d3..b96f5bf9fdf5 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1873,7 +1873,8 @@ func TestPom_Parse(t *testing.T) { }, }, }, - // [INFO] com.example:inherit-scopes-in-parents-of-children-from-root:jar:0.1.0 + // [INFO] --- dependency:3.7.0:tree (default-cli) @ inherit-scopes-in-parents-from-root --- + // [INFO] com.example:inherit-scopes-in-parents-from-root:jar:0.1.0 // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime @@ -1887,13 +1888,13 @@ func TestPom_Parse(t *testing.T) { // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes // scopes from `dependencyManagement` of root pom are used in parent dependencies { - name: "inherit scopes in children from root pom", - inputFile: filepath.Join("testdata", "inherit-scopes-in-parents-of-children-from-root", "pom.xml"), + name: "inherit scopes in parent from root pom", + inputFile: filepath.Join("testdata", "inherit-scopes-in-parents-from-root", "pom.xml"), local: true, want: []ftypes.Package{ { - ID: "com.example:inherit-scopes-in-parents-of-children-from-root:0.1.0", - Name: "com.example:inherit-scopes-in-parents-of-children-from-root", + ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", + Name: "com.example:inherit-scopes-in-parents-from-root", Version: "0.1.0", Relationship: ftypes.RelationshipRoot, }, diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml similarity index 96% rename from pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml rename to pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml index 392737e8309c..a47f8e78b21f 100644 --- a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/parent/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.example - inherit-scopes-in-parents-of-children-from-root-parent + inherit-scopes-in-parents-from-root-parent 0.0.1 pom diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml similarity index 74% rename from pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml rename to pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml index 13ae9686fb91..08f9a28c71ec 100644 --- a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-of-children-from-root/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml @@ -3,12 +3,12 @@ 4.0.0 com.example - inherit-scopes-in-parents-of-children-from-root + inherit-scopes-in-parents-from-root 0.1.0 com.example - inherit-scopes-in-parents-of-children-from-root-parent + inherit-scopes-in-parents-from-root-parent 0.0.1 ./parent From 8f2da1e10aad185f32fbce661b30d76731076704 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 13:23:46 +0600 Subject: [PATCH 06/16] fix: always inherit scopes from root pom --- pkg/dependency/parser/java/pom/pom.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index f6a7622d5975..6b199f6fa2e8 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -239,12 +239,10 @@ func (d pomDependency) Resolve(props map[string]string, depManagement, rootDepMa // If this dependency is managed in the root POM, // we need to overwrite fields according to the managed dependency. if managed, found := findDep(d.Name(), rootDepManagement); found { // dependencyManagement from the root POM - // We always need to use version from root POM + // We always need to use version and scope from root POM dep.Version = evaluateVariable(managed.Version, props, nil) + dep.Scope = evaluateVariable(managed.Scope, props, nil) - if managed.Scope == "" { - dep.Scope = evaluateVariable(managed.Scope, props, nil) - } if managed.Optional { dep.Optional = managed.Optional } From a1007346602c547665ffa612da59caa09a31f5bd Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 13:23:54 +0600 Subject: [PATCH 07/16] test: fix tests --- pkg/dependency/parser/java/pom/parse_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index b96f5bf9fdf5..4ed1e0ac8cfb 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1761,7 +1761,7 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:inherit-scopes-for-child-deps-and-parents:0.0.1", + ID: "com.example:inherit-scopes-from-child-deps-and-their-parents:0.0.1", DependsOn: []string{ "org.example:example-nested-scope-compile:1.0.0", "org.example:example-nested-scope-empty:1.0.0", @@ -1840,7 +1840,7 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:inherit-scopes-for-child-deps-and-parents:0.0.1", + ID: "com.example:inherit-scopes-in-children-from-root:0.0.1", DependsOn: []string{ "org.example:example-nested-scope-compile:1.0.0", "org.example:example-nested-scope-empty:1.0.0", @@ -1908,7 +1908,7 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:inherit-scopes-for-child-deps-and-parents:0.0.1", + ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", DependsOn: []string{ "org.example:example-nested-scope-compile:1.0.0", "org.example:example-nested-scope-empty:1.0.0", From 0568cf19d88dbe92c634cd06308147a37079f805 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 13:24:54 +0600 Subject: [PATCH 08/16] refactor: remove TODO comments --- pkg/dependency/parser/java/pom/parse_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 4ed1e0ac8cfb..b1c1cfbb0682 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1707,13 +1707,13 @@ func TestPom_Parse(t *testing.T) { ID: "org.example:example-api:1.0.1", Name: "org.example:example-api", Version: "1.0.1", - Relationship: ftypes.RelationshipDirect, // TODO change this!!! + Relationship: ftypes.RelationshipDirect, }, { ID: "org.example:example-api2:1.0.2", Name: "org.example:example-api2", Version: "1.0.2", - Relationship: ftypes.RelationshipDirect, // TODO change this!!! + Relationship: ftypes.RelationshipDirect, }, }, wantDeps: []ftypes.Dependency{ From 93a022859a411d138c34d207f05f75a98d9b47ef Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 13:35:02 +0600 Subject: [PATCH 09/16] test: update tests --- pkg/dependency/parser/java/pom/parse_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index b1c1cfbb0682..272215468ca3 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1726,16 +1726,16 @@ func TestPom_Parse(t *testing.T) { }, }, }, - // [INFO] com.example:inherit-scopes-in-child-deps:jar:1.0.0 + // [INFO] com.example:inherit-scopes-from-child-deps-and-their-parents:jar:0.0.1 // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime - // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile - // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:test + // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:runtime + // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile - // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime - // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test + // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:compile + // [INFO] | \- org.example:example-api-compile:jar:3.0.0:compile // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile - // [INFO] \- org.example:example-scope-empty:jar:2.0.0:runtime - // [INFO] \- org.example:example-api-empty:jar:3.0.0:test + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:compile + // [INFO] \- org.example:example-api-empty:jar:3.0.0:compile // // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes { @@ -1806,7 +1806,7 @@ func TestPom_Parse(t *testing.T) { }, }, }, - // [INFO] com.example:inherit-scopes-in-children-from-root:jar:0.0.1 + // [INFO] com.example:inherit-scopes-in-parents-from-root:jar:0.1.0 // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile // [INFO] | \- org.example:example-api-runtime:jar:3.0.0:runtime From 2e7367ee334471fec5734984bf8ab5c4086c51fa Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 20 Sep 2024 14:04:57 +0600 Subject: [PATCH 10/16] test: add test scopes in inherit-scopes-in-parents-from-root --- pkg/dependency/parser/java/pom/parse_test.go | 5 ++-- .../parent/pom.xml | 14 ++++++++++- .../pom.xml | 23 +++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 272215468ca3..38ac76c818e7 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1873,7 +1873,6 @@ func TestPom_Parse(t *testing.T) { }, }, }, - // [INFO] --- dependency:3.7.0:tree (default-cli) @ inherit-scopes-in-parents-from-root --- // [INFO] com.example:inherit-scopes-in-parents-from-root:jar:0.1.0 // [INFO] +- org.example:example-nested-scope-runtime:jar:1.0.0:runtime // [INFO] | \- org.example:example-scope-runtime:jar:2.0.0:compile @@ -1881,8 +1880,8 @@ func TestPom_Parse(t *testing.T) { // [INFO] +- org.example:example-nested-scope-compile:jar:1.0.0:compile // [INFO] | \- org.example:example-scope-compile:jar:2.0.0:runtime // [INFO] | \- org.example:example-api-compile:jar:3.0.0:test - // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:compile - // [INFO] \- org.example:example-scope-empty:jar:2.0.0:runtime + // [INFO] \- org.example:example-nested-scope-empty:jar:1.0.0:test + // [INFO] \- org.example:example-scope-empty:jar:2.0.0:test // [INFO] \- org.example:example-api-empty:jar:3.0.0:test // // `example-nested-*" dependencies and their parents contain `dependencyManagement` with changed scopes diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml index a47f8e78b21f..dad0101e3f25 100644 --- a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/parent/pom.xml @@ -31,7 +31,7 @@ org.example example-scope-empty 2.0.0 - runtime + test org.example @@ -39,6 +39,18 @@ 3.0.0 test + + org.example + example-nested-scope-compile + 1.0.0 + runtime + + + org.example + example-nested-scope-empty + 1.0.0 + compile + diff --git a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml index 08f9a28c71ec..45ef37785e60 100644 --- a/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/inherit-scopes-in-parents-from-root/pom.xml @@ -13,4 +13,27 @@ ./parent + + + + org.example + example-nested-scope-runtime + 1.0.0 + test + + + org.example + example-nested-scope-compile + 1.0.0 + test + + + org.example + example-nested-scope-empty + 1.0.0 + test + + + + From 854576124e68d1c222fd3cfe6527a251097596a9 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 23 Sep 2024 13:42:06 +0600 Subject: [PATCH 11/16] test: update tests --- pkg/dependency/parser/java/pom/parse_test.go | 19 +++++++++---------- .../testdata/transitive-parents/base/pom.xml | 2 +- .../parent/pom.xml | 6 ++++++ .../pom.xml | 7 +++++++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 38ac76c818e7..385b9d284421 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1691,7 +1691,8 @@ func TestPom_Parse(t *testing.T) { }, // [INFO] com.example:child-depManagement-in-parent:jar:1.0.0 // [INFO] +- org.example:example-api:jar:1.0.1:compile - // [INFO] \- org.example:example-api2:jar:1.0.2:runtime + // [INFO] +- org.example:example-api2:jar:1.0.2:runtime + // [INFO] \- org.example:example-api3:jar:4.0.3:compile { name: "dependency from parent uses version from child(scanned) pom depManagement", inputFile: filepath.Join("testdata", "use-child-dep-management-in-parent", "pom.xml"), @@ -1715,12 +1716,19 @@ func TestPom_Parse(t *testing.T) { Version: "1.0.2", Relationship: ftypes.RelationshipDirect, }, + { + ID: "org.example:example-api3:4.0.3", + Name: "org.example:example-api3", + Version: "4.0.3", + Relationship: ftypes.RelationshipDirect, + }, }, wantDeps: []ftypes.Dependency{ { ID: "com.example:child-depManagement-in-parent:1.0.0", DependsOn: []string{ "org.example:example-api2:1.0.2", + "org.example:example-api3:4.0.3", "org.example:example-api:1.0.1", }, }, @@ -1898,11 +1906,9 @@ func TestPom_Parse(t *testing.T) { Relationship: ftypes.RelationshipRoot, }, exampleNestedScopeCompile(0, 0), - exampleNestedScopeEmpty(0, 0), exampleNestedScopeRuntime(0, 0), exampleApiRuntime, exampleScopeCompile, - exampleScopeEmpty, exampleScopeRuntime, }, wantDeps: []ftypes.Dependency{ @@ -1910,7 +1916,6 @@ func TestPom_Parse(t *testing.T) { ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", DependsOn: []string{ "org.example:example-nested-scope-compile:1.0.0", - "org.example:example-nested-scope-empty:1.0.0", "org.example:example-nested-scope-runtime:1.0.0", }, }, @@ -1920,12 +1925,6 @@ func TestPom_Parse(t *testing.T) { "org.example:example-scope-compile:2.0.0", }, }, - { - ID: "org.example:example-nested-scope-empty:1.0.0", - DependsOn: []string{ - "org.example:example-scope-empty:2.0.0", - }, - }, { ID: "org.example:example-nested-scope-runtime:1.0.0", DependsOn: []string{ diff --git a/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml b/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml index 5662c0c9e8de..ae1d6ced6e3f 100644 --- a/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/transitive-parents/base/pom.xml @@ -13,7 +13,7 @@ com.example parent 3.0.0 - ../parent + ../ diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml index 73e4de2814c7..ce2e2e816912 100644 --- a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml @@ -24,5 +24,11 @@ org.example example-api2 + + org.example + example-api3 + 4.0.3 + compile + \ No newline at end of file diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml index 0e9ac955a942..651fbba9f885 100644 --- a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/pom.xml @@ -17,6 +17,7 @@ 1.0.1 1.0.2 + 1.0.3 @@ -33,6 +34,12 @@ ${api2.version} runtime + + org.example + example-api3 + ${api3.version} + runtime + From a2498df5a7ed338e67735110b1479da2ce972f5c Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 23 Sep 2024 13:42:20 +0600 Subject: [PATCH 12/16] fix: inherit props in parents --- pkg/dependency/parser/java/pom/parse.go | 47 +++++++++++++++---------- pkg/dependency/parser/java/pom/pom.go | 10 ++++-- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 37e67edfdee9..d298ca8123f0 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -299,8 +299,8 @@ func (p *Parser) resolve(art artifact, rootDepManagement []pomDependency) (analy p.logger.Debug("Repository error", log.Err(err)) } result, err := p.analyze(pomContent, analysisOptions{ - exclusions: art.Exclusions, - depManagement: rootDepManagement, + exclusions: art.Exclusions, + rootDepManagement: rootDepManagement, }) if err != nil { return analysisResult{}, xerrors.Errorf("analyze error: %w", err) @@ -320,9 +320,11 @@ type analysisResult struct { } type analysisOptions struct { - exclusions map[string]struct{} - depManagement []pomDependency // from the root POM - lineNumber bool // Save line numbers + exclusions map[string]struct{} + depManagementForParent []pomDependency // from current and root POMs - used for parents + propsForParent properties // from current and root POMs - used for parents + rootDepManagement []pomDependency // from the root POM + lineNumber bool // Save line numbers } func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) { @@ -335,26 +337,28 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) p.releaseRemoteRepos = lo.Uniq(append(pomReleaseRemoteRepos, p.releaseRemoteRepos...)) p.snapshotRemoteRepos = lo.Uniq(append(pomSnapshotRemoteRepos, p.snapshotRemoteRepos...)) + // Merge props from upper POM and current POM to use in parent + propsForParent := lo.Assign(opts.propsForParent, pom.content.Properties) + // We need to forward dependencyManagements from current and root pom to Parent, // to use them for dependencies in parent. // For better understanding see the following tests: // - `dependency from parent uses version from child pom depManagement` // - `dependency from parent uses version from root pom depManagement` // - `dependency from parent uses version from scanned pom depManagement` - // - // depManagements from root pom has higher priority than depManagements from current pom. - - var resolvedPomDepManagent []pomDependency + var resolvedPomDepManagement []pomDependency for _, dep := range pom.content.DependencyManagement.Dependencies.Dependency { - resolvedPomDepManagent = append(resolvedPomDepManagent, dep.Resolve(pom.content.Properties, nil, nil)) + resolvedPomDepManagement = append(resolvedPomDepManagement, dep.Resolve(propsForParent, nil, nil)) } - depManagementForParent := lo.UniqBy(append(opts.depManagement, resolvedPomDepManagent...), + // depManagements from root pom has higher priority than depManagements from current POM. + depManagementForParent := append(opts.rootDepManagement, opts.depManagementForParent...) + depManagementForParent = lo.UniqBy(append(depManagementForParent, resolvedPomDepManagement...), func(dep pomDependency) string { return dep.Name() }) // Parent - parent, err := p.parseParent(pom.filePath, pom.content.Parent, depManagementForParent) + parent, err := p.parseParent(pom.filePath, pom.content.Parent, depManagementForParent, propsForParent) if err != nil { return analysisResult{}, xerrors.Errorf("parent error: %w", err) } @@ -365,10 +369,16 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) // Generate properties props := pom.properties() + // To analyze parents: + // Take props from upper POM + props = lo.Assign(props, opts.propsForParent) + // dependencyManagements have the next priority: - // 1. Managed dependencies from this POM - // 2. Managed dependencies from parent of this POM - depManagement := p.mergeDependencyManagements(pom.content.DependencyManagement.Dependencies.Dependency, + // 1. Managed dependencies from upped POM (this case only works for parent analysis) + // 2. Managed dependencies from this POM + // 3. Managed dependencies from parent of this POM + depManagement := p.mergeDependencyManagements(opts.depManagementForParent, + pom.content.DependencyManagement.Dependencies.Dependency, parent.dependencyManagement) // Merge dependencies. Child dependencies must be preferred than parent dependencies. @@ -412,7 +422,7 @@ func (p *Parser) parseDependencies(deps []pomDependency, props map[string]string // Resolve dependencyManagement depManagement = p.resolveDepManagement(props, depManagement) - rootDepManagement := opts.depManagement + rootDepManagement := opts.rootDepManagement var dependencies []artifact for _, d := range deps { // Resolve dependencies @@ -495,7 +505,7 @@ func excludeDep(exclusions map[string]struct{}, art artifact) bool { return false } -func (p *Parser) parseParent(currentPath string, parent pomParent, rootDepManagement []pomDependency) (analysisResult, error) { +func (p *Parser) parseParent(currentPath string, parent pomParent, depManagementForParent []pomDependency, propsForParent properties) (analysisResult, error) { // Pass nil properties so that variables in are not evaluated. target := newArtifact(parent.GroupId, parent.ArtifactId, parent.Version, nil, nil) // if version is property (e.g. ${revision}) - we still need to parse this pom @@ -518,7 +528,8 @@ func (p *Parser) parseParent(currentPath string, parent pomParent, rootDepManage } result, err := p.analyze(parentPOM, analysisOptions{ - depManagement: rootDepManagement, + depManagementForParent: depManagementForParent, + propsForParent: propsForParent, }) if err != nil { return analysisResult{}, xerrors.Errorf("analyze error: %w", err) diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index 6b199f6fa2e8..77da23dc9a53 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -239,9 +239,13 @@ func (d pomDependency) Resolve(props map[string]string, depManagement, rootDepMa // If this dependency is managed in the root POM, // we need to overwrite fields according to the managed dependency. if managed, found := findDep(d.Name(), rootDepManagement); found { // dependencyManagement from the root POM - // We always need to use version and scope from root POM - dep.Version = evaluateVariable(managed.Version, props, nil) - dep.Scope = evaluateVariable(managed.Scope, props, nil) + if managed.Version != "" { + dep.Version = evaluateVariable(managed.Version, props, nil) + } + + if managed.Scope != "" { + dep.Scope = evaluateVariable(managed.Scope, props, nil) + } if managed.Optional { dep.Optional = managed.Optional From 42bc102a0ffc7bd0c47294265f2cd3a686c632b3 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 23 Sep 2024 14:39:08 +0600 Subject: [PATCH 13/16] refactor --- pkg/dependency/parser/java/pom/parse.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index d298ca8123f0..8994efb73298 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -346,13 +346,10 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) // - `dependency from parent uses version from child pom depManagement` // - `dependency from parent uses version from root pom depManagement` // - `dependency from parent uses version from scanned pom depManagement` - var resolvedPomDepManagement []pomDependency - for _, dep := range pom.content.DependencyManagement.Dependencies.Dependency { - resolvedPomDepManagement = append(resolvedPomDepManagement, dep.Resolve(propsForParent, nil, nil)) - } - // depManagements from root pom has higher priority than depManagements from current POM. + // + // Merge dependencyManagements from root, upper and current POM and remove duplicates depManagementForParent := append(opts.rootDepManagement, opts.depManagementForParent...) - depManagementForParent = lo.UniqBy(append(depManagementForParent, resolvedPomDepManagement...), + depManagementForParent = lo.UniqBy(append(depManagementForParent, pom.content.DependencyManagement.Dependencies.Dependency...), func(dep pomDependency) string { return dep.Name() }) From 7cb7a5cb8a5f1a66a4d63214a09b6ec67abf1913 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Wed, 16 Oct 2024 20:20:22 +0400 Subject: [PATCH 14/16] fix: inherit parents and then resolve Signed-off-by: knqyf263 --- pkg/dependency/parser/java/pom/parse.go | 169 +++++++++++------------- pkg/dependency/parser/java/pom/pom.go | 11 +- 2 files changed, 85 insertions(+), 95 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 8994efb73298..27b17620609e 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -96,7 +96,7 @@ func NewParser(filePath string, opts ...option) *Parser { } func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) { - content, err := parsePom(r) + content, err := parsePom(r, true) if err != nil { return nil, nil, xerrors.Errorf("failed to parse POM: %w", err) } @@ -107,7 +107,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc } // Analyze root POM - result, err := p.analyze(root, analysisOptions{lineNumber: true}) + result, err := p.analyze(root, analysisOptions{}) if err != nil { return nil, nil, xerrors.Errorf("analyze error (%s): %w", p.rootPath, err) } @@ -299,8 +299,8 @@ func (p *Parser) resolve(art artifact, rootDepManagement []pomDependency) (analy p.logger.Debug("Repository error", log.Err(err)) } result, err := p.analyze(pomContent, analysisOptions{ - exclusions: art.Exclusions, - rootDepManagement: rootDepManagement, + exclusions: art.Exclusions, + depManagement: rootDepManagement, }) if err != nil { return analysisResult{}, xerrors.Errorf("analyze error: %w", err) @@ -320,68 +320,29 @@ type analysisResult struct { } type analysisOptions struct { - exclusions map[string]struct{} - depManagementForParent []pomDependency // from current and root POMs - used for parents - propsForParent properties // from current and root POMs - used for parents - rootDepManagement []pomDependency // from the root POM - lineNumber bool // Save line numbers + exclusions map[string]struct{} + depManagement []pomDependency // from the root POM } func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) { if pom == nil || pom.content == nil { return analysisResult{}, nil } - // Update remoteRepositories pomReleaseRemoteRepos, pomSnapshotRemoteRepos := pom.repositories(p.servers) p.releaseRemoteRepos = lo.Uniq(append(pomReleaseRemoteRepos, p.releaseRemoteRepos...)) p.snapshotRemoteRepos = lo.Uniq(append(pomSnapshotRemoteRepos, p.snapshotRemoteRepos...)) - // Merge props from upper POM and current POM to use in parent - propsForParent := lo.Assign(opts.propsForParent, pom.content.Properties) - - // We need to forward dependencyManagements from current and root pom to Parent, - // to use them for dependencies in parent. - // For better understanding see the following tests: - // - `dependency from parent uses version from child pom depManagement` - // - `dependency from parent uses version from root pom depManagement` - // - `dependency from parent uses version from scanned pom depManagement` - // - // Merge dependencyManagements from root, upper and current POM and remove duplicates - depManagementForParent := append(opts.rootDepManagement, opts.depManagementForParent...) - depManagementForParent = lo.UniqBy(append(depManagementForParent, pom.content.DependencyManagement.Dependencies.Dependency...), - func(dep pomDependency) string { - return dep.Name() - }) - - // Parent - parent, err := p.parseParent(pom.filePath, pom.content.Parent, depManagementForParent, propsForParent) - if err != nil { - return analysisResult{}, xerrors.Errorf("parent error: %w", err) + // Resolve parent POM + if err := p.resolveParent(pom); err != nil { + return analysisResult{}, xerrors.Errorf("pom resolve error: %w", err) } - // Inherit values/properties from parent - pom.inherit(parent) - - // Generate properties + // Resolve dependencies props := pom.properties() - - // To analyze parents: - // Take props from upper POM - props = lo.Assign(props, opts.propsForParent) - - // dependencyManagements have the next priority: - // 1. Managed dependencies from upped POM (this case only works for parent analysis) - // 2. Managed dependencies from this POM - // 3. Managed dependencies from parent of this POM - depManagement := p.mergeDependencyManagements(opts.depManagementForParent, - pom.content.DependencyManagement.Dependencies.Dependency, - parent.dependencyManagement) - - // Merge dependencies. Child dependencies must be preferred than parent dependencies. - // Parents don't have to resolve dependencies. + depManagement := pom.content.DependencyManagement.Dependencies.Dependency deps := p.parseDependencies(pom.content.Dependencies.Dependency, props, depManagement, opts) - deps = p.mergeDependencies(parent.dependencies, deps, opts.exclusions) + deps = p.filterDependencies(deps, opts.exclusions) return analysisResult{ filePath: pom.filePath, @@ -393,6 +354,39 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) }, nil } +// resolveParent resolves its parent POMs and inherits properties, dependencies, and dependencyManagement. +func (p *Parser) resolveParent(pom *pom) error { + if pom == nil || pom.content == nil { + return nil + } + + // Parse parent POM + parent, err := p.parseParent(pom.filePath, pom.content.Parent) + if err != nil { + return xerrors.Errorf("parent error: %w", err) + } + + // Inherit values/properties from parent + pom.inherit(parent) + + // Merge properties + pom.content.Properties = p.mergeProperties(pom.content.Properties, parent.content.Properties) + + // Merge dependencyManagement with the following priority: + // 1. Managed dependencies from this POM + // 2. Managed dependencies from parent of this POM + pom.content.DependencyManagement.Dependencies.Dependency = p.mergeDependencyManagements( + pom.content.DependencyManagement.Dependencies.Dependency, + parent.content.DependencyManagement.Dependencies.Dependency) + + // Merge dependencies + pom.content.Dependencies.Dependency = p.mergeDependencies( + pom.content.Dependencies.Dependency, + parent.content.Dependencies.Dependency) + + return nil +} + func (p *Parser) mergeDependencyManagements(depManagements ...[]pomDependency) []pomDependency { uniq := make(map[string]struct{}) var depManagement []pomDependency @@ -419,7 +413,7 @@ func (p *Parser) parseDependencies(deps []pomDependency, props map[string]string // Resolve dependencyManagement depManagement = p.resolveDepManagement(props, depManagement) - rootDepManagement := opts.rootDepManagement + rootDepManagement := opts.depManagement var dependencies []artifact for _, d := range deps { // Resolve dependencies @@ -468,22 +462,20 @@ func (p *Parser) resolveDepManagement(props map[string]string, depManagement []p return newDepManagement } -func (p *Parser) mergeDependencies(parent, child []artifact, exclusions map[string]struct{}) []artifact { - var deps []artifact - unique := make(map[string]struct{}) +func (p *Parser) mergeProperties(child, parent properties) properties { + return lo.Assign(parent, child) +} - for _, d := range append(child, parent...) { - if excludeDep(exclusions, d) { - continue - } - if _, ok := unique[d.Name()]; ok { - continue - } - unique[d.Name()] = struct{}{} - deps = append(deps, d) - } +func (p *Parser) mergeDependencies(child, parent []pomDependency) []pomDependency { + return lo.UniqBy(append(child, parent...), func(d pomDependency) string { + return d.Name() + }) +} - return deps +func (p *Parser) filterDependencies(artifacts []artifact, exclusions map[string]struct{}) []artifact { + return lo.Filter(artifacts, func(art artifact, _ int) bool { + return !excludeDep(exclusions, art) + }) } func excludeDep(exclusions map[string]struct{}, art artifact) bool { @@ -502,39 +494,29 @@ func excludeDep(exclusions map[string]struct{}, art artifact) bool { return false } -func (p *Parser) parseParent(currentPath string, parent pomParent, depManagementForParent []pomDependency, propsForParent properties) (analysisResult, error) { +func (p *Parser) parseParent(currentPath string, parent pomParent) (*pom, error) { // Pass nil properties so that variables in are not evaluated. target := newArtifact(parent.GroupId, parent.ArtifactId, parent.Version, nil, nil) // if version is property (e.g. ${revision}) - we still need to parse this pom if target.IsEmpty() && !isProperty(parent.Version) { - return analysisResult{}, nil + return &pom{content: &pomXML{}}, nil } logger := p.logger.With("artifact", target.String()) logger.Debug("Start parent") defer logger.Debug("Exit parent") - // If the artifact is found in cache, it is returned. - if result := p.cache.get(target); result != nil { - return *result, nil - } - parentPOM, err := p.retrieveParent(currentPath, parent.RelativePath, target) if err != nil { logger.Debug("Parent POM not found", log.Err(err)) + return &pom{content: &pomXML{}}, nil } - result, err := p.analyze(parentPOM, analysisOptions{ - depManagementForParent: depManagementForParent, - propsForParent: propsForParent, - }) - if err != nil { - return analysisResult{}, xerrors.Errorf("analyze error: %w", err) + if err = p.resolveParent(parentPOM); err != nil { + return nil, xerrors.Errorf("parent pom resolve error: %w", err) } - p.cache.put(target, result) - - return result, nil + return parentPOM, nil } func (p *Parser) retrieveParent(currentPath, relativePath string, target artifact) (*pom, error) { @@ -571,7 +553,7 @@ func (p *Parser) retrieveParent(currentPath, relativePath string, target artifac } func (p *Parser) tryRelativePath(parentArtifact artifact, currentPath, relativePath string) (*pom, error) { - pom, err := p.openRelativePom(currentPath, relativePath) + parsedPOM, err := p.openRelativePom(currentPath, relativePath) if err != nil { return nil, err } @@ -582,19 +564,18 @@ func (p *Parser) tryRelativePath(parentArtifact artifact, currentPath, relativeP // But GroupID can be inherited from parent (`p.analyze` function is required to get the GroupID). // Version can contain a property (`p.analyze` function is required to get the GroupID). // So we can only match ArtifactID's. - if pom.artifact().ArtifactID != parentArtifact.ArtifactID { + if parsedPOM.artifact().ArtifactID != parentArtifact.ArtifactID { return nil, xerrors.New("'parent.relativePath' points at wrong local POM") } - result, err := p.analyze(pom, analysisOptions{}) - if err != nil { + if err := p.resolveParent(parsedPOM); err != nil { return nil, xerrors.Errorf("analyze error: %w", err) } - if !parentArtifact.Equal(result.artifact) { + if !parentArtifact.Equal(parsedPOM.artifact()) { return nil, xerrors.New("'parent.relativePath' points at wrong local POM") } - return pom, nil + return parsedPOM, nil } func (p *Parser) openRelativePom(currentPath, relativePath string) (*pom, error) { @@ -626,7 +607,7 @@ func (p *Parser) openPom(filePath string) (*pom, error) { } defer f.Close() - content, err := parsePom(f) + content, err := parsePom(f, false) if err != nil { return nil, xerrors.Errorf("failed to parse the local POM: %w", err) } @@ -783,7 +764,7 @@ func (p *Parser) fetchPOMFromRemoteRepository(repo string, paths []string) (*pom } defer resp.Body.Close() - content, err := parsePom(resp.Body) + content, err := parsePom(resp.Body, false) if err != nil { return nil, xerrors.Errorf("failed to parse the remote POM: %w", err) } @@ -794,13 +775,19 @@ func (p *Parser) fetchPOMFromRemoteRepository(repo string, paths []string) (*pom }, nil } -func parsePom(r io.Reader) (*pomXML, error) { +func parsePom(r io.Reader, lineNumber bool) (*pomXML, error) { parsed := &pomXML{} decoder := xml.NewDecoder(r) decoder.CharsetReader = charset.NewReaderLabel if err := decoder.Decode(parsed); err != nil { return nil, xerrors.Errorf("xml decode error: %w", err) } + if !lineNumber { + for i := range parsed.Dependencies.Dependency { + parsed.Dependencies.Dependency[i].StartLine = 0 + parsed.Dependencies.Dependency[i].EndLine = 0 + } + } return parsed, nil } diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index 77da23dc9a53..64f771c97b16 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -23,11 +23,14 @@ type pom struct { content *pomXML } -func (p *pom) inherit(result analysisResult) { +func (p *pom) inherit(parent *pom) { + if parent == nil { + return + } // Merge properties - p.content.Properties = utils.MergeMaps(result.properties, p.content.Properties) + p.content.Properties = utils.MergeMaps(parent.properties(), p.content.Properties) - art := p.artifact().Inherit(result.artifact) + art := p.artifact().Inherit(parent.artifact()) p.content.GroupId = art.GroupID p.content.ArtifactId = art.ArtifactID @@ -289,7 +292,7 @@ func (d pomDependency) ToArtifact(opts analysisOptions) artifact { } var locations ftypes.Locations - if opts.lineNumber { + if d.StartLine != 0 && d.EndLine != 0 { locations = ftypes.Locations{ { StartLine: d.StartLine, From c076a68a0a44f7b2c8b5e3deb627285c73d54c2e Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Wed, 16 Oct 2024 21:20:21 +0400 Subject: [PATCH 15/16] refactor: add nil() Signed-off-by: knqyf263 --- pkg/dependency/parser/java/pom/parse.go | 4 ++-- pkg/dependency/parser/java/pom/pom.go | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 27b17620609e..2cbaf5318aa7 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -325,7 +325,7 @@ type analysisOptions struct { } func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) { - if pom == nil || pom.content == nil { + if pom.nil() { return analysisResult{}, nil } // Update remoteRepositories @@ -356,7 +356,7 @@ func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) // resolveParent resolves its parent POMs and inherits properties, dependencies, and dependencyManagement. func (p *Parser) resolveParent(pom *pom) error { - if pom == nil || pom.content == nil { + if pom.nil() { return nil } diff --git a/pkg/dependency/parser/java/pom/pom.go b/pkg/dependency/parser/java/pom/pom.go index 64f771c97b16..83c5d4fec609 100644 --- a/pkg/dependency/parser/java/pom/pom.go +++ b/pkg/dependency/parser/java/pom/pom.go @@ -23,6 +23,10 @@ type pom struct { content *pomXML } +func (p *pom) nil() bool { + return p == nil || p.content == nil +} + func (p *pom) inherit(parent *pom) { if parent == nil { return @@ -43,12 +47,12 @@ func (p *pom) inherit(parent *pom) { } } -func (p pom) properties() properties { +func (p *pom) properties() properties { props := p.content.Properties return utils.MergeMaps(props, p.projectProperties()) } -func (p pom) projectProperties() map[string]string { +func (p *pom) projectProperties() map[string]string { val := reflect.ValueOf(p.content).Elem() props := p.listProperties(val) @@ -76,7 +80,7 @@ func (p pom) projectProperties() map[string]string { return projectProperties } -func (p pom) listProperties(val reflect.Value) map[string]string { +func (p *pom) listProperties(val reflect.Value) map[string]string { props := make(map[string]string) for i := 0; i < val.NumField(); i++ { f := val.Type().Field(i) @@ -109,17 +113,17 @@ func (p pom) listProperties(val reflect.Value) map[string]string { return props } -func (p pom) artifact() artifact { +func (p *pom) artifact() artifact { return newArtifact(p.content.GroupId, p.content.ArtifactId, p.content.Version, p.licenses(), p.content.Properties) } -func (p pom) licenses() []string { +func (p *pom) licenses() []string { return slices.ZeroToNil(lo.FilterMap(p.content.Licenses.License, func(lic pomLicense, _ int) (string, bool) { return lic.Name, lic.Name != "" })) } -func (p pom) repositories(servers []Server) ([]string, []string) { +func (p *pom) repositories(servers []Server) ([]string, []string) { logger := log.WithPrefix("pom") var releaseRepos, snapshotRepos []string for _, rep := range p.content.Repositories.Repository { From e12e46f6fd79311ff545db80d639b357f4fe661e Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 17 Oct 2024 12:25:29 +0600 Subject: [PATCH 16/16] test: add nested parents for `use-child-dep-management-in-parent` --- pkg/dependency/parser/java/pom/parse_test.go | 4 +-- .../parent/pom.xml | 14 ++++---- .../top-parent/pom.xml | 34 +++++++++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 385b9d284421..b95fc5baac07 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -1690,9 +1690,9 @@ func TestPom_Parse(t *testing.T) { }, }, // [INFO] com.example:child-depManagement-in-parent:jar:1.0.0 - // [INFO] +- org.example:example-api:jar:1.0.1:compile // [INFO] +- org.example:example-api2:jar:1.0.2:runtime - // [INFO] \- org.example:example-api3:jar:4.0.3:compile + // [INFO] +- org.example:example-api3:jar:4.0.3:compile + // [INFO] \- org.example:example-api:jar:1.0.1:compile { name: "dependency from parent uses version from child(scanned) pom depManagement", inputFile: filepath.Join("testdata", "use-child-dep-management-in-parent", "pom.xml"), diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml index ce2e2e816912..dec887e6eecc 100644 --- a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/parent/pom.xml @@ -4,6 +4,13 @@ 4.0.0 + + org.example + example-top-parent + 5.0.0 + ../top-parent/pom.xml + + org.example example-parent 4.0.0 @@ -12,14 +19,7 @@ 4.0.1 - - - org.example - example-api - ${api.version} - compile - org.example example-api2 diff --git a/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml new file mode 100644 index 000000000000..84d8954a4bf9 --- /dev/null +++ b/pkg/dependency/parser/java/pom/testdata/use-child-dep-management-in-parent/top-parent/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + + org.example + example-top-parent + 5.0.0 + pom + + + 5.0.1 + + + + + org.example + example-api + ${api.version} + compile + + + org.example + example-api2 + + + org.example + example-api3 + 5.0.3 + compile + + + \ No newline at end of file