diff --git a/docs/maintainers/vcpkg_from_git.md b/docs/maintainers/vcpkg_from_git.md index de56c60545..ffa8f3215f 100644 --- a/docs/maintainers/vcpkg_from_git.md +++ b/docs/maintainers/vcpkg_from_git.md @@ -12,6 +12,7 @@ vcpkg_from_git( REF <59f7335e4d...> [HEAD_REF ] [PATCHES ...] + [LFS] ) ``` @@ -42,6 +43,13 @@ A list of patches to be applied to the extracted sources. Relative paths are based on the port directory. +### LFS +Enable fetching files stored using Git LFS. +Only files pointed to by `REF` are fetched. + +This makes Git LFS mandatory for the port. +It's a fatal error if the extension is not installed. + ## Notes: `OUT_SOURCE_PATH`, `REF`, and `URL` must be specified. diff --git a/scripts/cmake/vcpkg_from_git.cmake b/scripts/cmake/vcpkg_from_git.cmake index 0d9d40fe51..86b6b411d4 100644 --- a/scripts/cmake/vcpkg_from_git.cmake +++ b/scripts/cmake/vcpkg_from_git.cmake @@ -1,6 +1,6 @@ function(vcpkg_from_git) cmake_parse_arguments(PARSE_ARGV 0 "arg" - "" + "LFS" "OUT_SOURCE_PATH;URL;REF;FETCH_REF;HEAD_REF;TAG" "PATCHES" ) @@ -87,6 +87,32 @@ function(vcpkg_from_git) WORKING_DIRECTORY "${git_working_directory}" LOGNAME "git-fetch-${TARGET_TRIPLET}" ) + if(arg_LFS) + # Running "git lfs" searches for "git-lfs[.exe]" on the path + vcpkg_execute_in_download_mode( + COMMAND "${GIT}" lfs --version + OUTPUT_VARIABLE lfs_version_output + ERROR_VARIABLE lfs_version_error + RESULT_VARIABLE lfs_version_result + WORKING_DIRECTORY "${git_working_directory}" + ) + if(lfs_version_result) + message(FATAL_ERROR "Git LFS is required for ${PORT}") + endif() + + vcpkg_execute_required_process( + ALLOW_IN_DOWNLOAD_MODE + COMMAND ${GIT} lfs install --local --force + WORKING_DIRECTORY "${git_working_directory}" + LOGNAME "git-lfs-install-${TARGET_TRIPLET}" + ) + vcpkg_execute_required_process( + ALLOW_IN_DOWNLOAD_MODE + COMMAND ${GIT} lfs fetch "${arg_URL}" "${ref_to_fetch}" + WORKING_DIRECTORY "${git_working_directory}" + LOGNAME "git-lfs-fetch-${TARGET_TRIPLET}" + ) + endif() if(VCPKG_USE_HEAD_VERSION) vcpkg_execute_in_download_mode( diff --git a/scripts/test_ports/vcpkg-from-git-test/portfile.cmake b/scripts/test_ports/vcpkg-from-git-test/portfile.cmake index b4c2a22432..c62d6dc9c2 100644 --- a/scripts/test_ports/vcpkg-from-git-test/portfile.cmake +++ b/scripts/test_ports/vcpkg-from-git-test/portfile.cmake @@ -1,7 +1,10 @@ set(VCPKG_POLICY_EMPTY_PACKAGE enabled) -set(git_remote "${CURRENT_BUILDTREES_DIR}/test-git-repo") -file(REMOVE_RECURSE "${git_remote}") +set(git_test_repo "${CURRENT_BUILDTREES_DIR}/test-git-repo") +file(REMOVE_RECURSE "${git_test_repo}") + +# LFS expects a URL for a local repository +set(git_remote "file:///${git_test_repo}") vcpkg_find_acquire_program(GIT) vcpkg_list(SET git_config @@ -13,59 +16,59 @@ vcpkg_list(SET git_config vcpkg_list(SET git ${GIT} ${git_config}) vcpkg_execute_required_process( - COMMAND ${git} init "${git_remote}" + COMMAND ${git} init "test-git-repo" WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" LOGNAME "git-init" ) vcpkg_execute_required_process( COMMAND ${git} config uploadpack.allowReachableSHA1InWant true - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-config" ) vcpkg_execute_required_process( COMMAND ${git} checkout -b main - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-new-branch" ) -file(WRITE "${git_remote}/README.txt" "first commit") +file(WRITE "${git_test_repo}/README.txt" "first commit") vcpkg_execute_required_process( - COMMAND ${git} add "${git_remote}/README.txt" - WORKING_DIRECTORY "${git_remote}" + COMMAND ${git} add "README.txt" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-add.1" ) vcpkg_execute_required_process( COMMAND ${git} commit -m "first commit" - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-commit.1" ) vcpkg_execute_in_download_mode( COMMAND ${git} rev-parse HEAD OUTPUT_VARIABLE ref RESULT_VARIABLE error_code - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" ) if(NOT "${error_code}" EQUAL "0") message(FATAL_ERROR "Failed to rev-parse HEAD: ${error_code}") endif() string(STRIP "${ref}" ref) -file(WRITE "${git_remote}/README.txt" "second commit") +file(WRITE "${git_test_repo}/README.txt" "second commit") vcpkg_execute_required_process( - COMMAND ${git} add "${git_remote}/README.txt" - WORKING_DIRECTORY "${git_remote}" + COMMAND ${git} add "README.txt" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-add.2" ) vcpkg_execute_required_process( COMMAND ${git} commit -m "second commit" - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-commit.2" ) vcpkg_execute_in_download_mode( COMMAND ${git} rev-parse HEAD OUTPUT_VARIABLE head_ref RESULT_VARIABLE error_code - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" ) if(NOT "${error_code}" EQUAL "0") message(FATAL_ERROR "Failed to rev-parse HEAD: ${error_code}") @@ -90,7 +93,7 @@ endif() # test regular mode with FETCH_REF vcpkg_execute_required_process( COMMAND ${git} config uploadpack.allowReachableSHA1InWant false - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-config" ) set(VCPKG_USE_HEAD_VERSION OFF) @@ -110,7 +113,7 @@ endif() vcpkg_execute_required_process( COMMAND ${git} config uploadpack.allowReachableSHA1InWant true - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git-config" ) @@ -150,22 +153,22 @@ ${contents} endif() # test new head ref -file(WRITE "${git_remote}/README.txt" "third commit") +file(WRITE "${git_test_repo}/README.txt" "third commit") vcpkg_execute_required_process( - COMMAND ${git} add "${git_remote}/README.txt" - WORKING_DIRECTORY "${git_remote}" + COMMAND ${git} add "README.txt" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git.7" ) vcpkg_execute_required_process( COMMAND ${git} commit -m "second commit" - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" LOGNAME "git.8" ) vcpkg_execute_in_download_mode( COMMAND ${git} rev-parse HEAD OUTPUT_VARIABLE new_head_ref RESULT_VARIABLE error_code - WORKING_DIRECTORY "${git_remote}" + WORKING_DIRECTORY "${git_test_repo}" ) if(NOT "${error_code}" EQUAL "0") message(FATAL_ERROR "Failed to rev-parse HEAD: ${error_code}") @@ -191,3 +194,73 @@ if(NOT "${VCPKG_HEAD_VERSION}" STREQUAL "${new_head_ref}") Actual : ${VCPKG_HEAD_VERSION} ") endif() + +# test LFS support +vcpkg_execute_in_download_mode( + COMMAND "${GIT}" lfs --version + OUTPUT_VARIABLE lfs_version_output + ERROR_VARIABLE lfs_version_error + RESULT_VARIABLE lfs_version_result + WORKING_DIRECTORY "${git_test_repo}" +) +if(NOT lfs_version_result) + vcpkg_execute_required_process( + COMMAND ${git} lfs install --local + WORKING_DIRECTORY "${git_test_repo}" + LOGNAME "git-lfs-install" + ) + + file(WRITE "${git_test_repo}/.gitattributes" "* text=auto\n*.bin filter=lfs diff=lfs merge=lfs -text\n") + file(WRITE "${git_test_repo}/lfs_file.bin" "fourth commit") + vcpkg_execute_required_process( + COMMAND ${git} add ".gitattributes" "lfs_file.bin" + WORKING_DIRECTORY "${git_test_repo}" + LOGNAME "git-lfs-add" + ) + vcpkg_execute_required_process( + COMMAND ${git} commit -m "fourth commit" + WORKING_DIRECTORY "${git_test_repo}" + LOGNAME "git-lfs-commit" + ) + vcpkg_execute_in_download_mode( + COMMAND ${git} rev-parse HEAD + OUTPUT_VARIABLE ref + RESULT_VARIABLE error_code + WORKING_DIRECTORY "${git_test_repo}" + ) + if(NOT "${error_code}" EQUAL "0") + message(FATAL_ERROR "Failed to rev-parse HEAD: ${error_code}") + endif() + string(STRIP "${ref}" ref) + + vcpkg_execute_in_download_mode( + COMMAND ${git} lfs ls-files --name-only + OUTPUT_VARIABLE lfs_files + RESULT_VARIABLE error_code + WORKING_DIRECTORY "${git_test_repo}" + ) + if(NOT "${error_code}" EQUAL "0") + message(FATAL_ERROR "Failed lfs ls-files: ${error_code}") + endif() + string(STRIP "${lfs_files}" lfs_files) + if(NOT "${lfs_files}" MATCHES [[lfs_file\.bin]]) + message(FATAL_ERROR "File was not added to LFS") + endif() + + set(VCPKG_USE_HEAD_VERSION OFF) + vcpkg_from_git( + OUT_SOURCE_PATH source_path + URL "${git_remote}" + REF "${ref}" + HEAD_REF main + LFS + ) + file(READ "${source_path}/lfs_file.bin" contents) + if(NOT "${contents}" STREQUAL "fourth commit") + message(FATAL_ERROR "Failed to checkout the fourth commit. Contents were: +${contents} + ") + endif() +else() + message(NOTICE "Git LFS is not available: some tests were skipped") +endif()