tools.go
1 package tools 2 3 import ( 4 "errors" 5 "fmt" 6 "sort" 7 8 pkgerrors "github.com/pkg/errors" 9 "golang.org/x/exp/maps" 10 11 "github.com/symflower/eval-dev-quality/log" 12 ) 13 14 // Tools holds a register of all tools. 15 var Tools = map[string]Tool{} 16 17 // Register adds a tool to the common tool list. 18 func Register(tool Tool) { 19 id := tool.ID() 20 if _, ok := Tools[id]; ok { 21 panic(pkgerrors.WithMessage(pkgerrors.New("tool was already registered"), id)) 22 } 23 24 Tools[id] = tool 25 } 26 27 // Tool defines an external tool. 28 type Tool interface { 29 // ID returns the unique ID of this tool. 30 ID() (id string) 31 // BinaryName returns the name of the tool's binary. 32 BinaryName() string 33 // BinaryPath returns the file path of the tool's binary or the command name that should be executed. 34 // The binary path might also be just the binary name in case the tool is expected to be on the system path. 35 BinaryPath() string 36 37 // CheckVersion checks if the tool's version is compatible with the required version. 38 CheckVersion(logger *log.Logger, binaryPath string) error 39 // RequiredVersion returns the required version of the tool. 40 RequiredVersion() string 41 42 // Install installs the tool's binary to the given install path. 43 Install(logger *log.Logger, installPath string) error 44 } 45 46 // InstallAll installs all tools. 47 func InstallAll(logger *log.Logger, installPath string) (err error) { 48 var installErrors []error 49 toolKeys := maps.Keys(Tools) 50 sort.Strings(toolKeys) 51 for _, toolID := range toolKeys { 52 tool := Tools[toolID] 53 54 if err := InstallTool(logger, tool, installPath); err != nil { 55 // Log if a tool is not supported by the operating system, but do not fail as it is not a necessary tool. 56 if pkgerrors.Is(err, ErrUnsupportedOperatingSystem) { 57 logger.Printf("WARNING: tool %s is not supported by the operating system", tool.ID()) 58 59 continue 60 } 61 62 err = pkgerrors.WithStack(pkgerrors.WithMessage(err, fmt.Sprintf("cannot install %q", tool.ID()))) 63 installErrors = append(installErrors, err) 64 } 65 } 66 67 if len(installErrors) > 0 { 68 return errors.Join(installErrors...) 69 } 70 71 return nil 72 } 73 74 // InstallEvaluation installs all basic evaluation tools. 75 func InstallEvaluation(logger *log.Logger, installPath string) (err error) { 76 if err := InstallTool(logger, NewSymflower(), installPath); err != nil { 77 return pkgerrors.WithStack(pkgerrors.WithMessage(err, "cannot install Symflower")) 78 } 79 80 return nil 81 }