@@ -11,6 +11,7 @@ import (
1111 "golang.org/x/sync/errgroup"
1212
1313 "go.wpm.so/cli/pkg/pm/registry"
14+ "go.wpm.so/cli/pkg/pm/signatures"
1415 "go.wpm.so/cli/pkg/pm/wpmjson"
1516 "go.wpm.so/cli/pkg/pm/wpmjson/manifest"
1617 "go.wpm.so/cli/pkg/pm/wpmjson/types"
@@ -37,6 +38,7 @@ type Resolver struct {
3738 rootConfig * wpmjson.Config
3839 lockfile * wpmlock.Lockfile
3940 client registry.Client
41+ verifier * signatures.Verifier
4042}
4143
4244func New (rootConfig * wpmjson.Config , lockfile * wpmlock.Lockfile , client registry.Client ) * Resolver {
@@ -59,6 +61,12 @@ type fetchResult struct {
5961}
6062
6163func (r * Resolver ) Resolve (ctx context.Context , progress ProgressReporter , w io.Writer ) (map [string ]Node , error ) {
64+ keys , err := r .client .GetKeysJson (ctx )
65+ if err != nil {
66+ return nil , fmt .Errorf ("failed to fetch signing keys: %w" , err )
67+ }
68+ r .verifier = signatures .New (keys )
69+
6270 resolved := make (map [string ]Node )
6371 queue := r .seedQueue ()
6472
@@ -94,7 +102,15 @@ func (r *Resolver) Resolve(ctx context.Context, progress ProgressReporter, w io.
94102}
95103
96104func (r * Resolver ) seedQueue () []dependencyRequest {
97- var queue []dependencyRequest
105+ n := 0
106+ if r .rootConfig .Dependencies != nil {
107+ n += len (* r .rootConfig .Dependencies )
108+ }
109+ if r .rootConfig .DevDependencies != nil {
110+ n += len (* r .rootConfig .DevDependencies )
111+ }
112+
113+ queue := make ([]dependencyRequest , 0 , n )
98114 if r .rootConfig .Dependencies != nil {
99115 for name , version := range * r .rootConfig .Dependencies {
100116 queue = append (queue , dependencyRequest {name : name , version : version , requestor : "<root>" })
@@ -108,21 +124,26 @@ func (r *Resolver) seedQueue() []dependencyRequest {
108124 return queue
109125}
110126
127+ type requestKey struct {
128+ name string
129+ version string
130+ }
131+
111132// dedupeRequests drops requests already satisfied at the same version
112133// and folds identical name@version pairs in this iteration into one entry.
113- func dedupeRequests (queue []dependencyRequest , resolved map [string ]Node ) map [string ]dependencyRequest {
114- uniqueRequests := make (map [string ]dependencyRequest )
134+ func dedupeRequests (queue []dependencyRequest , resolved map [string ]Node ) map [requestKey ]dependencyRequest {
135+ unique := make (map [requestKey ]dependencyRequest , len ( queue ) )
115136 for _ , req := range queue {
116137 if exists , ok := resolved [req .name ]; ok && exists .Version == req .version {
117138 continue
118139 }
119- uniqueRequests [ req .name + "@" + req .version ] = req
140+ unique [ requestKey { req .name , req .version } ] = req
120141 }
121- return uniqueRequests
142+ return unique
122143}
123144
124145// fetchAll fetches metadata for every request concurrently and returns the collected results.
125- func (r * Resolver ) fetchAll (ctx context.Context , requests map [string ]dependencyRequest , progress ProgressReporter , w io.Writer ) ([]fetchResult , error ) {
146+ func (r * Resolver ) fetchAll (ctx context.Context , requests map [requestKey ]dependencyRequest , progress ProgressReporter , w io.Writer ) ([]fetchResult , error ) {
126147 results := make (chan fetchResult , len (requests ))
127148 g , gtx := errgroup .WithContext (ctx )
128149 g .SetLimit (16 )
@@ -137,6 +158,9 @@ func (r *Resolver) fetchAll(ctx context.Context, requests map[string]dependencyR
137158 if err != nil {
138159 return fmt .Errorf ("failed to fetch metadata for %s@%s required by %s: %w" , req .name , req .version , req .requestor , err )
139160 }
161+ if err := r .verifier .Verify (manifest ); err != nil {
162+ return fmt .Errorf ("signature verification failed for %s@%s required by %s: %w" , req .name , req .version , req .requestor , err )
163+ }
140164 results <- fetchResult {req : req , manifest : manifest }
141165 return nil
142166 })
0 commit comments