find_program(GIT_EXECUTABLE git REQUIRED)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_DESCRIBE_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE)

function(si_get_git_version OUTPUT)
    # Try to parse complete version string {MAJ}.{MIN}.{PATCH}-{COMMIT COUNT}-g{HASH}
    string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)-([0-9]+)-g([0-9a-f]+)" "\\1;\\2;\\3;\\4;\\5" GIT_COMPLETE_DESCRIPTION "${GIT_DESCRIBE_OUTPUT}" )
    list(LENGTH GIT_COMPLETE_DESCRIPTION GIT_COMPLETE_DESCRIPTION_COUNT)
    if(GIT_COMPLETE_DESCRIPTION_COUNT EQUAL 5)
        list(GET GIT_COMPLETE_DESCRIPTION 0 VERSION_MAJOR)
        list(GET GIT_COMPLETE_DESCRIPTION 1 VERSION_MINOR)
        list(GET GIT_COMPLETE_DESCRIPTION 2 VERSION_PATCH)
        list(GET GIT_COMPLETE_DESCRIPTION 4 VERSION_TWEAK)
        set(${OUTPUT} "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_TWEAK}" PARENT_SCOPE)
        return()
    endif()

    # Try to parse release version string {MAJ}.{MIN}.{PATCH}
    string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1;\\2;\\3" GIT_RELEASE_DESCRIPTION "${GIT_DESCRIBE_OUTPUT}" )
    list(LENGTH GIT_RELEASE_DESCRIPTION GIT_RELEASE_DESCRIPTION_COUNT)
    if(GIT_RELEASE_DESCRIPTION_COUNT EQUAL 3)
        list(GET GIT_RELEASE_DESCRIPTION 0 VERSION_MAJOR)
        list(GET GIT_RELEASE_DESCRIPTION 1 VERSION_MINOR)
        list(GET GIT_RELEASE_DESCRIPTION 2 VERSION_PATCH)
        set(${OUTPUT} "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" PARENT_SCOPE)
        return()
    endif()

    # Try to parse non-tagged string {PATCH}
    string(REGEX REPLACE "([0-9a-f]+)" "\\1" GIT_NOTAG_DESCRIPTION "${GIT_DESCRIBE_OUTPUT}" )
    if(GIT_NOTAG_DESCRIPTION)
        set(${OUTPUT} "0.0.0.${GIT_NOTAG_DESCRIPTION}" PARENT_SCOPE)
        return()
    endif()

    set(${OUTPUT} "NO_VERSION" PARENT_SCOPE)
endfunction()
