4 #include "SharedMutex.h"
6 /* Copy from Git cache.h*/
12 #define CACHE_SIGNATURE 0x44495243 /* "DIRC" */
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.
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
;
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
56 struct ondisk_cache_entry_extended
{
57 struct cache_time ctime
;
58 struct cache_time mtime
;
68 char name
[FLEX_ARRAY
]; /* more */
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
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"
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)
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
];
134 static inline size_t ce_namelen(T
*ce
)
136 size_t len
= Big2lit(ce
->flags
) & CE_NAMEMASK
;
137 if (len
< CE_NAMEMASK
)
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)))
152 static inline size_t ondisk_ce_size(T
*ce
)
154 return flexible_size(T
,ce_namelen(ce
));
161 __time64_t m_ModifyTime
;
164 CGitHash m_IndexHash
;
166 int FillData(ondisk_cache_entry
* entry
);
167 int FillData(ondisk_cache_entry_extended
* entry
);
176 CAutoReadLock(SharedMutex
* lock
)
179 lock
->AcquireShared();
183 m_Lock
->ReleaseShared();
191 CAutoWriteLock(SharedMutex
* lock
)
194 lock
->AcquireExclusive();
198 m_Lock
->ReleaseExclusive();
202 class CGitIndexList
:public std::vector
<CGitIndex
>
207 __time64_t m_LastModifyTime
;
210 int ReadIndex(CString file
);
211 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
);
213 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
);
214 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
);
217 typedef std::tr1::shared_ptr
<CGitIndexList
> SHARED_INDEX_PTR
;
218 typedef CComCritSecLock
<CComCriticalSection
> CAutoLocker
;
220 class CGitIndexFileMap
:public std::map
<CString
, SHARED_INDEX_PTR
>
223 CComCriticalSection m_critGitDllSec
;
225 CGitIndexFileMap() { m_critGitDllSec
.Init(); }
226 ~CGitIndexFileMap() { m_critGitDllSec
.Term(); }
228 SHARED_INDEX_PTR
SafeGet(const CString
&path
)
230 CAutoLocker
lock(m_critGitDllSec
);
231 if(this->find(path
) == end())
232 return SHARED_INDEX_PTR();
234 return (*this)[path
];
237 void SafeSet(const CString
&path
, SHARED_INDEX_PTR ptr
)
239 CAutoLocker
lock(m_critGitDllSec
);
243 int Check(const CString
&gitdir
, bool *isChanged
);
244 int LoadIndex(const CString
&gitdir
);
246 void CheckAndUpdate(const CString
&gitdir
,bool isLoadUpdatedIndex
)
248 bool isChanged
=false;
249 if(isLoadUpdatedIndex
&& Check(gitdir
,&isChanged
))
252 if(isChanged
&& isLoadUpdatedIndex
)
255 int GetFileStatus(const CString
&gitdir
,const CString
&path
,git_wc_status_kind
* status
,
256 BOOL IsFull
=false, BOOL IsRecursive
=false,
257 FIll_STATUS_CALLBACK callback
=NULL
,
258 void *pData
=NULL
,CGitHash
*pHash
=NULL
,
259 bool isLoadUpdatedIndex
=true);
261 int IsUnderVersionControl(const CString
&gitdir
,
265 bool isLoadUpdateIndex
=true);
277 class CGitHeadFileList
:public std::vector
<CGitTreeItem
>
281 int GetPackRef(const CString
&gitdir
);
284 std::map
<CString
,int> m_Map
;
285 __time64_t m_LastModifyTimeHead
;
286 __time64_t m_LastModifyTimeRef
;
287 __time64_t m_LastModifyTimePackRef
;
289 CString m_HeadRefFile
;
293 CString m_PackRefFile
;
295 SharedMutex m_SharedMutex
;
297 std::map
<CString
,CGitHash
> m_PackRefMap
;
299 CGitHash m_TreeHash
; /* buffered tree hash value */
303 m_LastModifyTimeHead
=0;
304 m_LastModifyTimeRef
=0;
305 m_LastModifyTimePackRef
= 0;
308 int ReadHeadHash(CString gitdir
);
309 bool CheckHeadUpdate();
311 static int CallBack(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
315 class CGitHeadFileMap
:public std::map
<CString
,CGitHeadFileList
>
319 SharedMutex m_SharedMutex
;
321 CGitHeadFileMap(){ m_SharedMutex
.Init(); }
322 ~CGitHeadFileMap() { m_SharedMutex
.Release(); }
324 int GetFileStatus(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
);
325 int CheckHeadUpdate(const CString
&gitdir
);
326 int GetHeadHash(const CString
&gitdir
, CGitHash
&hash
);
328 bool IsHashChanged(const CString
&gitdir
)
330 CAutoReadLock
lock(&m_SharedMutex
);
331 if( find(gitdir
) == end())
334 CAutoReadLock
lock1(&(*this).m_SharedMutex
);
335 return (*this)[gitdir
].m_Head
!= (*this)[gitdir
].m_TreeHash
;
344 SharedMutex m_SharedMutex
;
349 m_pExcludeList
=NULL
;
354 git_free_exclude_list(m_pExcludeList
);
357 __time64_t m_LastModifyTime
;
359 EXCLUDE_LIST m_pExcludeList
;
360 int FetchIgnoreList(const CString
&projectroot
, const CString
&file
);
366 bool CheckFileChanged(const CString
&path
);
367 int FetchIgnoreFile(const CString
&gitdir
, const CString
&gitignore
);
369 int CheckIgnore(const CString
&path
,const CString
&root
);
372 SharedMutex m_SharedMutex
;
374 CGitIgnoreList(){ m_SharedMutex
.Init(); }
375 ~CGitIgnoreList() { m_SharedMutex
.Release(); }
377 std::map
<CString
, CGitIgnoreItem
> m_Map
;
379 int GetIgnoreFileChangeTimeList(const CString
&dir
, std::vector
<__int64
> &timelist
);
380 bool CheckIgnoreChanged(const CString
&gitdir
,const CString
&path
);
381 int LoadAllIgnoreFile(const CString
&gitdir
,const CString
&path
);
382 bool IsIgnore(const CString
&path
,const CString
&root
);
386 int GetRangeInSortVector(T
&vector
,LPTSTR pstr
,int len
, int *start
, int *end
, int pos
)
392 if(start
== 0 || end
== NULL
)
396 if( _tcsnccmp(vector
[pos
].m_FileName
, pstr
,len
) != 0)
398 for(int i
=0;i
< vector
.size();i
++)
400 if( _tcsnccmp(vector
[i
].m_FileName
, pstr
,len
) == 0 )
411 *end
= vector
.size();
413 for(int i
=pos
;i
<vector
.size();i
++)
415 if( _tcsnccmp(vector
[i
].m_FileName
, pstr
,len
) == 0 )
423 for(int i
=pos
;i
>=0;i
--)
425 if( _tcsnccmp(vector
[i
].m_FileName
, pstr
,len
) == 0 )
438 int SearchInSortVector(T
&vector
, LPTSTR pstr
, int len
)
440 int end
=vector
.size()-1;
442 int mid
= (start
+end
)/2;
444 if(vector
.size() == 0)
447 while(!( start
== end
&& start
==mid
))
450 cmp
= _tcsnccmp( vector
[mid
].m_FileName
,pstr
,len
);
464 mid
=(start
+end
) /2;
468 if(_tcsnccmp( vector
[mid
].m_FileName
,pstr
,len
) == 0)
478 int GetFileStatus(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
);
480 CGitIgnoreList m_IgnoreList
;
481 CGitHeadFileMap m_HeadFilesMap
;
482 CGitIndexFileMap m_IndexFilesMap
;
484 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
);