bool GitStatus::IsExistIndexLockFile(const CString &gitdir) { CString sDirName= gitdir; if (!PathIsDirectory(sDirName)) { int x = sDirName.ReverseFind(_T('\\')); if (x < 2) return false; sDirName = sDirName.Left(x); } for (;;) { if(PathFileExists(sDirName + _T("\\.git"))) { if(PathFileExists(g_AdminDirMap.GetAdminDir(sDirName) + _T("index.lock"))) return true; else return false; } int x = sDirName.ReverseFind(_T('\\')); if (x < 2) return false; sDirName = sDirName.Left(x); } }
int CGitIndexFileMap::Check(const CString &gitdir, bool *isChanged) { __int64 time; int result; CString IndexFile = g_AdminDirMap.GetAdminDir(gitdir) + _T("index"); /* Get data associated with "crt_stat.c": */ result = g_Git.GetFileModifyTime(IndexFile, &time); if (result) return result; SHARED_INDEX_PTR pIndex; pIndex = this->SafeGet(gitdir); if (pIndex.get() == NULL) { if(isChanged) *isChanged = true; return 0; } if (pIndex->m_LastModifyTime == time) { if (isChanged) *isChanged = false; } else { if (isChanged) *isChanged = true; } return 0; }
bool CGitIgnoreList::CheckIgnoreChanged(const CString &gitdir, const CString &path, bool isDir) { CString temp; temp = gitdir; temp += _T("\\"); temp += path; temp.Replace(_T('/'), _T('\\')); if (!isDir) { int x = temp.ReverseFind(_T('\\')); if (x >= 2) temp = temp.Left(x); } while(!temp.IsEmpty()) { CString tempOrig = temp; temp += _T("\\.git"); if (CGit::GitPathFileExists(temp)) { CString gitignore=temp; gitignore += _T("ignore"); if (CheckFileChanged(gitignore)) return true; CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig); CString wcglobalgitignore = adminDir + _T("info\\exclude"); if (CheckFileChanged(wcglobalgitignore)) return true; if (CheckAndUpdateCoreExcludefile(adminDir)) return true; return false; } else { temp += _T("ignore"); if (CheckFileChanged(temp)) return true; } int found=0; int i; for (i = temp.GetLength() - 1; i >= 0; i--) { if(temp[i] == _T('\\')) ++found; if(found == 2) break; } temp = temp.Left(i); } return true; }
int CGitIndexFileMap::LoadIndex(const CString &gitdir) { SHARED_INDEX_PTR pIndex(new CGitIndexList); if (pIndex->ReadIndex(g_AdminDirMap.GetAdminDir(gitdir))) return -1; this->SafeSet(gitdir, pIndex); return 0; }
int CGitIgnoreList::LoadAllIgnoreFile(const CString &gitdir, const CString &path, bool isDir) { CString temp(gitdir); temp += _T('\\'); temp += path; temp.Replace(_T('/'), _T('\\')); if (!isDir) { int x = temp.ReverseFind(_T('\\')); if (x >= 2) temp.Truncate(x); } while (!temp.IsEmpty()) { CString tempOrig = temp; temp += _T("\\.git"); if (CGit::GitPathFileExists(temp)) { CString gitignore = temp; gitignore += _T("ignore"); if (CheckFileChanged(gitignore)) FetchIgnoreFile(gitdir, gitignore, false); CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig); CString wcglobalgitignore = adminDir; wcglobalgitignore += _T("info\\exclude"); if (CheckFileChanged(wcglobalgitignore)) { FetchIgnoreFile(gitdir, wcglobalgitignore, true); } if (CheckAndUpdateCoreExcludefile(adminDir)) { CString excludesFile; { CAutoReadLock lock(m_SharedMutex); excludesFile = m_CoreExcludesfiles[adminDir]; } if (!excludesFile.IsEmpty()) FetchIgnoreFile(gitdir, excludesFile, true); } return 0; } temp += _T("ignore"); if (CheckFileChanged(temp)) FetchIgnoreFile(gitdir, temp, false); int found = 0; int i; for (i = temp.GetLength() - 1; i >= 0; --i) { if(temp[i] == _T('\\')) ++found; if(found == 2) break; } temp.Truncate(i); } return 0; }
int CGitHeadFileList::ReadHeadHash(const CString& gitdir) { CAutoWriteLock lock(m_SharedMutex); m_Gitdir = g_AdminDirMap.GetAdminDir(gitdir); m_HeadFile = m_Gitdir; m_HeadFile += _T("HEAD"); if( CGit::GetFileModifyTime(m_HeadFile, &m_LastModifyTimeHead)) return -1; CAutoFile hfile = CreateFile(m_HeadFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (!hfile) return -1; DWORD size = 0; unsigned char buffer[40]; ReadFile(hfile, buffer, 4, &size, nullptr); if (size != 4) return -1; buffer[4] = 0; if (strcmp((const char*)buffer, "ref:") == 0) { m_HeadRefFile.Empty(); DWORD filesize = GetFileSize(hfile, nullptr); if (filesize < 5) return -1; unsigned char *p = (unsigned char*)malloc(filesize - 4); if (!p) return -1; ReadFile(hfile, p, filesize - 4, &size, nullptr); CGit::StringAppend(&m_HeadRefFile, p, CP_UTF8, filesize - 4); free(p); CString ref = m_HeadRefFile.Trim(); int start = 0; ref = ref.Tokenize(_T("\n"), start); m_HeadRefFile = m_Gitdir + m_HeadRefFile; m_HeadRefFile.Replace(_T('/'), _T('\\')); __int64 time; if (CGit::GetFileModifyTime(m_HeadRefFile, &time, nullptr)) { m_HeadRefFile.Empty(); if (GetPackRef(gitdir)) return -1; if (m_PackRefMap.find(ref) == m_PackRefMap.end()) return -1; m_Head = m_PackRefMap[ref]; return 0; } CAutoFile href = CreateFile(m_HeadRefFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (!href) { m_HeadRefFile.Empty(); if (GetPackRef(gitdir)) return -1; if (m_PackRefMap.find(ref) == m_PackRefMap.end()) return -1; m_Head = m_PackRefMap[ref]; return 0; } ReadFile(href, buffer, 40, &size, nullptr); if (size != 40) return -1; m_Head.ConvertFromStrA((char*)buffer); m_LastModifyTimeRef = time; return 0; } ReadFile(hfile, buffer + 4, 40 - 4, &size, nullptr); if (size != 36) return -1; m_HeadRefFile.Empty(); m_Head.ConvertFromStrA((char*)buffer); return 0; }
int CGitIgnoreList::CheckIgnore(const CString &path, const CString &projectroot, bool isDir) { CString temp = CombinePath(projectroot, path); temp.Replace(_T('/'), _T('\\')); CStringA patha = CUnicodeUtils::GetMulti(path, CP_UTF8); patha.Replace('\\', '/'); int type = 0; if (isDir) { type = DT_DIR; // strip directory name // we do not need to check for a .ignore file inside a directory we might ignore int i = temp.ReverseFind(_T('\\')); if (i >= 0) temp.Truncate(i); } else { type = DT_REG; int x = temp.ReverseFind(_T('\\')); if (x >= 2) temp.Truncate(x); } int pos = patha.ReverseFind('/'); const char * base = (pos >= 0) ? ((const char*)patha + pos + 1) : patha; int ret = -1; CAutoReadLock lock(m_SharedMutex); while (!temp.IsEmpty()) { CString tempOrig = temp; temp += _T("\\.git"); if (CGit::GitPathFileExists(temp)) { CString gitignore = temp; gitignore += _T("ignore"); if ((ret = CheckFileAgainstIgnoreList(gitignore, patha, base, type)) != -1) break; CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig); CString wcglobalgitignore = adminDir; wcglobalgitignore += _T("info\\exclude"); if ((ret = CheckFileAgainstIgnoreList(wcglobalgitignore, patha, base, type)) != -1) break; CString excludesFile = m_CoreExcludesfiles[adminDir]; if (!excludesFile.IsEmpty()) ret = CheckFileAgainstIgnoreList(excludesFile, patha, base, type); break; } temp += _T("ignore"); if ((ret = CheckFileAgainstIgnoreList(temp, patha, base, type)) != -1) break; int found = 0; int i; for (i = temp.GetLength() - 1; i >= 0; i--) { if (temp[i] == _T('\\')) ++found; if (found == 2) break; } temp.Truncate(i); } return ret; }
int CGitHeadFileList::ReadHeadHash(CString gitdir) { int ret = 0; CAutoWriteLock lock(&this->m_SharedMutex); m_Gitdir = g_AdminDirMap.GetAdminDir(gitdir); m_HeadFile = m_Gitdir + _T("HEAD"); if( g_Git.GetFileModifyTime(m_HeadFile, &m_LastModifyTimeHead)) return -1; try { do { CAutoFile hfile = CreateFile(m_HeadFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (!hfile) { ret = -1; break; } DWORD size = 0; unsigned char buffer[40] ; ReadFile(hfile, buffer, 4, &size, NULL); if (size != 4) { ret = -1; break; } buffer[4]=0; if (strcmp((const char*)buffer,"ref:") == 0) { DWORD filesize = GetFileSize(hfile, NULL); if (filesize < 5) { m_HeadRefFile.Empty(); ret = -1; break; } unsigned char *p = (unsigned char*)malloc(filesize -4); ReadFile(hfile, p, filesize - 4, &size, NULL); m_HeadRefFile.Empty(); g_Git.StringAppend(&this->m_HeadRefFile, p, CP_UTF8, filesize - 4); CString ref = this->m_HeadRefFile; ref = ref.Trim(); int start = 0; ref = ref.Tokenize(_T("\n"), start); free(p); m_HeadRefFile = m_Gitdir + m_HeadRefFile.Trim(); m_HeadRefFile.Replace(_T('/'),_T('\\')); __int64 time; if (g_Git.GetFileModifyTime(m_HeadRefFile, &time, NULL)) { m_HeadRefFile.Empty(); if (GetPackRef(gitdir)) { ret = -1; break; } if (this->m_PackRefMap.find(ref) == m_PackRefMap.end()) { ret = -1; break; } this ->m_Head = m_PackRefMap[ref]; ret = 0; break; } CAutoFile href = CreateFile(m_HeadRefFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (!href) { m_HeadRefFile.Empty(); if (GetPackRef(gitdir)) { ret = -1; break; } if (this->m_PackRefMap.find(ref) == m_PackRefMap.end()) { ret = -1; break; } this ->m_Head = m_PackRefMap[ref]; ret = 0; break; } ReadFile(href, buffer, 40, &size, NULL); if (size != 40) { ret = -1; break; } this->m_Head.ConvertFromStrA((char*)buffer); this->m_LastModifyTimeRef = time; } else { ReadFile(hfile, buffer + 4, 40 - 4, &size, NULL); if(size != 36) { ret = -1; break; } m_HeadRefFile.Empty(); this->m_Head.ConvertFromStrA((char*)buffer); } } while(0); } catch(...) { ret = -1; } return ret; }
// This method is assumed to be called with m_SharedMutex locked. int CGitHeadFileList::GetPackRef(const CString &gitdir) { CString PackRef = g_AdminDirMap.GetAdminDir(gitdir) + _T("packed-refs"); __int64 mtime; if (g_Git.GetFileModifyTime(PackRef, &mtime)) { //packed refs is not existed this->m_PackRefFile.Empty(); this->m_PackRefMap.clear(); return 0; } else if(mtime == m_LastModifyTimePackRef) { return 0; } else { this->m_PackRefFile = PackRef; this->m_LastModifyTimePackRef = mtime; } int ret = 0; { this->m_PackRefMap.clear(); CAutoFile hfile = CreateFile(PackRef, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); do { if (!hfile) { ret = -1; break; } DWORD filesize = GetFileSize(hfile, NULL); if (filesize == 0) { ret = -1; break; } DWORD size =0; char *buff; buff = new char[filesize]; ReadFile(hfile, buff, filesize, &size, NULL); if (size != filesize) { delete[] buff; ret = -1; break; } CString hash; CString ref; for(DWORD i=0; i<filesize;) { hash.Empty(); ref.Empty(); if (buff[i] == '#' || buff[i] == '^') { while (buff[i] != '\n') { ++i; if (i == filesize) break; } ++i; } if (i >= filesize) break; while (buff[i] != ' ') { hash.AppendChar(buff[i]); ++i; if (i == filesize) break; } ++i; if (i >= filesize) break; while (buff[i] != '\n') { ref.AppendChar(buff[i]); ++i; if (i == filesize) break; } if (!ref.IsEmpty() ) { this->m_PackRefMap[ref] = hash; } while (buff[i] == '\n') { ++i; if (i == filesize) break; } } delete[] buff; } while(0); } return ret; }
int CGitIgnoreList::CheckIgnore(const CString &path,const CString &projectroot) { __int64 time = 0; bool dir = 0; CString temp = projectroot + _T("\\") + path; temp.Replace(_T('/'), _T('\\')); CStringA patha = CUnicodeUtils::GetMulti(path, CP_UTF8); patha.Replace('\\', '/'); if(g_Git.GetFileModifyTime(temp, &time, &dir)) return -1; int type = 0; if (dir) { type = DT_DIR; // strip directory name // we do not need to check for a .ignore file inside a directory we might ignore int i = temp.ReverseFind(_T('\\')); if (i >= 0) temp = temp.Left(i); } else type = DT_REG; char * base = NULL; int pos = patha.ReverseFind('/'); base = pos >= 0 ? patha.GetBuffer() + pos + 1 : patha.GetBuffer(); int ret = -1; CAutoReadLock lock(&this->m_SharedMutex); while (!temp.IsEmpty()) { CString tempOrig = temp; temp += _T("\\.git"); if (CGit::GitPathFileExists(temp)) { CString gitignore = temp; gitignore += _T("ignore"); if ((ret = CheckFileAgainstIgnoreList(gitignore, patha, base, type)) != -1) break; CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig); CString wcglobalgitignore = adminDir + _T("info\\exclude"); if ((ret = CheckFileAgainstIgnoreList(wcglobalgitignore, patha, base, type)) != -1) break; m_SharedMutex.AcquireShared(); CString excludesFile = m_CoreExcludesfiles[adminDir]; m_SharedMutex.ReleaseShared(); if (!excludesFile.IsEmpty()) ret = CheckFileAgainstIgnoreList(excludesFile, patha, base, type); break; } else { temp += _T("ignore"); if ((ret = CheckFileAgainstIgnoreList(temp, patha, base, type)) != -1) break; } int found = 0; int i; for (i = temp.GetLength() - 1; i >= 0; i--) { if (temp[i] == _T('\\')) ++found; if (found == 2) break; } temp = temp.Left(i); } patha.ReleaseBuffer(); return ret; }
int CGitIgnoreList::LoadAllIgnoreFile(const CString &gitdir,const CString &path) { CString temp; temp = gitdir; temp += _T("\\"); temp += path; temp.Replace(_T('/'), _T('\\')); while (!temp.IsEmpty()) { CString tempOrig = temp; temp += _T("\\.git"); if (CGit::GitPathFileExists(temp)) { CString gitignore = temp; gitignore += _T("ignore"); if (CheckFileChanged(gitignore)) { FetchIgnoreFile(gitdir, gitignore, false); } CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig); CString wcglobalgitignore = adminDir + _T("info\\exclude"); if (CheckFileChanged(wcglobalgitignore)) { FetchIgnoreFile(gitdir, wcglobalgitignore, true); } if (CheckAndUpdateCoreExcludefile(adminDir)) { m_SharedMutex.AcquireShared(); CString excludesFile = m_CoreExcludesfiles[adminDir]; m_SharedMutex.ReleaseShared(); if (!excludesFile.IsEmpty()) FetchIgnoreFile(gitdir, excludesFile, true); } return 0; } else { temp += _T("ignore"); if (CheckFileChanged(temp)) { FetchIgnoreFile(gitdir, temp, false); } } int found = 0; int i; for (i = temp.GetLength() - 1; i >= 0; i--) { if(temp[i] == _T('\\')) ++found; if(found == 2) break; } temp = temp.Left(i); } return 0; }
// This method is assumed to be called with m_SharedMutex locked. int CGitHeadFileList::GetPackRef(const CString &gitdir) { CString PackRef = g_AdminDirMap.GetAdminDir(gitdir) + _T("packed-refs"); __int64 mtime; if (g_Git.GetFileModifyTime(PackRef, &mtime)) { //packed refs is not existed this->m_PackRefFile.Empty(); this->m_PackRefMap.clear(); return 0; } else if(mtime == m_LastModifyTimePackRef) { return 0; } else { this->m_PackRefFile = PackRef; this->m_LastModifyTimePackRef = mtime; } m_PackRefMap.clear(); CAutoFile hfile = CreateFile(PackRef, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (!hfile) return -1; DWORD filesize = GetFileSize(hfile, nullptr); if (filesize == 0) return -1; DWORD size = 0; std::unique_ptr<char[]> buff(new char[filesize]); ReadFile(hfile, buff.get(), filesize, &size, nullptr); if (size != filesize) return -1; CString hash; CString ref; for (DWORD i = 0; i < filesize;) { hash.Empty(); ref.Empty(); if (buff[i] == '#' || buff[i] == '^') { while (buff[i] != '\n') { ++i; if (i == filesize) break; } ++i; } if (i >= filesize) break; while (buff[i] != ' ') { hash.AppendChar(buff[i]); ++i; if (i == filesize) break; } ++i; if (i >= filesize) break; while (buff[i] != '\n') { ref.AppendChar(buff[i]); ++i; if (i == filesize) break; } if (!ref.IsEmpty()) m_PackRefMap[ref] = hash; while (buff[i] == '\n') { ++i; if (i == filesize) break; } } return 0; }