mirror of
https://github.com/docker/docker-agent.git
synced 2026-11-04 10:02:15 +00:00
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// Helpers shared by the cops in this package. They centralise the parsing of
|
|
// pkg/config/<dir>/ paths and pkg/config/vN import paths, so each cop can
|
|
// focus on its rule rather than on regular expressions.
|
|
|
|
// versionFromDir parses a "vN" directory name and returns N. Returns false
|
|
// for any other name (latest, types, vendor, ...).
|
|
func versionFromDir(dir string) (int, bool) {
|
|
if len(dir) < 2 || dir[0] != 'v' {
|
|
return 0, false
|
|
}
|
|
n, err := strconv.Atoi(dir[1:])
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
return n, true
|
|
}
|
|
|
|
// versionFromImport returns N if importPath ends with "pkg/config/vN".
|
|
// Re-uses [versionFromDir] for the vN suffix, so the two helpers cannot
|
|
// drift apart.
|
|
func versionFromImport(importPath string) (int, bool) {
|
|
_, dir, found := strings.CutLast(importPath, "pkg/config/")
|
|
if !found {
|
|
return 0, false
|
|
}
|
|
return versionFromDir(dir)
|
|
}
|
|
|
|
// highestSiblingVersion returns the largest N such that pkg/config/vN/
|
|
// exists as a sibling of filename's directory. Result is cached per
|
|
// parent directory so callers can invoke it once per file cheaply.
|
|
func highestSiblingVersion(filename string) (int, bool) {
|
|
abs, err := filepath.Abs(filename)
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
parent := filepath.Dir(filepath.Dir(abs))
|
|
|
|
if v, ok := highestCache.Load(parent); ok {
|
|
n := v.(int)
|
|
return n, n >= 0
|
|
}
|
|
n := scanHighestVN(parent)
|
|
highestCache.Store(parent, n)
|
|
return n, n >= 0
|
|
}
|
|
|
|
// highestCache memoises highestSiblingVersion. Value is -1 when no vN/
|
|
// directory exists under the key.
|
|
var highestCache sync.Map
|
|
|
|
func scanHighestVN(dir string) int {
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return -1
|
|
}
|
|
highest := -1
|
|
for _, e := range entries {
|
|
if !e.IsDir() {
|
|
continue
|
|
}
|
|
if n, ok := versionFromDir(e.Name()); ok && n > highest {
|
|
highest = n
|
|
}
|
|
}
|
|
return highest
|
|
}
|