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