# Calculates the tweak string based on the results of "git describe"
# ..assumes the following files exist: with "<<GIT_PREFIX>>" 
# ..replaced by the argument in the GET_GIT_VERSION function below
#
# VERSION -- of the format VERSION.SUBVERSION.PATCH
# cmake/modules/GetGitVersion.cmake -- this file
#
# version.h -- in any includes directory should include: extern const char *<<GIT_PREFIX>>_VERSION;
# .. also available are <<GIT_PREFIX>>_VERSION_DATE and <<GIT_PREFIX>>_BUILD_DATE
#
# The following OBJECT library will be necessary as compile target for anything that includes version.h
# $<TARGET_OBJECTS:<<GIT_PREFIX}>>_VERSION>
# and/or the following library to the target_link_libraries:
# <<GIT_PREFIX>>_VERSION_LIB
#
# The following target can be an additional build dependency of version.h
# <<GIT_PREFIX>>_REPLACE_VERSION_H
#
# Auto generates the following in the build directory:
# makeVersionFile/makeGitVersionFile.cmake.in
# makeVersionFile/makeGitVersionFile.version.c.in
# makeVersionFile/get_git_version.sh -- queries the contents of VERSION and calls git describe for the TWEAK, forth part of the string
# makeVersionFile/<<GIT_PREFIX>>_VERSION
# makeVersionFile/<<GIT_PREFIX>>_makeVersionFile.cmake - and includes its generated contents


function(GET_GIT_VERSION)

set(GIT_PREFIX ${ARGV})

# get the base version string from the top level file in the source tree: "VERSION"
set(${GIT_PREFIX}_BASE_VERSION_FILE "${CMAKE_CURRENT_LIST_DIR}/VERSION") # VER.SUBVER.PATCH - manual change by developer
set(${GIT_PREFIX}_BASE_VERSION_FILE "${CMAKE_CURRENT_LIST_DIR}/VERSION" PARENT_SCOPE) # VER.SUBVER.PATCH - manual change by developer
file(READ "${${GIT_PREFIX}_BASE_VERSION_FILE}" ${GIT_PREFIX}_FULL_VERSION_STRING LIMIT_COUNT 1)
string(REGEX REPLACE "(\n|\r)" "" ${GIT_PREFIX}_FULL_VERSION_STRING "${${GIT_PREFIX}_FULL_VERSION_STRING}")
string(REGEX REPLACE "[A-Za-z].*" "" ${GIT_PREFIX}_VERSION_STRING "${${GIT_PREFIX}_FULL_VERSION_STRING}")
set(${GIT_PREFIX}_BASE_VERSION "${${GIT_PREFIX}_VERSION_STRING}")
set(${GIT_PREFIX}_BASE_VERSION "${${GIT_PREFIX}_VERSION_STRING}" PARENT_SCOPE)
message(STATUS "${GIT_PREFIX} base version ${${GIT_PREFIX}_BASE_VERSION} (${${GIT_PREFIX}_FULL_VERSION_STRING})")


# get the version from git
set(${GIT_PREFIX}_GET_VERSION_SH              "${PROJECT_BINARY_DIR}/makeVersionFile/get_version.sh") # autogen
set(${GIT_PREFIX}_VERSION_FILE                "${PROJECT_BINARY_DIR}/makeVersionFile/${GIT_PREFIX}_VERSION") # autogen: VER.SUBVER.PATCH.git-commit-hash
set(${GIT_PREFIX}_VERSION_FILE                "${PROJECT_BINARY_DIR}/makeVersionFile/${GIT_PREFIX}_VERSION" PARENT_SCOPE) # autogen: VER.SUBVER.PATCH.git-commit-hash
set(${GIT_PREFIX}_VERSION_C_FILE              "${PROJECT_BINARY_DIR}/makeVersionFile/___${GIT_PREFIX}_AUTOGEN_version.c") # autogen
set(${GIT_PREFIX}_VERSION_C_FILE_TEMPLATE     "${PROJECT_BINARY_DIR}/makeVersionFile/version.cpp.in") # template for autogen
set(${GIT_PREFIX}_VERSION_C_FILE1             "${PROJECT_BINARY_DIR}/makeVersionFile/version.cpp") # autogen includes autogen

set(${GIT_PREFIX}_MAKE_VERSION_FILE_CMAKE_IN  "${PROJECT_BINARY_DIR}/makeVersionFile/${GIT_PREFIX}_makeVersionFile.cmake.in")
set(${GIT_PREFIX}_MAKE_VERSION_FILE_CMAKE     "${PROJECT_BINARY_DIR}/makeVersionFile/${GIT_PREFIX}_makeVersionFile.cmake")


#
# create the cmake.in template
#
file(WRITE ${${GIT_PREFIX}_MAKE_VERSION_FILE_CMAKE_IN}
"#
# This file is autogenerated by GetGitVersion.cmake
#
file(READ ${${GIT_PREFIX}_VERSION_FILE}     ${GIT_PREFIX}_VERSION_RAW LIMIT 1024)
string(STRIP \"\${${GIT_PREFIX}_VERSION_RAW}\" ${GIT_PREFIX}_VERSION_AND_BRANCH)
separate_arguments(${GIT_PREFIX}_VERSION_AND_BRANCH)
list(GET ${GIT_PREFIX}_VERSION_AND_BRANCH 0 ${GIT_PREFIX}_VERSION)
list(LENGTH ${GIT_PREFIX}_VERSION_AND_BRANCH ${GIT_PREFIX}_VERSION_AND_BRANCH_LEN)
if (${GIT_PREFIX}_VERSION_AND_BRANCH_LEN GREATER 1)
  list(GET ${GIT_PREFIX}_VERSION_AND_BRANCH 1 ${GIT_PREFIX}_BRANCH)
else()
  set(${GIT_PREFIX}_BRANCH)
endif()

set(${GIT_PREFIX}_BUILD_DATE \"@BUILD_DATE@\")

set(${GIT_PREFIX}_VERSION_STRING  \"\${${GIT_PREFIX}_VERSION}\")
message(STATUS \"Building ${GIT_PREFIX} version \${${GIT_PREFIX}_VERSION_STRING} on branch \${${GIT_PREFIX}_BRANCH}\")
configure_file(${${GIT_PREFIX}_VERSION_C_FILE_TEMPLATE} ${${GIT_PREFIX}_VERSION_C_FILE})

")

#
# create the get_version.sh that will be executed to detect the tweak
#
file(WRITE ${${GIT_PREFIX}_GET_VERSION_SH} "#!/bin/bash

# 
# This file is autogenerated by GetGitVersion.cmake
#

ver=\$(cat VERSION);
if [ -e .git ]
then
  GIT_EXECUTABLE=$(which git)

  base=\$(\${GIT_EXECUTABLE} describe --abbrev=0 --always)
  hash=\$(\${GIT_EXECUTABLE} describe --dirty --always)
  branch=\$(\${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD )

  # check if the latest tag is the same base VERSION
  if [ \"\${base}\" != \"v\${ver}\" ]
  then
    base=XXX_dummy_XXX # keep the whole tag
  fi

  tweak=
  if [ \"\${base}\" != \"\${hash}\" ]
  then
    tweak=\$(echo \$hash | sed 's/'\$base'-//;')
  fi
  if [ -n \"\${tweak}\" ]
  then
    echo \"\${ver}.\${tweak}\" \"\${branch}\"
    exit
  fi
fi
echo \${ver}
")

#
# create the version.c.in template file
#
file(WRITE ${${GIT_PREFIX}_VERSION_C_FILE_TEMPLATE} "
/* This file is auto generated by GetGitVersion.cmake and necessary for build dependencies */

#include \"version.h\"

#define _${GIT_PREFIX}_VERSION_ \"@${GIT_PREFIX}_VERSION@\"
#define _${GIT_PREFIX}_BUILD_DATE \"@${GIT_PREFIX}_BUILD_DATE@\"
#define _${GIT_PREFIX}_BRANCH \"@${GIT_PREFIX}_BRANCH@\"

const char *${GIT_PREFIX}_VERSION = _${GIT_PREFIX}_VERSION_;
const char *${GIT_PREFIX}_BUILD_DATE = _${GIT_PREFIX}_BUILD_DATE;
const char *${GIT_PREFIX}_VERSION_DATE = _${GIT_PREFIX}_VERSION_ \"-\" _${GIT_PREFIX}_BUILD_DATE;
const char *${GIT_PREFIX}_BRANCH = _${GIT_PREFIX}_BRANCH;
")

#
# create the version.c to be compiled and linked
#
file(WRITE ${${GIT_PREFIX}_VERSION_C_FILE1} "
/* This file is auto generated by GetGitVersion.cmake and necessary for build dependencies */

#include \"___${GIT_PREFIX}_AUTOGEN_version.c\"
")

#
# add target to discover the tweak
#
find_package(Git QUIET)
add_custom_target(${GIT_PREFIX}_GET_VERSION_FILE ALL
                  COMMAND chmod +x ${${GIT_PREFIX}_GET_VERSION_SH} && ${${GIT_PREFIX}_GET_VERSION_SH} > ${${GIT_PREFIX}_VERSION_FILE}
                  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
                  COMMENT "Retrieving git commit hash by executing ${${GIT_PREFIX}_GET_VERSION_SH}"
                  VERBATIM
                 )

#
# timestamp is of the last cmake execution
#
string(TIMESTAMP ${GIT_PREFIX}_BUILD_DATE "%Y%m%d_%H%M%S")
set(BUILD_DATE "${${GIT_PREFIX}_BUILD_DATE}")
message(STATUS "${GIT_PREFIX}_BUILD_DATE=${${GIT_PREFIX}_BUILD_DATE}")

#
# create the cmake file to be executed
# and execute it
configure_file(${${GIT_PREFIX}_MAKE_VERSION_FILE_CMAKE_IN} ${${GIT_PREFIX}_MAKE_VERSION_FILE_CMAKE} @ONLY)
add_custom_target(${GIT_PREFIX}_REPLACE_VERSION_H ALL
                  COMMAND ${CMAKE_COMMAND}
                    -D${GIT_PREFIX}_VERSION=${${GIT_PREFIX}_VERSION}
                    -D${GIT_PREFIX}_VERSION_C_FILE=${${GIT_PREFIX}_VERSION_C_FILE} # output
                    -D${GIT_PREFIX}_VERSION_FILE=${${GIT_PREFIX}_VERSION_FILE}
                    -D${GIT_PREFIX}_VERSION_C_FILE_TEMPLATE=${${GIT_PREFIX}_VERSION_C_FILE_TEMPLATE}
                    -DBUILD_DATE=${${GIT_PREFIX}_BUILD_DATE}
                    -D${GIT_PREFIX}_BUILD_DATE=${${GIT_PREFIX}_BUILD_DATE}
                    -D${GIT_PREFIX}_BRANCH=${${GIT_PREFIX}_BRANCH}
                    -P ${${GIT_PREFIX}_MAKE_VERSION_FILE_CMAKE}
                BYPRODUCTS ${${GIT_PREFIX}_VERSION_FILE} ${${GIT_PREFIX}_VERSION_C_FILE}
		WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
		DEPENDS ${GIT_PREFIX}_GET_VERSION_FILE
		COMMENT "Building ${${GIT_PREFIX}_VERSION_FILE} and ${${GIT_PREFIX}_VERSION_C_FILE}"
                )

add_dependencies(${GIT_PREFIX}_REPLACE_VERSION_H ${GIT_PREFIX}_GET_VERSION_FILE)

#
# the rules to build the version object library
#
include_directories(${PROJECT_BINARY_DIR}/makeVersionFile)
add_library(${GIT_PREFIX}_VERSION OBJECT ${${GIT_PREFIX}_VERSION_C_FILE1})
add_dependencies(${GIT_PREFIX}_VERSION ${GIT_PREFIX}_REPLACE_VERSION_H)

add_library(${GIT_PREFIX}_VERSION_LIB $<TARGET_OBJECTS:${GIT_PREFIX}_VERSION>)

endfunction()


