55 lines
1.7 KiB
Go
55 lines
1.7 KiB
Go
package skills
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/cli/cli/v2/internal/skills/discovery"
|
|
)
|
|
|
|
// NameCollision represents a group of skills that share the same InstallName
|
|
// and would overwrite each other when installed to the same directory.
|
|
type NameCollision struct {
|
|
Name string // the conflicting install name (may include namespace prefix)
|
|
DisplayNames []string // display names of each conflicting skill
|
|
}
|
|
|
|
// FindNameCollisions detects skills that share the same InstallName and returns a
|
|
// sorted slice of collisions. Callers decide how to present the conflict to
|
|
// the user (different flows need different error messages).
|
|
func FindNameCollisions(skills []discovery.Skill) []NameCollision {
|
|
byName := make(map[string][]discovery.Skill)
|
|
for _, s := range skills {
|
|
byName[s.InstallName()] = append(byName[s.InstallName()], s)
|
|
}
|
|
|
|
var collisions []NameCollision
|
|
for name, group := range byName {
|
|
if len(group) <= 1 {
|
|
continue
|
|
}
|
|
names := make([]string, len(group))
|
|
for i, s := range group {
|
|
names[i] = s.DisplayName()
|
|
}
|
|
collisions = append(collisions, NameCollision{Name: name, DisplayNames: names})
|
|
}
|
|
|
|
sort.Slice(collisions, func(i, j int) bool {
|
|
return collisions[i].Name < collisions[j].Name
|
|
})
|
|
return collisions
|
|
}
|
|
|
|
// FormatCollisions builds a human-readable string listing each collision,
|
|
// suitable for embedding in an error message. Each collision is formatted as
|
|
// "name: display1, display2" and collisions are separated by newlines with
|
|
// leading indentation.
|
|
func FormatCollisions(collisions []NameCollision) string {
|
|
lines := make([]string, len(collisions))
|
|
for i, c := range collisions {
|
|
lines[i] = fmt.Sprintf("%s: %s", c.Name, strings.Join(c.DisplayNames, ", "))
|
|
}
|
|
return strings.Join(lines, "\n ")
|
|
}
|