|
5 | 5 | "fmt"
|
6 | 6 | "net"
|
7 | 7 | "path"
|
| 8 | + "slices" |
| 9 | + "sync" |
8 | 10 |
|
9 | 11 | "github.com/containerd/containerd/platforms"
|
10 | 12 | "github.com/google/shlex"
|
@@ -111,16 +113,16 @@ func Reset(other State) StateOption {
|
111 | 113 | }
|
112 | 114 | }
|
113 | 115 |
|
114 |
| -func getEnv(s State) func(context.Context, *Constraints) (EnvList, error) { |
115 |
| - return func(ctx context.Context, c *Constraints) (EnvList, error) { |
| 116 | +func getEnv(s State) func(context.Context, *Constraints) (*EnvList, error) { |
| 117 | + return func(ctx context.Context, c *Constraints) (*EnvList, error) { |
116 | 118 | v, err := s.getValue(keyEnv)(ctx, c)
|
117 | 119 | if err != nil {
|
118 | 120 | return nil, err
|
119 | 121 | }
|
120 | 122 | if v != nil {
|
121 |
| - return v.(EnvList), nil |
| 123 | + return v.(*EnvList), nil |
122 | 124 | }
|
123 |
| - return EnvList{}, nil |
| 125 | + return &EnvList{}, nil |
124 | 126 | }
|
125 | 127 | }
|
126 | 128 |
|
@@ -346,54 +348,83 @@ func getSecurity(s State) func(context.Context, *Constraints) (pb.SecurityMode,
|
346 | 348 | }
|
347 | 349 | }
|
348 | 350 |
|
349 |
| -type EnvList []KeyValue |
350 |
| - |
351 |
| -type KeyValue struct { |
352 |
| - key string |
353 |
| - value string |
| 351 | +type EnvList struct { |
| 352 | + parent *EnvList |
| 353 | + key string |
| 354 | + value string |
| 355 | + del bool |
| 356 | + once sync.Once |
| 357 | + l int |
| 358 | + values map[string]string |
| 359 | + keys []string |
354 | 360 | }
|
355 | 361 |
|
356 |
| -func (e EnvList) AddOrReplace(k, v string) EnvList { |
357 |
| - e = e.Delete(k) |
358 |
| - e = append(e, KeyValue{key: k, value: v}) |
359 |
| - return e |
| 362 | +func (e *EnvList) AddOrReplace(k, v string) *EnvList { |
| 363 | + return &EnvList{ |
| 364 | + parent: e, |
| 365 | + key: k, |
| 366 | + value: v, |
| 367 | + l: e.l + 1, |
| 368 | + } |
360 | 369 | }
|
361 | 370 |
|
362 |
| -func (e EnvList) SetDefault(k, v string) EnvList { |
| 371 | +func (e *EnvList) SetDefault(k, v string) *EnvList { |
363 | 372 | if _, ok := e.Get(k); !ok {
|
364 |
| - e = append(e, KeyValue{key: k, value: v}) |
| 373 | + return e.AddOrReplace(k, v) |
365 | 374 | }
|
366 | 375 | return e
|
367 | 376 | }
|
368 | 377 |
|
369 |
| -func (e EnvList) Delete(k string) EnvList { |
370 |
| - e = append([]KeyValue(nil), e...) |
371 |
| - if i, ok := e.Index(k); ok { |
372 |
| - return append(e[:i], e[i+1:]...) |
| 378 | +func (e *EnvList) Delete(k string) EnvList { |
| 379 | + return EnvList{ |
| 380 | + parent: e, |
| 381 | + key: k, |
| 382 | + del: true, |
| 383 | + l: e.l + 1, |
373 | 384 | }
|
374 |
| - return e |
375 | 385 | }
|
376 | 386 |
|
377 |
| -func (e EnvList) Get(k string) (string, bool) { |
378 |
| - if index, ok := e.Index(k); ok { |
379 |
| - return e[index].value, true |
380 |
| - } |
381 |
| - return "", false |
| 387 | +func (e *EnvList) makeValues() { |
| 388 | + m := make(map[string]string, e.l) |
| 389 | + seen := make(map[string]struct{}, e.l) |
| 390 | + keys := make([]string, 0, e.l) |
| 391 | + e.keys = e.addValue(keys, m, seen) |
| 392 | + e.values = m |
| 393 | + slices.Reverse(e.keys) |
382 | 394 | }
|
383 | 395 |
|
384 |
| -func (e EnvList) Index(k string) (int, bool) { |
385 |
| - for i, kv := range e { |
386 |
| - if kv.key == k { |
387 |
| - return i, true |
388 |
| - } |
| 396 | +func (e *EnvList) addValue(keys []string, vals map[string]string, seen map[string]struct{}) []string { |
| 397 | + if e.parent == nil { |
| 398 | + return keys |
389 | 399 | }
|
390 |
| - return -1, false |
| 400 | + if _, ok := seen[e.key]; !e.del && !ok { |
| 401 | + vals[e.key] = e.value |
| 402 | + keys = append(keys, e.key) |
| 403 | + } |
| 404 | + seen[e.key] = struct{}{} |
| 405 | + if e.parent != nil { |
| 406 | + keys = e.parent.addValue(keys, vals, seen) |
| 407 | + } |
| 408 | + return keys |
| 409 | +} |
| 410 | + |
| 411 | +func (e *EnvList) Get(k string) (string, bool) { |
| 412 | + e.once.Do(e.makeValues) |
| 413 | + v, ok := e.values[k] |
| 414 | + return v, ok |
| 415 | +} |
| 416 | + |
| 417 | +func (e *EnvList) Keys() []string { |
| 418 | + e.once.Do(e.makeValues) |
| 419 | + return e.keys |
391 | 420 | }
|
392 | 421 |
|
393 |
| -func (e EnvList) ToArray() []string { |
394 |
| - out := make([]string, 0, len(e)) |
395 |
| - for _, kv := range e { |
396 |
| - out = append(out, kv.key+"="+kv.value) |
| 422 | +func (e *EnvList) ToArray() []string { |
| 423 | + keys := e.Keys() |
| 424 | + out := make([]string, 0, len(keys)) |
| 425 | + for _, k := range keys { |
| 426 | + v, _ := e.Get(k) |
| 427 | + out = append(out, k+"="+v) |
397 | 428 | }
|
398 | 429 | return out
|
399 | 430 | }
|
0 commit comments