Drop unnecessary code
[TortoiseGit.git] / src / Git / gitindex.h
blobd1b1a04d2a548f2346d1a545c5e67d2f3da75f6c
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2012 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "GitHash.h"
21 #include "gitdll.h"
22 #include "gitstatus.h"
23 #include "SharedMutex.h"
24 #include "git2.h"
26 class CGitIndex
28 public:
29 CString m_FileName;
30 __time64_t m_ModifyTime;
31 unsigned short m_Flags;
32 CGitHash m_IndexHash;
34 int Print();
37 class CGitIndexList:public std::vector<CGitIndex>
39 protected:
41 public:
42 __time64_t m_LastModifyTime;
44 CGitIndexList();
45 ~CGitIndexList();
47 int ReadIndex(CString file);
48 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);
49 protected:
50 bool m_bCheckContent;
51 CComCriticalSection m_critRepoSec;
52 git_repository * repository;
53 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);
54 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);
57 typedef std::tr1::shared_ptr<CGitIndexList> SHARED_INDEX_PTR;
58 typedef CComCritSecLock<CComCriticalSection> CAutoLocker;
60 class CGitIndexFileMap:public std::map<CString, SHARED_INDEX_PTR>
62 public:
63 CComCriticalSection m_critIndexSec;
65 CGitIndexFileMap() { m_critIndexSec.Init(); }
66 ~CGitIndexFileMap() { m_critIndexSec.Term(); }
68 SHARED_INDEX_PTR SafeGet(const CString &path)
70 CString thePath = path;
71 thePath.MakeLower();
72 CAutoLocker lock(m_critIndexSec);
73 if(this->find(thePath) == end())
74 return SHARED_INDEX_PTR();
75 else
76 return (*this)[thePath];
79 void SafeSet(const CString &path, SHARED_INDEX_PTR ptr)
81 CString thePath = path;
82 thePath.MakeLower();
83 CAutoLocker lock(m_critIndexSec);
84 (*this)[thePath] = ptr;
87 int Check(const CString &gitdir, bool *isChanged);
88 int LoadIndex(const CString &gitdir);
90 bool CheckAndUpdate(const CString &gitdir,bool isLoadUpdatedIndex)
92 bool isChanged=false;
93 if(isLoadUpdatedIndex && Check(gitdir,&isChanged))
94 return false;
96 if(isChanged && isLoadUpdatedIndex)
98 LoadIndex(gitdir);
99 return true;
102 return false;
104 int GetFileStatus(const CString &gitdir,const CString &path,git_wc_status_kind * status,
105 BOOL IsFull=false, BOOL IsRecursive=false,
106 FIll_STATUS_CALLBACK callback=NULL,
107 void *pData=NULL,CGitHash *pHash=NULL,
108 bool isLoadUpdatedIndex = true, bool * assumeValid = NULL, bool * skipWorktree = NULL);
110 int IsUnderVersionControl(const CString &gitdir,
111 const CString &path,
112 bool isDir,
113 bool *isVersion,
114 bool isLoadUpdateIndex=true);
118 class CGitTreeItem
120 public:
121 CString m_FileName;
122 CGitHash m_Hash;
123 int m_Flags;
126 /* After object create, never change field agains
127 * that needn't lock to get field
129 class CGitHeadFileList:public std::vector<CGitTreeItem>
131 private:
133 int GetPackRef(const CString &gitdir);
134 SharedMutex m_SharedMutex;
136 public:
137 __time64_t m_LastModifyTimeHead;
138 __time64_t m_LastModifyTimeRef;
139 __time64_t m_LastModifyTimePackRef;
141 CString m_HeadRefFile;
142 CGitHash m_Head;
143 CString m_HeadFile;
144 CString m_Gitdir;
145 CString m_PackRefFile;
147 CGitHash m_TreeHash; /* buffered tree hash value */
149 std::map<CString,CGitHash> m_PackRefMap;
151 CGitHeadFileList()
153 m_LastModifyTimeHead=0;
154 m_LastModifyTimeRef=0;
155 m_LastModifyTimePackRef = 0;
156 m_SharedMutex.Init();
159 ~CGitHeadFileList()
161 m_SharedMutex.Release();
164 int ReadTree();
165 int ReadHeadHash(CString gitdir);
166 bool CheckHeadUpdate();
167 static int CallBack(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
170 typedef std::tr1::shared_ptr<CGitHeadFileList> SHARED_TREE_PTR;
171 class CGitHeadFileMap:public std::map<CString,SHARED_TREE_PTR>
173 public:
175 CComCriticalSection m_critTreeSec;
177 CGitHeadFileMap() { m_critTreeSec.Init(); }
178 ~CGitHeadFileMap() { m_critTreeSec.Term(); }
180 SHARED_TREE_PTR SafeGet(const CString &path)
182 CString thePath = path;
183 thePath.MakeLower();
184 CAutoLocker lock(m_critTreeSec);
185 if(this->find(thePath) == end())
186 return SHARED_TREE_PTR();
187 else
188 return (*this)[thePath];
191 void SafeSet(const CString &path, SHARED_TREE_PTR ptr)
193 CString thePath = path;
194 thePath.MakeLower();
195 CAutoLocker lock(m_critTreeSec);
196 (*this)[thePath] = ptr;
199 int GetFileStatus(const CString &gitdir,const CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,
200 FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL,
201 bool isLoaded=false);
202 bool CheckHeadUpdate(const CString &gitdir);
203 int IsUnderVersionControl(const CString &gitdir, const CString &path, bool isDir, bool *isVersion);
205 bool IsHashChanged(const CString &gitdir)
207 SHARED_TREE_PTR ptr = SafeGet(gitdir);
209 if( ptr.get() == NULL)
210 return false;
212 return ptr->m_Head != ptr->m_TreeHash;
216 class CGitFileName
218 public:
219 CString m_FileName;
220 CString m_CaseFileName;
223 class CGitIgnoreItem
225 public:
226 SharedMutex m_SharedMutex;
228 CGitIgnoreItem()
230 m_LastModifyTime =0;
231 m_pExcludeList =NULL;
233 ~CGitIgnoreItem()
235 if(m_pExcludeList)
236 git_free_exclude_list(m_pExcludeList);
237 m_pExcludeList=NULL;
239 __time64_t m_LastModifyTime;
240 CStringA m_BaseDir;
241 EXCLUDE_LIST m_pExcludeList;
242 int FetchIgnoreList(const CString &projectroot, const CString &file, bool isGlobal);
245 class CGitIgnoreList
247 private:
248 bool CheckFileChanged(const CString &path);
249 int FetchIgnoreFile(const CString &gitdir, const CString &gitignore, bool isGlobal);
251 int CheckIgnore(const CString &path,const CString &root);
252 int CheckFileAgainstIgnoreList(const CString &ignorefile, const CStringA &patha, const char * base, int &type);
254 // core.excludesfile stuff
255 std::map<CString, CString> m_CoreExcludesfiles;
256 CString m_sMsysGitBinPath;
257 DWORD m_dMsysGitBinPathLastChecked;
258 SharedMutex m_coreExcludefilesSharedMutex;
259 // checks if the msysgit path has changed and return true/false
260 // if the path changed, the cache is update
261 // force is only ised in constructor
262 bool CheckAndUpdateMsysGitBinpath(bool force = true);
263 bool CheckAndUpdateCoreExcludefile(const CString &adminDir);
264 const CString GetWindowsHome();
266 public:
267 SharedMutex m_SharedMutex;
269 CGitIgnoreList(){ m_SharedMutex.Init(); m_coreExcludefilesSharedMutex.Init(); CheckAndUpdateMsysGitBinpath(true); }
270 ~CGitIgnoreList() { m_SharedMutex.Release(); m_coreExcludefilesSharedMutex.Release(); }
272 std::map<CString, CGitIgnoreItem> m_Map;
274 bool CheckIgnoreChanged(const CString &gitdir,const CString &path);
275 int LoadAllIgnoreFile(const CString &gitdir,const CString &path);
276 bool IsIgnore(const CString &path,const CString &root);
279 template<class T>
280 int GetRangeInSortVector(T &vector,LPTSTR pstr,int len, int *start, int *end, int pos)
282 if( pos < 0)
284 return -1;
286 if(start == 0 || end == NULL)
287 return -1;
289 *start=*end=-1;
291 if (vector.empty())
292 return -1;
294 if (pos >= (int)vector.size())
295 return -1;
297 if( _tcsnccmp(vector[pos].m_FileName, pstr,len) != 0)
299 for (int i = 0; i < (int)vector.size(); i++)
301 if( _tcsnccmp(vector[i].m_FileName, pstr,len) == 0 )
303 if(*start<0)
304 *start =i;
305 *end =i;
308 return -1;
310 else
312 *start =0;
313 *end = (int)vector.size();
315 for (int i = pos; i < (int)vector.size(); i++)
317 if( _tcsnccmp(vector[i].m_FileName, pstr,len) == 0 )
319 *end=i;
321 else
323 break;
326 for(int i=pos;i>=0;i--)
328 if( _tcsnccmp(vector[i].m_FileName, pstr,len) == 0 )
330 *start=i;
332 else
334 break;
338 return 0;
341 template<class T>
342 int SearchInSortVector(T &vector, LPTSTR pstr, int len)
344 int end = (int)vector.size() - 1;
345 int start = 0;
346 int mid = (start+end)/2;
348 if (vector.empty())
349 return -1;
351 while(!( start == end && start==mid))
353 int cmp;
354 if(len < 0)
355 cmp = _tcscmp(vector[mid].m_FileName,pstr);
356 else
357 cmp = _tcsnccmp( vector[mid].m_FileName,pstr,len );
359 if (cmp == 0)
360 return mid;
361 else if (cmp < 0)
362 start = mid + 1;
363 else // (cmp > 0)
364 end = mid;
366 mid=(start +end ) /2;
369 if(len <0)
371 if(_tcscmp(vector[mid].m_FileName,pstr) == 0)
372 return mid;
374 else
376 if(_tcsnccmp( vector[mid].m_FileName,pstr,len ) == 0)
377 return mid;
379 return -1;
382 class CGitAdminDirMap:public std::map<CString, CString>
384 public:
385 CComCriticalSection m_critIndexSec;
386 std::map<CString, CString> m_reverseLookup;
388 CGitAdminDirMap() { m_critIndexSec.Init(); }
389 ~CGitAdminDirMap() { m_critIndexSec.Term(); }
391 CString GetAdminDir(const CString &path)
393 CString thePath = path;
394 thePath.MakeLower();
395 CAutoLocker lock(m_critIndexSec);
396 if(this->find(thePath) == end())
398 if (PathIsDirectory(thePath + _T("\\.git")))
400 (*this)[thePath] = thePath + _T("\\.git\\");
401 m_reverseLookup[thePath + _T("\\.git")] = thePath;
402 return (*this)[thePath];
404 else
406 FILE * pFile = _tfsopen(thePath + _T("\\.git"), _T("r"), SH_DENYWR);
407 if (pFile)
409 int size = 65536;
410 auto_buffer<char> buffer(size);
411 if (fread(buffer, sizeof(char), size, pFile))
413 fclose(pFile);
414 CString str = CString(buffer);
415 if (str.Left(8) == _T("gitdir: "))
417 str = str.TrimRight().Mid(8);
418 str.Replace(_T("/"), _T("\\"));
419 str.TrimRight(_T("\\"));
420 if (str.GetLength() > 0 && str[0] == _T('.'))
422 str = thePath + _T("\\") + str;
423 CString newPath;
424 PathCanonicalize(newPath.GetBuffer(MAX_PATH), str.GetBuffer());
425 newPath.ReleaseBuffer();
426 str.ReleaseBuffer();
427 str = newPath;
429 (*this)[thePath] = str + _T("\\");
430 m_reverseLookup[str.MakeLower()] = path;
431 return (*this)[thePath];
434 else
435 fclose(pFile);
437 return thePath + _T("\\.git\\"); // in case of an error stick to old behavior
440 else
441 return (*this)[thePath];
444 CString GetWorkingCopy(const CString &gitDir)
446 CString path = gitDir;
447 path.MakeLower();
448 CAutoLocker lock(m_critIndexSec);
449 if (m_reverseLookup.find(path) == m_reverseLookup.end())
450 return gitDir;
451 else
452 return m_reverseLookup[path];