From 26c94eb3db62ec6eebbf8d22c11afe691d9520c4 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Sun, 13 Sep 2026 02:31:32 +0200 Subject: krino: release 0.0.1 — man pages, install, examples, cross and release, README, changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also: undo removes the directories its run created; a hardlink is never a duplicate of its own other name; a flag written before "undo" is honoured; --version prints no leading v. Duplicate conditions with different scopes not sharing an original is documented as a known limitation. --- Makefile | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 6 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 9dfc7d4..62e2b7e 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,15 @@ DESTDIR ?= PREFIX ?= $(HOME)/.local BINDIR = $(DESTDIR)$(PREFIX)/bin +SHAREDIR = $(DESTDIR)$(PREFIX)/share +MANDIR = $(SHAREDIR)/man +DOCDIR = $(SHAREDIR)/doc/krino BIN = krino VERSION != git describe --tags --always --dirty 2>/dev/null || echo dev LDFLAGS = -s -w -X main.version=$(VERSION) +CROSS_PLATFORMS = linux/amd64 linux/arm64 freebsd/amd64 openbsd/amd64 -.PHONY: all help build install uninstall test vet fmt ci install-hooks clean +.PHONY: all help build install uninstall test vet fmt lint ci bench cross dist release deps install-hooks clean all: build @@ -17,16 +21,36 @@ help: ## show this help awk 'BEGIN {FS = ":.*## "}; {printf " %-10s %s\n", $$1, $$2}' @echo " version: $(VERSION) prefix: $(PREFIX)" -build: ## build ./krino; Go fetches module dependencies itself +build: ## build ./krino; Go fetches module dependencies itself; reports missing optional extractors CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN) ./cmd/krino + @missing=""; \ + for t in pdftotext antiword catdoc xls2csv catppt; do \ + command -v "$$t" >/dev/null 2>&1 || missing="$$missing $$t"; \ + done; \ + if [ -n "$$missing" ]; then \ + echo "optional extractors not found:$$missing (needed for some content rules; run 'make deps' or install by hand)"; \ + else \ + echo "all optional extractors found: pdftotext antiword catdoc xls2csv catppt"; \ + fi -install: build ## install to $(PREFIX)/bin - mkdir -p $(BINDIR) +install: build ## install binary, man pages and examples under $(PREFIX) + mkdir -p $(BINDIR) $(MANDIR)/man1 $(MANDIR)/man5 $(DOCDIR)/examples rm -f $(BINDIR)/$(BIN) install -m 755 $(BIN) $(BINDIR)/$(BIN) + install -m 644 man/krino.1 $(MANDIR)/man1/krino.1 + install -m 644 man/krino.conf.5 $(MANDIR)/man5/krino.conf.5 + install -m 644 examples/*.conf $(DOCDIR)/examples/ + install -m 644 docs/sexp-primer.md $(DOCDIR)/sexp-primer.md -uninstall: ## remove the installed binary +uninstall: ## remove everything install placed, and nothing else rm -f $(BINDIR)/$(BIN) + rm -f $(MANDIR)/man1/krino.1 + rm -f $(MANDIR)/man5/krino.conf.5 + rm -f $(DOCDIR)/sexp-primer.md + for f in examples/*.conf; do \ + rm -f $(DOCDIR)/examples/$$(basename "$$f"); \ + done + -rmdir $(DOCDIR)/examples $(DOCDIR) 2>/dev/null test: ## run the tests go test ./... @@ -37,7 +61,10 @@ vet: ## go vet fmt: ## gofmt the tree gofmt -w . -ci: ## the gate: gofmt, vet, tests, dependencies, no personal data staged +lint: ## lint the man pages + scripts/man-lint + +ci: ## the gate: gofmt, vet, tests, dependencies, no personal data staged, man page lint @test -z "$$(gofmt -l .)" || { echo "gofmt needed:"; gofmt -l .; exit 1; } go vet ./... GOOS=freebsd CGO_ENABLED=0 go vet ./... @@ -46,8 +73,72 @@ ci: ## the gate: gofmt, vet, tests, dependencies, no personal data staged @deps=$$(go list -deps ./... | grep -E '^[a-z0-9-]+\.[a-z]+/' | grep -vE '^golang\.org/x/(term|text|sys)(/|$$)' || true); \ test -z "$$deps" || { echo "unexpected dependencies:"; echo "$$deps"; exit 1; } @scripts/leak-check + @scripts/man-lint @echo "ci ok" +bench: ## run the Go benchmarks on generated trees + go test -run '^$$' -bench . -benchmem ./... + +cross: ## cross-compile linux/amd64, linux/arm64, freebsd/amd64, openbsd/amd64 into dist/krino-$(VERSION)--/ + @case '$(VERSION)' in \ + ''|*[!A-Za-z0-9._+-]*) \ + echo "refusing: VERSION must contain only letters, digits, and the characters . - _ +" >&2; \ + exit 1 ;; \ + esac + @for t in $(CROSS_PLATFORMS); do \ + os=$${t%/*}; arch=$${t#*/}; \ + dir=dist/krino-$(VERSION)-$$os-$$arch; \ + case "$$dir" in \ + dist/krino-*) rm -rf "$$dir" ;; \ + *) echo "refusing to remove unexpected path: $$dir" >&2; exit 1 ;; \ + esac; \ + mkdir -p "$$dir"; \ + echo "cross: $$os/$$arch -> $$dir/$(BIN)"; \ + CGO_ENABLED=0 GOOS=$$os GOARCH=$$arch go build -trimpath -ldflags "$(LDFLAGS)" -o "$$dir/$(BIN)" ./cmd/krino || exit 1; \ + for f in README.md LICENSE CHANGELOG.md man/krino.1 man/krino.conf.5 docs/sexp-primer.md; do \ + test -f "$$f" && cp "$$f" "$$dir/$$(basename "$$f")"; \ + done; \ + test -d examples && cp -r examples "$$dir/examples"; \ + done + +# dist: cross plus tarballs and SHA256SUMS, no tag. Undocumented plumbing so +# `make release` is verifiable without tagging; deliberately absent from +# `make help` (no `## ` comment). +dist: cross + @command -v sha256sum >/dev/null 2>&1 && SUM=sha256sum || SUM="sha256 -r"; \ + tarballs=""; \ + cd dist && \ + for t in $(CROSS_PLATFORMS); do \ + os=$${t%/*}; arch=$${t#*/}; \ + name=krino-$(VERSION)-$$os-$$arch; \ + tar czf "$$name.tar.gz" "$$name" || exit 1; \ + tarballs="$$tarballs $$name.tar.gz"; \ + done && \ + $$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); \ + 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)" || \ + { echo "refusing: working tree is not clean (git status --porcelain)"; exit 1; } + @git rev-parse -q --verify refs/tags/v$(VERSION) >/dev/null 2>&1 && \ + { echo "refusing: tag v$(VERSION) already exists"; exit 1; } || true + @test -f README.md || \ + { echo "refusing: README.md is missing"; exit 1; } + $(MAKE) ci + $(MAKE) dist VERSION=$(VERSION) + git tag -a "v$(VERSION)" -m "krino v$(VERSION)" + @echo "release v$(VERSION) built in dist/; tag v$(VERSION) created, not pushed" + +deps: ## install the optional content extractors; may ask for privileges + scripts/deps + install-hooks: ## install the pre-commit hook that runs the leak check install -m 755 scripts/hooks/pre-commit "$$(git rev-parse --git-path hooks)/pre-commit" -- cgit v1.3