From 508b7dc522dbcbd3cc63b9250ac08378dd8e6b2d Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Sat, 22 Sep 2012 02:06:50 +0200 Subject: [PATCH] Fixed issue #861: TGitCache gets confused about file status (should detect touched file as unmodified) Signed-off-by: Sven Strickroth --- .../TortoiseGit/tsvn_dug/dug_settings_advanced.xml | 6 +-- src/Changelog.txt | 8 +-- src/Git/GitIndex.cpp | 60 +++++++++++++++++++--- src/Git/gitindex.h | 4 ++ 4 files changed, 63 insertions(+), 15 deletions(-) diff --git a/doc/source/en/TortoiseGit/tsvn_dug/dug_settings_advanced.xml b/doc/source/en/TortoiseGit/tsvn_dug/dug_settings_advanced.xml index 325330c4a..422693232 100644 --- a/doc/source/en/TortoiseGit/tsvn_dug/dug_settings_advanced.xml +++ b/doc/source/en/TortoiseGit/tsvn_dug/dug_settings_advanced.xml @@ -156,10 +156,8 @@ This makes TGitCache check file contents if timestamps (to index) missmatch in order to calculate the file status. - TortoiseGit 1.7.0 up to 1.7.12 calculated the file status based on the timestamp only, - this is still the default, because checking the content of the files only works - if AutoCrLf is disabled at the moment. - If you want TGitCache to check the file contents (this might increase disk access and CPU time), set this value to true. + TortoiseGit 1.7.0 up to 1.7.12 calculated the file status based on the timestamp only. + If do not you want TGitCache to check the file contents (this lowers disk access and CPU time), set this value to false. diff --git a/src/Changelog.txt b/src/Changelog.txt index 7104311ea..e94cd4eb5 100644 --- a/src/Changelog.txt +++ b/src/Changelog.txt @@ -11,9 +11,6 @@ Released: unreleased * Fixed issue #1350: Commit Dialog set focus to message editor after clicking amend checkbox * Fixed issue #811: Log the history of a submodule not its contents * Fixed issue #1344: Log list add copy to clipboard only with commit message - * TGitCache only checked timestamps of files in order to get their state since 1.7.0 (see issue #861). - If you have AutoCrLf disabled, you can make TGitCache check the contents of modified files. - This can be done via the Settings dialog -> Advanced and set TGitCacheCheckContent to "true". * Fixed issue #1336: Have visible the name of the branch in Repository Browser * Fixed issue #1351: Add Hotkey to (de)select all files and commit * Fixed issue #1363: copy email in the log window @@ -51,6 +48,11 @@ Released: unreleased * Fixed issue #1392: Window with rebase results is non-manageable via keyboard (no focus, can't press Done) * Fixed issue #1405: Cannot show branch description in Browse Reference Dialog with separate .git directory * Fixed issue #1406: Commit dialog cannot check MERGE_HEAD with separate .git directory + * Fixed issue #861: TGitCache gets confused about file status (should detect touched file as unmodified) + TGitCache only checked timestamps of files in order to get their state since 1.7.0. + This fix makes TortoiseGit check the content of the files. + If you want to restore the old behavior, you can disable checking the contents via + the Settings dialog -> Advanced and set TGitCacheCheckContent to "false". = Release 1.7.12.0 = Released: 2012-08-10 diff --git a/src/Git/GitIndex.cpp b/src/Git/GitIndex.cpp index 397c32395..6ef456964 100644 --- a/src/Git/GitIndex.cpp +++ b/src/Git/GitIndex.cpp @@ -29,7 +29,6 @@ #include "gitindex.h" #include #include -#include "git2.h" #include "SmartHandle.h" class CAutoReadLock @@ -78,9 +77,20 @@ int CGitIndex::Print() CGitIndexList::CGitIndexList() { this->m_LastModifyTime = 0; + m_critRepoSec.Init(); + repository = NULL; m_bCheckContent = !!(CRegDWORD(_T("Software\\TortoiseGit\\TGitCacheCheckContent"), FALSE) == TRUE); } +CGitIndexList::~CGitIndexList() +{ + if (repository != NULL) + { + git_repository_free(repository); + m_critRepoSec.Term(); + } +} + static bool SortIndex(CGitIndex &Item1, CGitIndex &Item2) { return Item1.m_FileName.Compare(Item2.m_FileName) < 0; @@ -96,7 +106,13 @@ int CGitIndexList::ReadIndex(CString dgitdir) this->clear(); CStringA gitdir = CUnicodeUtils::GetMulti(dgitdir, CP_UTF8); - git_repository *repository = NULL; + + m_critRepoSec.Lock(); + if (repository != NULL) + { + git_repository_free(repository); + repository = NULL; + } git_index *index = NULL; int ret = git_repository_open(&repository, gitdir.GetBuffer()); @@ -104,9 +120,35 @@ int CGitIndexList::ReadIndex(CString dgitdir) if (ret) return -1; + // add config files + git_config * config; + git_config_new(&config); + + CString projectConfig = dgitdir + _T("config"); + CString globalConfig = g_Git.GetHomeDirectory() + _T("\\.gitconfig"); + CString msysGitBinPath(CRegString(REG_MSYSGIT_PATH, _T(""), FALSE)); + + CStringA projectConfigA = CUnicodeUtils::GetMulti(projectConfig, CP_UTF8); + git_config_add_file_ondisk(config, projectConfigA.GetBuffer(), 3); + projectConfigA.ReleaseBuffer(); + CStringA globalConfigA = CUnicodeUtils::GetMulti(globalConfig, CP_UTF8); + git_config_add_file_ondisk(config, globalConfigA.GetBuffer(), 2); + globalConfigA.ReleaseBuffer(); + if (!msysGitBinPath.IsEmpty()) + { + CString systemConfig = msysGitBinPath + _T("\\..\\etc\\gitconfig"); + CStringA systemConfigA = CUnicodeUtils::GetMulti(systemConfig, CP_UTF8); + git_config_add_file_ondisk(config, systemConfigA.GetBuffer(), 1); + systemConfigA.ReleaseBuffer(); + } + + git_repository_set_config(repository, config); + + // load index in order to enumerate files if (git_repository_index(&index, repository)) { - git_repository_free(repository); + repository = NULL; + m_critRepoSec.Unlock(); return -1; } @@ -125,11 +167,12 @@ int CGitIndexList::ReadIndex(CString dgitdir) } git_index_free(index); - git_repository_free(repository); g_Git.GetFileModifyTime(dgitdir + _T("index"), &this->m_LastModifyTime); std::sort(this->begin(), this->end(), SortIndex); + m_critRepoSec.Unlock(); + return 0; } @@ -175,12 +218,12 @@ int CGitIndexList::GetFileStatus(const CString &gitdir,const CString &pathorg,gi { *status = git_wc_status_normal; } - else if (m_bCheckContent) + else if (m_bCheckContent && repository) { git_oid actual; - CString file = gitdir + _T("\\") + pathorg; - CStringA fileA = CUnicodeUtils::GetMulti(file, CP_UTF8); - if (!git_odb_hashfile(&actual, fileA.GetBuffer(), GIT_OBJ_BLOB) && !git_oid_cmp(&actual, (const git_oid*)at(index).m_IndexHash.m_hash)) + CStringA fileA = CUnicodeUtils::GetMulti(pathorg, CP_UTF8); + m_critRepoSec.Lock(); // prevent concurrent access to repository instance and especially filter-lists + if (!git_repository_hashfile(&actual, repository, fileA.GetBuffer(), GIT_OBJ_BLOB, NULL) && !git_oid_cmp(&actual, (const git_oid*)at(index).m_IndexHash.m_hash)) { at(index).m_ModifyTime = time; *status = git_wc_status_normal; @@ -188,6 +231,7 @@ int CGitIndexList::GetFileStatus(const CString &gitdir,const CString &pathorg,gi else *status = git_wc_status_modified; fileA.ReleaseBuffer(); + m_critRepoSec.Unlock(); } else *status = git_wc_status_modified; diff --git a/src/Git/gitindex.h b/src/Git/gitindex.h index e341bd3fa..52cf7b97e 100644 --- a/src/Git/gitindex.h +++ b/src/Git/gitindex.h @@ -21,6 +21,7 @@ #include "gitdll.h" #include "gitstatus.h" #include "SharedMutex.h" +#include "git2.h" class CGitIndex { @@ -41,11 +42,14 @@ public: __time64_t m_LastModifyTime; CGitIndexList(); + ~CGitIndexList(); int ReadIndex(CString file); int GetStatus(const CString &gitdir, const CString &path, git_wc_status_kind * status, BOOL IsFull=false, BOOL IsRecursive=false, FIll_STATUS_CALLBACK callback = NULL, void *pData = NULL,CGitHash *pHash=NULL, bool * assumeValid = NULL, bool * skipWorktree = NULL); protected: bool m_bCheckContent; + CComCriticalSection m_critRepoSec; + git_repository * repository; int GetFileStatus(const CString &gitdir, const CString &path, git_wc_status_kind * status, __int64 time, FIll_STATUS_CALLBACK callback = NULL, void *pData = NULL, CGitHash *pHash = NULL, bool * assumeValid = NULL, bool * skipWorktree = NULL); int GetDirStatus(const CString &gitdir,const CString &path, git_wc_status_kind * status,__int64 time,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL,CGitHash *pHash=NULL); }; -- 2.11.4.GIT