2019-09-23 21:30:20 +03:00

73 lines
1.8 KiB
Go

// Package glob provides file globbing for use in nfpm.Packager implementations
package glob
import (
"fmt"
"os"
"path/filepath"
"github.com/mattn/go-zglob"
"github.com/pkg/errors"
)
// longestCommonPrefix returns the longest prefix of all strings the argument
// slice. If the slice is empty the empty string is returned
func longestCommonPrefix(strs []string) string {
if len(strs) == 0 {
return ""
}
lcp := strs[0]
for _, str := range strs {
lcp = strlcp(lcp, str)
}
return lcp
}
func strlcp(a string, b string) string {
var min int
if len(a) > len(b) {
min = len(b)
} else {
min = len(a)
}
for i := 0; i < min; i++ {
if a[i] != b[i] {
return a[0:i]
}
}
return a[0:min]
}
// Glob returns a map with source file path as keys and destination as values.
// First the longest common prefix (lcp) of all globbed files is found. The destination
// for each globbed file is then dst joined with src with the lcp trimmed off.
func Glob(glob, dst string) (map[string]string, error) {
matches, err := zglob.Glob(glob)
if err != nil {
return nil, errors.Wrap(err, glob)
}
if len(matches) == 0 {
return nil, fmt.Errorf("%s: no matching files", glob)
}
files := make(map[string]string)
prefix := longestCommonPrefix(matches)
// the prefix may not be a complete path, in that case use the parent directory
if _, err := os.Stat(prefix); os.IsNotExist(err) {
prefix = filepath.Dir(prefix)
}
for _, src := range matches {
// only include files
if f, err := os.Stat(src); err == nil && f.Mode().IsDir() {
continue
}
relpath, err := filepath.Rel(prefix, src)
if err != nil {
// since prefix is a prefix of src a relative path should always be found
panic(err)
}
globdst := filepath.Join(dst, relpath)
files[src] = globdst
}
return files, nil
}