all: local

# Configuration (override on the commandline)

LUA_VER := 5.1
LUA := /usr/bin/lua$(LUA_VER)
LUAC := /usr/bin/luac$(LUA_VER)
PREFIX ?= /usr/local
INST_ROOT := $(PREFIX)
SYSCONF_DIR ?= /etc

# Internal stuff
LUA_MOD_PATH := $(INST_ROOT)/share/lua/$(LUA_VER)
LUA_MOD_INST_PATH := $(DESTDIR)$(LUA_MOD_PATH)
BIN_PATH := $(INST_ROOT)/bin
BIN_INST_PATH := $(DESTDIR)$(BIN_PATH)
LIB_BIN_PATH := $(INST_ROOT)/lib/gitano/bin
LIB_BIN_INST_PATH := $(DESTDIR)$(LIB_BIN_PATH)
SHARE_PATH := $(INST_ROOT)/share/gitano
SHARE_INST_PATH := $(DESTDIR)$(SHARE_PATH)
SKEL_INST_PATH := $(SHARE_INST_PATH)/skel
LANG_INST_PATH := $(SHARE_INST_PATH)/lang
MAN_PATH := $(INST_ROOT)/share/man
MAN_INST_PATH := $(DESTDIR)$(MAN_PATH)
PLUGIN_PATH := $(SYSCONF_DIR)/gitano/plugins:$(INST_ROOT)/lib/gitano/plugins

LIB_BINS := gitano-auth gitano-post-receive-hook gitano-update-hook	\
	    gitano-update-ssh gitano-pre-receive-hook gitano-smart-http.cgi \
	    gitano-command.cgi

BINS := gitano-setup

TEST_BIN_NAMES := gitano-test-tool

TESTS := 01-basics 01-hooks 02-commands-as 02-commands-config 02-commands-copy  \
         02-commands-count-objects 02-commands-create 02-commands-destroy       \
         02-commands-fsck 02-commands-gc 02-commands-graveyard                  \
         02-commands-git-upload-archive 02-commands-group 02-commands-help      \
         02-commands-keyring                                                    \
         02-commands-ls 02-commands-rename 02-commands-rsync                    \
         02-commands-sshkey 02-commands-user 02-commands-whoami 03-cgit-support \
         03-shallow-push 03-treedelta-rules 03-force-pushing                    \
         03-dangling-HEAD 03-config-user-whitelist


MODS := gitano 								\
									\
	gitano.util							\
	gitano.actions gitano.config gitano.lace gitano.log		\
	gitano.repository gitano.supple 		\
	gitano.command gitano.admincommand gitano.usercommand		\
	gitano.repocommand gitano.copycommand gitano.auth gitano.plugins\
	gitano.i18n gitano.hooks gitano.patterns

SKEL_FILES := gitano-admin/rules/selfchecks.lace			\
	      gitano-admin/rules/aschecks.lace 				\
	      gitano-admin/rules/siteadmin.lace				\
	      gitano-admin/rules/destroyrepo.lace			\
	      gitano-admin/rules/remoteconfigchecks.lace		\
	      gitano-admin/rules/core.lace				\
	      gitano-admin/rules/renamerepo.lace			\
	      gitano-admin/rules/defines.lace				\
	      gitano-admin/rules/project.lace				\
	      gitano-admin/rules/adminchecks.lace			\
	      gitano-admin/rules/createrepo.lace			\
	      gitano-admin/rules/simpleprojectauth.lace

LANG_FILES := json.lua en.lua

MAN1S := gitano-setup.1


PLUGINS := rsync.lua archive.lua git-annex.lua

TEST_PLUGINS := testing-hooks.lua demo.lua

UNSUPPORTED_PLUGINS := git-multimail.lua

COVERAGE := no

ifeq ($(COVERAGE),yes)

MODS := $(MODS) gitano.coverage

endif

MOD_DIRS := gitano
MOD_FILES := $(patsubst %,%.lua,$(subst .,/,$(MODS)))
SRC_MOD_FILES := $(patsubst %,lib/%,$(MOD_FILES))

LOCAL_BINS := $(patsubst %,bin/%,$(BINS) $(LIB_BINS))
LIB_BIN_SRCS := $(patsubst %,bin/%.in,$(LIB_BINS))

TEST_BINS := $(patsubst %,testing/%,$(TEST_BIN_NAMES))
TEST_BIN_SRCS := $(patsubst %,%.in,$(TEST_BINS))

YARN := yarn

TESTS := $(patsubst %,testing/%.yarn,$(TESTS))

GEN_BIN := utils/install-lua-bin
RUN_GEN_BIN := $(LUA) $(GEN_BIN) $(LUA)

ifeq ($(COVERAGE),yes)
define GEN_LOCAL_BIN

$(RUN_GEN_BIN) $(shell pwd) $(shell pwd)/bin $(shell pwd)/lib $(shell pwd)/plugins $1 $2 $(shell pwd)/extras/luacov/src $(shell pwd)/.coverage/
chmod 755 $2

endef
ifeq ($(COVER_GTT),yes)
define GEN_LOCAL_TESTING_BIN

$(RUN_GEN_BIN) $(shell pwd)/testing/inst/share/gitano $(shell pwd)/testing/inst/lib/gitano/bin $(shell pwd)/testing/inst/share/lua/5.1 $(shell pwd)/testing/inst/lib/gitano/plugins $1 $2 $(shell pwd)/extras/luacov/src $(shell pwd)/.coverage/
chmod 755 $2

endef
else
define GEN_LOCAL_TESTING_BIN

$(RUN_GEN_BIN) $(shell pwd)/testing/inst/share/gitano $(shell pwd)/testing/inst/lib/gitano/bin $(shell pwd)/testing/inst/share/lua/5.1 $(shell pwd)/testing/inst/lib/gitano/plugins $1 $2
chmod 755 $2

endef
endif
else
define GEN_LOCAL_BIN

$(RUN_GEN_BIN) $(shell pwd) $(shell pwd)/bin $(shell pwd)/lib $(shell pwd)/plugins $1 $2
chmod 755 $2

endef
define GEN_LOCAL_TESTING_BIN

$(RUN_GEN_BIN) $(shell pwd)/testing/inst/share/gitano $(shell pwd)/testing/inst/lib/gitano/bin $(shell pwd)/testing/inst/share/lua/5.1 $(shell pwd)/testing/inst/lib/gitano/plugins $1 $2
chmod 755 $2

endef
endif

ifeq ($(COVERAGE),yes)
define GEN_INSTALL_BIN

$(RUN_GEN_BIN) $(SHARE_PATH) $(LIB_BIN_PATH) $(LUA_MOD_PATH) $(PLUGIN_PATH) $1 $2 $(shell pwd)/extras/luacov/src $(shell pwd)/.coverage/
chmod 755 $2

endef
else
define GEN_INSTALL_BIN

$(RUN_GEN_BIN) $(SHARE_PATH) $(LIB_BIN_PATH) $(LUA_MOD_PATH) $(PLUGIN_PATH) $1 $2
chmod 755 $2

endef
endif
define GEN_INSTALL_MAN

cp $1 $2
chmod 644 $2

endef

define GEN_INSTALL_MOD

install -m 644 $1 $2

endef

define GEN_LOCAL_MOD

$(RUN_GEN_BIN) $(shell pwd) $(shell pwd)/bin $(shell pwd)/lib $(shell pwd)/plugins $1 $2

endef

LOCAL_MODS := lib/gitano/coverage.lua

local: $(LOCAL_BINS) $(LOCAL_MODS)
	@$(LUAC) -p $(LOCAL_BINS) $(LOCAL_MODS)
	@mkdir -p .coverage
ifeq ($(COVERAGE),yes)
	@echo NOTE: Coverage gathering enabled
	@if ! test -r extras/luacov/src/luacov; then \
		echo "CANNOT COVERAGE TEST, LUACOV MODULE NOT AVAILABLE"; \
		echo "Please run: git submodule init && git submodule update"; \
	fi
else
	@echo NOTE: Coverage gathering is not enabled
endif

clean: cleanbins
	@echo "CLEAN: coverage stats and reports"
	@$(RM) -r .coverage luacov.stats.out luacov.report.out

cleanbins:
	@echo "CLEAN: local binaries and modules"
	@$(RM) $(LOCAL_BINS) $(LOCAL_MODS)
	@echo "CLEAN: test binaries"
	@$(RM) $(TEST_BINS)
	@echo "CLEAN: test install"
	@$(RM) -r testing/inst

distclean: clean
	@find . -name "*~" -delete

bin/%: bin/%.in $(GEN_BIN) FORCE
	@$(call GEN_LOCAL_BIN,$<,$@)

testing/%: testing/%.in $(GEN_BIN) FORCE
	@$(call GEN_LOCAL_TESTING_BIN,$<,$@)

lib/gitano/%.lua: lib/gitano/%.lua.in $(GEN_BIN) FORCE
	@$(call GEN_LOCAL_MOD,$<,$@)

FORCE:
.PHONY: FORCE

install: install-bins install-lib-bins install-mods install-skel install-man install-plugins install-lang

install-man:
	mkdir -p $(MAN_INST_PATH)/man1
	$(foreach MAN,$(MAN1S),$(call GEN_INSTALL_MAN,doc/$(MAN),$(MAN_INST_PATH)/man1/$(MAN)))

install-bins: $(BIN_SRCS) $(GEN_BIN)
	mkdir -p $(BIN_INST_PATH)
	$(foreach BIN,$(BINS),$(call GEN_INSTALL_BIN,bin/$(BIN).in,$(BIN_INST_PATH)/$(BIN)))

install-lib-bins: $(LIB_BIN_SRCS) $(GEN_BIN)
	mkdir -p $(LIB_BIN_INST_PATH)
	$(foreach BIN,$(LIB_BINS),$(call GEN_INSTALL_BIN,bin/$(BIN).in,$(LIB_BIN_INST_PATH)/$(BIN)))

install-mods: $(SRC_MOD_FILES)
	mkdir -p $(patsubst %,$(LUA_MOD_INST_PATH)/%,$(MOD_DIRS))
	$(foreach MOD,$(MOD_FILES),$(call GEN_INSTALL_MOD,lib/$(MOD),$(LUA_MOD_INST_PATH)/$(MOD)))

install-skel:
	mkdir -p $(SKEL_INST_PATH)/gitano-admin/rules
	for SKELFILE in $(SKEL_FILES); do \
		install -m 644 skel/$$SKELFILE $(SKEL_INST_PATH)/$$SKELFILE; \
	done

install-lang:
	mkdir -p $(LANG_INST_PATH)
	for LANGFILE in $(LANG_FILES); do \
		install -m 644 lang/$$LANGFILE $(LANG_INST_PATH)/$$LANGFILE; \
	done

install-plugins:
	mkdir -p $(DESTDIR)$(INST_ROOT)/lib/gitano/plugins
	mkdir -p $(DESTDIR)$(SYSCONF_DIR)/gitano/plugins
	for PLUGIN in $(PLUGINS); do \
		install -m 644 plugins/$$PLUGIN $(DESTDIR)$(INST_ROOT)/lib/gitano/plugins; \
	done
	for LANGFILE in $(wildcard $(patsubst %.lua,plugins/%_*.lua,$(PLUGINS))); do \
		install -m 644 $$LANGFILE $(DESTDIR)$(INST_ROOT)/lib/gitano/plugins; \
	done

override YARN_ARGS := $(YARN_ARGS)
ifneq ($(LUA_PATH),)
override YARN_ARGS += --env LUA_PATH="$(LUA_PATH)"
endif
ifneq ($(LUA_CPATH),)
override YARN_ARGS += --env LUA_CPATH="$(LUA_CPATH)"
endif
ifneq ($(SCENARIO),)
override YARN_ARGS += --run "$(SCENARIO)"
endif

ifneq ($(YARN_SNAPSHOT),)
override YARN_ARGS += --snapshot
endif

TEST_PROTO ?= ssh

ifeq ($(filter $(TEST_PROTO),ssh http),)
$(error TEST_PROTO should be ssh or http)
endif

ifeq ($(HTTP_FIRST_TEST_PORT),)
HTTP_FIRST_TEST_PORT = 8080
endif

test-install:
	@$(RM) -r testing/inst
	@$(MAKE) PREFIX="$(shell pwd)/testing/inst" \
              SYSCONF_DIR="$(shell pwd)/testing/inst/etc" \
              install >/dev/null
	@for P in $(TEST_PLUGINS); do \
		cp plugins/$$P "$(shell pwd)/testing/inst/etc/gitano/plugins/"; \
	done

plugin-check:
	$(LUAC) -p $(patsubst %,plugins/%,$(PLUGINS) $(TEST_PLUGINS) $(UNSUPPORTED_PLUGINS))
	for PLUGIN in $(patsubst %,plugins/%,$(PLUGINS) $(TEST_PLUGINS)); do \
		env LUA_PATH="$(shell pwd)/lib/?.lua;;" $(LUA) $$PLUGIN; \
	done

basictest: local plugin-check $(TEST_BINS) test-install
	@echo "Running basic yarns in '$(TEST_PROTO)' mode"
	@echo "Set TEST_PROTO if you want to change that"
	@$(YARN)							 \
		--env GTT="$$(pwd)/testing/gitano-test-tool"		 \
		--env GTT_PROTO=$(TEST_PROTO) 				 \
		--env HTTP_FIRST_TEST_PORT=$(HTTP_FIRST_TEST_PORT)       \
		$(YARN_ARGS)                                             \
	        testing/library.yarn testing/01*.yarn

test: local plugin-check sshtests httptests

sshtests: $(TEST_BINS) test-install
	@echo "Running full yarns in 'ssh' mode"
	@$(YARN)							 \
		--env GTT="$$(pwd)/testing/gitano-test-tool"		 \
		--env GTT_PROTO=ssh 					 \
		--env HTTP_FIRST_TEST_PORT=$(HTTP_FIRST_TEST_PORT)       \
		$(YARN_ARGS)                                             \
	        testing/library.yarn $(TESTS)

ifeq ($(SKIP_HTTP_TESTS),)
httptests: $(TEST_BINS) test-install
	@echo "Running full yarns in 'http' mode"
	@$(YARN)							 \
		--env GTT="$$(pwd)/testing/gitano-test-tool"		 \
		--env GTT_PROTO=http 					 \
		--env HTTP_FIRST_TEST_PORT=$(HTTP_FIRST_TEST_PORT)       \
		$(YARN_ARGS)                                             \
	        testing/library.yarn $(TESTS)
else
httptests:
	@echo "WARNING: Running of yarns in 'http' mode disabled."
	@echo "WARNING: Cannot guarantee Gitano will work in HTTP mode."
endif

check: test

coverage-report:
	@echo "COVERAGE: Merge stats..."
	@env LUA_PATH="$(shell pwd)/extras/luacov/src/?.lua;;" $(LUA) utils/merge-luacov-stats .coverage/luacov.stats-*.out
	@echo "COVERAGE: Generate report..."
	@env LUA_PATH="$(shell pwd)/extras/luacov/src/?.lua;;" $(LUA) extras/luacov/src/bin/luacov
	@echo "COVERAGE: Summary:"
	@sed '0,/^Summary/d' < luacov.report.out | tail -n +2 | sed -e's/^/COVERAGE: /'
