257 lines
7.1 KiB
CMake
257 lines
7.1 KiB
CMake
# Set TAG_RELEASE to ON/TRUE/1 to increment minor, or to new version, or to
|
|
# UNDO to undo release.
|
|
|
|
# Increment version.
|
|
# Update CHANGELOG.md with git log.
|
|
# Make release commit.
|
|
# Tag release commit.
|
|
|
|
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
|
message(FATAL_ERROR "releases can only be done from a git clone")
|
|
endif()
|
|
|
|
find_package(Git)
|
|
|
|
if(NOT GIT_FOUND)
|
|
message(FATAL_ERROR "git is required to make a release")
|
|
endif()
|
|
|
|
find_program(GPG_EXECUTABLE gpg)
|
|
|
|
if(NOT GPG_EXECUTABLE)
|
|
message(FATAL_ERROR "gpg must be installed and set up with your key to make a release")
|
|
endif()
|
|
|
|
# From: https://gist.github.com/alorence/59d18896aaad5188b7b4.
|
|
macro(CURRENT_DATE RESULT)
|
|
if(CMAKE_HOST_SYSTEM MATCHES Windows OR ((NOT DEFINED CMAKE_HOST_SYSTEM) AND WIN32))
|
|
execute_process(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE ${RESULT})
|
|
string(REGEX REPLACE ".*(..)/(..)/(....).*" "\\3-\\1-\\2" ${RESULT} ${${RESULT}})
|
|
else()
|
|
execute_process(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE ${RESULT})
|
|
endif()
|
|
endmacro()
|
|
|
|
function(make_release_commit_and_tag)
|
|
|
|
# First make sure we are on master.
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} rev-parse --short --abbrev-ref=strict HEAD
|
|
OUTPUT_VARIABLE git_branch
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
if(NOT git_branch STREQUAL master)
|
|
message(FATAL_ERROR "you must be on the git master branch to release")
|
|
endif()
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} status --porcelain=2
|
|
OUTPUT_VARIABLE git_status
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
string(LENGTH "${git_status}" git_status_length)
|
|
|
|
if(NOT git_status_length EQUAL 0)
|
|
message(FATAL_ERROR "working tree must be clean to do a release")
|
|
endif()
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} tag --sort=-v:refname
|
|
OUTPUT_VARIABLE git_tags
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
string(REGEX REPLACE ";" "\\\\;" git_tags_lines "${git_tags}")
|
|
string(REGEX REPLACE "\r?\n" ";" git_tags_lines "${git_tags_lines}")
|
|
|
|
foreach(line ${git_tags_lines})
|
|
if(line MATCHES "^v[0-9]")
|
|
set(git_last_tag ${line})
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
|
|
if(NOT DEFINED git_last_tag)
|
|
message(FATAL_ERROR "cannot find last release tag")
|
|
endif()
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} log ${git_last_tag}.. "--pretty=format:* %h - %s [%aL]"
|
|
OUTPUT_VARIABLE release_log
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
# Calculate new release version, unless it was passed in.
|
|
|
|
if(TAG_RELEASE STREQUAL UNDO)
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} tag -d ${git_last_tag}
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} reset HEAD~1
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} checkout HEAD CHANGELOG.md
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
message(FATAL_ERROR [=[
|
|
**** RELEASE COMMIT AND TAG HAVE BEEN REMOVED ****"
|
|
|
|
The git and working tree state have been restored to their state before the
|
|
TAG_RELEASE operation.
|
|
|
|
Ignore the following cmake error.
|
|
]=])
|
|
elseif(NOT (TAG_RELEASE STREQUAL TRUE OR TAG_RELEASE STREQUAL ON OR TAG_RELEASE STREQUAL 1))
|
|
set(new_tag ${TAG_RELEASE})
|
|
else()
|
|
string(REGEX MATCH "\\.[0-9]+$" last_tag_minor_part ${git_last_tag})
|
|
string(REGEX REPLACE "\\.[0-9]+$" "" last_tag_minor_stripped ${git_last_tag})
|
|
|
|
string(SUBSTRING ${last_tag_minor_part} 1 -1 last_tag_minor)
|
|
|
|
math(EXPR last_minor_incremented "${last_tag_minor} + 1")
|
|
|
|
string(CONCAT new_tag ${last_tag_minor_stripped} . ${last_minor_incremented})
|
|
endif()
|
|
|
|
# Make sure tag begins with "v".
|
|
|
|
if(NOT new_tag MATCHES "^v")
|
|
set(new_tag "v${new_tag}")
|
|
endif()
|
|
|
|
# But remove the "v" for the version string.
|
|
|
|
string(REGEX REPLACE "^v" "" new_version ${new_tag})
|
|
|
|
current_date(current_date)
|
|
|
|
# Rewrite CHANGELOG.md
|
|
|
|
# First make a copy for backing out.
|
|
configure_file(
|
|
${CMAKE_SOURCE_DIR}/CHANGELOG.md
|
|
${CMAKE_BINARY_DIR}/CHANGELOG.md.orig
|
|
COPYONLY
|
|
)
|
|
|
|
# Now read it and add the new release.
|
|
|
|
include(FileIterator)
|
|
|
|
fi_open_file(${CMAKE_SOURCE_DIR}/CHANGELOG.md)
|
|
|
|
set(work_file ${CMAKE_BINARY_DIR}/CHANGELOG.md.work)
|
|
|
|
file(REMOVE ${work_file})
|
|
|
|
set(last_release_found FALSE)
|
|
|
|
while(NOT fi_done)
|
|
fi_get_next_line()
|
|
|
|
if(NOT last_release_found AND fi_line MATCHES "^## \\[[0-9]")
|
|
set(last_release_found TRUE)
|
|
|
|
set(tag_line "## [${new_version}] - ${current_date}")
|
|
|
|
string(LENGTH "${tag_line}" tag_line_length)
|
|
|
|
unset(tag_line_under_bar)
|
|
|
|
foreach(i RANGE 1 ${tag_line_length})
|
|
set(tag_line_under_bar "=${tag_line_under_bar}")
|
|
endforeach()
|
|
|
|
file(APPEND ${work_file} ${tag_line} "\n")
|
|
file(APPEND ${work_file} ${tag_line_under_bar} "\n")
|
|
file(APPEND ${work_file} "${release_log}" "\n")
|
|
file(APPEND ${work_file} "\n")
|
|
endif()
|
|
|
|
file(APPEND ${work_file} "${fi_line}" "\n")
|
|
endwhile()
|
|
|
|
# Convert to UNIX line endings on Windows, just copy the file otherwise.
|
|
|
|
if(CMAKE_HOST_SYSTEM MATCHES Windows OR ((NOT DEFINED CMAKE_HOST_SYSTEM) AND WIN32))
|
|
execute_process(
|
|
COMMAND powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command [=[
|
|
$text = [IO.File]::ReadAllText("CHANGELOG.md.work") -replace "`r`n", "`n"
|
|
[IO.File]::WriteAllText("CHANGELOG.md", $text)
|
|
]=]
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
)
|
|
else()
|
|
configure_file(
|
|
${CMAKE_BINARY_DIR}/CHANGELOG.md.work
|
|
${CMAKE_BINARY_DIR}/CHANGELOG.md
|
|
COPYONLY
|
|
)
|
|
endif()
|
|
|
|
# Copy the new file and add it to the commit.
|
|
|
|
configure_file(
|
|
${CMAKE_BINARY_DIR}/CHANGELOG.md
|
|
${CMAKE_SOURCE_DIR}/CHANGELOG.md
|
|
COPYONLY
|
|
)
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} add CHANGELOG.md
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
# Make the release commit.
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} commit -m "release ${new_tag}" --signoff -S
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
# Make release tag.
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} tag -s -m${new_tag} ${new_tag}
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
)
|
|
|
|
message(FATAL_ERROR [=[
|
|
|
|
Release commit and tag generated.
|
|
|
|
**** IF YOU ARE SURE YOU WANT TO RELEASE ****
|
|
|
|
Run the following commands to push the release commit and tag:
|
|
|
|
git push
|
|
git push --tags
|
|
|
|
**** TO UNDO THE RELEASE ****
|
|
|
|
To rollback these changes, run this command:
|
|
|
|
cmake .. -DTAG_RELEASE=UNDO
|
|
|
|
Ignore the "configuration incomplete" message following, this mode does not
|
|
build anything.
|
|
|
|
]=])
|
|
endfunction()
|
|
|
|
make_release_commit_and_tag()
|