miqt/cmd/miqt-docker/filepath.go

65 lines
1.4 KiB
Go

package main
import (
"errors"
"fmt"
"path/filepath"
"runtime"
"strings"
)
// highestCommonParent finds the oldest ancestor of a set of paths.
// If there is no common ancestor, returns / on Linux or an error on Windows.
func highestCommonParent(paths []string) (string, error) {
if len(paths) == 0 {
return "", errors.New("no input")
}
parts := strings.Split(paths[0], string(filepath.Separator))
caseSensitive := runtime.GOOS != "windows"
for _, check := range paths {
checkn := strings.Split(check, string(filepath.Separator))
// If this check path is shorter, the common part must also shrink
if len(checkn) < len(parts) {
parts = parts[0:len(checkn)]
}
for i, checkpart := range checkn[0:len(parts)] { // len(parts) is now <= len(checkn) so this is safe
if caseSensitive {
if parts[i] == checkpart {
continue
}
} else {
// case insensitive comparison
if strings.EqualFold(parts[i], checkpart) {
continue
}
}
// Divergence from i: onwards
parts = parts[0:i]
break
}
// Early failure case
if len(parts) == 0 {
break
}
}
isEmpty := len(parts) == 0 || (len(parts) == 1 && parts[0] == "")
if isEmpty {
if runtime.GOOS == "windows" {
return "", fmt.Errorf("Selected paths have no common ancestor: %v", paths)
}
return `/`, nil
}
return strings.Join(parts, string(filepath.Separator)), nil
}