ExternalProject runs git commands on the main source directory sometimes
If you have a build directory in your source tree, and the external project's .git directory gets corrupted for some reason, all the git commands run by gitupdate.cmake effectively get run on your main source directory, as git goes looking through the parents for some other .git directory. Since those git commands potentially include git reset --hard
, this can delete the code you're working on. This has happened to people in my company a couple of times now, we're not sure exactly how but I think it might be down to cancelling the configure process at an inopportune moment. Or maybe two cmake configures running simultaneously by accident.
The following script demonstrates the gist of it:
#!/bin/bash
mkdir git-test-source
cd git-test-source
git init
echo build > .gitignore
cat <<EOF >CMakeLists.txt
project(git-test)
include(FetchContent)
FetchContent_Declare(doctest
GIT_REPOSITORY https://github.com/doctest/doctest/
GIT_TAG v2.4.8
GIT_PROGRESS ON
)
FetchContent_GetProperties(doctest)
if (NOT doctest_POPULATED)
FetchContent_Populate(doctest)
endif()
EOF
echo a > test
git add .gitignore CMakeLists.txt test
git commit -m "First Commit"
cd ..
git clone git-test-source git-test
cd git-test
mkdir build
cmake -B build -S .
echo b > test
rm -rf build/_deps/doctest-src/.git
cmake -B build -S .
cat test
This prints 'a' on the last line, i.e. our local change setting test
to 'b' has gone. You get an error from cmake, but the file has already been stashed by that point. Obivously we're not intentionally running rm -rf build/_deps/doctest-src/.git
, so this isn't an exact reproduction (I don't know what we did to cause it, it's extremely rare), but it illustrates the possibility.