.PHONY: all bootstrap setup check test lint lint-fix fmt fmt-check build clean deps test-coverage local install release release-snapshot docker hooks

# Version number, derived from git by script/version -- the tag when
# HEAD is on one, otherwise dev-<sha>. This used to be a hardcoded
# constant, which meant every local build claimed to be a release that
# had never been tagged.
VERSION := $(shell script/version)

# $(shell) discards exit status, so a script/version that is missing,
# non-executable or broken would otherwise leave VERSION empty and every
# binary built here would print "vaultik " with no version at all. A
# build that cannot determine what it is must not produce an artifact.
ifeq ($(strip $(VERSION)),)
$(error script/version produced no version string; a build that cannot \
determine its version will not be made. Check that script/version exists \
and is executable)
endif

# Build variables
GIT_REVISION := $(shell git rev-parse HEAD 2>/dev/null || echo "unknown")
GIT_COMMIT_DATE := $(shell git show -s --format=%cs HEAD 2>/dev/null || echo "unknown")

# Linker flags
LDFLAGS := -X 'sneak.berlin/go/vaultik/internal/globals.Version=$(VERSION)' \
           -X 'sneak.berlin/go/vaultik/internal/globals.Commit=$(GIT_REVISION)' \
           -X 'sneak.berlin/go/vaultik/internal/globals.CommitDate=$(GIT_COMMIT_DATE)'

# Default target
all: vaultik

# Install all development dependencies.
bootstrap:
	@script/bootstrap

# Prepare a fresh clone: bootstrap plus pre-commit hook.
setup:
	@script/setup

# Combined pre-commit/CI gate: tests, lint, format check.
check:
	@script/check

# Run tests only. This runs the ENTIRE suite -- there is no separate
# integration target and no build-tagged subset held back. In
# particular internal/vaultik/integration_test.go, which does full
# chunk -> pack -> encrypt -> upload -> restore round-trips, runs here.
# A `test-integration` target used to exist and was removed: no file in
# the repo carried a build tag, so `-tags=integration` selected nothing
# extra and the target was an exact duplicate of this one.
test:
	@script/test

# Check if code is formatted (read-only).
fmt-check:
	@script/fmt-check

# Format code.
fmt:
	@script/fmt

# Run linter only.
lint:
	@script/lint

# Apply the linter's autofixes (rewrites files).
lint-fix:
	@script/lint-fix

# Build binary. `build` is the name the org convention reaches for and
# the one a caller checks the exit code of; `vaultik` is the file rule
# that does the work, so an unchanged tree still short-circuits.
#
# This alias is not decorative. `build` was listed in .PHONY with no
# rule, and a phony target with no prerequisites and no recipe is
# already satisfied: `make build` printed "Nothing to be done" and
# exited 0 without producing a binary (issue #110). Every name in
# .PHONY needs a rule for that reason; TestPhonyTargetsAllHaveRules in
# cmd/vaultik keeps it that way.
build: vaultik

vaultik: internal/*/*.go cmd/vaultik/*.go
	go build -ldflags "$(LDFLAGS)" -o $@ ./cmd/vaultik

# Clean build artifacts.
clean:
	rm -f vaultik
	go clean

# Install dependencies. The linter is deliberately not installed here:
# script/lint lints by building Dockerfile.lint, whose FROM line is the
# single source of truth for the linter version. A second, separately
# pinned copy on PATH could drift from it and make a local `make lint`
# disagree with CI.
deps:
	go mod download

# Run tests with coverage. -count=1 for the same reason script/test
# uses it: without it an unchanged package is served from Go's test
# result cache, and a coverage profile assembled from cached results
# describes a run that did not happen.
test-coverage:
	go test -v -count=1 -coverprofile=coverage.out ./...
	go tool cover -html=coverage.out -o coverage.html

local:
	VAULTIK_CONFIG=$(HOME)/etc/vaultik/config.yml ./vaultik snapshot --debug list 2>&1
	VAULTIK_CONFIG=$(HOME)/etc/vaultik/config.yml ./vaultik snapshot --debug create 2>&1

install: vaultik
	cp ./vaultik $(HOME)/bin/

# Build and publish release artifacts (linux/darwin × amd64/arm64) via goreleaser.
release:
	@script/release

# Dry-run a release build without publishing or tagging.
release-snapshot:
	@script/release-snapshot

# Build Docker image.
docker:
	@script/docker

# Install pre-commit hook.
hooks:
	@script/install-precommit
