2 #include "ATLComTime.h"
\r
7 class CException; //Just in case afx.h is not included (cannot be included in every project which uses this file)
\r
9 // provide an ASSERT macro for when compiled without MFC
\r
11 // 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
12 #define ASSERT(x) _ASSERTE(x)
\r
16 GitRev::GitRev(void)
\r
21 // fetch local machine timezone info
\r
22 if ( GetTimeZoneInformation( &m_TimeZone ) == TIME_ZONE_ID_INVALID )
\r
28 GitRev::~GitRev(void)
\r
33 GitRev::GitRev(GitRev & rev)
\r
36 GitRev& GitRev::operator=(GitRev &rev)
\r
41 void GitRev::Clear()
\r
44 this->m_Files.Clear();
\r
46 this->m_ParentHash.clear();
\r
47 m_CommitterName.Empty();
\r
48 m_CommitterEmail.Empty();
\r
51 m_CommitHash.Empty();
\r
53 m_RefAction.Empty();
\r
57 int GitRev::CopyFrom(GitRev &rev,bool OmitParentAndMark)
\r
59 m_AuthorName =rev.m_AuthorName ;
\r
60 m_AuthorEmail =rev.m_AuthorEmail ;
\r
61 m_AuthorDate =rev.m_AuthorDate ;
\r
62 m_CommitterName =rev.m_CommitterName ;
\r
63 m_CommitterEmail=rev.m_CommitterEmail;
\r
64 m_CommitterDate =rev.m_CommitterDate ;
\r
65 m_Subject =rev.m_Subject ;
\r
66 m_Body =rev.m_Body ;
\r
67 m_CommitHash =rev.m_CommitHash ;
\r
68 m_Files =rev.m_Files ;
\r
69 m_Action =rev.m_Action ;
\r
70 m_IsFull =rev.m_IsFull;
\r
72 if(!OmitParentAndMark)
\r
74 m_ParentHash =rev.m_ParentHash ;
\r
79 int GitRev::ParserFromLog(BYTE_VECTOR &log,int start)
\r
85 BYTE_VECTOR filelist;
\r
88 this->m_Files.Clear();
\r
93 while( pos < log.size() && pos>=0)
\r
96 //one=log.Tokenize(_T("\n"),pos);
\r
97 if(log[pos]==_T('#') && log[pos+1] == _T('<') && log[pos+3] == _T('>'))
\r
99 //text = one.Right(one.GetLength()-4);
\r
101 g_Git.StringAppend(&text,&log[pos+4],CGit::m_LogEncode);
\r
106 case LOG_REV_ITEM_BEGIN:
\r
113 case LOG_REV_AUTHOR_NAME:
\r
114 this->m_AuthorName = text;
\r
116 case LOG_REV_AUTHOR_EMAIL:
\r
117 this->m_AuthorEmail = text;
\r
119 case LOG_REV_AUTHOR_DATE:
\r
120 this->m_AuthorDate =ConverFromString(text);
\r
122 case LOG_REV_COMMIT_NAME:
\r
123 this->m_CommitterName = text;
\r
125 case LOG_REV_COMMIT_EMAIL:
\r
126 this->m_CommitterEmail = text;
\r
128 case LOG_REV_COMMIT_DATE:
\r
129 this->m_CommitterDate =ConverFromString(text);
\r
131 case LOG_REV_COMMIT_SUBJECT:
\r
132 this->m_Subject = text;
\r
134 case LOG_REV_COMMIT_BODY:
\r
135 this->m_Body = text +_T("\n");
\r
137 case LOG_REV_COMMIT_HASH:
\r
138 this->m_CommitHash = text.Right(40);
\r
139 if(text.GetLength()>40)
\r
141 this->m_Mark=text[0];
\r
144 case LOG_REV_COMMIT_PARENT:
\r
145 while(text.GetLength()>0)
\r
147 this->m_ParentHash.insert(this->m_ParentHash.end(),text.Left(40));
\r
148 if(text.GetLength()>40)
\r
149 text=text.Right(text.GetLength()-41);
\r
153 if(m_ParentHash.size()>1)
\r
158 case LOG_REV_COMMIT_FILE:
\r
165 // case LOG_REV_COMMIT_BODY:
\r
166 // this->m_Body += one+_T("\n");
\r
168 case LOG_REV_COMMIT_FILE:
\r
169 //filelist += one +_T("\n");
\r
170 //filelist.append(log,pos,log.find(0,pos));
\r
182 //find next string start
\r
183 pos=log.findNextString(pos);
\r
189 filelist.append(log,filebegin,pos);
\r
190 this->m_Files.ParserFromLog(filelist);
\r
191 this->m_Action=this->m_Files.GetAction();
\r
196 CTime GitRev::ConverFromString(CString input)
\r
198 // pick up date from string
\r
201 COleDateTime tm(_wtoi(input.Mid(0,4)),
\r
202 _wtoi(input.Mid(5,2)),
\r
203 _wtoi(input.Mid(8,2)),
\r
204 _wtoi(input.Mid(11,2)),
\r
205 _wtoi(input.Mid(14,2)),
\r
206 _wtoi(input.Mid(17,2)));
\r
207 if( tm.GetStatus() != COleDateTime::valid )
\r
208 return CTime();//Error parsing time-string
\r
210 // pick up utc offset
\r
211 CString sign = input.Mid(20,1); // + or -
\r
212 int hoursOffset = _wtoi(input.Mid(21,2));
\r
213 int minsOffset = _wtoi(input.Mid(23,2));
\r
214 // convert to a fraction of a day
\r
215 double offset = (hoursOffset*60 + minsOffset) / 1440.0; // 1440 mins = 1 day
\r
220 // we have to subtract this from the time given to get UTC
\r
222 // get utc time as a SYSTEMTIME
\r
223 SYSTEMTIME sysTime;
\r
224 tm.GetAsSystemTime( sysTime );
\r
225 // and convert to users local time
\r
227 if ( SystemTimeToTzSpecificLocalTime( &m_TimeZone, &sysTime, &local ) )
\r
233 ASSERT(false); // this should not happen but leave time in utc if it does
\r
235 // convert to CTime and return
\r
236 return CTime( sysTime, -1 );;
\r
238 catch(CException* e)
\r
240 //Probably the date was something like 1970-01-01 00:00:00. _mktime64() doesnt like this.
\r
241 //Dont let the application crash on this exception
\r
243 #ifdef _AFX //CException classes are only defined when afx.h is included.
\r
244 //When afx.h is not included, the exception is leaked.
\r
245 //This will probably never happen because when CException is not defined, it cannot be thrown.
\r
247 #endif //ifdef _AFX
\r
249 return CTime(); //Return an invalid time
\r
252 int GitRev::SafeFetchFullInfo(CGit *git)
\r
254 if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
\r
258 BYTE_VECTOR onelog;
\r
259 TCHAR oldmark=this->m_Mark;
\r
260 CString commithash = m_CommitHash;
\r
261 git->GetLog(onelog,commithash,NULL,1,CGit::LOG_INFO_FULL_DIFF|CGit::LOG_INFO_STAT|CGit::LOG_INFO_FILESTATE|CGit::LOG_INFO_DETECT_COPYRENAME|CGit::LOG_INFO_SHOW_MERGEDFILE);
\r
262 CString oldhash=m_CommitHash;
\r
263 GIT_REV_LIST oldlist=this->m_ParentHash;
\r
264 ParserFromLog(onelog);
\r
266 //ASSERT(oldhash==m_CommitHash);
\r
268 this->m_Mark=oldmark; //parser full log will cause old mark overwrited.
\r
269 //So we need keep old bound mark.
\r
270 this->m_ParentHash=oldlist;
\r
271 InterlockedExchange(&m_IsUpdateing,FALSE);
\r
272 InterlockedExchange(&m_IsFull,TRUE);
\r
275 this->m_Files.Clear();
\r
276 git->CheckAndInitDll();
\r
278 GIT_COMMIT_LIST list;
\r
280 if(git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))
\r
284 git_get_commit_first_parent(&commit,&list);
\r
285 while(git_get_commit_next_parent(&list,parent) == 0)
\r
289 git_diff(git->GetGitDiff(),parent,commit.m_hash,&file,&count);
\r
291 CString strnewname;
\r
292 CString stroldname;
\r
294 for(int j=0;j<count;j++)
\r
300 strnewname.Empty();
\r
301 stroldname.Empty();
\r
303 int mode,IsBin,inc,dec;
\r
304 git_get_diff_file(git->GetGitDiff(),file,j,&newname,&oldname,
\r
305 &mode,&IsBin,&inc,&dec);
\r
307 git->StringAppend(&strnewname,(BYTE*)newname,CP_ACP);
\r
308 git->StringAppend(&stroldname,(BYTE*)oldname,CP_ACP);
\r
310 path.m_ParentNo = i;
\r
311 path.SetFromGit(strnewname,&stroldname);
\r
312 path.ParserAction((BYTE)mode);
\r
314 this->m_Action|=path.m_Action;
\r
318 path.m_StatAdd=_T("-");
\r
319 path.m_StatDel=_T("-");
\r
322 path.m_StatAdd.Format(_T("%d"),inc);
\r
323 path.m_StatDel.Format(_T("%d"),dec);
\r
325 m_Files.AddPath(path);
\r
327 git_diff_flush(git->GetGitDiff());
\r
331 InterlockedExchange(&m_IsUpdateing,FALSE);
\r
332 InterlockedExchange(&m_IsFull,TRUE);
\r
338 int GitRev::ParserParentFromCommit(GIT_COMMIT *commit)
\r
340 this->m_ParentHash.clear();
\r
341 GIT_COMMIT_LIST list;
\r
344 git_get_commit_first_parent(commit,&list);
\r
345 while(git_get_commit_next_parent(&list,parent)==0)
\r
347 m_ParentHash.push_back(CGitHash((char *)parent));
\r
352 int GitRev::ParserFromCommit(GIT_COMMIT *commit)
\r
354 this->m_AuthorDate = commit->m_Author.Date;
\r
356 this->m_AuthorEmail.Empty();
\r
357 g_Git.StringAppend(&m_AuthorEmail,(BYTE*)commit->m_Author.Email,CP_ACP,commit->m_Author.EmailSize);
\r
359 this->m_AuthorName.Empty();
\r
360 g_Git.StringAppend(&m_AuthorName,(BYTE*)commit->m_Author.Name,CP_ACP,commit->m_Author.NameSize);
\r
362 this->m_Body.Empty();
\r
363 g_Git.StringAppend(&m_Body,(BYTE*)commit->m_Body,CP_ACP,commit->m_BodySize);
\r
365 this->m_CommitterDate = commit->m_Committer.Date;
\r
367 this->m_CommitterEmail.Empty();
\r
368 g_Git.StringAppend(&m_CommitterEmail, (BYTE*)commit->m_Committer.Email,CP_ACP, commit->m_Committer.EmailSize);
\r
370 this->m_CommitterName.Empty();
\r
371 g_Git.StringAppend(&m_CommitterName, (BYTE*)commit->m_Committer.Name,CP_ACP, commit->m_Committer.NameSize);
\r
373 this->m_Subject.Empty();
\r
374 g_Git.StringAppend(&m_Subject, (BYTE*)commit->m_Subject,CP_ACP,commit->m_SubjectSize);
\r