Skip to content

Commit

Permalink
Factor out functions into TribitsGitRepoVersionInfo.cmake (TriBITSPub…
Browse files Browse the repository at this point in the history
…#483)

We need to be breaking up TribitsGlobalMacros.cmake because it is too long.

I also added a new function to get just the 40-char SHA1 and I added unit
tests for it.
  • Loading branch information
bartlettroscoe committed Jun 7, 2022
1 parent b383ed2 commit 11c8d2d
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 71 deletions.
2 changes: 1 addition & 1 deletion test/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ tribits_add_advanced_test( TestingFunctionMacro_UnitTests
-D${PROJECT_NAME}_TRIBITS_DIR=${${PROJECT_NAME}_TRIBITS_DIR}
-P "${CMAKE_CURRENT_SOURCE_DIR}/TestingFunctionMacro_UnitTests.cmake"
PASS_REGULAR_EXPRESSION_ALL
"Final UnitTests Result: num_run = 695"
"Final UnitTests Result: num_run = 702"
"Final UnitTests Result: PASSED"
)

Expand Down
53 changes: 52 additions & 1 deletion test/core/TestingFunctionMacro_UnitTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ include(TribitsFilepathHelpers)
include(TribitsGetVersionDate)
include(TribitsTplFindIncludeDirsAndLibraries)
include(TribitsReportInvalidTribitsUsage)
include(TribitsGitRepoVersionInfo)
include(UnitTestHelpers)
include(GlobalSet)
include(GlobalNullSet)
Expand Down Expand Up @@ -487,6 +488,55 @@ function(unittest_tribits_get_version_date_from_raw_git_commit_utc_time)
endfunction()


function(unittest_tribits_git_repo_sha1)

message("\n***")
message("*** Testing tribits_git_repo_sha1()")
message("***\n")

find_program(GIT_EXECUTABLE ${GIT_NAME})

set(tribitsProjDir "${${PROJECT_NAME}_TRIBITS_DIR}/..")

# Matches any 40-char SHA1
set(anySha1Regex "")
foreach(i RANGE 0 39)
string(APPEND anySha1Regex "[a-z0-9]")
endforeach()

if (IS_DIRECTORY "${tribitsProjDir}/.git")

message("Testing tribits_git_repo_sha1() with the base TriBITS project (without FAILURE_MESSAGE_OUT)\n")
tribits_git_repo_sha1("${tribitsProjDir}" gitRepoSha1)
unittest_string_var_regex(gitRepoSha1 REGEX_STRINGS "${anySha1Regex}")

message("Testing tribits_git_repo_sha1() with the base TriBITS project (with FAILURE_MESSAGE_OUT)\n")
tribits_git_repo_sha1("${tribitsProjDir}" gitRepoSha1
FAILURE_MESSAGE_OUT failureMsg)
unittest_string_var_regex(gitRepoSha1 REGEX_STRINGS "${anySha1Regex}")
unittest_compare_const(failureMsg "")

endif()

message("Testing tribits_git_repo_sha1(): No GIT_EXECUTABLE (with FAILURE_MESSAGE_OUT)\n")
set(GIT_EXECUTABLE_SAVED "${GIT_EXECUTABLE}")
set(GIT_EXECUTABLE "")
tribits_git_repo_sha1("${tribitsProjDir}" gitRepoSha1
FAILURE_MESSAGE_OUT failureMsg)
unittest_compare_const(gitRepoSha1 "")
unittest_compare_const(failureMsg "ERROR: The program 'git' could not be found!")
set(GIT_EXECUTABLE "${GIT_EXECUTABLE_SAVED}")
unset(GIT_EXECUTABLE_SAVED)

message("Testing tribits_git_repo_sha1(): Invalid repo dir (with FAILURE_MESSAGE_OUT)\n")
tribits_git_repo_sha1("/repo/does/not/exist" gitRepoSha1
FAILURE_MESSAGE_OUT failureMsg)
unittest_compare_const(gitRepoSha1 "")
unittest_compare_const(failureMsg "ERROR: The directory /repo/does/not/exist/.git does not exist!")

endfunction()


function(unittest_tribits_tpl_allow_pre_find_package)

message("\n***")
Expand Down Expand Up @@ -4520,6 +4570,7 @@ unittest_tribits_misc()
unittest_tribits_strip_quotes_from_str()
unittest_tribits_get_version_date_from_raw_git_commit_utc_time()
unittest_tribits_get_raw_git_commit_utc_time()
unittest_tribits_git_repo_sha1()
unittest_tribits_tpl_allow_pre_find_package()
unittest_tribits_report_invalid_tribits_usage()

Expand Down Expand Up @@ -4576,4 +4627,4 @@ message("*** Determine final result of all unit tests")
message("***\n")

# Pass in the number of expected tests that must pass!
unittest_final_result(695)
unittest_final_result(702)
187 changes: 187 additions & 0 deletions tribits/core/package_arch/TribitsGitRepoVersionInfo.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# @HEADER
# ************************************************************************
#
# TriBITS: Tribal Build, Integrate, and Test System
# Copyright 2013 Sandia Corporation
#
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Corporation nor the names of the
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ************************************************************************
# @HEADER

################################################################################
#
# Module containing functions for getting Git repo information
#
################################################################################


# @FUNCTION: tribits_git_repo_sha1()
#
# Get the Git repo version SHA1.
#
# Usage::
#
# tribits_git_repo_sha1(<gitRepoDir> <gitRepoSha1Out>
# FAILURE_MESSAGE_OUT <failureMsgOut>)
#
# If ``<failureMsgOut>`` is non-empty on input, then the variable
# ``<failureMsgOut>`` will be set to a non-empty value on output with the
# error message if an error occurs and the SHA1 for ``<gitRepoDir>`` can not
# be computed. If ``<failureMsgOut>`` is empty in input, and there is an
# error, a ``FATAL_ERROR`` will be raised.
#
# NOTE: To get the SHA1 for the Git repo ``<gitRepoDir>``, it must contain the
# ``.git/`` directory and the ``git`` executable var ``GIT_EXECUTABLE`` must
# be set. Otherwise, it is an error.
#
function(tribits_git_repo_sha1 gitRepoDir gitRepoSha1Out)

cmake_parse_arguments( PARSE_ARGV 2
PARSE "" "" # prefix, options, one_value_keywords
"FAILURE_MESSAGE_OUT" # multi_value_keywords
)
tribits_check_for_unparsed_arguments()
tribits_assert_parse_arg_zero_or_one_value(PARSE FAILURE_MESSAGE_OUT)

set(failureMsg "")

if (NOT GIT_EXECUTABLE)
set(failureMsg "ERROR: The program '${GIT_NAME}' could not be found!")
elseif (NOT IS_DIRECTORY "${gitRepoDir}/.git")
set(failureMsg "ERROR: The directory ${gitRepoDir}/.git does not exist!")
endif()

set(gitRepoSha1 "")
if (failureMsg STREQUAL "")
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%H"
WORKING_DIRECTORY ${gitRepoDir}
RESULT_VARIABLE gitCmndRtn OUTPUT_VARIABLE gitCmndOutput
)
# NOTE: Above we have to add quotes '"' or CMake will not accept the
# command. However, git will put those quotes in the output so we have to
# strip them out below!

if (NOT gitCmndRtn STREQUAL 0)
set(failureMsg "ERROR: ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0 for repo ${gitRepoDir}!")
else()
# Strip the quotes off :-(
string(LENGTH "${gitCmndOutput}" gitCmndOutputLen)
math(EXPR outputNumCharsToKeep "${gitCmndOutputLen}-2")
string(SUBSTRING "${gitCmndOutput}" 1 ${outputNumCharsToKeep} gitRepoSha1)
endif()
endif()
# ToDo: Factor above out into its own function!

if (NOT failureMsg STREQUAL "" AND PARSE_FAILURE_MESSAGE_OUT STREQUAL "")
message(FATAL_ERROR "${failureMsg}")
elseif (PARSE_FAILURE_MESSAGE_OUT)
set(${PARSE_FAILURE_MESSAGE_OUT} "${failureMsg}" PARENT_SCOPE)
endif()
set(${gitRepoSha1Out} "${gitRepoSha1}" PARENT_SCOPE)

endfunction()


# Run the git log command to get the version info for a git repo
#
function(tribits_generate_single_repo_version_string gitRepoDir
repoVersionStringOut
)

tribits_assert_git_executable()

# A) Get the basic version info.

execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%h [%ad] <%ae>"
WORKING_DIRECTORY ${gitRepoDir}
RESULT_VARIABLE gitCmndRtn
OUTPUT_VARIABLE gitCmndOutput
)
# NOTE: Above we have to add quotes '"' or CMake will not accept the
# command. However, git will put those quotes in the output so we have to
# strip them out later :-(

if (NOT gitCmndRtn STREQUAL 0)
message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0"
" for repo ${gitRepoDir}!")
set(gitVersionLine "Error, could not get version info!")
else()
# Strip the quotes off :-(
string(LENGTH "${gitCmndOutput}" gitCmndOutputLen)
math(EXPR outputNumCharsToKeep "${gitCmndOutputLen}-2")
string(SUBSTRING "${gitCmndOutput}" 1 ${outputNumCharsToKeep}
gitVersionLine)
endif()

# B) Get the first 80 chars of the summary message for more info

execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%s"
WORKING_DIRECTORY ${gitRepoDir}
RESULT_VARIABLE gitCmndRtn
OUTPUT_VARIABLE gitCmndOutput
)

if (NOT gitCmndRtn STREQUAL 0)
message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${gitCmndRtn}!=0"
" for extra repo ${gitRepoDir}!")
set(gitSummaryStr "Error, could not get version summary!")
else()
# Strip off quotes and quote the 80 char string
set(maxSummaryLen 80)
math(EXPR maxSummaryLen_PLUS_2 "${maxSummaryLen}+2")
string(LENGTH "${gitCmndOutput}" gitCmndOutputLen)
math(EXPR outputNumCharsToKeep "${gitCmndOutputLen}-2")
string(SUBSTRING "${gitCmndOutput}" 1 ${outputNumCharsToKeep}
gitCmndOutputStripped)
if (gitCmndOutputLen GREATER ${maxSummaryLen_PLUS_2})
string(SUBSTRING "${gitCmndOutputStripped}" 0 ${maxSummaryLen}
gitSummaryStr)
else()
set(gitSummaryStr "${gitCmndOutputStripped}")
endif()
endif()

set(${repoVersionStringOut}
"${gitVersionLine}\n${gitSummaryStr}" PARENT_SCOPE)

endfunction()


function(tribits_assert_git_executable)
if (NOT GIT_EXECUTABLE)
message(SEND_ERROR "ERROR, the program '${GIT_NAME}' could not be found!"
" We can not generate the repo version file!")
endif()
endfunction()
70 changes: 1 addition & 69 deletions tribits/core/package_arch/TribitsGlobalMacros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ include(TribitsGetVersionDate)
include(TribitsReportInvalidTribitsUsage)
include(TribitsReadAllProjectDepsFilesCreateDepsGraph)
include(TribitsAdjustPackageEnables)
include(TribitsGitRepoVersionInfo)

# Standard TriBITS utilities includes
include(TribitsAddOptionAndDefine)
Expand Down Expand Up @@ -1251,75 +1252,6 @@ macro(tribits_copy_installer_resource _varname _source _destination)
COPYONLY)
endmacro()

# Run the git log command to get the version info for a git repo
#
function(tribits_generate_single_repo_version_string GIT_REPO_DIR
SINGLE_REPO_VERSION_STRING_OUT
)

if (NOT GIT_EXECUTABLE)
message(SEND_ERROR "ERROR, the program '${GIT_NAME}' could not be found!"
" We can not generate the repo version file!")
endif()

# A) Get the basic version info.

execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%h [%ad] <%ae>"
WORKING_DIRECTORY ${GIT_REPO_DIR}
RESULT_VARIABLE GIT_RETURN
OUTPUT_VARIABLE GIT_OUTPUT
)
# NOTE: Above we have to add quotes '"' or CMake will not accept the
# command. However, git will put those quotes in the output so we have to
# strip them out later :-(

if (NOT GIT_RETURN STREQUAL 0)
message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${GIT_RETURN}!=0"
" for extra repo ${GIT_REPO_DIR}!")
set(GIT_VERSION_INFO "Error, could not get version info!")
else()
# Strip the quotes off :-(
string(LENGTH "${GIT_OUTPUT}" GIT_OUTPUT_LEN)
math(EXPR OUTPUT_NUM_CHARS_TO_KEEP "${GIT_OUTPUT_LEN}-2")
string(SUBSTRING "${GIT_OUTPUT}" 1 ${OUTPUT_NUM_CHARS_TO_KEEP}
GIT_VERSION_INFO)
endif()

# B) Get the first 80 chars of the summary message for more info

execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:"%s"
WORKING_DIRECTORY ${GIT_REPO_DIR}
RESULT_VARIABLE GIT_RETURN
OUTPUT_VARIABLE GIT_OUTPUT
)

if (NOT GIT_RETURN STREQUAL 0)
message(FATAL_ERROR "ERROR, ${GIT_EXECUTABLE} command returned ${GIT_RETURN}!=0"
" for extra repo ${GIT_REPO_DIR}!")
set(GIT_VERSION_SUMMARY "Error, could not get version summary!")
else()
# Strip ouf quotes and quote the 80 char string
set(MAX_SUMMARY_LEN 80)
math(EXPR MAX_SUMMARY_LEN_PLUS_2 "${MAX_SUMMARY_LEN}+2")
string(LENGTH "${GIT_OUTPUT}" GIT_OUTPUT_LEN)
math(EXPR OUTPUT_NUM_CHARS_TO_KEEP "${GIT_OUTPUT_LEN}-2")
string(SUBSTRING "${GIT_OUTPUT}" 1 ${OUTPUT_NUM_CHARS_TO_KEEP}
GIT_OUTPUT_STRIPPED)
if (GIT_OUTPUT_LEN GREATER ${MAX_SUMMARY_LEN_PLUS_2})
string(SUBSTRING "${GIT_OUTPUT_STRIPPED}" 0 ${MAX_SUMMARY_LEN}
GIT_SUMMARY_STR)
else()
set(GIT_SUMMARY_STR "${GIT_OUTPUT_STRIPPED}")
endif()
endif()

set(${SINGLE_REPO_VERSION_STRING_OUT}
"${GIT_VERSION_INFO}\n${GIT_SUMMARY_STR}" PARENT_SCOPE)

endfunction()


# Get the versions of all the git repos
#
Expand Down

0 comments on commit 11c8d2d

Please sign in to comment.