ExternalProject_Add git stash with --include-untracked rather than --all to avoid stashing .gitignore content.
ExternalProject's "git_stash_save_options" is set to --all which INCLUDES .gitignored content in the stash. I would prefer it to use the git stash option --include-untracked which grabs less and certainly not a .gitignored build directory which can be SLOW if huge. i.e just say you have a .gitignored build directory containing a build of LLVM in it.
I seek to use the new feature CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY=REBASE_CHECKOUT for my local development environment of the SuperProject.
My use case involves switching between coordinating a super project with many FetchContent style dependencies AND performing isolated builds which involve minor experimentation, or cross dependency interface changes of one or more of the dependencies in isolation of the super project.
It is exceptionally convenient to be able to switch between the two use cases, especially because it allows processing of the current dependencies checkouts to help derive accurate GIT_TAGS to apply to the Super Project, in order to "Roll Up" dependencies, rather than through manual cmake file manipulation of separate source/build trees.
IOW - I want to be able to build one or more of the git based ExternalProject/FetchContent dependencies in a "build" directory that I create within its ExternalProject/FetchContet -src directory. This "-src/build" directory is naturally mentioned in *-src/.gitignore
When I swap back to the Super Project mode, the ExternalProject stash operation uses the git stash --all option, to protect my local changes if necessary, which causes git to stash the .gitignored *-src/build directory, rebase any local changes and then pop it. This is slow when the "git_stash_save_options" is set to --all AND the *-src/build directory is large. Git also sees large amounts of unreachable objects which causes an automatic git gc to run, only for it to abort and seek a manual run of git gc prune. Something that should be a swift stash save and pop becomes a long unnecessary stall.
5 years ago the git_stash_save_options option --all was added https://gitlab.kitware.com/cmake/cmake/-/blame/v3.18.3/Modules/ExternalProject.cmake#L1291 when it was first supported by git 1.7.6
The option git option -u/--include-untracked was introduced 9 years ago in git 1.7.7 and would be my preferred option. https://github.com/git/git/commit/787513027a7d0af3c2cd2f04b85bc7136d580586
I propose either a detection of git version 1.7.7 to set(git_stash_options '--include-untracked') OR would be happy to have to set a global option or property if that was deemed more backward compatible.
Here is what I am currently running.
function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_repository work_dir git_update_strategy)
if("${git_tag}" STREQUAL "")
message(FATAL_ERROR "Tag for git checkout should not be empty.")
endif()
if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.7)
set(git_stash_save_options --include-untracked --quiet)
elseif(NOT GIT_VERSION_STRING VERSION_LESS 1.7.6)
set(git_stash_save_options --all --quiet)
else()
set(git_stash_save_options --quiet)
endif()
configure_file(
"${_ExternalProject_SELF_DIR}/ExternalProject-gitupdate.cmake.in"
"${script_filename}"
@ONLY
)
endfunction()