diff --git a/ChangeLog.manual b/ChangeLog.manual index 29162e9ef..b93586025 100644 --- a/ChangeLog.manual +++ b/ChangeLog.manual @@ -15,6 +15,7 @@ Changes since CMake 2.8.1 - CTest: Report failure in Update.xml - CTest: Submit author email in Update.xml - CTest: Teach ctest_update about Git submodules +- CTest: Teach ctest_update to handle Git upstream branch rewrites - Cygwin: Export all symbols with ENABLE_EXPORTS (#10122) - Do not list file names during 'cmake -E tar xz' - Documentation: Comply with "XHTML 1.0 Strict" diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 5972d39bc..6c3631c90 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -85,16 +85,14 @@ void cmCTestGIT::NoteNewRevision() } //---------------------------------------------------------------------------- -bool cmCTestGIT::UpdateByPull() +bool cmCTestGIT::UpdateByFetchAndReset() { const char* git = this->CommandLineTool.c_str(); - // Use "git pull" to update the working tree. - std::vector git_pull; - git_pull.push_back(git); - git_pull.push_back("pull"); - - // TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY) + // Use "git fetch" to get remote commits. + std::vector git_fetch; + git_fetch.push_back(git); + git_fetch.push_back("fetch"); // Add user-specified update options. std::string opts = this->CTest->GetCTestConfiguration("UpdateOptions"); @@ -106,15 +104,44 @@ bool cmCTestGIT::UpdateByPull() for(std::vector::const_iterator ai = args.begin(); ai != args.end(); ++ai) { - git_pull.push_back(ai->c_str()); + git_fetch.push_back(ai->c_str()); } // Sentinel argument. - git_pull.push_back(0); + git_fetch.push_back(0); - OutputLogger out(this->Log, "pull-out> "); - OutputLogger err(this->Log, "pull-err> "); - return this->RunUpdateCommand(&git_pull[0], &out, &err); + // Fetch upstream refs. + OutputLogger fetch_out(this->Log, "fetch-out> "); + OutputLogger fetch_err(this->Log, "fetch-err> "); + if(!this->RunUpdateCommand(&git_fetch[0], &fetch_out, &fetch_err)) + { + return false; + } + + // Identify the merge head that would be used by "git pull". + std::string sha1; + { + std::string fetch_head = this->SourceDirectory + "/.git/FETCH_HEAD"; + std::ifstream fin(fetch_head.c_str(), std::ios::in | std::ios::binary); + std::string line; + while(sha1.empty() && cmSystemTools::GetLineFromStream(fin, line)) + { + if(line.find("\tnot-for-merge\t") == line.npos) + { + std::string::size_type pos = line.find('\t'); + if(pos != line.npos) + { + sha1 = line.substr(0, pos); + } + } + } + } + + // Reset the local branch to point at that tracked from upstream. + char const* git_reset[] = {git, "reset", "--hard", sha1.c_str(), 0}; + OutputLogger reset_out(this->Log, "reset-out> "); + OutputLogger reset_err(this->Log, "reset-err> "); + return this->RunChild(&git_reset[0], &reset_out, &reset_err); } //---------------------------------------------------------------------------- @@ -143,7 +170,7 @@ bool cmCTestGIT::UpdateInternal() { return this->UpdateByCustom(custom); } - return this->UpdateByPull(); + return this->UpdateByFetchAndReset(); } //---------------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h index bdb2c6269..d8681fe4f 100644 --- a/Source/CTest/cmCTestGIT.h +++ b/Source/CTest/cmCTestGIT.h @@ -32,7 +32,7 @@ private: virtual void NoteNewRevision(); virtual bool UpdateImpl(); - bool UpdateByPull(); + bool UpdateByFetchAndReset(); bool UpdateByCustom(std::string const& custom); bool UpdateInternal(); diff --git a/Tests/CTestUpdateCommon.cmake b/Tests/CTestUpdateCommon.cmake index c62505c8f..a52cb148d 100644 --- a/Tests/CTestUpdateCommon.cmake +++ b/Tests/CTestUpdateCommon.cmake @@ -191,13 +191,17 @@ function(run_dashboard_command_line bin_dir) # Verify the updates reported by CTest. list(APPEND UPDATE_MAYBE Updated{subdir}) + set(_modified Modified{CTestConfig.cmake}) + if(UPDATE_NO_MODIFIED) + set(_modified "") + endif() check_updates(${bin_dir} Updated{foo.txt} Updated{bar.txt} Updated{zot.txt} Updated{subdir/foo.txt} Updated{subdir/bar.txt} - Modified{CTestConfig.cmake} + ${_modified} ) endfunction(run_dashboard_command_line) diff --git a/Tests/CTestUpdateGIT.cmake.in b/Tests/CTestUpdateGIT.cmake.in index 95461bb96..4ac1b3177 100644 --- a/Tests/CTestUpdateGIT.cmake.in +++ b/Tests/CTestUpdateGIT.cmake.in @@ -227,7 +227,9 @@ UpdateCommand: ${GIT} ") # Run the dashboard command line interface. +set(UPDATE_NO_MODIFIED 1) run_dashboard_command_line(user-binary) +set(UPDATE_NO_MODIFIED 0) rewind_source(user-source) modify_content(user-source) diff --git a/Tests/CTestUpdateGIT.sh.in b/Tests/CTestUpdateGIT.sh.in index 4761d3293..e7586d6bf 100755 --- a/Tests/CTestUpdateGIT.sh.in +++ b/Tests/CTestUpdateGIT.sh.in @@ -1,5 +1,5 @@ #!/bin/sh -if test "x$1" = "xpull"; then +if test "x$1" = "xpull" -o "x$1" = "xreset"; then "@GIT@" "$@" && sleep 1 && touch foo.txt else exec "@GIT@" "$@"