Repository navigation
Expand file tree
/
Copy pathproject.go
More file actions
84 lines (74 loc) · 2.15 KB
/
Copy pathproject.go
File metadata and controls
84 lines (74 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package provides
import (
"context"
"errors"
"fmt"
"sort"
)
// ProjectSurfaceResult contains the package surfaces resolved for one set of
// project dependencies and any non-fatal diagnostics.
type ProjectSurfaceResult struct {
Surfaces []Surface
Diagnostics []Diagnostic
}
// ResolveProjectSurfaces resolves surfaces for caller-supplied project
// dependencies. It continues after resolver errors and returns successful
// surfaces alongside the joined error.
func ResolveProjectSurfaces(
ctx context.Context,
resolver SurfaceResolver,
packages []Package,
options SurfaceOptions,
) (ProjectSurfaceResult, error) {
if resolver == nil {
return ProjectSurfaceResult{}, fmt.Errorf("resolve project surfaces: nil resolver")
}
unique := make(map[string]Package, len(packages))
for _, pkg := range packages {
unique[pkg.PURL] = pkg
}
ordered := make([]Package, 0, len(unique))
for _, pkg := range unique {
ordered = append(ordered, pkg)
}
sort.Slice(ordered, func(i, j int) bool {
return ordered[i].PURL < ordered[j].PURL
})
byPURL := make(map[string][]SurfaceResult)
diagnostics := make([]Diagnostic, 0)
var errs []error
for _, pkg := range ordered {
if err := ctx.Err(); err != nil {
errs = append(errs, err)
break
}
result, err := resolver.ResolveSurface(ctx, pkg, options)
diagnostics = append(diagnostics, result.Diagnostics...)
if err != nil {
errs = append(errs, fmt.Errorf("resolve surface %q: %w", pkg.PURL, err))
}
if len(result.Surface.Provides) == 0 {
continue
}
resolvedPURL := result.Surface.PURL
if resolvedPURL == "" {
resolvedPURL = pkg.PURL
result.Surface.PURL = resolvedPURL
}
byPURL[resolvedPURL] = append(byPURL[resolvedPURL], result)
}
purls := make([]string, 0, len(byPURL))
for packagePURL := range byPURL {
purls = append(purls, packagePURL)
}
sort.Strings(purls)
surfaces := make([]Surface, 0, len(purls))
for _, packagePURL := range purls {
merged := MergeSurfaceResults(packagePURL, byPURL[packagePURL]...)
surfaces = append(surfaces, merged.Surface)
}
return ProjectSurfaceResult{
Surfaces: surfaces,
Diagnostics: mergeDiagnostics(diagnostics),
}, errors.Join(errs...)
}