OSDN Git Service

f9ddc4fe578c92af4ac57dc30d08e6d335e209c4
[tortoisegit/TortoiseGitJp.git] / src / Git / GitRev.cpp
1 #include "StdAfx.h"\r
2 #include "GitRev.h"\r
3 #include "Git.h"\r
4 \r
5 class CException; //Just in case afx.h is not included (cannot be included in every project which uses this file)\r
6 \r
7 // provide an ASSERT macro for when compiled without MFC\r
8 #if !defined ASSERT\r
9         // Don't use _asm here, it isn't supported by x64 version of compiler. In fact, MFC's ASSERT() is the same with _ASSERTE().\r
10         #define ASSERT(x) _ASSERTE(x)\r
11 #endif\r
12 \r
13 \r
14 GitRev::GitRev(void)\r
15 {\r
16         m_Action=0;\r
17         m_IsFull = 0;\r
18         m_IsUpdateing = 0;\r
19         // fetch local machine timezone info\r
20         if ( GetTimeZoneInformation( &m_TimeZone ) == TIME_ZONE_ID_INVALID )\r
21         {\r
22                 ASSERT(false);\r
23         }\r
24 }\r
25 \r
26 GitRev::~GitRev(void)\r
27 {\r
28 }\r
29 \r
30 #if 0\r
31 GitRev::GitRev(GitRev & rev)\r
32 {\r
33 }\r
34 GitRev& GitRev::operator=(GitRev &rev)\r
35 {\r
36         return *this;\r
37 }\r
38 #endif\r
39 void GitRev::Clear()\r
40 {\r
41         this->m_Action=0;\r
42         this->m_Files.Clear();\r
43         this->m_Action=0;\r
44         this->m_ParentHash.clear();\r
45         m_CommitterName.Empty();\r
46         m_CommitterEmail.Empty();\r
47         m_Body.Empty();\r
48         m_Subject.Empty();\r
49         m_CommitHash.Empty();\r
50         m_Mark=0;\r
51 \r
52 }\r
53 int GitRev::CopyFrom(GitRev &rev,bool OmitParentAndMark)\r
54 {\r
55         m_AuthorName    =rev.m_AuthorName       ;\r
56         m_AuthorEmail   =rev.m_AuthorEmail      ;\r
57         m_AuthorDate    =rev.m_AuthorDate       ;\r
58         m_CommitterName =rev.m_CommitterName    ;\r
59         m_CommitterEmail=rev.m_CommitterEmail;\r
60         m_CommitterDate =rev.m_CommitterDate    ;\r
61         m_Subject               =rev.m_Subject          ;\r
62         m_Body                  =rev.m_Body                     ;\r
63         m_CommitHash    =rev.m_CommitHash       ;\r
64         m_Files                 =rev.m_Files                    ;       \r
65         m_Action                =rev.m_Action           ;\r
66 \r
67         if(!OmitParentAndMark)\r
68         {\r
69                 m_ParentHash    =rev.m_ParentHash       ;\r
70                 m_Mark                  =rev.m_Mark;\r
71         }\r
72         return 0;\r
73 }\r
74 int GitRev::ParserFromLog(BYTE_VECTOR &log,int start)\r
75 {\r
76         int pos=start;\r
77         CString one;\r
78         CString key;\r
79         CString text;\r
80         BYTE_VECTOR filelist;\r
81         BYTE mode=0;\r
82         CTGitPath  path;\r
83         this->m_Files.Clear();\r
84     m_Action=0;\r
85         int begintime=0;\r
86         int filebegin=-1;\r
87 \r
88         while( pos < log.size() && pos>=0)\r
89         {\r
90                 \r
91                 //one=log.Tokenize(_T("\n"),pos);\r
92                 if(log[pos]==_T('#') && log[pos+1] == _T('<') && log[pos+3] == _T('>'))\r
93                 {\r
94                         //text = one.Right(one.GetLength()-4);\r
95                         text.Empty();\r
96                         g_Git.StringAppend(&text,&log[pos+4],CP_UTF8);\r
97                         mode = log[pos+2];\r
98                         \r
99                         switch(mode)\r
100                         {\r
101                         case LOG_REV_ITEM_BEGIN:\r
102                                 begintime++;\r
103                                 if(begintime>1)\r
104                                         break;\r
105                                 else\r
106                                         this->Clear();\r
107                                 break;\r
108                         case LOG_REV_AUTHOR_NAME:\r
109                                 this->m_AuthorName = text;\r
110                                 break;\r
111                         case LOG_REV_AUTHOR_EMAIL:\r
112                                 this->m_AuthorEmail = text;\r
113                                 break;\r
114                         case LOG_REV_AUTHOR_DATE:\r
115                                 this->m_AuthorDate =ConverFromString(text);\r
116                                 break;\r
117                         case LOG_REV_COMMIT_NAME:\r
118                                 this->m_CommitterName = text;\r
119                                 break;\r
120                         case LOG_REV_COMMIT_EMAIL:\r
121                                 this->m_CommitterEmail = text;\r
122                                 break;\r
123                         case LOG_REV_COMMIT_DATE:\r
124                                 this->m_CommitterDate =ConverFromString(text);\r
125                                 break;\r
126                         case LOG_REV_COMMIT_SUBJECT:\r
127                                 this->m_Subject = text;\r
128                                 break;\r
129                         case LOG_REV_COMMIT_BODY:\r
130                                 this->m_Body = text +_T("\n");\r
131                                 break;\r
132                         case LOG_REV_COMMIT_HASH:\r
133                                 this->m_CommitHash = text.Right(40);\r
134                                 if(text.GetLength()>40)\r
135                                 {\r
136                                         this->m_Mark=text[0];\r
137                                 }\r
138                                 break;\r
139                         case LOG_REV_COMMIT_PARENT:\r
140                                 while(text.GetLength()>0)\r
141                                 {\r
142                                         this->m_ParentHash.insert(this->m_ParentHash.end(),text.Left(40));\r
143                                         if(text.GetLength()>40)\r
144                                                 text=text.Right(text.GetLength()-41);\r
145                                         else\r
146                                                 break;\r
147                                 }\r
148                                 if(m_ParentHash.size()>1)\r
149                                 {\r
150                                         int a=1;\r
151                                 }\r
152                                 break;\r
153                         case LOG_REV_COMMIT_FILE:\r
154                                 break;\r
155                         }\r
156                 }else\r
157                 {\r
158                         switch(mode)\r
159                         {\r
160 //                      case LOG_REV_COMMIT_BODY:\r
161 //                              this->m_Body += one+_T("\n");\r
162 //                              break;\r
163                         case LOG_REV_COMMIT_FILE:\r
164                                 //filelist += one +_T("\n");\r
165                                 //filelist.append(log,pos,log.find(0,pos));\r
166                                 if(filebegin<0)\r
167                                         filebegin=pos;\r
168                                 break;\r
169                         }\r
170                 }\r
171                 \r
172                 if(begintime>1)\r
173                 {\r
174                         break;\r
175                 }\r
176 \r
177                 //find next string start \r
178                 pos=log.findNextString(pos);\r
179         }\r
180         \r
181         if(filebegin>=0)\r
182         {\r
183                 \r
184                 filelist.append(log,filebegin,pos);     \r
185                 this->m_Files.ParserFromLog(filelist);\r
186                 this->m_Action=this->m_Files.GetAction();\r
187         }\r
188         return pos;\r
189 }\r
190 \r
191 CTime GitRev::ConverFromString(CString input)\r
192 {\r
193         // pick up date from string\r
194         try\r
195         {\r
196                 CTime tm(_wtoi(input.Mid(0,4)),\r
197                                  _wtoi(input.Mid(5,2)),\r
198                                  _wtoi(input.Mid(8,2)),\r
199                                  _wtoi(input.Mid(11,2)),\r
200                                  _wtoi(input.Mid(14,2)),\r
201                                  _wtoi(input.Mid(17,2)),\r
202                                  0);\r
203                 if(tm.GetTime()<=1)\r
204                         return CTime();//Error parsing time-string\r
205 \r
206                 // pick up utc offset\r
207                 CString sign = input.Mid(20,1);         // + or -\r
208                 int hoursOffset =  _wtoi(input.Mid(21,2));\r
209                 int minsOffset = _wtoi(input.Mid(23,2));\r
210                 if ( sign == "-" )\r
211                 {\r
212                         hoursOffset = -hoursOffset;\r
213                         minsOffset = -minsOffset;\r
214                 }\r
215                 // make a timespan object with this value\r
216                 CTimeSpan offset( 0, hoursOffset, minsOffset, 0 );\r
217                 // we have to subtract this from the time given to get UTC\r
218                 tm -= offset;\r
219                 // get local timezone\r
220                 SYSTEMTIME sysTime;\r
221                 tm.GetAsSystemTime( sysTime );\r
222                 SYSTEMTIME local;\r
223                 if ( SystemTimeToTzSpecificLocalTime( &m_TimeZone, &sysTime, &local ) )\r
224                 {\r
225                         sysTime = local;\r
226                 }\r
227                 else\r
228                 {\r
229                         ASSERT(false);\r
230                 }\r
231                 tm = CTime( sysTime, 0 );\r
232                 return tm;\r
233         }\r
234         catch(CException* e)\r
235         {\r
236                 //Probably the date was something like 1970-01-01 00:00:00. _mktime64() doesnt like this.\r
237                 //Dont let the application crash on this exception\r
238 \r
239 #ifdef _AFX //CException classes are only defined when afx.h is included.\r
240                         //When afx.h is not included, the exception is leaked.\r
241                         //This will probably never happen because when CException is not defined, it cannot be thrown.\r
242                 e->Delete();\r
243 #endif //ifdef _AFX\r
244         }\r
245         return CTime(); //Return an invalid time\r
246 }\r
247 \r
248 int GitRev::SafeFetchFullInfo(CGit *git)\r
249 {\r
250         if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)\r
251         {\r
252                 //GitRev rev;\r
253                 BYTE_VECTOR onelog;\r
254                 TCHAR oldmark=this->m_Mark;\r
255         \r
256                 git->GetLog(onelog,m_CommitHash,NULL,1,CGit::LOG_INFO_STAT|CGit::LOG_INFO_FILESTATE|CGit::LOG_INFO_DETECT_COPYRENAME|CGit::LOG_INFO_SHOW_MERGEDFILE);\r
257                 CString oldhash=m_CommitHash;\r
258                 GIT_REV_LIST oldlist=this->m_ParentHash;\r
259                 ParserFromLog(onelog);\r
260                 \r
261                 //ASSERT(oldhash==m_CommitHash);\r
262                 if(oldmark!=0)\r
263                         this->m_Mark=oldmark;  //parser full log will cause old mark overwrited. \r
264                                                                //So we need keep old bound mark.\r
265                 this->m_ParentHash=oldlist;\r
266                 InterlockedExchange(&m_IsUpdateing,FALSE);\r
267                 InterlockedExchange(&m_IsFull,TRUE);\r
268                 return 0;\r
269         }\r
270         return -1;\r
271 }