aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 23:55:57 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 23:55:57 +0200
commit04f46bf180cf506ceadb76b5afacf9c02700cc65 (patch)
treeeee384915f80b8243ff807b239515d1c7525095c
parent0b155e8df3205aebf129091b517f4116665a5adc (diff)
downloadkrino-04f46bf180cf506ceadb76b5afacf9c02700cc65.tar.gz
krino-04f46bf180cf506ceadb76b5afacf9c02700cc65.zip
build: VERSION checked for build and install, cross names without v, dependency gate covers tests and BSDs, tarball install, examples and extractor list tested
-rw-r--r--CHANGELOG.md7
-rw-r--r--Makefile24
-rw-r--r--README.md9
-rw-r--r--docs/design.md12
-rw-r--r--internal/engine/examples_test.go37
-rw-r--r--internal/extract/tools_test.go14
-rwxr-xr-xscripts/deps2
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.
diff --git a/Makefile b/Makefile
index 1a713b7..6d5d488 100644
--- a/Makefile
+++ b/Makefile
@@ -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)" || \
diff --git a/README.md b/README.md
index c453726..a028ab9 100644
--- a/README.md
+++ b/README.md
@@ -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"