# histgen — one target per verb.
#
# The folder is meant to be copied out of soleprint and used on its own, so
# everything here is derived from where this file sits rather than written down:
# copy the directory anywhere, `cd` into it, and `make` works. Renaming it works
# too, since the package name comes from the directory.
#
# Two directories, and the whole tool hangs off the difference:
#
#   SOURCE  the tree to read. Read-only, always. Nothing is written into it.
#   OUT     the plan, the briefs, and OUT/<name>/ — a copy of the source with
#           the designed history committed into it.
#
#   make check                              prove it works, on its own fixture
#   make copy   SOURCE=~/work/x OUT=~/out   just the files, no repo, no keys
#   make run    SOURCE=~/work/x OUT=~/out   scan + plan + brief
#   make list                               the commits, to confirm
#   make commands                           copy the files, hand back git commands
#   make export                             ...or have it commit them for you
#
# Set them once and the verbs take no arguments:
#
#   make init-config SOURCE=... OUT=...
#   make config                             what everything resolves to
#   make status                             what is in OUT, and what is left
#
# The logic lives in the Python, never here. Each target is one invocation.

HERE    := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
PKG     := $(notdir $(HERE))
PARENT  := $(patsubst %/,%,$(dir $(HERE)))
PY      ?= python3
PREFIX  ?= $(HOME)/.local

# Run the package from its parent, which is what `python -m` needs and what
# lets this work without installing anything.
HISTGEN := PYTHONPATH=$(PARENT) $(PY) -m $(PKG)

# Extra flags for the verb being run: make plan REPO=x ARGS=--max-files=12
ARGS ?=

# Left empty, these say nothing and the config file decides. Passing REPO= or
# OUT= on the command line overrides it, which is the precedence the tool
# already applies — the Makefile just has to not invent a default of its own.
SOURCE ?=
OUT    ?=
CONFIG ?=

WHERE := $(if $(SOURCE),--source $(SOURCE)) $(if $(OUT),--out $(OUT)) \
         $(if $(CONFIG),--config $(CONFIG))

.PHONY: help check run copy scan plan list brief export keep commands dry-run verify status \
        against-history clean install uninstall doctor config init-config

help:  ## List every target
	@echo "histgen — seed a clean, logical history into a repo"
	@echo
	@grep -E '^[a-z-]+:.*?## .*$$' $(MAKEFILE_LIST) \
	  | awk 'BEGIN{FS=":.*?## "}{printf "  \033[1m%-16s\033[0m %s\n", $$1, $$2}'
	@echo
	@echo "  SOURCE=/path/to/tree  what to read  (read-only, never written to)"
	@echo "  OUT=/path/to/out      what to write (plan, briefs, and OUT/<name>/)"
	@echo "  ARGS=...              extra flags, e.g. ARGS=\"--max-files 25\""
	@echo
	@echo "  Both can live in histgen.json instead: make init-config SOURCE=.. OUT=.."

check:  ## Prove the whole pipeline works, needing no repo and nothing installed
	@$(PY) $(HERE)/selftest.py

config:  ## Show what repo, out and max-files resolve to
	@$(HISTGEN) config $(WHERE)

init-config:  ## Write a starter histgen.json beside the tool
	@$(HISTGEN) config --init $(WHERE)

doctor:  ## Report whether this machine can run it
	@printf 'python : '; $(PY) --version 2>&1 || echo MISSING
	@printf 'git    : '; git --version 2>&1 || echo MISSING
	@printf 'package: %s (from %s)\n' '$(PKG)' '$(PARENT)'
	@$(HISTGEN) --help >/dev/null 2>&1 \
	  && echo 'import : ok' || echo 'import : FAILED — is the folder intact?'

run:  ## scan + plan + brief, everything before the messages are needed
	@$(HISTGEN) run $(WHERE) $(ARGS)

list:  ## Print the commits, to confirm before exporting
	@$(HISTGEN) list $(WHERE) $(ARGS)

status:  ## What is in OUT, what state it is in, and what is left to do
	@$(HISTGEN) status $(WHERE) $(ARGS)

copy:  ## Copy the files out: no .git, nothing ignored, no keys, no build output
	@$(HISTGEN) copy $(WHERE) $(ARGS)

scan:  ## Read the source and cache what was read
	@$(HISTGEN) scan $(WHERE) $(ARGS)

plan:  ## Order the files and cut them into commits
	@$(HISTGEN) plan $(WHERE) $(ARGS)

brief:  ## Write one brief per commit, for the messages
	@$(HISTGEN) brief $(WHERE) $(ARGS)

against-history:  ## Report how an existing history compares. Reads only
	@$(HISTGEN) plan $(WHERE) --against-history $(ARGS)

dry-run:  ## Write the export as a reviewable regen.sh instead of running it
	@$(HISTGEN) export $(WHERE) --dry-run $(ARGS)

export:  ## Copy the source into OUT and commit the history. Resumes if interrupted
	@$(HISTGEN) export $(WHERE) $(ARGS)

keep:  ## Export, carrying an existing history over onto its own branch
	@$(HISTGEN) export $(WHERE) --keep-history $(ARGS)

commands:  ## Copy the files, create no repo, print the git commands to run yourself
	@$(HISTGEN) export $(WHERE) --commands $(ARGS)

verify:  ## Nothing left untracked, and the exported tree matches the source
	@$(HISTGEN) verify $(WHERE) $(ARGS)

clean:  ## Delete the whole OUT directory. The source is not touched
	@d=$$($(HISTGEN) config $(WHERE) | awk '/^out /{print $$2}'); \
	 test -n "$$d" -a "$$d" != "(unset)" || { echo "Error: no OUT set." >&2; exit 1; }; \
	 rm -rf "$$d" && echo "Removed $$d. The source was never written to."

install:  ## Put a `histgen` command on PATH, pointing back at this folder
	@mkdir -p $(PREFIX)/bin
	@printf '#!/bin/sh\n# Generated by histgen'"'"'s Makefile; points at the folder it was run from.\nPYTHONPATH="%s" exec "%s" -m %s "$$@"\n' \
	  '$(PARENT)' '$(shell command -v $(PY))' '$(PKG)' > $(PREFIX)/bin/histgen
	@chmod +x $(PREFIX)/bin/histgen
	@echo "Installed $(PREFIX)/bin/histgen -> $(HERE)"
	@case ":$$PATH:" in *":$(PREFIX)/bin:"*) ;; \
	  *) echo "Note: $(PREFIX)/bin is not on PATH." ;; esac

uninstall:  ## Remove that command
	@rm -f $(PREFIX)/bin/histgen && echo "Removed $(PREFIX)/bin/histgen"
