.DEFAULT_GOAL := build
PREFIX ?= /usr/local

GO = _support/go

LOCAL_GO_FILES = $(shell find . -type f -name '*.go' -not -path './.go' -not -path './.go/*')
GO_PACKAGES = $(shell go list ./...)

# run_go_tests will execute Go tests with all required parameters. Its
# behaviour can be modified via the following variables:
#
# TEST_OPTIONS: any additional options
# GO_PACKAGES: packages which shall be tested
TEST_OPTIONS = -timeout 1m
run_go_tests = $(GO) test $(if $V,-v) -race ${TEST_OPTIONS} $(GO_PACKAGES)

MACOS_HOMEBREW_PREFIX := $(shell command -v brew > /dev/null 2>&1 && brew --prefix || true)

# PKG_CONFIG_PATH needs to explicitly be set for macOS platforms
ifneq ($(MACOS_HOMEBREW_PREFIX),)
export PKG_CONFIG_PATH := ${PKG_CONFIG_PATH}:${MACOS_HOMEBREW_PREFIX}/opt/icu4c/lib/pkgconfig
# On macOS, statically link icu4c libraries by specifying full paths to .a files
ICU4C_LIB_DIR := $(shell PKG_CONFIG_PATH=${PKG_CONFIG_PATH} pkg-config --variable=libdir icu-i18n 2>/dev/null)
ICU4C_INCLUDE_DIR := $(shell PKG_CONFIG_PATH=${PKG_CONFIG_PATH} pkg-config --variable=includedir icu-i18n 2>/dev/null)

ifeq ($(ICU4C_LIB_DIR),)
$(error icu4c libraries not found! Run 'brew install icu4c')
endif

ifeq ($(ICU4C_INCLUDE_DIR),)
$(error icu4c headers not found! Run 'brew install icu4c')
endif

ICU4C_STATIC_LIBS := $(ICU4C_LIB_DIR)/libicuio.a $(ICU4C_LIB_DIR)/libicui18n.a $(ICU4C_LIB_DIR)/libicuuc.a $(ICU4C_LIB_DIR)/libicudata.a
# Override pkg-config directives in gitlab.com/gitlab-org/go/icu by setting CGO flags directly
export CGO_LDFLAGS := -L$(shell pwd)/tmp/libparser/lib $(ICU4C_STATIC_LIBS) -lc++ -lpthread -lm
export CGO_CFLAGS := -I$(shell pwd)/tmp/libparser/include -I$(ICU4C_INCLUDE_DIR)
# Disable pkg-config to prevent dynamic linking
export PKG_CONFIG := /usr/bin/true
else
export CGO_LDFLAGS := -L$(shell pwd)/tmp/libparser/lib
export CGO_CFLAGS := -I$(shell pwd)/tmp/libparser/include
endif

# V := 1 # When V is set, print commands and build progress.

help: ## Display available commands
	@echo "Available targets:"
	@awk -F':' '/^[a-zA-Z0-9_-]+:/ { \
		target = $$1; \
		has_help = match($$0, /##[^#].*$$/); \
		if (has_help) { \
			help = substr($$0, RSTART + 2, RLENGTH - 2); \
		} else { \
			help = ""; \
		} \
		printf "\033[36m%-20s\033[0m %s\n", target, help; \
	}' $(MAKEFILE_LIST) | sort
.PHONY: help

.PHONY: all
all: build

.PHONY: build
build: tmp/libparser
	$Q $(GO) build $(if $V,-v) $(VERSION_FLAGS) -o bin/gitlab-elasticsearch-indexer .

install: build
	install -d ${PREFIX}/bin
	install -m755 bin/gitlab-elasticsearch-indexer ${PREFIX}/bin

.PHONY: clean test list cover format

clean:
	$Q rm -rf bin tmp

tmp/libparser: tmp
	$Q $(GO) run gitlab.com/gitlab-org/rust/gitlab-code-parser/bindings/go/cmd/libparser-download tmp/libparser

.PHONY: test-infra
test-infra:
	$Q docker-compose down
	$Q docker-compose up -d

test: tmp/libparser
	$Q $(call run_go_tests) # install -race libs to speed up next run
	$Q $(GO) vet $(GO_PACKAGES)
	$Q $(GO) test $(if $V,-v) -race $(GO_PACKAGES)

cover: TEST_OPTIONS  := ${TEST_OPTIONS} -cover -coverprofile=tmp/test.coverage
cover: tmp/libparser
	@echo "NOTE: make cover does not exit 1 on failure, don't use it to check for tests success!"
	$Q $(call run_go_tests)
	$Q $(GO) tool cover -html tmp/test.coverage -o tmp/test.coverage.html
	$Q $(GO) install github.com/boumenot/gocover-cobertura@latest
	$Q ${GOPATH}/bin/gocover-cobertura < tmp/test.coverage > coverage.xml
	@echo ""
	@echo "=====> Total test coverage: <====="
	@echo ""
	$Q $(GO) tool cover -func tmp/test.coverage

.PHONY: bench
bench: tmp/libparser
	$Q $(GO) test $(if $V,-v) -bench=. ${TEST_OPTIONS} $(GO_PACKAGES)

.PHONY: golangci-lint
golangci-lint: tmp/libparser
	$Q golangci-lint run -v

format: bin/goimports
	$Q bin/goimports $(if $V,-v) -w $(LOCAL_GO_FILES)

watch-test: check-watchexec ## Watch for changes and run tests
	watchexec -c -n -e go -- make test
.PHONY: watch-test

check-watchexec: ## Check watchexec is installed
ifeq (, $(shell which watchexec))
	$(error "No watchexec installed, consider running brew install watchexec")
endif
.PHONY: check-watchexec

##### =====> Internals <===== #####

VERSION          := $(shell git describe --tags --always --dirty="-dev")
DATE             := $(shell date -u '+%Y-%m-%d-%H%M UTC')
VERSION_FLAGS    := -ldflags='-X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"'

Q := $(if $V,,@)

.PHONY: tmp
tmp:
	mkdir -p tmp

bin/goimports:
	$Q $(GO) build -o bin/goimports golang.org/x/tools/cmd/goimports

# Based on https://github.com/cloudflare/hellogopher - v1.1 - MIT License
#
# Copyright (c) 2017 Cloudflare
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
