(root string)
| 406 | } |
| 407 | |
| 408 | func discoverCurrentPluginFiles(root string) ([]pluginFileInfo, error) { |
| 409 | root = strings.TrimSpace(root) |
| 410 | if root == "" { |
| 411 | root = "plugins" |
| 412 | } |
| 413 | candidates := pluginCandidateDirs(root, runtime.GOOS, runtime.GOARCH) |
| 414 | extension := pluginExtension(runtime.GOOS) |
| 415 | selected := make([]pluginFileInfo, 0) |
| 416 | seen := make(map[string]struct{}) |
| 417 | for _, dir := range candidates { |
| 418 | entries, errReadDir := os.ReadDir(dir) |
| 419 | if errReadDir != nil { |
| 420 | if os.IsNotExist(errReadDir) { |
| 421 | continue |
| 422 | } |
| 423 | return nil, errReadDir |
| 424 | } |
| 425 | files := make([]string, 0, len(entries)) |
| 426 | for _, entry := range entries { |
| 427 | if entry == nil || !entry.Type().IsRegular() { |
| 428 | continue |
| 429 | } |
| 430 | if strings.HasSuffix(strings.ToLower(entry.Name()), extension) { |
| 431 | files = append(files, filepath.Join(dir, entry.Name())) |
| 432 | } |
| 433 | } |
| 434 | sort.Strings(files) |
| 435 | for _, path := range files { |
| 436 | file, okFile := pluginFileInfoFromPath(path, extension) |
| 437 | if !okFile { |
| 438 | continue |
| 439 | } |
| 440 | if _, exists := seen[file.ID]; exists { |
| 441 | continue |
| 442 | } |
| 443 | seen[file.ID] = struct{}{} |
| 444 | selected = append(selected, file) |
| 445 | } |
| 446 | } |
| 447 | return selected, nil |
| 448 | } |
| 449 | |
| 450 | func pluginCandidateDirs(root string, goos string, goarch string) []string { |
| 451 | dirs := make([]string, 0, 2) |
nothing calls this directly
no test coverage detected