From 65cb72f7583a25bd3bec3f6a41a7a71cffa44ee2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 20 Jul 2010 16:57:50 -0400 Subject: ctest_update: Abort if Git FETCH_HEAD has no candidates If .git/FETCH_HEAD provides no merge candidate do not attempt to update. Also log FETCH_HEAD lines as we parse them since they are essentially output from the git fetch command. --- Source/CTest/cmCTestGIT.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 6c3631c..41c1393 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -126,6 +126,7 @@ bool cmCTestGIT::UpdateByFetchAndReset() std::string line; while(sha1.empty() && cmSystemTools::GetLineFromStream(fin, line)) { + this->Log << "FETCH_HEAD> " << line << "\n"; if(line.find("\tnot-for-merge\t") == line.npos) { std::string::size_type pos = line.find('\t'); @@ -135,6 +136,11 @@ bool cmCTestGIT::UpdateByFetchAndReset() } } } + if(sha1.empty()) + { + this->Log << "FETCH_HEAD has no upstream branch candidate!\n"; + return false; + } } // Reset the local branch to point at that tracked from upstream. -- cgit v0.12 From 7bf8dc1ac9d2c2430e247c2cfb54a6a4cb5f698a Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 26 Jul 2010 11:40:20 -0400 Subject: ctest_update: Support ".git file" work trees Commit c3781efb (Support Git upstream branch rewrites, 2010-06-08) assumed that ".git/FETCH_HEAD" exists inside the source tree. Fix the implementation to handle a work tree using a ".git file" to link to its repository. Use "git rev-parse --git-dir" to locate the real .git dir. --- Source/CTest/cmCTestGIT.cxx | 55 ++++++++++++++++++++++++++++++++++++++++++- Source/CTest/cmCTestGIT.h | 2 ++ Tests/CTestUpdateGIT.cmake.in | 5 ++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 41c1393..e44f81d 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -85,6 +85,54 @@ void cmCTestGIT::NoteNewRevision() } //---------------------------------------------------------------------------- +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() { const char* git = this->CommandLineTool.c_str(); @@ -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 d8681fe..760def0 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 4ac1b31..e1d345c 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 -- cgit v0.12 From a7319cf1c155a0e82c88689c0b4fe54b389a580e Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 27 Jul 2010 11:31:59 -0400 Subject: ctest_update: Run 'git submodule' at top level The git submodule porcelain must be executed from the top level of the work tree. Use 'git rev-parse --show-cdup' to find the top level relative to the source tree. This is better than searching up the tree for .git ourselves because it will always work the same way Git does and thus honors settings like GIT_DISCOVERY_ACROSS_FILESYSTEM. --- Source/CTest/cmCTestGIT.cxx | 25 ++++++++++++++++++++++++- Source/CTest/cmCTestGIT.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index e44f81d..0fbc92e 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -133,6 +133,27 @@ std::string cmCTestGIT::FindGitDir() } //---------------------------------------------------------------------------- +std::string cmCTestGIT::FindTopDir() +{ + std::string top_dir = this->SourceDirectory; + + // Run "git rev-parse --show-cdup" to locate the top of the tree. + const char* git = this->CommandLineTool.c_str(); + char const* git_rev_parse[] = {git, "rev-parse", "--show-cdup", 0}; + std::string cdup; + OneLineParser rev_parse_out(this, "rev-parse-out> ", cdup); + OutputLogger rev_parse_err(this->Log, "rev-parse-err> "); + if(this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err) && + !cdup.empty()) + { + top_dir += "/"; + top_dir += cdup; + top_dir = cmSystemTools::CollapseFullPath(top_dir.c_str()); + } + return top_dir; +} + +//---------------------------------------------------------------------------- bool cmCTestGIT::UpdateByFetchAndReset() { const char* git = this->CommandLineTool.c_str(); @@ -240,11 +261,13 @@ bool cmCTestGIT::UpdateImpl() return false; } + std::string top_dir = this->FindTopDir(); const char* git = this->CommandLineTool.c_str(); char const* git_submodule[] = {git, "submodule", "update", 0}; OutputLogger submodule_out(this->Log, "submodule-out> "); OutputLogger submodule_err(this->Log, "submodule-err> "); - return this->RunChild(git_submodule, &submodule_out, &submodule_err); + return this->RunChild(git_submodule, &submodule_out, &submodule_err, + top_dir.c_str()); } //---------------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h index 760def0..1765340 100644 --- a/Source/CTest/cmCTestGIT.h +++ b/Source/CTest/cmCTestGIT.h @@ -33,6 +33,7 @@ private: virtual bool UpdateImpl(); std::string FindGitDir(); + std::string FindTopDir(); bool UpdateByFetchAndReset(); bool UpdateByCustom(std::string const& custom); -- cgit v0.12