1# Git helper functions and macros 2 3# git_get_versioned(VERSION <version> FILES <path> ...) 4# 5# Get files by name relative to the current source directory but read it from 6# branch VERSION. Note that the version referenced has to exists as a branch, 7# otherwise you get an error. 8# 9# VERSION <version> 10# 11# Version to read files from. Any object name is accepted as given in 12# gitrevision(7), but typically you should use a tag name. 13# 14# FILES <path> ... 15# 16# Paths to extract. These are relative or absolute paths to files to extract. If 17# relative, the path names are resolved relative the current source directory. 18# 19# RESULT_FILES <var> 20# 21# Variable for the list of the full paths of the retrieved files. 22# 23# IGNORE_ERRORS 24# 25# Ignore errors when fetching file from previous version. This is currently used 26# to ignore missing files, but we should probably be more selective in the 27# following versions. 28function(git_versioned_get) 29 set(options IGNORE_ERRORS) 30 set(oneValueArgs VERSION RESULT_FILES) 31 set(multiValueArgs FILES) 32 cmake_parse_arguments(_git_get "${options}" "${oneValueArgs}" 33 "${multiValueArgs}" ${ARGN}) 34 35 execute_process( 36 COMMAND git show-ref --verify --quiet refs/tags/${_git_get_VERSION} 37 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 38 RESULT_VARIABLE _version_missing) 39 if(_version_missing) 40 message( 41 FATAL_ERROR "Version ${_git_get_VERSION} do not exist in repository.") 42 endif() 43 44 set(_result_files) 45 foreach(_file ${_git_get_FILES}) 46 # Build full path, if the path is not absolute. 47 if(IS_ABSOLUTE ${_file}) 48 set(_path "${_file}") 49 else() 50 set(_path "${CMAKE_CURRENT_SOURCE_DIR}/${_file}") 51 endif() 52 53 # Remove root source directory to get path relative to source root. This is 54 # necessary for git-show to work correctly and then use that to generate a 55 # full path for the version. (Yeah, we could use ./ before, but this is 56 # less clear in the log what file is actually fetched.) 57 string(REPLACE ${CMAKE_SOURCE_DIR}/ "" _relpath ${_path}) 58 set(_fullpath "${CMAKE_BINARY_DIR}/v${_git_get_VERSION}/${_relpath}") 59 get_filename_component(_dirname ${_fullpath} DIRECTORY) 60 file(MAKE_DIRECTORY ${_dirname}) 61 62 # We place the output file next to the final file to avoid cross-device 63 # renames but give it a different name since it is created even if the 64 # command fails. 65 execute_process( 66 COMMAND ${GIT_EXECUTABLE} show ${_git_get_VERSION}:${_relpath} 67 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 68 OUTPUT_FILE "${_fullpath}.part" 69 RESULT_VARIABLE _error 70 ERROR_VARIABLE _message) 71 72 if(_error) 73 if(_git_get_IGNORE_ERRORS) 74 string(STRIP "${_message}" _stripped_message) 75 message(STATUS "${_stripped_message} (ignored).") 76 else() 77 message(FATAL_ERROR "${_message}") 78 endif() 79 else() 80 file(RENAME "${_fullpath}.part" "${_fullpath}") 81 list(APPEND _result_files "${_fullpath}") 82 endif() 83 endforeach() 84 set(${_git_get_RESULT_FILES} 85 ${_result_files} 86 PARENT_SCOPE) 87endfunction() 88