diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 41c139359..e44f81d98 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -84,6 +84,54 @@ void cmCTestGIT::NoteNewRevision() << this->NewRevision << "\n"); } +//---------------------------------------------------------------------------- +std::string cmCTestGIT::FindGitDir() +{ + std::string git_dir; + + // Run "git rev-parse --git-dir" to locate the real .git directory. + const char* git = this->CommandLineTool.c_str(); + char const* git_rev_parse[] = {git, "rev-parse", "--git-dir", 0}; + std::string git_dir_line; + OneLineParser rev_parse_out(this, "rev-parse-out> ", git_dir_line); + OutputLogger rev_parse_err(this->Log, "rev-parse-err> "); + if(this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err)) + { + git_dir = git_dir_line; + } + if(git_dir.empty()) + { + git_dir = ".git"; + } + + // Git reports a relative path only when the .git directory is in + // the current directory. + if(git_dir[0] == '.') + { + git_dir = this->SourceDirectory + "/" + git_dir; + } +#if defined(_WIN32) && !defined(__CYGWIN__) + else if(git_dir[0] == '/') + { + // Cygwin Git reports a full path that Cygwin understands, but we + // are a Windows application. Run "cygpath" to get Windows path. + std::string cygpath_exe = cmSystemTools::GetFilenamePath(git); + cygpath_exe += "/cygpath.exe"; + if(cmSystemTools::FileExists(cygpath_exe.c_str())) + { + char const* cygpath[] = {cygpath_exe.c_str(), "-w", git_dir.c_str(), 0}; + OneLineParser cygpath_out(this, "cygpath-out> ", git_dir_line); + OutputLogger cygpath_err(this->Log, "cygpath-err> "); + if(this->RunChild(cygpath, &cygpath_out, &cygpath_err)) + { + git_dir = git_dir_line; + } + } + } +#endif + return git_dir; +} + //---------------------------------------------------------------------------- bool cmCTestGIT::UpdateByFetchAndReset() { @@ -121,8 +169,13 @@ bool cmCTestGIT::UpdateByFetchAndReset() // Identify the merge head that would be used by "git pull". std::string sha1; { - std::string fetch_head = this->SourceDirectory + "/.git/FETCH_HEAD"; + std::string fetch_head = this->FindGitDir() + "/FETCH_HEAD"; std::ifstream fin(fetch_head.c_str(), std::ios::in | std::ios::binary); + if(!fin) + { + this->Log << "Unable to open " << fetch_head << "\n"; + return false; + } std::string line; while(sha1.empty() && cmSystemTools::GetLineFromStream(fin, line)) { diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h index d8681fe4f..760def079 100644 --- a/Source/CTest/cmCTestGIT.h +++ b/Source/CTest/cmCTestGIT.h @@ -32,6 +32,8 @@ private: virtual void NoteNewRevision(); virtual bool UpdateImpl(); + std::string FindGitDir(); + bool UpdateByFetchAndReset(); bool UpdateByCustom(std::string const& custom); bool UpdateInternal(); diff --git a/Tests/CTestUpdateGIT.cmake.in b/Tests/CTestUpdateGIT.cmake.in index 4ac1b3177..e1d345cd9 100644 --- a/Tests/CTestUpdateGIT.cmake.in +++ b/Tests/CTestUpdateGIT.cmake.in @@ -259,6 +259,11 @@ execute_process( WORKING_DIRECTORY \"${TOP}\" COMMAND \"${GIT}\" clone \"${REPO}\" dash-source ) + +# Test .git file. +file(RENAME \"${TOP}/dash-source/.git\" \"${TOP}/dash-source/repo.git\") +file(WRITE \"${TOP}/dash-source/.git\" \"gitdir: repo.git\n\") + execute_process( WORKING_DIRECTORY \"${TOP}/dash-source\" COMMAND \"${GIT}\" reset --hard master~2