diff --git a/go.mod b/go.mod index 8fb0449fce..13ea845b56 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module github.com/google/osv-scanner go 1.21.12 require ( - deps.dev/api/v3 v3.0.0-20240711010811-c5a1406b0470 - deps.dev/util/maven v0.0.0-20240711010811-c5a1406b0470 - deps.dev/util/resolve v0.0.0-20240711010811-c5a1406b0470 - deps.dev/util/semver v0.0.0-20240711010811-c5a1406b0470 + deps.dev/api/v3 v3.0.0-20240730004939-e80e6658c33b + deps.dev/util/maven v0.0.0-20240730004939-e80e6658c33b + deps.dev/util/resolve v0.0.0-20240730004939-e80e6658c33b + deps.dev/util/semver v0.0.0-20240730004939-e80e6658c33b github.com/BurntSushi/toml v1.4.0 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/charmbracelet/bubbles v0.18.0 diff --git a/go.sum b/go.sum index 6dfe294a16..feca9a9981 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,13 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -deps.dev/api/v3 v3.0.0-20240711010811-c5a1406b0470 h1:AXexCbWOahap0SWSsyDbEkeGJt2KxX4+1zWWZ+RsWQU= -deps.dev/api/v3 v3.0.0-20240711010811-c5a1406b0470/go.mod h1:DyBY3wNVqRCwvb4tLvz6LL/FupH3FMflEROyQAv2Vi0= -deps.dev/util/maven v0.0.0-20240711010811-c5a1406b0470 h1:T990wxZ1ph9gKl8K4/qzorVmS24rNj2pNBTl5BYMxXA= -deps.dev/util/maven v0.0.0-20240711010811-c5a1406b0470/go.mod h1:SBW3EribdkZYk6zxi5oVn/ZECvi4ixb7EGgEWfSimNk= -deps.dev/util/resolve v0.0.0-20240711010811-c5a1406b0470 h1:/djBEKpc04deGl+68W1nv7GnsygaVnmAFZCgadZEWPs= -deps.dev/util/resolve v0.0.0-20240711010811-c5a1406b0470/go.mod h1:XXi6yRYqhtxw5DvGX/mbG6fHSLn8OgoPowNd8EAxDgk= -deps.dev/util/semver v0.0.0-20240711010811-c5a1406b0470 h1:3wJIdP0Z4so7k3PjqwxVIhCOrrYDsTOe2GBsInNEZWM= -deps.dev/util/semver v0.0.0-20240711010811-c5a1406b0470/go.mod h1:jkcH+k02gWHBiZ7G4OnUOkSZ6WDq54Pt5DrOA8FN8Uo= +deps.dev/api/v3 v3.0.0-20240730004939-e80e6658c33b h1:uWv66hsFIMA+4mfvYroVOpJ4+trL7PVc4zTiJ+FVUpE= +deps.dev/api/v3 v3.0.0-20240730004939-e80e6658c33b/go.mod h1:DyBY3wNVqRCwvb4tLvz6LL/FupH3FMflEROyQAv2Vi0= +deps.dev/util/maven v0.0.0-20240730004939-e80e6658c33b h1:4/2szyn/8mZhaI3PW/JkRRDpv0aVMILL/R0rICgAA50= +deps.dev/util/maven v0.0.0-20240730004939-e80e6658c33b/go.mod h1:SBW3EribdkZYk6zxi5oVn/ZECvi4ixb7EGgEWfSimNk= +deps.dev/util/resolve v0.0.0-20240730004939-e80e6658c33b h1:MTE07TVpmsX13qjSHiVxLPR2u52R7w8m0TBlk7rNvF8= +deps.dev/util/resolve v0.0.0-20240730004939-e80e6658c33b/go.mod h1:XXi6yRYqhtxw5DvGX/mbG6fHSLn8OgoPowNd8EAxDgk= +deps.dev/util/semver v0.0.0-20240730004939-e80e6658c33b h1:kGG4/rm/slq+X/SfMVS7JnDBWeJhX2u2EudaPJeHyHI= +deps.dev/util/semver v0.0.0-20240730004939-e80e6658c33b/go.mod h1:jkcH+k02gWHBiZ7G4OnUOkSZ6WDq54Pt5DrOA8FN8Uo= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= diff --git a/internal/manifest/fixtures/maven/my-app/pom.xml b/internal/manifest/fixtures/maven/my-app/pom.xml new file mode 100644 index 0000000000..d01d047889 --- /dev/null +++ b/internal/manifest/fixtures/maven/my-app/pom.xml @@ -0,0 +1,8 @@ + + + + org.test + my-app + 1.0.0 + + diff --git a/internal/resolution/manifest/fixtures/maven/pom.xml b/internal/manifest/fixtures/maven/pom.xml similarity index 80% rename from internal/resolution/manifest/fixtures/maven/pom.xml rename to internal/manifest/fixtures/maven/pom.xml index cb678cdf43..1d2896858e 100644 --- a/internal/resolution/manifest/fixtures/maven/pom.xml +++ b/internal/manifest/fixtures/maven/pom.xml @@ -1,8 +1,6 @@ - 4.0.0 - org.test test 1.0.0 diff --git a/internal/manifest/maven.go b/internal/manifest/maven.go index f1a39ce347..f7b39bf9ab 100644 --- a/internal/manifest/maven.go +++ b/internal/manifest/maven.go @@ -14,12 +14,18 @@ import ( mavenresolve "deps.dev/util/resolve/maven" "github.com/google/osv-scanner/internal/resolution/client" "github.com/google/osv-scanner/internal/resolution/datasource" - "github.com/google/osv-scanner/internal/resolution/manifest" "github.com/google/osv-scanner/internal/resolution/util" "github.com/google/osv-scanner/pkg/lockfile" "golang.org/x/exp/maps" ) +const ( + OriginManagement = "management" + OriginParent = "parent" + OriginPlugin = "plugin" + OriginProfile = "profile" +) + type MavenResolverExtractor struct { client.DependencyClient datasource.MavenRegistryAPIClient @@ -37,7 +43,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD return []lockfile.PackageDetails{}, fmt.Errorf("could not extract from %s: %w", f.Path(), err) } // Merging parents data by parsing local parent pom.xml or fetching from upstream. - if err := e.mergeParents(ctx, &project, project.Parent, 1, true, f.Path()); err != nil { + if err := MergeMavenParents(ctx, e.MavenRegistryAPIClient, &project, project.Parent, 1, f.Path(), true); err != nil { return []lockfile.PackageDetails{}, fmt.Errorf("failed to merge parents: %w", err) } // Process the dependencies: @@ -47,7 +53,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD project.ProcessDependencies(func(groupID, artifactID, version maven.String) (maven.DependencyManagement, error) { root := maven.Parent{ProjectKey: maven.ProjectKey{GroupID: groupID, ArtifactID: artifactID, Version: version}} var result maven.Project - if err := e.mergeParents(ctx, &result, root, 0, false, f.Path()); err != nil { + if err := MergeMavenParents(ctx, e.MavenRegistryAPIClient, &result, root, 0, f.Path(), false); err != nil { return maven.DependencyManagement{}, err } @@ -91,7 +97,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD VersionType: resolve.Requirement, Version: string(d.Version), }, - Type: resolve.MavenDepType(d, manifest.OriginManagement), + Type: resolve.MavenDepType(d, OriginManagement), } } overrideClient.AddVersion(root, reqs) @@ -130,7 +136,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD // MaxParent sets a limit on the number of parents to avoid indefinite loop. const MaxParent = 100 -// mergeParents parses local accessible parent pom.xml or fetches it from +// MergeMavenParents parses local accessible parent pom.xml or fetches it from // upstream, merges into root project, then interpolate the properties. // result holds the merged Maven project. // current holds the current parent project to merge. @@ -139,7 +145,7 @@ const MaxParent = 100 // allowLocal indicates whether parsing local parent pom.xml is allowed. // path holds the path to the current pom.xml, which is used to compute the // relative path of parent. -func (e MavenResolverExtractor) mergeParents(ctx context.Context, result *maven.Project, current maven.Parent, start int, allowLocal bool, path string) error { +func MergeMavenParents(ctx context.Context, mavenClient datasource.MavenRegistryAPIClient, result *maven.Project, current maven.Parent, start int, path string, allowLocal bool) error { currentPath := path visited := make(map[maven.ProjectKey]bool, MaxParent) for n := start; n < MaxParent; n++ { @@ -154,7 +160,7 @@ func (e MavenResolverExtractor) mergeParents(ctx context.Context, result *maven. var proj maven.Project parentFound := false - if parentPath := manifest.MavenParentPOMPath(currentPath, string(current.RelativePath)); allowLocal && parentPath != "" { + if parentPath := MavenParentPOMPath(currentPath, string(current.RelativePath)); allowLocal && parentPath != "" { currentPath = parentPath f, err := os.Open(parentPath) if err != nil { @@ -174,7 +180,7 @@ func (e MavenResolverExtractor) mergeParents(ctx context.Context, result *maven. allowLocal = false var err error - proj, err = e.MavenRegistryAPIClient.GetProject(ctx, string(current.GroupID), string(current.ArtifactID), string(current.Version)) + proj, err = mavenClient.GetProject(ctx, string(current.GroupID), string(current.ArtifactID), string(current.Version)) if err != nil { return fmt.Errorf("failed to get Maven project %s:%s:%s: %w", current.GroupID, current.ArtifactID, current.Version, err) } @@ -198,6 +204,28 @@ func (e MavenResolverExtractor) mergeParents(ctx context.Context, result *maven. return result.Interpolate() } +// Maven looks for the parent POM first in 'relativePath', +// then the local repository '../pom.xml', +// and lastly in the remote repo. +func MavenParentPOMPath(currentPath, relativePath string) string { + if relativePath == "" { + relativePath = "../pom.xml" + } + path := filepath.Join(filepath.Dir(currentPath), relativePath) + if info, err := os.Stat(path); err == nil { + if !info.IsDir() { + return path + } + // Current path is a directory, so look for pom.xml in the directory. + path = filepath.Join(path, "pom.xml") + if _, err := os.Stat(path); err == nil { + return path + } + } + + return "" +} + func ParseMavenWithResolver(depClient client.DependencyClient, mavenClient datasource.MavenRegistryAPIClient, pathToLockfile string) ([]lockfile.PackageDetails, error) { f, err := lockfile.OpenLocalDepFile(pathToLockfile) if err != nil { diff --git a/internal/manifest/maven_test.go b/internal/manifest/maven_test.go index 0b8e73048f..d8b9fe1aba 100644 --- a/internal/manifest/maven_test.go +++ b/internal/manifest/maven_test.go @@ -2,6 +2,8 @@ package manifest_test import ( "io/fs" + "os" + "path/filepath" "testing" "github.com/google/osv-scanner/internal/manifest" @@ -358,3 +360,65 @@ func TestParseMavenWithResolver_Transitive(t *testing.T) { }, }) } + +func TestParentPOMPath(t *testing.T) { + t.Parallel() + dir, err := os.Getwd() + if err != nil { + t.Fatalf("failed to get current directory: %v", err) + } + tests := []struct { + currentPath, relativePath string + want string + }{ + // fixtures + // |- maven + // | |- my-app + // | | |- pom.xml + // | |- parent + // | | |- pom.xml + // |- pom.xml + { + // Parent path is specified correctly. + currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), + relativePath: "../parent/pom.xml", + want: filepath.Join(dir, "fixtures", "maven", "parent", "pom.xml"), + }, + { + // Wrong file name is specified in relative path. + currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), + relativePath: "../parent/abc.xml", + want: "", + }, + { + // Wrong directory is specified in relative path. + currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), + relativePath: "../not-found/pom.xml", + want: "", + }, + { + // Only directory is specified. + currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), + relativePath: "../parent", + want: filepath.Join(dir, "fixtures", "maven", "parent", "pom.xml"), + }, + { + // Parent relative path is default to '../pom.xml'. + currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), + relativePath: "", + want: filepath.Join(dir, "fixtures", "maven", "pom.xml"), + }, + { + // No pom.xml is found even in the default path. + currentPath: filepath.Join(dir, "fixtures", "maven", "pom.xml"), + relativePath: "", + want: "", + }, + } + for _, test := range tests { + got := manifest.MavenParentPOMPath(test.currentPath, test.relativePath) + if got != test.want { + t.Errorf("parentPOMPath(%s, %s): got %s, want %s", test.currentPath, test.relativePath, got, test.want) + } + } +} diff --git a/internal/remediation/override.go b/internal/remediation/override.go index bc75c2651b..9cedc63974 100644 --- a/internal/remediation/override.go +++ b/internal/remediation/override.go @@ -9,9 +9,10 @@ import ( "deps.dev/util/resolve" "deps.dev/util/resolve/dep" "deps.dev/util/semver" + "github.com/google/osv-scanner/internal/manifest" "github.com/google/osv-scanner/internal/resolution" "github.com/google/osv-scanner/internal/resolution/client" - "github.com/google/osv-scanner/internal/resolution/manifest" + resolutionmanifest "github.com/google/osv-scanner/internal/resolution/manifest" "github.com/google/osv-scanner/internal/resolution/util" "github.com/google/osv-scanner/internal/utility/vulns" ) @@ -76,9 +77,9 @@ func ComputeOverridePatches(ctx context.Context, cl client.ResolutionClient, res // CalculateDiff does not compute override manifest patches correctly, manually fill it out. // TODO: CalculateDiff maybe should not be reconstructing patches. // Refactor CalculateDiff, Relaxer, Override to make patches in a more sane way. - diff.Deps = make([]manifest.DependencyPatch, len(res.patches)) + diff.Deps = make([]resolutionmanifest.DependencyPatch, len(res.patches)) for i, p := range res.patches { - diff.Deps[i] = manifest.DependencyPatch{ + diff.Deps[i] = resolutionmanifest.DependencyPatch{ Pkg: p.PackageKey, Type: dep.Type{}, OrigRequire: "", // Using empty original to signal this is an override patch @@ -279,9 +280,9 @@ func getVersionsGreater(ctx context.Context, cl client.DependencyClient, vk reso } // patchManifest applies the overridePatches to the manifest in-memory. Returns a copy of the manifest that has been patched. -func patchManifest(patches []overridePatch, m manifest.Manifest) (manifest.Manifest, error) { +func patchManifest(patches []overridePatch, m resolutionmanifest.Manifest) (resolutionmanifest.Manifest, error) { if m.System() != resolve.Maven { - return manifest.Manifest{}, errors.New("unsupported ecosystem") + return resolutionmanifest.Manifest{}, errors.New("unsupported ecosystem") } // TODO: The overridePatch does not have an artifact's type or classifier, which is part of what uniquely identifies them. diff --git a/internal/resolution/manifest/maven.go b/internal/resolution/manifest/maven.go index 46a7c31676..6e18ec0b52 100644 --- a/internal/resolution/manifest/maven.go +++ b/internal/resolution/manifest/maven.go @@ -8,25 +8,17 @@ import ( "errors" "fmt" "io" - "os" - "path/filepath" "slices" "strings" "deps.dev/util/maven" "deps.dev/util/resolve" "deps.dev/util/resolve/dep" + "github.com/google/osv-scanner/internal/manifest" "github.com/google/osv-scanner/internal/resolution/datasource" "github.com/google/osv-scanner/pkg/lockfile" ) -const ( - OriginManagement = "management" - OriginParent = "parent" - OriginPlugin = "plugin" - OriginProfile = "profile" -) - func mavenRequirementKey(requirement resolve.RequirementVersion) RequirementKey { // Maven dependencies must have unique groupId:artifactId:type:classifier. artifactType, _ := requirement.Type.GetAttr(dep.MavenArtifactType) @@ -89,7 +81,7 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { VersionType: resolve.Requirement, Version: string(project.Parent.Version), }, - Type: resolve.MavenDepType(maven.Dependency{Type: "pom"}, OriginParent), + Type: resolve.MavenDepType(maven.Dependency{Type: "pom"}, manifest.OriginParent), }) } @@ -99,7 +91,7 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { } // Merging parents data by parsing local parent pom.xml or fetching from upstream. - if err := m.mergeParents(ctx, &project, project.Parent, 1, df.Path(), true); err != nil { + if err := manifest.MergeMavenParents(ctx, m.MavenRegistryAPIClient, &project, project.Parent, 1, df.Path(), true); err != nil { return Manifest{}, fmt.Errorf("failed to merge parents: %w", err) } @@ -108,7 +100,7 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { // dependencies, so add them to requirements first. for _, dep := range project.DependencyManagement.Dependencies { if dep.Scope == "import" && dep.Type == "pom" { - reqsForUpdates = append(reqsForUpdates, makeRequirementVersion(dep, OriginManagement)) + reqsForUpdates = append(reqsForUpdates, makeRequirementVersion(dep, manifest.OriginManagement)) } } @@ -122,7 +114,7 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { // To get dependency management from another project, we need the // project with parents merged, so we call mergeParents by passing // an empty project. - if err := m.mergeParents(ctx, &result, root, 0, "", false); err != nil { + if err := manifest.MergeMavenParents(ctx, m.MavenRegistryAPIClient, &result, root, 0, "", false); err != nil { return maven.DependencyManagement{}, err } @@ -131,12 +123,12 @@ func (m MavenManifestIO) Read(df lockfile.DepFile) (Manifest, error) { groups := make(map[RequirementKey][]string) requirements := addRequirements([]resolve.RequirementVersion{}, groups, project.Dependencies, "") - requirements = addRequirements(requirements, groups, project.DependencyManagement.Dependencies, OriginManagement) + requirements = addRequirements(requirements, groups, project.DependencyManagement.Dependencies, manifest.OriginManagement) // Requirements may not appear in the dependency graph but needs to be updated. for _, profile := range project.Profiles { reqsForUpdates = addRequirements(reqsForUpdates, groups, profile.Dependencies, "") - reqsForUpdates = addRequirements(reqsForUpdates, groups, profile.DependencyManagement.Dependencies, OriginManagement) + reqsForUpdates = addRequirements(reqsForUpdates, groups, profile.DependencyManagement.Dependencies, manifest.OriginManagement) } for _, plugin := range project.Build.PluginManagement.Plugins { reqsForUpdates = addRequirements(reqsForUpdates, groups, plugin.Dependencies, "") @@ -190,7 +182,7 @@ func buildPropertiesWithOrigins(project maven.Project) []PropertyWithOrigin { for _, prop := range profile.Properties.Properties { properties = append(properties, PropertyWithOrigin{ Property: prop, - Origin: mavenOrigin(OriginProfile, string(profile.ID)), + Origin: mavenOrigin(manifest.OriginProfile, string(profile.ID)), }) } } @@ -208,7 +200,7 @@ func buildOriginalRequirements(project maven.Project) []DependencyWithOrigin { Version: project.Parent.Version, Type: "pom", }, - Origin: OriginParent, + Origin: manifest.OriginParent, }) } for _, d := range project.Dependencies { @@ -217,20 +209,20 @@ func buildOriginalRequirements(project maven.Project) []DependencyWithOrigin { for _, d := range project.DependencyManagement.Dependencies { dependencies = append(dependencies, DependencyWithOrigin{ Dependency: d, - Origin: OriginManagement, + Origin: manifest.OriginManagement, }) } for _, prof := range project.Profiles { for _, d := range prof.Dependencies { dependencies = append(dependencies, DependencyWithOrigin{ Dependency: d, - Origin: mavenOrigin(OriginProfile, string(prof.ID)), + Origin: mavenOrigin(manifest.OriginProfile, string(prof.ID)), }) } for _, d := range prof.DependencyManagement.Dependencies { dependencies = append(dependencies, DependencyWithOrigin{ Dependency: d, - Origin: mavenOrigin(OriginProfile, string(prof.ID), OriginManagement), + Origin: mavenOrigin(manifest.OriginProfile, string(prof.ID), manifest.OriginManagement), }) } } @@ -238,7 +230,7 @@ func buildOriginalRequirements(project maven.Project) []DependencyWithOrigin { for _, d := range plugin.Dependencies { dependencies = append(dependencies, DependencyWithOrigin{ Dependency: d, - Origin: mavenOrigin(OriginPlugin, plugin.ProjectKey.Name()), + Origin: mavenOrigin(manifest.OriginPlugin, plugin.ProjectKey.Name()), }) } } @@ -246,89 +238,6 @@ func buildOriginalRequirements(project maven.Project) []DependencyWithOrigin { return dependencies } -// To avoid indefinite loop when fetching parents, -// set a limit on the number of parents. -const MaxParent = 100 - -func (m MavenManifestIO) mergeParents(ctx context.Context, result *maven.Project, current maven.Parent, start int, path string, allowLocal bool) error { - currentPath := path - visited := make(map[maven.ProjectKey]bool, MaxParent) - for n := start; n < MaxParent; n++ { - if current.GroupID == "" || current.ArtifactID == "" || current.Version == "" { - break - } - if visited[current.ProjectKey] { - // A cycle of parents is detected - return errors.New("a cycle of parents is detected") - } - visited[current.ProjectKey] = true - var proj maven.Project - parentFound := false - if parentPath := MavenParentPOMPath(currentPath, string(current.RelativePath)); allowLocal && parentPath != "" { - currentPath = parentPath - f, err := os.Open(parentPath) - if err != nil { - return fmt.Errorf("failed to open parent file %s: %w", parentPath, err) - } - if err := xml.NewDecoder(f).Decode(&proj); err != nil { - return fmt.Errorf("failed to unmarshal project: %w", err) - } - if proj.ProjectKey == current.ProjectKey && proj.Packaging == "pom" { - // Only mark parent is found when the identifiers and packaging are exptected. - parentFound = true - } - } - if !parentFound { - // Once we fetch a parent pom.xml from upstream, we should not allow - // parsing parent pom.xml locally anymore. - allowLocal = false - var err error - proj, err = m.MavenRegistryAPIClient.GetProject(ctx, string(current.GroupID), string(current.ArtifactID), string(current.Version)) - if err != nil { - return fmt.Errorf("failed to get Maven project %s:%s:%s: %w", current.GroupID, current.ArtifactID, current.Version, err) - } - if n > 0 && proj.Packaging != "pom" { - // A parent project should only be of "pom" packaging type. - return fmt.Errorf("invalid packaging for parent project %s", proj.Packaging) - } - if proj.ProjectKey != current.ProjectKey { - // The identifiers in parent does not match what we want. - return fmt.Errorf("parent identifiers mismatch: %v, expect %v", proj.ProjectKey, current.ProjectKey) - } - } - // Empty JDK and ActivationOS indicates merging the default profiles. - if err := result.MergeProfiles("", maven.ActivationOS{}); err != nil { - return err - } - result.MergeParent(proj) - current = proj.Parent - } - - return result.Interpolate() -} - -// Maven looks for the parent POM first in 'relativePath', -// then the local repository '../pom.xml', -// and lastly in the remote repo. -func MavenParentPOMPath(currentPath, relativePath string) string { - if relativePath == "" { - relativePath = "../pom.xml" - } - path := filepath.Join(filepath.Dir(currentPath), relativePath) - if info, err := os.Stat(path); err == nil { - if !info.IsDir() { - return path - } - // Current path is a directory, so look for pom.xml in the directory. - path = filepath.Join(path, "pom.xml") - if _, err := os.Stat(path); err == nil { - return path - } - } - - return "" -} - // For dependencies in profiles and plugins, we use origin to indicate where they are from. // The origin is in the format prefix@identifier[@postfix] (where @ is the separator): // - prefix indicates it is from profile or plugin @@ -466,9 +375,9 @@ func buildPatches(patches []DependencyPatch, specific MavenManifestSpecific) (Ma } depOrigin := origDep.Origin - if strings.HasPrefix(depOrigin, OriginProfile) { + if strings.HasPrefix(depOrigin, manifest.OriginProfile) { // Dependency management is not indicated in property origin. - depOrigin, _ = strings.CutSuffix(depOrigin, "@"+OriginManagement) + depOrigin, _ = strings.CutSuffix(depOrigin, "@"+manifest.OriginManagement) } else { // Properties are defined either universally or in a profile. For property // origin not starting with 'profile', this is an universal property. @@ -663,7 +572,7 @@ func write(buf *bytes.Buffer, w io.Writer, depPatches MavenDependencyPatches, pr } // Check whether dependency management is updated, if not, add a new section of dependency management. - if dmPatches := depPatches[OriginManagement]; len(dmPatches) > 0 && !updated[OriginManagement] { + if dmPatches := depPatches[manifest.OriginManagement]; len(dmPatches) > 0 && !updated[manifest.OriginManagement] { enc.Indent(" ", " ") var dm dependencyManagement for p := range dmPatches { @@ -763,7 +672,7 @@ func writeProject(w io.Writer, enc *xml.Encoder, raw, prefix, id string, patches if err := dec.DecodeElement(&rawProfile, &tt); err != nil { return err } - if err := writeProject(w, enc, ""+rawProfile.InnerXML+"", OriginProfile, string(rawProfile.ID), patches, properties, updated); err != nil { + if err := writeProject(w, enc, ""+rawProfile.InnerXML+"", manifest.OriginProfile, string(rawProfile.ID), patches, properties, updated); err != nil { return fmt.Errorf("updating profile: %w", err) } @@ -781,7 +690,7 @@ func writeProject(w io.Writer, enc *xml.Encoder, raw, prefix, id string, patches if err := dec.DecodeElement(&rawPlugin, &tt); err != nil { return err } - if err := writeProject(w, enc, ""+rawPlugin.InnerXML+"", OriginPlugin, rawPlugin.ProjectKey.Name(), patches, properties, updated); err != nil { + if err := writeProject(w, enc, ""+rawPlugin.InnerXML+"", manifest.OriginPlugin, rawPlugin.ProjectKey.Name(), patches, properties, updated); err != nil { return fmt.Errorf("updating profile: %w", err) } @@ -795,7 +704,7 @@ func writeProject(w io.Writer, enc *xml.Encoder, raw, prefix, id string, patches if err := dec.DecodeElement(&rawDepMgmt, &tt); err != nil { return err } - o := mavenOrigin(prefix, id, OriginManagement) + o := mavenOrigin(prefix, id, manifest.OriginManagement) updated[o] = true dmPatches := patches[o] if err := writeDependency(w, enc, ""+rawDepMgmt.InnerXML+"", dmPatches); err != nil { diff --git a/internal/resolution/manifest/maven_test.go b/internal/resolution/manifest/maven_test.go index 84f0c4fe0a..fd4cb32aa1 100644 --- a/internal/resolution/manifest/maven_test.go +++ b/internal/resolution/manifest/maven_test.go @@ -257,7 +257,7 @@ func TestMavenRead(t *testing.T) { {Property: maven.Property{Name: "maven.compiler.source", Value: "1.7"}}, {Property: maven.Property{Name: "maven.compiler.target", Value: "1.7"}}, {Property: maven.Property{Name: "junit.version", Value: "4.12"}}, - {Property: maven.Property{Name: "zeppelin.daemon.package.base", Value: "\n\t ../bin\n "}}, + {Property: maven.Property{Name: "zeppelin.daemon.package.base", Value: "../bin"}}, {Property: maven.Property{Name: "def.version", Value: "2.3.4"}, Origin: "profile@profile-one"}, }, OriginalRequirements: []DependencyWithOrigin{ @@ -868,65 +868,3 @@ func TestGeneratePropertyPatches(t *testing.T) { } } } - -func TestParentPOMPath(t *testing.T) { - t.Parallel() - dir, err := os.Getwd() - if err != nil { - t.Fatalf("failed to get current directory: %v", err) - } - tests := []struct { - currentPath, relativePath string - want string - }{ - // fixtures - // |- maven - // | |- my-app - // | | |- pom.xml - // | |- parent - // | | |- pom.xml - // |- pom.xml - { - // Parent path is specified correctly. - currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), - relativePath: "../parent/pom.xml", - want: filepath.Join(dir, "fixtures", "maven", "parent", "pom.xml"), - }, - { - // Wrong file name is specified in relative path. - currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), - relativePath: "../parent/abc.xml", - want: "", - }, - { - // Wrong directory is specified in relative path. - currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), - relativePath: "../not-found/pom.xml", - want: "", - }, - { - // Only directory is specified. - currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), - relativePath: "../parent", - want: filepath.Join(dir, "fixtures", "maven", "parent", "pom.xml"), - }, - { - // Parent relative path is default to '../pom.xml'. - currentPath: filepath.Join(dir, "fixtures", "maven", "my-app", "pom.xml"), - relativePath: "", - want: filepath.Join(dir, "fixtures", "maven", "pom.xml"), - }, - { - // No pom.xml is found even in the default path. - currentPath: filepath.Join(dir, "fixtures", "maven", "pom.xml"), - relativePath: "", - want: "", - }, - } - for _, test := range tests { - got := MavenParentPOMPath(test.currentPath, test.relativePath) - if got != test.want { - t.Errorf("parentPOMPath(%s, %s): got %s, want %s", test.currentPath, test.relativePath, got, test.want) - } - } -}