Join 11: refuse a committed program anywhere in the repository
A compiled program reached a commit a second time (the view's 18 MB program at its module's root, which the command-folder pattern did not cover): the sdk's nobinaries test refuses every tracked executable, as the catalogue's checks/nobinaries does, and .gitignore covers a module's root. Builds: design 47 G join (the kind's guard, fix-a-bug-met-twice) Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -2,3 +2,5 @@ vendor/
|
||||
# A compiled program never enters a commit (issue 1577): `go build .` in a command directory leaves one there.
|
||||
modules/*/cmd/*/mesh-*
|
||||
!modules/*/cmd/*/mesh-*.go
|
||||
# `go build .` at a module's root leaves its program there too (the view's, met a second time).
|
||||
modules/*/mesh-*
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Package nobinaries refuses a compiled program anywhere in the repository, as the catalogue's checks/nobinaries does
|
||||
// (issue 1577): a compiled program 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 (met a second time: the view's 18 MB program at the
|
||||
// module's root, which the command-folder pattern of .gitignore does not cover).
|
||||
package nobinaries
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// 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 ""
|
||||
}
|
||||
|
||||
// found names each tracked file under root that is a compiled program, with its format.
|
||||
func found(t *testing.T, root string) []string {
|
||||
t.Helper()
|
||||
out, err := exec.Command("git", "-C", root, "ls-files", "-z").Output()
|
||||
if err != nil {
|
||||
t.Fatalf("git ls-files in %s: %v", root, err)
|
||||
}
|
||||
var names []string
|
||||
for _, f := range strings.Split(strings.TrimRight(string(out), "\x00"), "\x00") {
|
||||
if f == "" {
|
||||
continue
|
||||
}
|
||||
p := filepath.Join(root, f)
|
||||
st, err := os.Lstat(p)
|
||||
if err != nil || !st.Mode().IsRegular() { // a file the change deletes is not there
|
||||
continue
|
||||
}
|
||||
fh, err := os.Open(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
head := make([]byte, 8)
|
||||
n, err := io.ReadFull(fh, head)
|
||||
fh.Close()
|
||||
if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if k := kind(head[:n]); k != "" {
|
||||
names = append(names, f+" ("+k+")")
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func TestKindNamesEachExecutableFormatAndNothingElse(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
head []byte
|
||||
want string
|
||||
}{
|
||||
{[]byte("\x7fELF\x02\x01\x01\x00"), "ELF"},
|
||||
{[]byte("MZ\x90\x00"), "PE"},
|
||||
{[]byte{0xcf, 0xfa, 0xed, 0xfe, 7, 0, 0, 1}, "Mach-O"},
|
||||
{[]byte("package main\n"), ""},
|
||||
{[]byte("\x7f"), ""},
|
||||
{nil, ""},
|
||||
{[]byte{0xca, 0xfe, 0xba, 0xbe, 0, 0, 0, 52}, ""}, // a Java class, not a Mach-O
|
||||
} {
|
||||
if got := kind(c.head); got != c.want {
|
||||
t.Errorf("kind(%q) = %q, want %q", c.head, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The repository holds no compiled program, in any module or outside one.
|
||||
func TestTheRepositoryHoldsNoCompiledProgram(t *testing.T) {
|
||||
for _, f := range found(t, filepath.Join("..", "..")) {
|
||||
t.Errorf("%s: a compiled program is build output: remove it and add it to .gitignore (issue 1577)", f)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
# every tracked file of the repository (git ls-files, no path limit): the whole tree, so this package's verdict is never kept.
|
||||
Reference in New Issue
Block a user