Skip to content

Commit

Permalink
ENH: Version info in repo (ANTsX#1246)
Browse files Browse the repository at this point in the history
* ENH: Encode version information in repo

This avoids the placeholder version name 0.0.0.0 for tarball builds,
which causes problems with external builds.

Version.cmake now contains hard-coded version numbers that are used
for builds (from git or tarball source). For releases, a variable
is set so that binaries have version vA.B.C. For other commits (not a
tagged release), the version is vA.B.C.dev. Builds from git repos
still contain the additional information about the number of commits
post-tag, and the short hash.

To make a release, first be up to date on master, with a clean repo.
Then run Utilities/tagRelease.pl. This will update Version.cmake,
commit + push the changes, tag that commit, then change Version.cmake
back into dev mode, and commit + push the result.

Use 7 chars for short hash instead of 5 (git default is 7)
  • Loading branch information
cookpa authored Oct 18, 2021
1 parent 7bc7c9d commit 31f7a61
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 111 deletions.
34 changes: 1 addition & 33 deletions ANTS.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,10 @@ set(CMAKE_MODULE_PATH
set (CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
#-----------------------------------------------------------------------------
# Version information
include(Version.cmake)

if(DEFINED ${PROJECT_NAME}_VERSION_RC)
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}${${PROJECT_NAME}_VERSION_RC}")
endif()
if(DEFINED ${PROJECT_NAME}_VERSION_POST)
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}.post${${PROJECT_NAME}_VERSION_POST}")
elseif(DEFINED ${PROJECT_NAME}_VERSION_DEV)
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}.dev${${PROJECT_NAME}_VERSION_DEV}")
endif()


option( ${PROJECT_NAME}_BUILD_DISTRIBUTE "Remove '-g#####' from version. ( for official distribution only )" OFF )
mark_as_advanced( ${PROJECT_NAME}_BUILD_DISTRIBUTE )
if( NOT ${PROJECT_NAME}_BUILD_DISTRIBUTE AND NOT ${PROJECT_NAME}_VERSION_HASH STREQUAL "GITDIR-NOTFOUND" )
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}-g${${PROJECT_NAME}_VERSION_HASH}")
endif()

# When building from a snapshot, the git version information does not get populated
# Allow the user to specify a hash or version tag on the command line
if( ${PROJECT_NAME}_VERSION_HASH STREQUAL "GITDIR-NOTFOUND" AND NOT "${ANTS_SNAPSHOT_VERSION}" STREQUAL "" )
set(${PROJECT_NAME}_VERSION_MAJOR 0)
set(${PROJECT_NAME}_VERSION_MINOR 0)
set(${PROJECT_NAME}_VERSION_PATCH 0)
set(${PROJECT_NAME}_VERSION_TWEAK 0)
set(${PROJECT_NAME}_VERSION "snapshot-${ANTS_SNAPSHOT_VERSION}")
endif()

# If no version information exists and the user has not passed version info to cmake, set defaults
if("${${PROJECT_NAME}_VERSION_MAJOR}" STREQUAL "")
set(${PROJECT_NAME}_VERSION_MAJOR 0)
set(${PROJECT_NAME}_VERSION_MINOR 0)
set(${PROJECT_NAME}_VERSION_PATCH 0)
set(${PROJECT_NAME}_VERSION_TWEAK 0)
set(${PROJECT_NAME}_VERSION "0.0.0.0")
endif()
include(Version.cmake)

#-----------------------------------------------------------------------------
# CPACK Version
Expand Down
27 changes: 3 additions & 24 deletions CMake/ProjectSourceVersion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ if(_GIT_VERSION_HASH STREQUAL "GITDIR-NOTFOUND")
endif()

if(_GIT_VERSION_HASH MATCHES "[a-fA-F0-9]+")
string(SUBSTRING "${_GIT_VERSION_HASH}" 0 5 _GIT_VERSION_HASH)
# Get first seven chars of hash (git default for short hash)
# https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection
string(SUBSTRING "${_GIT_VERSION_HASH}" 0 7 _GIT_VERSION_HASH)
endif()

# find the closest anotated tag with the v prefix for version
Expand Down Expand Up @@ -90,26 +92,3 @@ elseif(DEFINED ${CMAKE_PROJECT_NAME}_VERSION_PATCH)
endif()
endif()

set(_${CMAKE_PROJECT_NAME}_VERSION "${${CMAKE_PROJECT_NAME}_VERSION_MAJOR}.${${CMAKE_PROJECT_NAME}_VERSION_MINOR}")
if(DEFINED ${CMAKE_PROJECT_NAME}_VERSION_PATCH)
set(_${CMAKE_PROJECT_NAME}_VERSION "${_${CMAKE_PROJECT_NAME}_VERSION}.${${CMAKE_PROJECT_NAME}_VERSION_PATCH}")
if(DEFINED ${CMAKE_PROJECT_NAME}_VERSION_TWEAK)
set(_${CMAKE_PROJECT_NAME}_VERSION "${_${CMAKE_PROJECT_NAME}_VERSION}.${${CMAKE_PROJECT_NAME}_VERSION_TWEAK}")
endif()
endif()


if(_GIT_VERSION VERSION_EQUAL _${CMAKE_PROJECT_NAME}_VERSION)
if(_GIT_TAG_COUNT) #ignore if 0
set(_GIT_VERSION_POST "${_GIT_TAG_COUNT}")
endif()
else()
# The first commit after a tag should increase the project version
# number in Version.cmake and be "dev1"
math(EXPR _GIT_VERSION_COUNT "${_GIT_VERSION_COUNT}+1")
set(_GIT_VERSION_DEV "${_GIT_VERSION_COUNT}")
endif()

# save variable in a configuration file in case we have no git directory
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CMake/ProjectSourceVersionVars.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/ProjectSourceVersionVars.cmake" @ONLY)
14 changes: 0 additions & 14 deletions CMake/ProjectSourceVersion.cmake.in

This file was deleted.

14 changes: 0 additions & 14 deletions CMake/ProjectSourceVersionVars.cmake.in

This file was deleted.

4 changes: 0 additions & 4 deletions SuperBuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ option(RUN_SHORT_TESTS "Run the quick unit tests."
option(RUN_LONG_TESTS "Run the time consuming tests. i.e. real world registrations" ON )
option(OLD_BASELINE_TESTS "Use reported metrics from old tests" OFF )

set(ANTS_SNAPSHOT_VERSION "" CACHE STRING "Version info for binaries. Only used if source is not a git repo. Identify source snapshot by commit hash or release tag")
mark_as_advanced(ANTS_SNAPSHOT_VERSION)

option(ANTS_INSTALL_LIBS_ONLY "Do not install binaries" OFF)
mark_as_advanced(ANTS_INSTALL_LIBS_ONLY)

Expand Down Expand Up @@ -253,7 +250,6 @@ list(APPEND ${CMAKE_PROJECT_NAME}_SUPERBUILD_EP_VARS
RUN_SHORT_TESTS:BOOL
RUN_LONG_TESTS:BOOL
OLD_BASELINE_TESTS:BOOL
ANTS_SNAPSHOT_VERSION:STRING
ANTS_INSTALL_LIBS_ONLY:BOOL

${LOCAL_PROJECT_NAME}_CLI_LIBRARY_OUTPUT_DIRECTORY:PATH
Expand Down
110 changes: 110 additions & 0 deletions Utilities/tagRelease.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env perl

use strict;

my $masterBranchLabel = "master";

if ($#ARGV < 0) {
print qq{
$0 <tag>
Run this from the ANTs/ directory to tag a release.
Given a tag "vX.Y.Z", the script will
1. Check user is on the ${masterBranchLabel} branch, with no uncommitted changes
2. Update Version.cmake to set the version major, minor, patch
3. Commit Version.cmake and push to origin ${masterBranchLabel}
4. git tag with the release tag and push the tags
};

exit 1;
}

my $tag = $ARGV[0];

if (!($tag =~ m/^v[0-9]\.[0-9]\.[0-9]/) ) {
print "Tags for release should be in the format vX.Y.Z where X,Y,Z are integers\n";
exit(1);
}

# Check that we are ready to update version

my $cleanTree = qq{On branch ${masterBranchLabel}
Your branch is up to date with 'origin/${masterBranchLabel}'.
nothing to commit, working tree clean
};

my $status = `git status -b`;

if (!($status eq $cleanTree)) {
print "Must be up to date and on branch $masterBranchLabel to tag a release.\ngit status output:\n";
# run it again so output is colorized
system("git status -b");
exit(1);
}

# Multiple tags get weird
chomp(my $existingTag = `git tag --points-at HEAD`);
if ($existingTag) {
print "There is already a tag $existingTag on this commit. Exiting\n";
exit(1);
}

# Check tag matches Version.cmake
open(my $inFH, "<", "Version.cmake");
my $versionDotCmake = do { local $/; <$inFH> };
close($inFH);

my ($tagVersionMajor,$tagVersionMinor,$tagVersionPatch) = ($tag =~ m/^v([0-9])\.([0-9])\.([0-9])/);

$versionDotCmake =~ s/set\(\$\{PROJECT_NAME\}_VERSION_MAJOR "[0-9]+"\)/set\(\$\{PROJECT_NAME\}_VERSION_MAJOR "${tagVersionMajor}"\)/
or die("Cannot find version information in Version.cmake");

$versionDotCmake =~ s/set\(\$\{PROJECT_NAME\}_VERSION_MINOR "[0-9]+"\)/set\(\$\{PROJECT_NAME\}_VERSION_MINOR "${tagVersionMinor}"\)/
or die("Cannot find version information in Version.cmake");

$versionDotCmake =~ s/set\(\$\{PROJECT_NAME\}_VERSION_PATCH "[0-9]+"\)/set\(\$\{PROJECT_NAME\}_VERSION_PATCH "${tagVersionPatch}"\)/
or die("Cannot find version information in Version.cmake");

$versionDotCmake =~ s/set\(\$\{PROJECT_NAME\}_RELEASE_VERSION 0\)/set\(\$\{PROJECT_NAME\}_RELEASE_VERSION 1\)/;

open(my $outFH, ">", "Version.cmake");
print $outFH $versionDotCmake;
close($outFH);

print "Modified version information in Version.cmake. Review git diff:\n";
system("git diff");
print "\nProceed with tag? Please enter (yY/nN):";
chomp(my $proceed = <STDIN>);

if (!(lc($proceed) eq "y")) {
print "Reverting changes\n";
system("git checkout Version.cmake");
exit(1);
}

print("\nUpdating Version.cmake\n");
system("git add Version.cmake");
system("git commit -m \"Updating version for release $tag\"");
print("\nPushing changed Version.cmake\n");
system("git push origin $masterBranchLabel") == 0
or die("Could not push updated Version.cmake");
print("\nApplying tag\n");
system("git tag -a $tag -m \"Tagging release $tag\"");
system("git push --tags");

print("\nUpdating Version.cmake for development");

$versionDotCmake =~ s/set\(\$\{PROJECT_NAME\}_RELEASE_VERSION 1\)/set\(\$\{PROJECT_NAME\}_RELEASE_VERSION 0\)/;

open(my $outFH, ">", "Version.cmake");
print $outFH $versionDotCmake;
close($outFH);

system("git add Version.cmake");
system("git commit -m \"Updating version for development post $tag\"");
print("\nPushing changed Version.cmake\n");
system("git push origin $masterBranchLabel") == 0
95 changes: 73 additions & 22 deletions Version.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,84 @@
# version.
#

# Version info
# Version info from git
include(ProjectSourceVersion)

# pre-release codes are defined based on suffix of most recent tags.

# a[N]+<b[N]+<c[N]+=rc[N]+
if(NOT ${_GIT_VERSION_RC} STREQUAL "" )
set(${PROJECT_NAME}_VERSION_RC "${_GIT_VERSION_RC}")
endif()

set(${PROJECT_NAME}_VERSION "${_GIT_VERSION}")
set(${PROJECT_NAME}_VERSION_MAJOR "${_GIT_VERSION_MAJOR}")
set(${PROJECT_NAME}_VERSION_MINOR "${_GIT_VERSION_MINOR}")
set(${PROJECT_NAME}_VERSION_PATCH "${_GIT_VERSION_PATCH}")
set(${PROJECT_NAME}_VERSION_TWEAK "${_GIT_VERSION_TWEAK}")
set(${PROJECT_NAME}_VERSION_MAJOR "2")
set(${PROJECT_NAME}_VERSION_MINOR "3")
set(${PROJECT_NAME}_VERSION_PATCH "5")
# set(${PROJECT_NAME}_VERSION_TWEAK "")

# The hash is the current git sha1 hash tag of the HEAD.
set(${PROJECT_NAME}_VERSION_HASH "${_GIT_VERSION_HASH}")

if ( NOT ${PROJECT_NAME}_VERSION_HASH STREQUAL "GITDIR-NOTFOUND" )
# Use version information from git if the source directory is a git repository
# Compare git version (major.minor[.patch[.tweak]]) with version number hard-coded above
set(_${PROJECT_NAME}_VERSION_NUMBER "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}")

if(DEFINED ${PROJECT_NAME}_VERSION_PATCH)
set(_${PROJECT_NAME}_VERSION_NUMBER "${_${PROJECT_NAME}_VERSION_NUMBER}.${${PROJECT_NAME}_VERSION_PATCH}")
if(DEFINED ${PROJECT_NAME}_VERSION_TWEAK)
set(_${PROJECT_NAME}_VERSION_NUMBER "${_${PROJECT_NAME}_VERSION_NUMBER}.${${PROJECT_NAME}_VERSION_TWEAK}")
endif()
endif()

if(_GIT_VERSION VERSION_EQUAL _${PROJECT_NAME}_VERSION_NUMBER)
if(_GIT_TAG_COUNT) #ignore if 0
set(_GIT_VERSION_POST "${_GIT_TAG_COUNT}")
endif()
else()
# The first commit after a tag should increase the project version
# number in Version.cmake and be "dev1"
math(EXPR _GIT_VERSION_COUNT "${_GIT_VERSION_COUNT}+1")
set(_GIT_VERSION_DEV "${_GIT_VERSION_COUNT}")
endif()

# DEV or POST is set to the number of commits since this file has been
# changed. If the MAJOR.MINOR.[PATCH[.TWEAK]] matches "closest"
# version tag then its considered in the release branch and POST is set
# while DEV is undefined, otherwise we are considered under
# development and DEV is set and POST is undefined.
#
if(DEFINED _GIT_VERSION_POST)
set(${PROJECT_NAME}_VERSION_POST "${_GIT_VERSION_POST}")
elseif(DEFINED _GIT_VERSION_DEV)
set(${PROJECT_NAME}_VERSION_DEV "${_GIT_VERSION_DEV}")
endif()

# pre-release codes are defined based on suffix of most recent tags.
# a[N]+<b[N]+<c[N]+=rc[N]+
if(NOT ${_GIT_VERSION_RC} STREQUAL "" )
set(${PROJECT_NAME}_VERSION_RC "${_GIT_VERSION_RC}")
endif()

if(DEFINED ${PROJECT_NAME}_VERSION_RC)
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}${${PROJECT_NAME}_VERSION_RC}")
endif()

set(${PROJECT_NAME}_VERSION "v${_${PROJECT_NAME}_VERSION_NUMBER}")

if(DEFINED ${PROJECT_NAME}_VERSION_POST)
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}.post${${PROJECT_NAME}_VERSION_POST}")
elseif(DEFINED ${PROJECT_NAME}_VERSION_DEV)
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}.dev${${PROJECT_NAME}_VERSION_DEV}")
endif()

if( NOT ${PROJECT_NAME}_BUILD_DISTRIBUTE AND NOT ${PROJECT_NAME}_VERSION_HASH STREQUAL "GITDIR-NOTFOUND" )
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}-g${${PROJECT_NAME}_VERSION_HASH}")
endif()
else()
# No git version information
# Set version information from numbers only
set(${PROJECT_NAME}_VERSION "v${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}")

# Set to 1 for release commits only
set(${PROJECT_NAME}_RELEASE_VERSION 0)

if( NOT ${PROJECT_NAME}_RELEASE_VERSION )
set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}.dev")
endif()

# DEV or POST is set to the number of commits since this file has been
# changed. If the MAJOR.MINOR.[PATCH[.TWEAK]] matches "closest"
# version tag then its consider in the release branch and POST is set
# while DEV is undefined, otherwise we are considered under
# development and DEV is set and POST is undefined.
if(DEFINED _GIT_VERSION_POST)
set(${PROJECT_NAME}_VERSION_POST "${_GIT_VERSION_POST}")
elseif(DEFINED _GIT_VERSION_DEV)
set(${PROJECT_NAME}_VERSION_DEV "${_GIT_VERSION_DEV}")
endif()

0 comments on commit 31f7a61

Please sign in to comment.