From c25477d1fd0af8edd8efaeb800a6a71fb4be5ebe Mon Sep 17 00:00:00 2001 From: Yue Lin Ho Date: Sun, 1 Mar 2015 17:10:08 +0800 Subject: [PATCH] Use libgit2 to check clean working tree Currently, libgit2 does not support racy-git problem. Signed-off-by: Yue Lin Ho Signed-off-by: Sven Strickroth --- src/Git/Git.cpp | 20 ++++++++++++++++++++ src/Git/Git.h | 4 ++++ src/Utils/SmartLibgit2Ref.h | 14 ++++++++++++++ test/UnitTests/GitTest.cpp | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/src/Git/Git.cpp b/src/Git/Git.cpp index 48554b1d9..5f80d68c2 100644 --- a/src/Git/Git.cpp +++ b/src/Git/Git.cpp @@ -2142,6 +2142,26 @@ CString CGit::GetGitSystemConfig() const BOOL CGit::CheckCleanWorkTree(bool stagedOk /* false */) { + if (UsingLibGit2(GIT_CMD_CHECK_CLEAN_WT)) + { + CAutoRepository repo = GetGitRepository(); + if (!repo) + return FALSE; + + if (git_repository_head_unborn(repo)) + return FALSE; + + git_status_options statusopt = GIT_STATUS_OPTIONS_INIT; + statusopt.show = stagedOk ? GIT_STATUS_SHOW_WORKDIR_ONLY : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + statusopt.flags = GIT_STATUS_OPT_UPDATE_INDEX | GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + + CAutoStatusList status; + if (git_status_list_new(status.GetPointer(), repo, &statusopt)) + return FALSE; + + return (0 == git_status_list_entrycount(status)); + } + CString out; CString cmd; cmd=_T("git.exe rev-parse --verify HEAD"); diff --git a/src/Git/Git.h b/src/Git/Git.h index 8d9cbf04f..266a8e5bb 100644 --- a/src/Git/Git.h +++ b/src/Git/Git.h @@ -166,6 +166,7 @@ public: GIT_CMD_GETONEFILE, GIT_CMD_ADD, GIT_CMD_PUSH, + GIT_CMD_CHECK_CLEAN_WT, } LIBGIT2_CMD; bool UsingLibGit2(LIBGIT2_CMD cmd) const; /** @@ -238,6 +239,9 @@ public: void GetRemoteTrackedBranchForHEAD(CString& remote, CString& branch); // read current branch name from HEAD file, returns 0 on success, -1 on failure, 1 detached (branch name "HEAD" returned) static int GetCurrentBranchFromFile(const CString &sProjectRoot, CString &sBranchOut, bool fallback = false); + /** + Use this method only when the HEAD is exist. + */ BOOL CheckCleanWorkTree(bool stagedOk = false); int Revert(const CString& commit, const CTGitPathList &list, CString& err); int Revert(const CString& commit, const CTGitPath &path, CString& err); diff --git a/src/Utils/SmartLibgit2Ref.h b/src/Utils/SmartLibgit2Ref.h index cca4efe85..f08d082c9 100644 --- a/src/Utils/SmartLibgit2Ref.h +++ b/src/Utils/SmartLibgit2Ref.h @@ -460,6 +460,20 @@ protected: } }; +class CAutoStatusList : public CSmartLibgit2Ref +{ +public: + ~CAutoStatusList() + { + CleanUp(); + } +protected: + virtual void FreeRef() + { + git_status_list_free(m_Ref); + } +}; + template class CSmartBuffer : public FreeFunction { diff --git a/test/UnitTests/GitTest.cpp b/test/UnitTests/GitTest.cpp index 9baea968d..5c3606d8d 100644 --- a/test/UnitTests/GitTest.cpp +++ b/test/UnitTests/GitTest.cpp @@ -110,3 +110,35 @@ TEST_P(CBasicGitWithEmptyRepositoryFixture, IsInitRepos) EXPECT_FALSE(m_Git.IsInitRepos()); } + +TEST_P(CBasicGitWithEmptyRepositoryFixture, CheckCleanWorkTree) +{ + CString output; + CString testFile = m_Dir.GetTempDir() + L"\\test.txt"; + EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFile, L"this is testing file.")); + EXPECT_EQ(0, m_Git.Run(_T("git.exe add test.txt"), &output, CP_UTF8)); + output.Empty(); + EXPECT_EQ(0, m_Git.Run(_T("git.exe commit -m \"Add test.txt\""), &output, CP_UTF8)); + // repo with 1 versioned file + EXPECT_FALSE(output.IsEmpty()); + EXPECT_TRUE(m_Git.CheckCleanWorkTree()); + EXPECT_TRUE(m_Git.CheckCleanWorkTree(true)); + + EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFile, L"Overwriting this testing file.")); + // repo with 1 modified versioned file + EXPECT_FALSE(m_Git.CheckCleanWorkTree()); + EXPECT_FALSE(m_Git.CheckCleanWorkTree(true)); + + output.Empty(); + EXPECT_EQ(0, m_Git.Run(_T("git.exe add test.txt"), &output, CP_UTF8)); + // repo with 1 modified versioned and staged file + EXPECT_TRUE(output.IsEmpty()); + EXPECT_FALSE(m_Git.CheckCleanWorkTree()); + EXPECT_TRUE(m_Git.CheckCleanWorkTree(true)); + + EXPECT_EQ(0, m_Git.Run(_T("git.exe commit -m \"Modified test.txt\""), &output, CP_UTF8)); + testFile = m_Dir.GetTempDir() + L"\\test2.txt"; + EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFile, L"this is ANOTHER testing file.")); + EXPECT_TRUE(m_Git.CheckCleanWorkTree()); + EXPECT_TRUE(m_Git.CheckCleanWorkTree(true)); +} -- 2.11.4.GIT