OSDN Git Service

give up save cache when m_GitDir is empty
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / GitLogCache.cpp
1 #include "stdafx.h"\r
2 #include "GitLogCache.h"\r
3 \r
4 CLogCache::CLogCache()\r
5 {\r
6 \r
7 }\r
8 \r
9 CLogCache::~CLogCache()\r
10 {\r
11         //this->m_IndexFile.Close();\r
12         //this->m_DataFile.Close();\r
13 }\r
14 int CLogCache::AddCacheEntry(GitRev &Rev)\r
15 {\r
16         this->m_HashMap[Rev.m_CommitHash] = Rev;\r
17         return 0;\r
18 }\r
19 \r
20 GitRev * CLogCache::GetCacheData(CGitHash &hash)\r
21 {\r
22         if(this->m_HashMapIndex.find(hash)==m_HashMapIndex.end())\r
23         {\r
24                 if(this->m_HashMap.IsExist(hash))\r
25                 {\r
26                         return &m_HashMap[hash];\r
27                 }\r
28                 m_HashMap[hash].m_CommitHash=hash;\r
29                 return &m_HashMap[hash];\r
30         }\r
31         else\r
32         {\r
33                 GitRev rev;\r
34                 if(!LoadOneItem(rev,m_HashMapIndex[hash]))\r
35                 {\r
36                         m_HashMap[hash].CopyFrom(rev);\r
37                         m_HashMap[hash].m_IsFull=true;\r
38                         \r
39                         return &m_HashMap[hash];\r
40                 }\r
41         }\r
42         m_HashMap[hash].m_CommitHash=hash;\r
43         return &m_HashMap[hash];\r
44 }\r
45 int CLogCache::FetchCacheIndex(CString GitDir)\r
46 {\r
47 \r
48         if(this->m_IndexFile.m_hFile == CFile::hFileNull)\r
49         {\r
50                 BOOL b=m_IndexFile.Open(GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
51                         CFile::modeRead|CFile::shareDenyNone|\r
52                         CFile::modeNoTruncate|CFile::modeCreate);\r
53                 if(!b)\r
54                         return -1;\r
55         }\r
56         //Cache has been fetched.\r
57         //if(m_GitDir == GitDir)\r
58         //      return 0;\r
59 \r
60         m_GitDir=GitDir;\r
61         m_IndexFile.SeekToBegin();\r
62 \r
63         SLogCacheIndexHeader header;\r
64         UINT count=m_IndexFile.Read(&header,sizeof(SLogCacheIndexHeader));\r
65         if(count != sizeof(SLogCacheIndexHeader))\r
66                 return -2;\r
67 \r
68         if( header.m_Magic != LOG_INDEX_MAGIC )\r
69                 return -3;\r
70 \r
71         if( header.m_Version != LOG_INDEX_VERSION )\r
72                 return -4;\r
73 \r
74 \r
75         SLogCacheItem Item;\r
76 \r
77         //for(int i=0;i<header.m_ItemCount;i++)\r
78         this->m_HashMapIndex.clear();\r
79 \r
80         while(1)\r
81         {\r
82                 count=m_IndexFile.Read(&Item,sizeof(SLogCacheItem));    \r
83                 if( count != sizeof(SLogCacheItem) )\r
84                         break;\r
85 \r
86                 this->m_HashMapIndex[Item.m_Hash]=Item.m_Offset;\r
87         }\r
88 \r
89         return 0;\r
90 }\r
91 \r
92 int CLogCache::SaveOneItem(GitRev &Rev,ULONGLONG offset)\r
93 {\r
94         \r
95         SLogCacheRevItemHeader header;\r
96         m_DataFile.Seek(offset,CFile::begin);\r
97 \r
98         if(this->m_DataFile.m_hFile == CFile::hFileNull)\r
99         {\r
100                 BOOL b=m_DataFile.Open(m_GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
101                         CFile::modeRead|CFile::shareDenyNone|\r
102                         CFile::modeNoTruncate|CFile::modeCreate);\r
103                 if(!b)\r
104                         return -1;\r
105         }\r
106 \r
107         header.m_Magic=LOG_DATA_ITEM_MAGIC;\r
108         header.m_Version=LOG_INDEX_VERSION;\r
109         header.m_FileCount=Rev.m_Files.GetCount();\r
110 \r
111         m_DataFile.Write(&header,sizeof(SLogCacheRevItemHeader));\r
112         \r
113         CArchive ar(&m_DataFile, CArchive::store);\r
114 \r
115         ar<<Rev.m_AuthorName;\r
116         ar<<Rev.m_AuthorEmail;\r
117         ar<<Rev.m_AuthorDate;\r
118         ar<<Rev.m_CommitterName;\r
119         ar<<Rev.m_CommitterEmail;\r
120         ar<<Rev.m_CommitterDate;\r
121         ar<<Rev.m_Subject;\r
122         ar<<Rev.m_Body;\r
123         ar<<Rev.m_CommitHash;\r
124         ar<<Rev.m_Action;\r
125 \r
126         for(int i=0;i<Rev.m_Files.GetCount();i++)\r
127         {\r
128                 SLogCacheRevFileHeader header;\r
129                 header.m_Magic=LOG_DATA_FILE_MAGIC;\r
130                 header.m_Version=LOG_INDEX_VERSION;\r
131 \r
132                 ar<<header.m_Magic;\r
133                 ar<<header.m_Version;\r
134                 ar<<Rev.m_Files[i].GetGitPathString();\r
135                 ar<<Rev.m_Files[i].GetGitOldPathString();\r
136                 ar<<Rev.m_Files[i].m_Action;\r
137                 ar<<Rev.m_Files[i].m_Stage;\r
138                 ar<<Rev.m_Files[i].m_StatAdd;\r
139                 ar<<Rev.m_Files[i].m_StatDel;\r
140                 \r
141         }\r
142         return 0;\r
143 }\r
144 \r
145 int CLogCache::LoadOneItem(GitRev &Rev,ULONGLONG offset)\r
146 {\r
147         SLogCacheRevItemHeader header;\r
148 \r
149         if(this->m_DataFile.m_hFile == CFile::hFileNull)\r
150         {\r
151                 BOOL b=m_DataFile.Open(m_GitDir+_T("\\.git\\")+DATA_FILE_NAME,\r
152                         CFile::modeRead|CFile::shareDenyNone|\r
153                         CFile::modeNoTruncate|CFile::modeCreate);\r
154                 if(!b)\r
155                         return -1;\r
156         }\r
157         m_DataFile.Seek(offset,CFile::begin);\r
158 \r
159         UINT count=m_DataFile.Read(&header,sizeof(SLogCacheRevItemHeader));\r
160         if( count != sizeof(SLogCacheRevItemHeader))\r
161                 return -1;\r
162         if( !CheckHeader(header))\r
163                 return -2;\r
164 \r
165 \r
166         CArchive ar(&m_DataFile, CArchive::load);\r
167 \r
168         ar>>Rev.m_AuthorName;\r
169         ar>>Rev.m_AuthorEmail;\r
170         ar>>Rev.m_AuthorDate;\r
171         ar>>Rev.m_CommitterName;\r
172         ar>>Rev.m_CommitterEmail;\r
173         ar>>Rev.m_CommitterDate;\r
174         ar>>Rev.m_Subject;\r
175         ar>>Rev.m_Body;\r
176         ar>>Rev.m_CommitHash;\r
177         ar>>Rev.m_Action;\r
178 \r
179         Rev.m_Files.Clear();\r
180 \r
181         for(int i=0;i<header.m_FileCount;i++)\r
182         {\r
183                 CTGitPath path;\r
184                 CString file,oldfile;\r
185                 path.Reset();\r
186                 SLogCacheRevFileHeader header;\r
187 \r
188                 ar>>header.m_Magic;\r
189                 ar>>header.m_Version;\r
190 \r
191                 if( this->CheckHeader(header) )\r
192                         return -1;\r
193                 ar>>file;\r
194                 ar>>oldfile;\r
195                 path.SetFromGit(file,&oldfile);\r
196 \r
197                 ar>>path.m_Action;\r
198                 ar>>path.m_Stage;\r
199                 ar>>path.m_StatAdd;\r
200                 ar>>path.m_StatDel;\r
201                 \r
202                 \r
203                 Rev.m_Files.AddPath(path);\r
204         }\r
205         return 0;\r
206 }\r
207 int CLogCache::RebuildCacheFile()\r
208 {\r
209         m_IndexFile.SetLength(0);\r
210         m_DataFile.SetLength(0);\r
211         {\r
212                 SLogCacheIndexHeader header;\r
213                 header.m_Magic=LOG_INDEX_MAGIC;\r
214                 header.m_Version=LOG_INDEX_VERSION;\r
215                 m_IndexFile.SeekToBegin();\r
216                 m_IndexFile.Write(&header,sizeof(SLogCacheIndexHeader));\r
217         }\r
218         \r
219         {\r
220                 SLogCacheRevFileHeader header;\r
221                 header.m_Magic=LOG_DATA_MAGIC;\r
222                 header.m_Version=LOG_INDEX_VERSION;\r
223 \r
224                 m_DataFile.SeekToBegin();\r
225                 m_DataFile.Write(&header,sizeof(SLogCacheRevFileHeader));\r
226         }\r
227         return 0;\r
228 }\r
229 int CLogCache::SaveCache()\r
230 {\r
231         if( this->m_HashMap.size() == 0 )\r
232                 return 0;\r
233 \r
234         if( this->m_GitDir.IsEmpty())\r
235                 return 0;\r
236 \r
237         bool bIsRebuild=false;\r
238         if(this->m_DataFile.m_hFile != CFile::hFileNull)\r
239                 m_DataFile.Close();\r
240         if(this->m_IndexFile.m_hFile!=CFile::hFileNull)\r
241                 m_IndexFile.Close();\r
242 \r
243         if(this->m_IndexFile.m_hFile == CFile::hFileNull)\r
244         {\r
245                 BOOL b=m_IndexFile.Open(m_GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
246                         CFile::modeReadWrite|CFile::shareDenyWrite|\r
247                         CFile::modeNoTruncate|CFile::modeCreate);\r
248                 if(!b)\r
249                         return -1;\r
250         }\r
251 \r
252         if(this->m_DataFile.m_hFile == CFile::hFileNull)\r
253         {\r
254                 BOOL b=m_DataFile.Open(m_GitDir+_T("\\.git\\")+DATA_FILE_NAME,\r
255                         CFile::modeReadWrite|CFile::shareDenyWrite|\r
256                         CFile::modeNoTruncate|CFile::modeCreate);\r
257 \r
258                 \r
259                 if(!b)\r
260                 {\r
261                         m_IndexFile.Close();\r
262                         return -1;\r
263                 }\r
264         }\r
265 \r
266         {\r
267                 SLogCacheIndexHeader header;\r
268                 memset(&header,0,sizeof(SLogCacheIndexHeader));\r
269                 UINT count=m_IndexFile.Read(&header,sizeof(SLogCacheIndexHeader));\r
270                 if(count != sizeof(SLogCacheIndexHeader) || !this->CheckHeader(header))\r
271                 {// new file\r
272                         RebuildCacheFile();\r
273                         bIsRebuild=true;\r
274                 }\r
275         }\r
276 \r
277         {\r
278 \r
279                 SLogCacheRevFileHeader header;\r
280         \r
281                 UINT count=m_DataFile.Read(&header,sizeof(SLogCacheRevFileHeader));\r
282                 if( count != sizeof(SLogCacheRevFileHeader) || !CheckHeader(header))\r
283                 {\r
284                         RebuildCacheFile();\r
285                         bIsRebuild=true;\r
286                 }\r
287         \r
288         }\r
289 \r
290         m_DataFile.SeekToEnd();\r
291         m_IndexFile.SeekToEnd();\r
292         CGitHashMap::iterator i;\r
293         for(i=m_HashMap.begin();i!=m_HashMap.end();i++)\r
294         {\r
295                 if(this->m_HashMapIndex.find((*i).second.m_CommitHash) == m_HashMapIndex.end() || bIsRebuild)\r
296                 {\r
297                         if((*i).second.m_IsFull && !(*i).second.m_CommitHash.IsEmpty())\r
298                         {\r
299                                 ULONGLONG offset = m_DataFile.GetPosition();\r
300                                 this->SaveOneItem((*i).second,offset);\r
301 \r
302                                 SLogCacheItem item;\r
303                                 item.m_Hash = (*i).second.m_CommitHash;\r
304                                 item.m_Offset=offset;\r
305 \r
306                                 m_IndexFile.Write(&item,sizeof(SLogCacheItem));\r
307                         }\r
308                 }\r
309         }\r
310         m_IndexFile.Close();\r
311         m_DataFile.Close();\r
312         return 0;\r
313 }\r
314 \r
315 int CLogCache::ClearAllParent()\r
316 {\r
317         CGitHashMap::iterator i;\r
318         for(i=m_HashMap.begin();i!=m_HashMap.end();i++)\r
319         {\r
320                 (*i).second.m_ParentHash.clear();\r
321                 (*i).second.m_Lanes.clear();\r
322         }\r
323         return 0;\r
324 }