OSDN Git Service

Merge Myagi exe shell version to show overlay
[tortoisegit/TortoiseGitJp.git] / src / Git / GitIndex.cpp
1 #include "StdAfx.h"\r
2 #include "Git.h"\r
3 #include "atlconv.h"\r
4 #include "GitRev.h"\r
5 #include "registry.h"\r
6 #include "GitConfig.h"\r
7 #include <map>\r
8 #include "UnicodeUtils.h"\r
9 #include "TGitPath.h"\r
10 #include "gitindex.h"\r
11 #include <sys/types.h> \r
12 #include <sys/stat.h>\r
13 \r
14 #define FILL_DATA() \\r
15         m_FileName.Empty();\\r
16         g_Git.StringAppend(&m_FileName,(BYTE*)entry->name,CP_OEMCP,Big2lit(entry->flags)&CE_NAMEMASK);\\r
17         m_FileName.Replace(_T('/'),_T('\\'));\\r
18         this->m_Flags=Big2lit(entry->flags);\\r
19         this->m_ModifyTime=Big2lit(entry->mtime.sec);\r
20         \r
21 int CGitIndex::FillData(ondisk_cache_entry * entry)\r
22 {\r
23         FILL_DATA();\r
24         return 0;\r
25 }\r
26 \r
27 int CGitIndex::FillData(ondisk_cache_entry_extended * entry)\r
28 {\r
29         FILL_DATA();\r
30         this->m_Flags |= ((int)Big2lit(entry->flags2))<<16;\r
31         return 0;\r
32 }\r
33 \r
34 CGitIndexList::CGitIndexList()\r
35 {\r
36         this->m_LastModifyTime=0;\r
37 }\r
38 \r
39 int CGitIndexList::ReadIndex(CString IndexFile)\r
40 {\r
41         HANDLE hfile=0;\r
42         int ret=0;\r
43         BYTE *buffer=NULL,*p;\r
44         CGitIndex GitIndex;\r
45 \r
46         try\r
47         {\r
48                 do\r
49                 {\r
50                         this->clear();\r
51                         this->m_Map.clear();\r
52 \r
53                         hfile = CreateFile(IndexFile,\r
54                                                                         GENERIC_READ,\r
55                                                                         FILE_SHARE_READ,\r
56                                                                         NULL,\r
57                                                                         OPEN_EXISTING,\r
58                                                                         FILE_ATTRIBUTE_NORMAL,\r
59                                                                         NULL);\r
60 \r
61 \r
62                         if(hfile == INVALID_HANDLE_VALUE)\r
63                         {\r
64                                 ret = -1 ;\r
65                                 break;\r
66                         }\r
67 \r
68                         cache_header *header;\r
69                         DWORD size=0,filesize=0;\r
70                         \r
71                         filesize=GetFileSize(hfile,NULL);\r
72 \r
73                         if(filesize == INVALID_FILE_SIZE )\r
74                         {\r
75                                 ret =-1;\r
76                                 break;\r
77                         }\r
78 \r
79                         buffer = new BYTE[filesize];\r
80                         p=buffer;\r
81                         if(buffer == NULL)\r
82                         {\r
83                                 ret = -1;\r
84                                 break;\r
85                         }\r
86                         if(! ReadFile( hfile, buffer,filesize,&size,NULL) )\r
87                         {\r
88                                 ret = GetLastError();\r
89                                 break;\r
90                         }\r
91 \r
92                         if (size != filesize)\r
93                         {\r
94                                 ret = -1;\r
95                                 break;\r
96                         }\r
97                         header = (cache_header *) buffer;\r
98                         if( Big2lit(header->hdr_signature) != CACHE_SIGNATURE )\r
99                         {\r
100                                 ret = -1;\r
101                                 break;\r
102                         }\r
103                         p+= sizeof(cache_header);\r
104 \r
105                         int entries = Big2lit(header->hdr_entries);\r
106                         for(int i=0;i<entries;i++)\r
107                         {\r
108                                 ondisk_cache_entry *entry;\r
109                                 ondisk_cache_entry_extended *entryex;\r
110                                 entry=(ondisk_cache_entry*)p;\r
111                                 entryex=(ondisk_cache_entry_extended*)p;\r
112                                 int flags=Big2lit(entry->flags);\r
113                                 if( flags & CE_EXTENDED)\r
114                                 {\r
115                                         GitIndex.FillData(entryex);\r
116                                         p+=ondisk_ce_size(entryex);\r
117 \r
118                                 }else\r
119                                 {\r
120                                         GitIndex.FillData(entry);\r
121                                         p+=ondisk_ce_size(entry);\r
122                                 }\r
123                                 \r
124                                 if(p>buffer+filesize)\r
125                                 {\r
126                                         ret = -1;\r
127                                         break;\r
128                                 }\r
129                                 this->push_back(GitIndex);\r
130                                 this->m_Map[GitIndex.m_FileName]=this->size()-1;\r
131 \r
132                         }\r
133                 }while(0);\r
134         }catch(...)\r
135         {\r
136                 ret= -1;\r
137         }\r
138 \r
139         if(hfile != INVALID_HANDLE_VALUE)\r
140                 CloseHandle(hfile);\r
141         if(buffer)\r
142                 delete buffer;\r
143         return ret;\r
144 }\r
145 \r
146 int CGitIndexList::GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind *status,struct __stat64 &buf,FIll_STATUS_CALLBACK callback,void *pData)\r
147 {\r
148 \r
149         if(status)\r
150         {\r
151                 if(m_Map.find(path) == m_Map.end() )\r
152                 {\r
153                         *status = git_wc_status_unversioned;\r
154                 }else\r
155                 {\r
156                         int index = m_Map[path];\r
157                         if(index <0)\r
158                                 return -1;\r
159                         if(index >= size() )\r
160                                 return -1;\r
161                 \r
162                         if( buf.st_mtime ==  at(index).m_ModifyTime )\r
163                         {\r
164                                 *status = git_wc_status_normal;\r
165                         }else\r
166                         {\r
167                                 *status = git_wc_status_modified;\r
168                         }\r
169 \r
170                         if(at(index).m_Flags & CE_STAGEMASK )\r
171                                 *status = git_wc_status_conflicted;\r
172                         else if(at(index).m_Flags & CE_INTENT_TO_ADD)\r
173                                 *status = git_wc_status_added;\r
174 \r
175                 }\r
176                 if(callback)\r
177                         callback(gitdir+_T("\\")+path,*status,pData);\r
178         }\r
179         return 0;\r
180 }\r
181 \r
182 int CGitIndexList::GetStatus(CString &gitdir,CString &path, git_wc_status_kind *status,\r
183                                                          BOOL IsFull, BOOL IsRecursive,\r
184                                                          FIll_STATUS_CALLBACK callback,void *pData)\r
185 {\r
186         int result;\r
187         struct __stat64 buf;\r
188         git_wc_status_kind dirstatus = git_wc_status_none;\r
189         if(status)\r
190         {\r
191                 if(path.IsEmpty())\r
192                         result = _tstat64( gitdir, &buf );\r
193                 else\r
194                         result = _tstat64( gitdir+_T("\\")+path, &buf );\r
195 \r
196                 if(result)\r
197                         return -1;\r
198 \r
199                 if(buf.st_mode & _S_IFDIR)\r
200                 {\r
201                         if(!path.IsEmpty())\r
202                         {\r
203                                 if( path.Right(1) != _T("\\"))\r
204                                         path+=_T("\\");\r
205                         }\r
206                         int len =path.GetLength();\r
207 \r
208                         for(int i=0;i<size();i++)\r
209                         {\r
210                                 if( at(i).m_FileName.GetLength() > len )\r
211                                 {\r
212                                         if(at(i).m_FileName.Left(len) == path)\r
213                                         {\r
214                                                 if( !IsFull )\r
215                                                 {\r
216                                                         *status = git_wc_status_normal; \r
217                                                         if(callback)\r
218                                                                 callback(gitdir+_T("\\")+path,*status,pData);\r
219                                                         return 0;\r
220 \r
221                                                 }else\r
222                                                 {       \r
223                                                         result = _tstat64( gitdir+_T("\\")+at(i).m_FileName, &buf );\r
224                                                         if(result)\r
225                                                                 continue;\r
226                                                         \r
227                                                         *status = git_wc_status_none;\r
228                                                         GetFileStatus(gitdir,at(i).m_FileName,status,buf,callback,pData);\r
229                                                         if( *status != git_wc_status_none )\r
230                                                         {\r
231                                                                 if( dirstatus == git_wc_status_none)\r
232                                                                 {\r
233                                                                         dirstatus = git_wc_status_normal;\r
234                                                                 }\r
235                                                                 if( *status != git_wc_status_normal )\r
236                                                                 {\r
237                                                                         dirstatus = git_wc_status_modified;\r
238                                                                 }\r
239                                                         }\r
240                                                         \r
241                                                 }\r
242                                         }\r
243                                 }\r
244                         }\r
245 \r
246                         if( dirstatus != git_wc_status_none )\r
247                         {\r
248                                 *status = dirstatus;\r
249                         }\r
250                         else\r
251                         {\r
252                                 *status = git_wc_status_unversioned;\r
253                         }\r
254                         if(callback)\r
255                                 callback(gitdir+_T("\\")+path,*status,pData);\r
256                                                         \r
257                         return 0;\r
258 \r
259                 }else\r
260                 {\r
261                         GetFileStatus(gitdir,path,status,buf,callback,pData);\r
262                 }\r
263         }       \r
264         return 0;\r
265 }\r
266 \r
267 int CGitIndexFileMap::GetFileStatus(CString &gitdir, CString &path, git_wc_status_kind *status,BOOL IsFull, BOOL IsRecursive,\r
268                                                                         FIll_STATUS_CALLBACK callback,void *pData)\r
269 {\r
270         struct __stat64 buf;\r
271         int result;\r
272         try\r
273         {\r
274                 CString IndexFile;\r
275                 IndexFile=gitdir+_T("\\.git\\index");\r
276                 /* Get data associated with "crt_stat.c": */\r
277                 result = _tstat64( IndexFile, &buf );\r
278 \r
279 //              WIN32_FILE_ATTRIBUTE_DATA FileInfo;\r
280 //              GetFileAttributesEx(_T("D:\\tortoisegit\\src\\gpl.txt"),GetFileExInfoStandard,&FileInfo);\r
281 //              result = _tstat64( _T("D:\\tortoisegit\\src\\gpl.txt"), &buf );\r
282 \r
283                 if(result)\r
284                    return result;\r
285 \r
286                 if((*this)[IndexFile].m_LastModifyTime != buf.st_mtime )\r
287                 {\r
288                         if((*this)[IndexFile].ReadIndex(IndexFile))\r
289                                 return -1;\r
290                 }\r
291                 (*this)[IndexFile].m_LastModifyTime = buf.st_mtime;\r
292 \r
293                 (*this)[IndexFile].GetStatus(gitdir,path,status,IsFull,IsRecursive,callback,pData);\r
294                                 \r
295         }catch(...)\r
296         {\r
297                 return -1;\r
298         }\r
299         return 0;\r
300 }