added first draft of RequestPull Dialog
[TortoiseGit.git] / src / Git / gitindex.h
blob78e91b464106a10217cc7ffe172c7f0b65939ec1
1 #include "GitHash.h"
2 #include "gitdll.h"
3 #include "gitstatus.h"
4 #include "SharedMutex.h"
6 /* Copy from Git cache.h*/
7 #define FLEX_ARRAY 4
9 #pragma pack(push)
10 #pragma pack(1)
11 //#pragma pack(show)
12 #define CACHE_SIGNATURE 0x44495243 /* "DIRC" */
13 struct cache_header {
14 unsigned int hdr_signature;
15 unsigned int hdr_version;
16 unsigned int hdr_entries;
20 * The "cache_time" is just the low 32 bits of the
21 * time. It doesn't matter if it overflows - we only
22 * check it for equality in the 32 bits we save.
24 struct cache_time {
25 UINT32 sec;
26 UINT32 nsec;
30 * dev/ino/uid/gid/size are also just tracked to the low 32 bits
31 * Again - this is just a (very strong in practice) heuristic that
32 * the inode hasn't changed.
34 * We save the fields in big-endian order to allow using the
35 * index file over NFS transparently.
37 struct ondisk_cache_entry {
38 struct cache_time ctime;
39 struct cache_time mtime;
40 UINT32 dev;
41 UINT32 ino;
42 UINT32 mode;
43 UINT32 uid;
44 UINT32 gid;
45 UINT32 size;
46 BYTE sha1[20];
47 UINT16 flags;
48 char name[FLEX_ARRAY]; /* more */
52 * This struct is used when CE_EXTENDED bit is 1
53 * The struct must match ondisk_cache_entry exactly from
54 * ctime till flags
56 struct ondisk_cache_entry_extended {
57 struct cache_time ctime;
58 struct cache_time mtime;
59 UINT32 dev;
60 UINT32 ino;
61 UINT32 mode;
62 UINT32 uid;
63 UINT32 gid;
64 UINT32 size;
65 BYTE sha1[20];
66 UINT16 flags;
67 UINT16 flags2;
68 char name[FLEX_ARRAY]; /* more */
71 #pragma pack(pop)
73 #define CE_NAMEMASK (0x0fff)
74 #define CE_STAGEMASK (0x3000)
75 #define CE_EXTENDED (0x4000)
76 #define CE_VALID (0x8000)
77 #define CE_STAGESHIFT 12
79 * Range 0xFFFF0000 in ce_flags is divided into
80 * two parts: in-memory flags and on-disk ones.
81 * Flags in CE_EXTENDED_FLAGS will get saved on-disk
82 * if you want to save a new flag, add it in
83 * CE_EXTENDED_FLAGS
85 * In-memory only flags
87 #define CE_UPDATE (0x10000)
88 #define CE_REMOVE (0x20000)
89 #define CE_UPTODATE (0x40000)
90 #define CE_ADDED (0x80000)
92 #define CE_HASHED (0x100000)
93 #define CE_UNHASHED (0x200000)
96 * Extended on-disk flags
98 #define CE_INTENT_TO_ADD 0x20000000
99 /* CE_EXTENDED2 is for future extension */
100 #define CE_EXTENDED2 0x80000000
102 #define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD)
105 * Safeguard to avoid saving wrong flags:
106 * - CE_EXTENDED2 won't get saved until its semantic is known
107 * - Bits in 0x0000FFFF have been saved in ce_flags already
108 * - Bits in 0x003F0000 are currently in-memory flags
110 #if CE_EXTENDED_FLAGS & 0x803FFFFF
111 #error "CE_EXTENDED_FLAGS out of range"
112 #endif
115 * Copy the sha1 and stat state of a cache entry from one to
116 * another. But we never change the name, or the hash state!
118 #define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)
120 template<class T>
121 T Big2lit(T data)
123 T ret;
124 BYTE *p1=(BYTE*)&data;
125 BYTE *p2=(BYTE*)&ret;
126 for(int i=0;i<sizeof(T);i++)
128 p2[sizeof(T)-i-1] = p1[i];
130 return ret;
133 template<class T>
134 static inline size_t ce_namelen(T *ce)
136 size_t len = Big2lit(ce->flags) & CE_NAMEMASK;
137 if (len < CE_NAMEMASK)
138 return len;
139 return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK;
142 #define flexible_size(STRUCT,len) ((offsetof(STRUCT,name) + (len) + 8) & ~7)
144 //#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
145 //#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
147 //#define ondisk_ce_size(ce) (((ce)->flags & CE_EXTENDED) ? \
148 // ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
149 // ondisk_cache_entry_size(ce_namelen(ce)))
151 template<class T>
152 static inline size_t ondisk_ce_size(T *ce)
154 return flexible_size(T,ce_namelen(ce));
157 class CGitIndex
159 public:
160 CString m_FileName;
161 __time64_t m_ModifyTime;
162 int m_Flags;
163 //int m_Status;
164 CGitHash m_IndexHash;
166 int FillData(ondisk_cache_entry* entry);
167 int FillData(ondisk_cache_entry_extended* entry);
168 int Print();
172 class CAutoReadLock
174 SharedMutex *m_Lock;
175 public:
176 CAutoReadLock(SharedMutex * lock)
178 m_Lock = lock;
179 lock->AcquireShared();
181 ~CAutoReadLock()
183 m_Lock->ReleaseShared();
187 class CAutoWriteLock
189 SharedMutex *m_Lock;
190 public:
191 CAutoWriteLock(SharedMutex * lock)
193 m_Lock = lock;
194 lock->AcquireExclusive();
196 ~CAutoWriteLock()
198 m_Lock->ReleaseExclusive();
202 class CGitIndexList:public std::vector<CGitIndex>
204 protected:
206 public:
207 std::map<CString,int> m_Map;
208 __time64_t m_LastModifyTime;
210 SharedMutex m_SharedMutex;
212 CGitIndexList();
213 int ReadIndex(CString file);
214 int GetStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL,CGitHash *pHash=NULL);
215 protected:
216 int GetFileStatus(CString &gitdir,CString &path, git_wc_status_kind * status,__int64 time,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL,CGitHash *pHash=NULL);
217 int GetDirStatus(CString &gitdir,CString &path, git_wc_status_kind * status,__int64 time,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL,CGitHash *pHash=NULL);
220 class CGitTreeItem
222 public:
223 CString m_FileName;
224 CGitHash m_Hash;
225 int m_Flags;
228 class CGitHeadFileList:public std::vector<CGitTreeItem>
230 private:
232 int GetPackRef(CString &gitdir);
234 public:
235 std::map<CString,int> m_Map;
236 __time64_t m_LastModifyTimeHead;
237 __time64_t m_LastModifyTimeRef;
238 __time64_t m_LastModifyTimePackRef;
240 CString m_HeadRefFile;
241 CGitHash m_Head;
242 CString m_HeadFile;
243 CString m_Gitdir;
244 CString m_PackRefFile;
246 SharedMutex m_SharedMutex;
248 std::map<CString,CGitHash> m_PackRefMap;
250 CGitHash m_TreeHash; /* buffered tree hash value */
252 CGitHeadFileList()
254 m_LastModifyTimeHead=0;
255 m_LastModifyTimeRef=0;
256 m_LastModifyTimePackRef = 0;
259 int ReadHeadHash(CString gitdir);
260 bool CheckHeadUpdate();
262 static int CallBack(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
263 int ReadTree();
266 class CGitHeadFileMap:public std::map<CString,CGitHeadFileList>
268 public:
270 SharedMutex m_SharedMutex;
272 CGitHeadFileMap(){ m_SharedMutex.Init(); }
273 ~CGitHeadFileMap() { m_SharedMutex.Release(); }
275 int GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL);
276 int CheckHeadUpdate(CString &gitdir);
277 int GetHeadHash(CString &gitdir, CGitHash &hash);
279 bool IsHashChanged(CString &gitdir)
281 CAutoReadLock lock(&m_SharedMutex);
282 if( find(gitdir) == end())
283 return false;
285 CAutoReadLock lock1(&(*this).m_SharedMutex);
286 return (*this)[gitdir].m_Head != (*this)[gitdir].m_TreeHash;
291 class CGitIndexFileMap:public std::map<CString,CGitIndexList>
293 public:
294 SharedMutex m_SharedMutex;
296 CGitIndexFileMap(){ m_SharedMutex.Init(); }
297 ~CGitIndexFileMap() { m_SharedMutex.Release(); }
299 int CheckAndUpdateIndex(CString &gitdir,bool *loaded=NULL);
301 int GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL,CGitHash *pHash=NULL);
303 int IsUnderVersionControl(CString &gitdir, CString &path, bool isDir,bool *isVersion);
306 class CGitIgnoreItem
308 public:
309 SharedMutex m_SharedMutex;
311 CGitIgnoreItem()
313 m_LastModifyTime =0;
314 m_pExcludeList =NULL;
316 ~CGitIgnoreItem()
318 if(m_pExcludeList)
319 git_free_exclude_list(m_pExcludeList);
320 m_pExcludeList=NULL;
322 __time64_t m_LastModifyTime;
323 CStringA m_BaseDir;
324 EXCLUDE_LIST m_pExcludeList;
325 int FetchIgnoreList(CString &projectroot, CString &file);
328 class CGitIgnoreList
330 private:
331 bool CheckFileChanged(CString &path);
332 int FetchIgnoreFile(CString &gitdir, CString &gitignore);
334 int CheckIgnore(CString &path,CString &root);
336 public:
337 SharedMutex m_SharedMutex;
339 CGitIgnoreList(){ m_SharedMutex.Init(); }
340 ~CGitIgnoreList() { m_SharedMutex.Release(); }
342 std::map<CString, CGitIgnoreItem> m_Map;
344 int GetIgnoreFileChangeTimeList(CString &dir, std::vector<__int64> &timelist);
345 bool CheckIgnoreChanged(CString &gitdir,CString &path);
346 int LoadAllIgnoreFile(CString &gitdir,CString &path);
347 bool IsIgnore(CString &path,CString &root);
350 template<class T>
351 int GetRangeInSortVector(T &vector,LPTSTR pstr,int len, int *start, int *end, int pos)
353 if( pos < 0)
355 return -1;
357 if(start == 0 || end == NULL)
358 return -1;
360 *start=*end=-1;
361 if( _tcsnccmp(vector[pos].m_FileName, pstr,len) != 0)
363 for(int i=0;i< vector.size();i++)
365 if( _tcsnccmp(vector[i].m_FileName, pstr,len) == 0 )
367 if(*start<0)
368 *start =i;
369 *end =i;
372 return -1;
373 }else
375 *start =0;
376 *end = vector.size();
378 for(int i=pos;i<vector.size();i++)
380 if( _tcsnccmp(vector[i].m_FileName, pstr,len) == 0 )
382 *end=i;
383 }else
385 break;
388 for(int i=pos;i>=0;i--)
390 if( _tcsnccmp(vector[i].m_FileName, pstr,len) == 0 )
392 *start=i;
393 }else
395 break;
399 return 0;
402 template<class T>
403 int SearchInSortVector(T &vector, LPTSTR pstr, int len)
405 int end=vector.size()-1;
406 int start = 0;
407 int mid = (start+end)/2;
409 if(vector.size() == 0)
410 return -1;
412 while(!( start == end && start==mid))
414 int cmp;
415 cmp = _tcsnccmp( vector[mid].m_FileName,pstr,len );
417 if(cmp ==0)
418 return mid;
420 if(cmp < 0)
422 start = mid+1;
425 if(cmp > 0)
427 end=mid;
429 mid=(start +end ) /2;
433 if(_tcsnccmp( vector[mid].m_FileName,pstr,len ) == 0)
434 return mid;
436 return -1;
438 #if 0
440 class CGitStatus
442 protected:
443 int GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL);
444 public:
445 CGitIgnoreList m_IgnoreList;
446 CGitHeadFileMap m_HeadFilesMap;
447 CGitIndexFileMap m_IndexFilesMap;
449 int GetStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL);
452 #endif