git clean can't deal with junctions and in case there is a loop
it follows them forever (or until stack overflow).
https://github.com/git-for-windows/git/issues/5320
To work around this try to delete all junctions in the clean
re-try code path.
Fixes#108
As found out here, os.walk() by default follows junctions, which we don't
want and can even lead to loops:
https://github.com/msys2/msys2-autobuild/issues/101#issuecomment-2583121845
Integrate the workaround mentioned in the CPython bug report:
https://github.com/python/cpython/issues/67596#issuecomment-1918112817
Since this is Python 3.12+ only and we still support 3.10 make
it optional though.
This also adds tests, which uncovered some other minor issues:
It was not chmoding top-down, which meant that os.walk would
skip things if there were no read permissions. So chmod before
os.walk() lists the dir.
For example it failed with:
warning: failed to remove B/mingw-w64-clang-i686-seacas-2023.02.03-2-any.pkg.tar.zst: Invalid argument
We now always use the same build directory, so if files can't be removed
we fail. Retry git clean/reset a few times before giving up and also
try before we start so in case it is fixed while the job isn't running on
a self-hosted runner we can continue automatically.