# release.mk -- shared build/publish logic for maturin projects
#
# Include from your project Makefile after setting these variables:
#
#   CARGO_MANIFEST  = daemon/Cargo.toml
#   INIT_PY         = python/mypackage/__init__.py  (empty for pyo3)
#   PYPIRC_REPO     = mypackage                     # -r name in ~/.pypirc
#   PYTHON_SRC      = python
#   TEST_PATHS      = python/tests
#   PYPI_UPLOAD     = 1                             # 0 to skip
#   CRATES_UPLOAD   = 1                             # 0 to skip
#
# Credentials: standard locations only
#   ~/.pypirc                  -- twine reads this by default
#   ~/.cargo/credentials.toml  -- cargo reads this by default
#
# Provides: build test pub pub-all release clean

CARGO_MANIFEST ?= Cargo.toml
INIT_PY        ?=
PYPIRC_REPO    ?= pypi
PYTHON_SRC     ?= python
TEST_PATHS     ?= tests
PYPI_UPLOAD    ?= 1
CRATES_UPLOAD  ?= 1
PYTHON_VERSION ?= 3.13

.PHONY: build build-rust wheel dist dev test test-rust test-python check clean
.PHONY: pub pub-all release _set-version _bump-patch _tag-and-push

# -- Build -------------------------------------------------------------------

build: build-rust wheel dist

build-rust:
	cargo build --manifest-path $(CARGO_MANIFEST) --release

wheel:
	uv run maturin build --release --strip -o target/wheels/

dist:
	uv run maturin sdist -o target/wheels/

dev:
	uv run maturin develop

# -- Test --------------------------------------------------------------------

test: test-rust test-python

test-rust:
	cargo test --manifest-path $(CARGO_MANIFEST)

test-python:
	PYTHONPATH=$(PYTHON_SRC) uv run --python $(PYTHON_VERSION) pytest $(TEST_PATHS) -q

check:
	cargo check --manifest-path $(CARGO_MANIFEST)
	cargo clippy --manifest-path $(CARGO_MANIFEST)

# -- Publish (host platform) -------------------------------------------------

pub:
	$(MAKE) test
	@if [ -n "$(V)" ]; then \
		$(MAKE) _set-version VERSION=$(V); \
	else \
		$(MAKE) _bump-patch; \
	fi
	rm -rf target/wheels/
	$(MAKE) build
	@if [ "$(CRATES_UPLOAD)" = "1" ]; then \
		cargo publish --manifest-path $(CARGO_MANIFEST) --allow-dirty; \
	fi
	@if [ "$(PYPI_UPLOAD)" = "1" ]; then \
		uv run twine upload -r $(PYPIRC_REPO) target/wheels/*.whl target/wheels/*.tar.gz; \
	fi
	@$(MAKE) _tag-and-push

# -- Publish (all platforms via podman) --------------------------------------

pub-all:
	$(MAKE) test
	@if [ -n "$(V)" ]; then \
		$(MAKE) _set-version VERSION=$(V); \
	else \
		$(MAKE) _bump-patch; \
	fi
	rm -rf target/wheels/
	./scripts/build-wheels.sh all
	@if [ "$(CRATES_UPLOAD)" = "1" ]; then \
		cargo publish --manifest-path $(CARGO_MANIFEST) --allow-dirty; \
	fi
	@if [ "$(PYPI_UPLOAD)" = "1" ]; then \
		uv run twine upload --verbose -r $(PYPIRC_REPO) target/wheels/*.whl target/wheels/*.tar.gz; \
	fi
	@$(MAKE) _tag-and-push

# -- Tag-only release (CI trigger) ------------------------------------------

release:
	@test -n "$(V)" || (echo "Usage: make release V=0.3.3" && exit 1)
	$(MAKE) _set-version VERSION=$(V)
	@$(MAKE) _tag-and-push

# -- Version management (portable GNU + BSD sed) -----------------------------

_set-version:
	@sed -i.bak 's/^version = ".*"/version = "$(VERSION)"/' pyproject.toml && rm -f pyproject.toml.bak
	@sed -i.bak 's/^version = ".*"/version = "$(VERSION)"/' $(CARGO_MANIFEST) && rm -f $(CARGO_MANIFEST).bak
	@if [ -n "$(INIT_PY)" ] && [ -f "$(INIT_PY)" ]; then \
		sed -i.bak 's/^__version__ = ".*"/__version__ = "$(VERSION)"/' $(INIT_PY) && rm -f $(INIT_PY).bak; \
	fi
	@echo "Version set to $(VERSION)"

_bump-patch:
	@CUR=$$(grep '^version' pyproject.toml | head -1 | sed 's/.*"\(.*\)"/\1/'); \
	MAJOR=$$(echo $$CUR | cut -d. -f1); \
	MINOR=$$(echo $$CUR | cut -d. -f2); \
	PATCH=$$(echo $$CUR | cut -d. -f3); \
	NEXT="$$MAJOR.$$MINOR.$$((PATCH + 1))"; \
	echo "Bumping $$CUR -> $$NEXT"; \
	$(MAKE) _set-version VERSION=$$NEXT

_tag-and-push:
	@NEW_V=$$(grep '^version' pyproject.toml | head -1 | sed 's/.*"\(.*\)"/\1/'); \
	git add pyproject.toml $(CARGO_MANIFEST); \
	if [ -n "$(INIT_PY)" ] && [ -f "$(INIT_PY)" ]; then git add $(INIT_PY); fi; \
	[ -f Cargo.lock ] && git add Cargo.lock; \
	git commit -m "release v$$NEW_V"; \
	git tag "v$$NEW_V"; \
	git push origin main "v$$NEW_V"; \
	echo "Published v$$NEW_V"

clean:
	cargo clean
	rm -rf target/wheels/ dist/ __pycache__
