Skip to content

Commit

Permalink
chore: Add CMake-based pre-commit hook
Browse files Browse the repository at this point in the history
  • Loading branch information
Tradias committed Sep 27, 2024
1 parent 0cdda66 commit aed9853
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
add_subdirectory(src)

if(CNTGS_BUILD_TESTS)
include("${CMAKE_CURRENT_LIST_DIR}/cmake/CntgsInstallGitHooks.cmake")
find_package(doctest REQUIRED)
enable_testing()
include(doctest)
Expand Down
22 changes: 22 additions & 0 deletions cmake/CntgsGitHooksInstaller.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2024 Dennis Hezel
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

file(
COPY "${GIT_HOOKS_SOURCE_DIR}/pre-commit" "${GIT_HOOKS_SOURCE_DIR}/CntgsPreCommit.cmake"
DESTINATION "${GIT_HOOKS_TARGET_DIR}"
FILE_PERMISSIONS
OWNER_READ
GROUP_READ
WORLD_READ
OWNER_WRITE
OWNER_EXECUTE
GROUP_EXECUTE
WORLD_EXECUTE)
63 changes: 63 additions & 0 deletions cmake/CntgsInstallGitHooks.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2024 Dennis Hezel
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

find_package(Git)

function(cntgs_create_init_git_hooks_target)
if(TARGET cntgs-init-git-hooks)
return()
endif()

set(CNTGS_GIT_HOOKS_TARGET_DIR "${CMAKE_SOURCE_DIR}/.git/hooks")
set(CNTGS_GIT_HOOKS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/git-hooks/")

if(NOT EXISTS "${CNTGS_GIT_HOOKS_TARGET_DIR}/pre-commit" OR NOT EXISTS
"${CNTGS_GIT_HOOKS_TARGET_DIR}/CntgsPreCommit.cmake")
message(
AUTHOR_WARNING
"Initialize clang-format and cmake-format pre-commit hooks by building the CMake target cntgs-init-git-hooks."
)
endif()

find_program(CNTGS_CMAKE_FORMAT_PROGRAM cmake-format)
find_program(CNTGS_CLANG_FORMAT_PROGRAM clang-format)

if(NOT CNTGS_CMAKE_FORMAT_PROGRAM OR NOT CNTGS_CLANG_FORMAT_PROGRAM)
message(
AUTHOR_WARNING
"Cannot create init-git-hooks target with\ncmake-format: ${CNTGS_CMAKE_FORMAT_PROGRAM}\nclang-format: ${CNTGS_CLANG_FORMAT_PROGRAM}"
)
return()
endif()

set(CNTGS_INIT_GIT_HOOKS_SOURCES "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hooks/pre-commit.in"
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hooks/CntgsPreCommit.cmake.in")
configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hooks/pre-commit.in" "${CNTGS_GIT_HOOKS_SOURCE_DIR}/pre-commit"
@ONLY NEWLINE_STYLE UNIX)
configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hooks/CntgsPreCommit.cmake.in"
"${CNTGS_GIT_HOOKS_SOURCE_DIR}/CntgsPreCommit.cmake" @ONLY NEWLINE_STYLE UNIX)

set(_cntgs_command_arguments
"-DGIT_HOOKS_TARGET_DIR=${CNTGS_GIT_HOOKS_TARGET_DIR}" "-DGIT_HOOKS_SOURCE_DIR=${CNTGS_GIT_HOOKS_SOURCE_DIR}"
-P "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CntgsGitHooksInstaller.cmake")
string(REPLACE ";" " " _cntgs_pretty_command_arguments "${_cntgs_command_arguments}")
add_custom_target(
cntgs-init-git-hooks
DEPENDS ${CNTGS_INIT_GIT_HOOKS_SOURCES}
SOURCES ${CNTGS_INIT_GIT_HOOKS_SOURCES}
COMMAND ${CMAKE_COMMAND} ${_cntgs_command_arguments}
COMMENT "cmake ${_cntgs_pretty_command_arguments}"
VERBATIM)
endfunction()

if(GIT_FOUND)
cntgs_create_init_git_hooks_target()
endif()
45 changes: 45 additions & 0 deletions cmake/hooks/CntgsPreCommit.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2024 Dennis Hezel
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

# Do not ignore empty list items
cmake_policy(SET CMP0007 NEW)

execute_process(
COMMAND "@GIT_EXECUTABLE@" "diff-index" "--cached" "--name-only" "--diff-filter=ACMRT" "HEAD"
OUTPUT_VARIABLE _git_output
WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@")

string(REPLACE "\r" "" _git_output_no_carriage "${_git_output}")
string(REPLACE "\n" ";" _git_output_list "${_git_output_no_carriage}")
list(REMOVE_ITEM _git_output_list "")

# process CMake files
foreach(_git_out IN LISTS _git_output_list)
string(REGEX MATCHALL ".*\\.cmake\\.in\$|.*\\.cmake\$|.*CMakeLists.txt\$" _file "${_git_out}")

if(NOT "${_file}" STREQUAL "")
execute_process(COMMAND "@CNTGS_CMAKE_FORMAT_PROGRAM@" "-i" "${_file}" WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@")

execute_process(COMMAND "@GIT_EXECUTABLE@" "add" "${_file}" WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@")
endif()
endforeach()

# process cpp files
foreach(_git_out IN LISTS _git_output_list)
string(REGEX MATCHALL ".*\\.hpp\$|.*\\.cpp\$|.*\\.h\$|.*\\.c\$" _file "${_git_out}")

if(NOT "${_file}" STREQUAL "")
execute_process(COMMAND "@CNTGS_CLANG_FORMAT_PROGRAM@" "-i" "-style=file" "${_file}"
WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@")

execute_process(COMMAND "@GIT_EXECUTABLE@" "add" "${_file}" WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@")
endif()
endforeach()
3 changes: 3 additions & 0 deletions cmake/hooks/pre-commit.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

"@CMAKE_COMMAND@" -P "@CNTGS_GIT_HOOKS_TARGET_DIR@/CntgsPreCommit.cmake"

0 comments on commit aed9853

Please sign in to comment.