-
Notifications
You must be signed in to change notification settings - Fork 193
fix(java): add hash of GAV+root pom file path for pkgID for packages from pom.xml files #9880
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
ec428df
71cec98
d3f4405
96a4159
d23481d
15af332
d0edab9
0c42925
643cbeb
9a2270b
c9cda67
c111673
6b8ceaa
e168939
1be9285
f4a5a14
62f5bd5
22d7f4a
88e2f7c
c846294
3adddfd
dec5adf
9d46a38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,9 +13,11 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "path/filepath" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "slices" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sort" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strconv" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/hashicorp/go-multierror" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/mitchellh/hashstructure/v2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/samber/lo" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "golang.org/x/net/html/charset" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "golang.org/x/xerrors" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -123,7 +125,9 @@ func (p *Parser) Parse(ctx context.Context, r xio.ReadSeekerAt) ([]ftypes.Packag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Analyze root POM | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result, err := p.analyze(ctx, root, analysisOptions{}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result, err := p.analyze(ctx, root, analysisOptions{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootFilePath: p.rootPath, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, xerrors.Errorf("analyze error (%s): %w", p.rootPath, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -133,12 +137,17 @@ func (p *Parser) Parse(ctx context.Context, r xio.ReadSeekerAt) ([]ftypes.Packag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootArt := root.artifact() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootArt.Relationship = ftypes.RelationshipRoot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootArt.RootFilePath = p.rootPath | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return p.parseRoot(ctx, rootArt, set.New[string]()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // nolint: gocyclo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (p *Parser) parseRoot(ctx context.Context, root artifact, uniqModules set.Set[string]) ([]ftypes.Package, []ftypes.Dependency, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if root.RootFilePath == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, xerrors.New("root file path should be filled") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Prepare a queue for dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| queue := newArtifactQueue() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -161,10 +170,11 @@ func (p *Parser) parseRoot(ctx context.Context, root artifact, uniqModules set.S | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Modules should be handled separately so that they can have independent dependencies. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // It means multi-module allows for duplicate dependencies. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if art.Module { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if uniqModules.Contains(art.String()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id := packageID(art.Name(), art.Version.String(), art.RootFilePath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if uniqModules.Contains(id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uniqModules.Append(art.String()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uniqModules.Append(id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| modulePkgs, moduleDeps, err := p.parseRoot(ctx, art, uniqModules) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -245,14 +255,14 @@ func (p *Parser) parseRoot(ctx context.Context, root artifact, uniqModules set.S | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn := lo.Map(result.dependencies, func(a artifact, _ int) string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return a.Name() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uniqDeps[packageID(art.Name(), art.Version.String())] = dependsOn | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uniqDeps[packageID(art.Name(), art.Version.String(), root.RootFilePath)] = dependsOn | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Convert to []ftypes.Package and []ftypes.Dependency | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for name, art := range uniqArtifacts { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pkg := ftypes.Package{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ID: packageID(name, art.Version.String()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ID: packageID(name, art.Version.String(), root.RootFilePath), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Name: name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Version: art.Version.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Licenses: art.Licenses, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -264,7 +274,7 @@ func (p *Parser) parseRoot(ctx context.Context, root artifact, uniqModules set.S | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Convert dependency names into dependency IDs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn := lo.FilterMap(uniqDeps[pkg.ID], func(dependOnName string, _ int) (string, bool) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ver := depVersion(dependOnName, uniqArtifacts) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return packageID(dependOnName, ver), ver != "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return packageID(dependOnName, ver, root.RootFilePath), ver != "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // `mvn` shows modules separately from the root package and does not show module nesting. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -303,13 +313,16 @@ func (p *Parser) parseModule(ctx context.Context, currentPath, relativePath stri | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return artifact{}, xerrors.Errorf("unable to open the relative path: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result, err := p.analyze(ctx, module, analysisOptions{}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result, err := p.analyze(ctx, module, analysisOptions{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootFilePath: module.filePath, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return artifact{}, xerrors.Errorf("analyze error: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleArtifact := module.artifact() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleArtifact.Module = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleArtifact.RootFilePath = module.filePath | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleArtifact.Relationship = ftypes.RelationshipWorkspace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| p.cache.put(moduleArtifact, result) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -343,6 +356,7 @@ func (p *Parser) resolve(ctx context.Context, art artifact, rootDepManagement [] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result, err := p.analyze(ctx, pomContent, analysisOptions{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclusions: art.Exclusions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| depManagement: rootDepManagement, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootFilePath: art.RootFilePath, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return analysisResult{}, xerrors.Errorf("analyze error: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -364,6 +378,7 @@ type analysisResult struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type analysisOptions struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclusions set.Set[string] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| depManagement []pomDependency // from the root POM | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootFilePath string // File path of the root POM or module POM | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (p *Parser) analyze(ctx context.Context, pom *pom, opts analysisOptions) (analysisResult, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -393,9 +408,12 @@ func (p *Parser) analyze(ctx context.Context, pom *pom, opts analysisOptions) (a | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| deps = p.filterDependencies(deps, opts.exclusions) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| art := pom.artifact() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| art.RootFilePath = opts.rootFilePath | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return analysisResult{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filePath: pom.filePath, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| artifact: pom.artifact(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| artifact: art, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependencies: deps, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependencyManagement: depManagement, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| properties: props, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -875,8 +893,19 @@ func parseMavenMetadata(r io.Reader) (*Metadata, error) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return parsed, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func packageID(name, version string) string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return dependency.ID(ftypes.Pom, name, version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func packageID(name, version, pomFilePath string) string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| v := map[string]any{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gav": dependency.ID(ftypes.Pom, name, version), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "path": filepath.ToSlash(pomFilePath), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| h, err := hashstructure.Hash(v, hashstructure.FormatV2, &hashstructure.HashOptions{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZeroNil: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IgnoreZeroValue: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Warn("Failed to calculate the pom.xml hash", log.String("name", name), log.String("version", version), log.Err(err)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return strconv.FormatUint(h, 16) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func packageID(name, version, pomFilePath string) string { | |
| v := map[string]any{ | |
| "gav": dependency.ID(ftypes.Pom, name, version), | |
| "path": filepath.ToSlash(pomFilePath), | |
| } | |
| h, err := hashstructure.Hash(v, hashstructure.FormatV2, &hashstructure.HashOptions{ | |
| ZeroNil: true, | |
| IgnoreZeroValue: true, | |
| }) | |
| if err != nil { | |
| log.Warn("Failed to calculate the pom.xml hash", log.String("name", name), log.String("version", version), log.Err(err)) | |
| } | |
| return strconv.FormatUint(h, 16) | |
| func packageID(name, version, pomFilePath string) string { | |
| gav := dependency.ID(ftypes.Pom, name, version) | |
| v := map[string]any{ | |
| "gav": gav, | |
| "path": filepath.ToSlash(pomFilePath), | |
| } | |
| h, err := hashstructure.Hash(v, hashstructure.FormatV2, &hashstructure.HashOptions{ | |
| ZeroNil: true, | |
| IgnoreZeroValue: true, | |
| }) | |
| if err != nil { | |
| log.Warn("Failed to calculate hash", log.Err(err)) | |
| return gav // fallback to GAV only | |
| } | |
| // Append 8-character hash suffix | |
| return fmt.Sprintf("%s::%s", gav, strconv.FormatUint(h, 16)[:8]) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good idea!
Updated in 1be9285
Uh oh!
There was an error while loading. Please reload this page.