diff options
| -rw-r--r-- | CHANGELOG.md | 7 | ||||
| -rw-r--r-- | Makefile | 24 | ||||
| -rw-r--r-- | README.md | 9 | ||||
| -rw-r--r-- | docs/design.md | 12 | ||||
| -rw-r--r-- | internal/engine/examples_test.go | 37 | ||||
| -rw-r--r-- | internal/extract/tools_test.go | 14 | ||||
| -rwxr-xr-x | scripts/deps | 2 |
7 files changed, 87 insertions, 18 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 37a9f50..0b82a8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,13 @@ could change its answer; `explain` shows `?`. A document read only in part answers the keywords found in what was read, and leaves the others unknown. +- Build: `make build` and `make install` refuse a `VERSION` that is not a + plain version string, as `cross` and `release` did; `make cross` names + its directories without the tag's `v`; the dependency gate covers test + imports and FreeBSD and OpenBSD builds; `scripts/deps --print` prints only + the command on stdout; the README says how to install from a release + tarball; tests check that the examples load and that the Makefile's + extractor list matches the code. - krino.conf's excludes are checked with the defaults' `case` and `fold` even while no directory is included; Latin-1 text is decoded in a third of the memory. @@ -8,8 +8,13 @@ SHAREDIR = $(DESTDIR)$(PREFIX)/share MANDIR = $(SHAREDIR)/man DOCDIR = $(SHAREDIR)/doc/krino BIN = krino -VERSION != git describe --tags --always --dirty 2>/dev/null || echo dev +# The tag's "v" is dropped, so dist directories read krino-0.0.8-..., as +# `make release VERSION=0.0.8` names them. +VERSION != (git describe --tags --always --dirty 2>/dev/null || echo dev) | sed 's/^v//' LDFLAGS = -s -w -X main.version=$(VERSION) +# VERSION reaches -ldflags and directory names, so every target using it +# refuses anything but a plain version string. +CHECK_VERSION = case '$(VERSION)' in ''|*[!A-Za-z0-9._+-]*) echo "refusing: VERSION must contain only letters, digits, and the characters . - _ +" >&2; exit 1 ;; esac CROSS_PLATFORMS = linux/amd64 linux/arm64 freebsd/amd64 openbsd/amd64 .PHONY: all help build install uninstall test vet fmt lint ci bench fuzz race vulncheck cross dist release deps install-hooks clean @@ -22,6 +27,7 @@ help: ## show this help @echo " version: $(VERSION) prefix: $(PREFIX)" build: ## build ./krino; Go fetches module dependencies itself; reports missing optional extractors + @$(CHECK_VERSION) CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN) ./cmd/krino @missing=""; \ for t in pdftotext antiword catdoc xls2csv catppt; do \ @@ -70,7 +76,7 @@ ci: ## the gate: gofmt, vet, tests, dependencies, no personal data staged, man p GOOS=freebsd CGO_ENABLED=0 go vet ./... GOOS=openbsd CGO_ENABLED=0 go vet ./... go test ./... - @deps=$$(go list -deps -f '{{with .Module}}{{.Path}}{{end}}' ./... | sort -u | grep -vxE '(krino|golang\.org/x/(term|text|sys))?' || true); \ + @deps=$$(for os in linux freebsd openbsd; do GOOS=$$os CGO_ENABLED=0 go list -deps -test -f '{{with .Module}}{{.Path}}{{end}}' ./... || echo "go list failed for $$os"; done | sort -u | grep -vxE '(krino|golang\.org/x/(term|text|sys))?' || true); \ test -z "$$deps" || { echo "unexpected dependencies:"; echo "$$deps"; exit 1; } @scripts/leak-check @scripts/man-lint @@ -116,11 +122,7 @@ vulncheck: ## check the standard library and dependencies against the Go vulnera go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 ./... cross: ## cross-compile linux/amd64, linux/arm64, freebsd/amd64, openbsd/amd64 into dist/krino-$(VERSION)-<os>-<arch>/ - @case '$(VERSION)' in \ - ''|*[!A-Za-z0-9._+-]*) \ - echo "refusing: VERSION must contain only letters, digits, and the characters . - _ +" >&2; \ - exit 1 ;; \ - esac + @$(CHECK_VERSION) @for t in $(CROSS_PLATFORMS); do \ os=$${t%/*}; arch=$${t#*/}; \ dir=dist/krino-$(VERSION)-$$os-$$arch; \ @@ -153,12 +155,8 @@ dist: cross $$SUM $$tarballs > SHA256SUMS release: ## make cross + tarballs + SHA256SUMS in dist/, then tag v$(VERSION) (annotated; never pushes) - usage: make release VERSION=0.0.1 - @case '$(VERSION)' in \ - ''|*[!A-Za-z0-9._+-]*) \ - echo "refusing: VERSION must contain only letters, digits, and the characters . - _ +" >&2; \ - exit 1 ;; \ - esac - @default_version=$$(git describe --tags --always --dirty 2>/dev/null || echo dev); \ + @$(CHECK_VERSION) + @default_version=$$( (git describe --tags --always --dirty 2>/dev/null || echo dev) | sed 's/^v//'); \ test -n "$(VERSION)" && test "$(VERSION)" != "$$default_version" || \ { echo "refusing: pass an explicit VERSION, e.g. make release VERSION=0.0.1"; exit 1; } @test -z "$$(git status --porcelain)" || \ @@ -23,6 +23,15 @@ install` puts the binary in `$PREFIX/bin` (default `~/.local/bin`), the man pages in `$PREFIX/share/man`, and the examples and `docs/sexp-primer.md` in `$PREFIX/share/doc/krino`. +A release tarball holds the built binary, the man pages, the examples and +this README, but no Makefile and no source; install it by hand: + +``` +install -m 755 krino ~/.local/bin/ +install -m 644 krino.1 ~/.local/share/man/man1/ +install -m 644 krino.conf.5 ~/.local/share/man/man5/ +``` + Some `(content ...)` tests need external extractors — `pdftotext` for PDF, `antiword`/`catdoc` for legacy Word, `xls2csv`/`catppt` for legacy Excel and PowerPoint. `make build` reports which of these are missing; install them diff --git a/docs/design.md b/docs/design.md index ef52d7e..60bfc92 100644 --- a/docs/design.md +++ b/docs/design.md @@ -811,9 +811,10 @@ Rules for the GUI to come: `CGO_ENABLED=0`: static binaries on Linux and FreeBSD; on OpenBSD Go links against the system libc, as that platform requires. - Go dependencies: `golang.org/x/term` (key-at-a-time input) and - `golang.org/x/text` (Unicode normalisation for `fold`). Everything else is - the standard library, including the s-expression reader and the gitignore - matcher. + `golang.org/x/text` (Unicode normalisation for `fold`, character widths). + Everything else is the standard library, including the s-expression + reader and the gitignore matcher. `make ci` refuses any other module, + tests included, for Linux, FreeBSD and OpenBSD alike. - `make` builds; Go downloads the module dependencies itself. It then checks for the optional extractors and prints what is missing. - `make deps` installs the extractors with the system package manager, @@ -829,7 +830,10 @@ Rules for the GUI to come: - `make release VERSION=0.0.1`: runs `ci` and `cross`, writes tarballs and `SHA256SUMS` into `dist/`, and creates the annotated tag **`v0.0.1`** (the `v` is required for `go install ...@v0.0.1`). It never pushes. -- Version stamped with `-ldflags -X main.version=...`. +- Version stamped with `-ldflags -X main.version=...`, without the tag's + `v`; every target that uses `VERSION` refuses one holding anything but + letters, digits and `. - _ +`. `make uninstall` removes krino's own files + and `share/doc/krino`, never the shared `bin` and `man` directories. - `scripts/leak-check` keeps personal data out of the repository. `make ci` runs it, and so does the pre-commit hook that `make install-hooks` installs. It checks the staged files against built-in patterns (the diff --git a/internal/engine/examples_test.go b/internal/engine/examples_test.go new file mode 100644 index 0000000..5f3d8e2 --- /dev/null +++ b/internal/engine/examples_test.go @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package engine + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// TestExamplesLoad: every shipped example directory file loads without a +// diagnostic, so a change to the config language cannot leave the examples +// installed under share/doc/krino broken (triage 34o). +func TestExamplesLoad(t *testing.T) { + examples, err := filepath.Glob(filepath.Join("..", "..", "examples", "*.conf")) + if err != nil || len(examples) == 0 { + t.Fatalf("no examples found: %v", err) + } + for _, ex := range examples { + t.Run(filepath.Base(ex), func(t *testing.T) { + h := sandbox(t) + for _, d := range []string{"Downloads", "Pictures"} { + os.MkdirAll(filepath.Join(h, d), 0o755) + } + body, err := os.ReadFile(ex) + if err != nil { + t.Fatal(err) + } + name := strings.TrimSuffix(filepath.Base(ex), ".conf") + main := writeConfig(t, h, `(include "`+name+`")`, map[string]string{name: string(body)}) + if _, errs := Load(main); len(errs) > 0 { + t.Errorf("%s: %v", ex, errs) + } + }) + } +} diff --git a/internal/extract/tools_test.go b/internal/extract/tools_test.go index 5af80fb..bafb7c2 100644 --- a/internal/extract/tools_test.go +++ b/internal/extract/tools_test.go @@ -280,3 +280,17 @@ func TestToolLookupSkipsRelativePathEntries(t *testing.T) { t.Errorf("tool found through a relative PATH entry: %q", e.tools["pdftotext"]) } } + +// TestMakefileListsEveryTool: `make build` reports missing extractors from +// its own list of tool names; it must be the list Extractor looks up +// (triage 34p). +func TestMakefileListsEveryTool(t *testing.T) { + mk, err := os.ReadFile(filepath.Join("..", "..", "Makefile")) + if err != nil { + t.Fatal(err) + } + want := "for t in " + strings.Join(toolNames, " ") + "; do" + if !strings.Contains(string(mk), want) { + t.Errorf("Makefile's extractor loop is not %q", want) + } +} diff --git a/scripts/deps b/scripts/deps index 06faaa2..bd7eff9 100755 --- a/scripts/deps +++ b/scripts/deps @@ -82,7 +82,7 @@ fi cmd=$(privileged $pkgcmd) -[ -n "$note" ] && echo "$note" +[ -n "$note" ] && echo "$note" >&2 if [ "$print_only" = 1 ]; then echo "$cmd" |
