mesh/delivery merged: source.main moved to novox/mesh-catalog@25f615456423
mesh/delivery-group group words/catalog merged: every member is merged
mesh/check being carried to b8ba9dd9669c on 25f615456423 | from 774fcdfa93ad, hq 8f8393fa9343 | novox/mesh-catalog#540 in group words/catalog
85 lines
2.7 KiB
Go
85 lines
2.7 KiB
Go
// Package nobinaries refuses a compiled program anywhere in the repository (issue 1577; first a checks/ binary slipped past a modules/-only rule): it is build output, made by the module's build step,
|
|
// and `go build` in a module's folder writes one beside go.mod where `git add -A` takes it.
|
|
package nobinaries
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// Kind says what executable format the first bytes of a file are, or "" when they are none.
|
|
func Kind(head []byte) string {
|
|
switch {
|
|
case bytes.HasPrefix(head, []byte("\x7fELF")):
|
|
return "ELF"
|
|
case bytes.HasPrefix(head, []byte("MZ")):
|
|
return "PE"
|
|
case bytes.HasPrefix(head, []byte{0xcf, 0xfa, 0xed, 0xfe}), bytes.HasPrefix(head, []byte{0xce, 0xfa, 0xed, 0xfe}),
|
|
bytes.HasPrefix(head, []byte{0xfe, 0xed, 0xfa, 0xcf}), bytes.HasPrefix(head, []byte{0xfe, 0xed, 0xfa, 0xce}),
|
|
bytes.HasPrefix(head, []byte{0xca, 0xfe, 0xba, 0xbe}) && len(head) >= 8 && head[7] < 0x20 && head[6] == 0 && head[5] == 0 && head[4] == 0:
|
|
return "Mach-O"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Files are the files of the catalogue's root that the change holds, anywhere: the tracked ones when the root is a git
|
|
// checkout (an ignored binary a local build left is not the change's), else every file there but .git's.
|
|
func Files(root string) ([]string, error) {
|
|
cmd := exec.Command("git", "-C", root, "ls-files", "-z")
|
|
if out, err := cmd.Output(); err == nil && len(out) > 0 {
|
|
var files []string
|
|
for _, f := range strings.Split(strings.TrimRight(string(out), "\x00"), "\x00") {
|
|
if _, err := os.Lstat(filepath.Join(root, f)); err == nil { // a file the change deletes is not there
|
|
files = append(files, f)
|
|
}
|
|
}
|
|
return files, nil
|
|
}
|
|
var files []string
|
|
err := filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if d.IsDir() && d.Name() == ".git" {
|
|
return filepath.SkipDir
|
|
}
|
|
if d.IsDir() || !d.Type().IsRegular() {
|
|
return nil
|
|
}
|
|
rel, _ := filepath.Rel(root, p)
|
|
files = append(files, rel)
|
|
return nil
|
|
})
|
|
return files, err
|
|
}
|
|
|
|
// Find names each file of files (paths from root) that is a compiled program, with its format.
|
|
func Find(root string, files []string) ([]string, error) {
|
|
var found []string
|
|
for _, f := range files {
|
|
p := filepath.Join(root, f)
|
|
if st, err := os.Lstat(p); err != nil || !st.Mode().IsRegular() {
|
|
continue
|
|
}
|
|
fh, err := os.Open(p)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
head := make([]byte, 8)
|
|
n, err := io.ReadFull(fh, head)
|
|
fh.Close()
|
|
if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF {
|
|
return nil, err
|
|
}
|
|
if k := Kind(head[:n]); k != "" {
|
|
found = append(found, fmt.Sprintf("%s (%s)", f, k))
|
|
}
|
|
}
|
|
return found, nil
|
|
}
|