Files
member-console/test/scripts_spdx_test.go
T
cgalo5758 f340def385 Take spdx-headers.sh's root from its own location
spdx-headers.sh changed into `git rev-parse --show-toplevel` before
stamping. Run from a copy of the repository that has no .git of its
own, such as a git archive export under the working tree, git names
the enclosing checkout, so the copy stamped the checkout's tracked
files instead of its own. The script now takes as its root the
directory above its own scripts/ directory. When git does not name
that directory as the top of a checkout, it prints a refusal on stderr
and exits 2 before it reads any file. Run from its own checkout it
behaves as before, which is how `make spdx-headers` and
`make sqlc-generate` call it.

TestSPDXHeadersStampsOnlyItsOwnCheckout builds a scratch git checkout
with one tracked Go file and, under it, an export holding the same
files without a .git. Run from the export, the script must exit 2 and
leave both Go files unstamped; run from the checkout's own copy, it
must stamp the checkout's file and not the export's. At the parent the
export case fails: the script exits 0 and stamps the checkout's a.go.
The checkout case passes on both sides.

Run in the working tree, the new script stamped 0 of 934 eligible
files and changed no path. go vet, gofmt, bash -n and make lint pass.
2026-10-15 20:34:33 -05:00

133 lines
3.9 KiB
Go

// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
package test
import (
"bytes"
"errors"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
// TestSPDXHeadersStampsOnlyItsOwnCheckout runs copies of
// scripts/spdx-headers.sh in a scratch checkout that holds an export of
// itself: a copy of the tree with no .git, the shape a drafting tool leaves
// under the working tree. Run from the export, git names the enclosing
// checkout, so the script must refuse instead of stamping the checkout's
// files. Run from the checkout's own copy, it stamps the checkout's tracked
// files and nothing in the export.
func TestSPDXHeadersStampsOnlyItsOwnCheckout(t *testing.T) {
sb := newStampBox(t)
t.Run("from an export inside the checkout", func(t *testing.T) {
code, stderr := sb.run(t, sb.export)
if code != 2 {
t.Errorf("exit status %d, want 2 (stderr %q)", code, stderr)
}
if !strings.Contains(stderr, "is not the top of a git checkout") {
t.Errorf("stderr %q, want the refusal", stderr)
}
if stamped(t, filepath.Join(sb.checkout, "a.go")) {
t.Error("the checkout's a.go was stamped from the export")
}
if stamped(t, filepath.Join(sb.export, "a.go")) {
t.Error("the export's a.go was stamped")
}
})
t.Run("from the checkout's own copy", func(t *testing.T) {
code, stderr := sb.run(t, sb.checkout)
if code != 0 {
t.Errorf("exit status %d, want 0 (stderr %q)", code, stderr)
}
if !stamped(t, filepath.Join(sb.checkout, "a.go")) {
t.Error("the checkout's a.go was not stamped")
}
if stamped(t, filepath.Join(sb.export, "a.go")) {
t.Error("the export's a.go was stamped")
}
})
}
// stampBox is a scratch git checkout with a copy of the stamper and one
// tracked Go file, and under it an export: the same two files with no .git.
type stampBox struct {
bash, checkout, export string
env []string
}
func newStampBox(t *testing.T) stampBox {
t.Helper()
src, err := os.ReadFile(filepath.Join("..", "scripts", "spdx-headers.sh"))
if err != nil {
t.Fatal(err)
}
bash, err := exec.LookPath("bash")
if err != nil {
t.Fatalf("bash: %v", err)
}
checkout := t.TempDir()
sb := stampBox{
bash: bash,
checkout: checkout,
export: filepath.Join(checkout, "notebook", "export"),
env: append(os.Environ(), "GIT_CONFIG_GLOBAL=/dev/null", "GIT_CONFIG_NOSYSTEM=1"),
}
for _, dir := range []string{sb.checkout, sb.export} {
writeFile(t, filepath.Join(dir, "scripts", "spdx-headers.sh"), src, 0o755)
writeFile(t, filepath.Join(dir, "a.go"), []byte("package a\n"), 0o644)
}
for _, args := range [][]string{
{"-c", "init.defaultBranch=main", "init", "-q"},
{"add", "a.go", "scripts/spdx-headers.sh"},
} {
cmd := exec.Command("git", args...)
cmd.Dir, cmd.Env = sb.checkout, sb.env
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
}
return sb
}
// run runs the copy of the stamper under dir, from dir, and returns its exit
// status and standard error.
func (sb stampBox) run(t *testing.T, dir string) (int, string) {
t.Helper()
cmd := exec.Command(sb.bash, filepath.Join(dir, "scripts", "spdx-headers.sh"))
cmd.Dir, cmd.Env = dir, sb.env
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
var exit *exec.ExitError
if !errors.As(err, &exit) {
t.Fatal(err)
}
return exit.ExitCode(), stderr.String()
}
return 0, stderr.String()
}
func writeFile(t *testing.T, path string, data []byte, mode os.FileMode) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, data, mode); err != nil {
t.Fatal(err)
}
}
// stamped reports whether the file at path opens with a Go SPDX header.
func stamped(t *testing.T, path string) bool {
t.Helper()
got, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
return strings.HasPrefix(string(got), "// SPDX-License-Identifier: ")
}