package model
import (
"cmp"
"path/filepath"
"slices"
"strings"
)
type LibraryMatcher struct {
libraries Libraries
cleanedPaths []string
}
func NewLibraryMatcher(libs Libraries) *LibraryMatcher {
libs = slices.Clone(libs)
slices.SortFunc(libs, func(i, j Library) int {
return cmp.Compare(len(j.Path), len(i.Path))
})
cleanedPaths := make([]string, len(libs))
for i, lib := range libs {
cleanedPaths[i] = filepath.Clean(lib.Path)
}
return &LibraryMatcher{libraries: libs, cleanedPaths: cleanedPaths}
}
func (lm *LibraryMatcher) FindLibrary(absolutePath string) (Library, bool) {
for i, libPath := range lm.cleanedPaths {
if strings.HasPrefix(absolutePath, libPath) && (len(absolutePath) == len(libPath) ||
absolutePath[len(libPath)] == filepath.Separator || strings.HasSuffix(libPath, string(filepath.Separator))) {
return lm.libraries[i], true
}
}
return Library{}, false
}
func LibraryRelativePath(libPath, path string) string {
if !filepath.IsAbs(path) {
return path
}
absLib, err := filepath.Abs(libPath)
if err != nil {
return path
}
rel, err := filepath.Rel(absLib, path)
if err != nil || !filepath.IsLocal(rel) {
return path
}
return filepath.ToSlash(rel)
}