#include "StdAfx.h"\r
+#include "ATLComTime.h"\r
#include "GitRev.h"\r
#include "Git.h"\r
+#include "GitDLL.h"\r
+#include "UnicodeUtils.h"\r
+\r
+class CException; //Just in case afx.h is not included (cannot be included in every project which uses this file)\r
+\r
+// provide an ASSERT macro for when compiled without MFC\r
+#if !defined ASSERT\r
+ // 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
+ #define ASSERT(x) _ASSERTE(x)\r
+#endif\r
+\r
\r
GitRev::GitRev(void)\r
{\r
m_Action=0;\r
m_IsFull = 0;\r
m_IsUpdateing = 0;\r
+ // fetch local machine timezone info\r
+ if ( GetTimeZoneInformation( &m_TimeZone ) == TIME_ZONE_ID_INVALID )\r
+ {\r
+ ASSERT(false);\r
+ }\r
}\r
\r
GitRev::~GitRev(void)\r
m_Body.Empty();\r
m_Subject.Empty();\r
m_CommitHash.Empty();\r
+ m_Ref.Empty();\r
+ m_RefAction.Empty();\r
m_Mark=0;\r
\r
}\r
-int GitRev::CopyFrom(GitRev &rev)\r
+int GitRev::CopyFrom(GitRev &rev,bool OmitParentAndMark)\r
{\r
m_AuthorName =rev.m_AuthorName ;\r
m_AuthorEmail =rev.m_AuthorEmail ;\r
m_Subject =rev.m_Subject ;\r
m_Body =rev.m_Body ;\r
m_CommitHash =rev.m_CommitHash ;\r
- m_ParentHash =rev.m_ParentHash ;\r
m_Files =rev.m_Files ; \r
m_Action =rev.m_Action ;\r
- m_Mark =rev.m_Mark;\r
+ m_IsFull =rev.m_IsFull;\r
+\r
+ if(!OmitParentAndMark)\r
+ {\r
+ m_ParentHash =rev.m_ParentHash ;\r
+ m_Mark =rev.m_Mark;\r
+ }\r
return 0;\r
}\r
-int GitRev::ParserFromLog(CString &log)\r
+int GitRev::ParserFromLog(BYTE_VECTOR &log,int start)\r
{\r
- int pos=0;\r
+ int pos=start;\r
CString one;\r
CString key;\r
CString text;\r
- CString filelist;\r
- TCHAR mode;\r
+ BYTE_VECTOR filelist;\r
+ BYTE mode=0;\r
CTGitPath path;\r
this->m_Files.Clear();\r
m_Action=0;\r
+ int begintime=0;\r
+ int filebegin=-1;\r
\r
- while( pos>=0 )\r
+ while( pos < log.size() && pos>=0)\r
{\r
- one=log.Tokenize(_T("\n"),pos);\r
- if(one[0]==_T('#') && one[1] == _T('<') && one[3] == _T('>'))\r
+ \r
+ //one=log.Tokenize(_T("\n"),pos);\r
+ if(log[pos]==_T('#') && log[pos+1] == _T('<') && log[pos+3] == _T('>'))\r
{\r
- text = one.Right(one.GetLength()-4);\r
- mode = one[2];\r
+ //text = one.Right(one.GetLength()-4);\r
+ text.Empty();\r
+ g_Git.StringAppend(&text,&log[pos+4],CGit::m_LogEncode);\r
+ mode = log[pos+2];\r
+ \r
switch(mode)\r
{\r
case LOG_REV_ITEM_BEGIN:\r
- this->Clear();\r
-\r
+ begintime++;\r
+ if(begintime>1)\r
+ break;\r
+ else\r
+ this->Clear();\r
+ break;\r
case LOG_REV_AUTHOR_NAME:\r
this->m_AuthorName = text;\r
break;\r
else\r
break;\r
}\r
+ if(m_ParentHash.size()>1)\r
+ {\r
+ int a=1;\r
+ }\r
break;\r
case LOG_REV_COMMIT_FILE:\r
break;\r
{\r
switch(mode)\r
{\r
- case LOG_REV_COMMIT_BODY:\r
- this->m_Body += one+_T("\n");\r
- break;\r
+// case LOG_REV_COMMIT_BODY:\r
+// this->m_Body += one+_T("\n");\r
+// break;\r
case LOG_REV_COMMIT_FILE:\r
- filelist += one +_T("\n");\r
+ //filelist += one +_T("\n");\r
+ //filelist.append(log,pos,log.find(0,pos));\r
+ if(filebegin<0)\r
+ filebegin=pos;\r
break;\r
}\r
}\r
+ \r
+ if(begintime>1)\r
+ {\r
+ break;\r
+ }\r
+\r
+ //find next string start \r
+ pos=log.findNextString(pos);\r
}\r
\r
- this->m_Files.ParserFromLog(filelist);\r
- this->m_Action=this->m_Files.GetAction();\r
- return 0;\r
+ if(filebegin>=0)\r
+ {\r
+ \r
+ filelist.append(log,filebegin,pos); \r
+ this->m_Files.ParserFromLog(filelist);\r
+ this->m_Action=this->m_Files.GetAction();\r
+ }\r
+ return pos;\r
}\r
\r
CTime GitRev::ConverFromString(CString input)\r
{\r
- CTime tm(_wtoi(input.Mid(0,4)),\r
- _wtoi(input.Mid(5,2)),\r
- _wtoi(input.Mid(8,2)),\r
- _wtoi(input.Mid(11,2)),\r
- _wtoi(input.Mid(14,2)),\r
- _wtoi(input.Mid(17,2)),\r
- _wtoi(input.Mid(20,4)));\r
- return tm;\r
+ // pick up date from string\r
+ try\r
+ {\r
+ COleDateTime tm(_wtoi(input.Mid(0,4)),\r
+ _wtoi(input.Mid(5,2)),\r
+ _wtoi(input.Mid(8,2)),\r
+ _wtoi(input.Mid(11,2)),\r
+ _wtoi(input.Mid(14,2)),\r
+ _wtoi(input.Mid(17,2)));\r
+ if( tm.GetStatus() != COleDateTime::valid )\r
+ return CTime();//Error parsing time-string\r
+\r
+ // pick up utc offset\r
+ CString sign = input.Mid(20,1); // + or -\r
+ int hoursOffset = _wtoi(input.Mid(21,2));\r
+ int minsOffset = _wtoi(input.Mid(23,2));\r
+ // convert to a fraction of a day\r
+ double offset = (hoursOffset*60 + minsOffset) / 1440.0; // 1440 mins = 1 day\r
+ if ( sign == "-" )\r
+ {\r
+ offset = -offset;\r
+ }\r
+ // we have to subtract this from the time given to get UTC\r
+ tm -= offset;\r
+ // get utc time as a SYSTEMTIME\r
+ SYSTEMTIME sysTime;\r
+ tm.GetAsSystemTime( sysTime );\r
+ // and convert to users local time\r
+ SYSTEMTIME local;\r
+ if ( SystemTimeToTzSpecificLocalTime( &m_TimeZone, &sysTime, &local ) )\r
+ {\r
+ sysTime = local;\r
+ }\r
+ else\r
+ {\r
+ ASSERT(false); // this should not happen but leave time in utc if it does\r
+ }\r
+ // convert to CTime and return\r
+ return CTime( sysTime, -1 );;\r
+ }\r
+ catch(CException* e)\r
+ {\r
+ //Probably the date was something like 1970-01-01 00:00:00. _mktime64() doesnt like this.\r
+ //Dont let the application crash on this exception\r
+\r
+#ifdef _AFX //CException classes are only defined when afx.h is included.\r
+ //When afx.h is not included, the exception is leaked.\r
+ //This will probably never happen because when CException is not defined, it cannot be thrown.\r
+ e->Delete();\r
+#endif //ifdef _AFX\r
+ }\r
+ return CTime(); //Return an invalid time\r
}\r
\r
int GitRev::SafeFetchFullInfo(CGit *git)\r
{\r
if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)\r
{\r
+#if 0\r
//GitRev rev;\r
- CString onelog;\r
+ BYTE_VECTOR onelog;\r
TCHAR oldmark=this->m_Mark;\r
- \r
- git->GetLog(onelog,m_CommitHash,NULL,1);\r
+ CString commithash = m_CommitHash;\r
+ 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
CString oldhash=m_CommitHash;\r
+ GIT_REV_LIST oldlist=this->m_ParentHash;\r
ParserFromLog(onelog);\r
\r
//ASSERT(oldhash==m_CommitHash);\r
if(oldmark!=0)\r
this->m_Mark=oldmark; //parser full log will cause old mark overwrited. \r
//So we need keep old bound mark.\r
-\r
+ this->m_ParentHash=oldlist;\r
InterlockedExchange(&m_IsUpdateing,FALSE);\r
InterlockedExchange(&m_IsFull,TRUE);\r
return 0;\r
+#endif\r
+ this->m_Files.Clear();\r
+ git->CheckAndInitDll();\r
+ GIT_COMMIT commit;\r
+ GIT_COMMIT_LIST list;\r
+ GIT_HASH parent;\r
+ if(git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))\r
+ return -1;\r
+\r
+ int i=0;\r
+ bool isRoot = this->m_ParentHash.size()==0;\r
+ git_get_commit_first_parent(&commit,&list);\r
+ while(git_get_commit_next_parent(&list,parent) == 0 || isRoot)\r
+ {\r
+ GIT_FILE file;\r
+ int count;\r
+ if(isRoot)\r
+ git_root_diff(git->GetGitDiff(), this->m_CommitHash.m_hash, &file, &count);\r
+ else\r
+ git_diff(git->GetGitDiff(),parent,commit.m_hash,&file,&count);\r
+ \r
+ isRoot = false;\r
+\r
+ CTGitPath path;\r
+ CString strnewname;\r
+ CString stroldname;\r
+ \r
+ for(int j=0;j<count;j++)\r
+ {\r
+ path.Reset();\r
+ char *newname;\r
+ char *oldname;\r
+ \r
+ strnewname.Empty();\r
+ stroldname.Empty();\r
+\r
+ int mode,IsBin,inc,dec;\r
+ git_get_diff_file(git->GetGitDiff(),file,j,&newname,&oldname,\r
+ &mode,&IsBin,&inc,&dec);\r
+ \r
+ git->StringAppend(&strnewname,(BYTE*)newname,CP_ACP);\r
+ git->StringAppend(&stroldname,(BYTE*)oldname,CP_ACP);\r
+\r
+ path.m_ParentNo = i;\r
+ path.SetFromGit(strnewname,&stroldname);\r
+ path.ParserAction((BYTE)mode);\r
+\r
+ this->m_Action|=path.m_Action;\r
+\r
+ if(IsBin)\r
+ {\r
+ path.m_StatAdd=_T("-");\r
+ path.m_StatDel=_T("-");\r
+ }else\r
+ {\r
+ path.m_StatAdd.Format(_T("%d"),inc);\r
+ path.m_StatDel.Format(_T("%d"),dec);\r
+ }\r
+ m_Files.AddPath(path);\r
+ }\r
+ git_diff_flush(git->GetGitDiff());\r
+ i++;\r
+ }\r
+\r
+ InterlockedExchange(&m_IsUpdateing,FALSE);\r
+ InterlockedExchange(&m_IsFull,TRUE);\r
+\r
}\r
return -1;\r
+}\r
+\r
+int GitRev::ParserParentFromCommit(GIT_COMMIT *commit)\r
+{\r
+ this->m_ParentHash.clear();\r
+ GIT_COMMIT_LIST list;\r
+ GIT_HASH parent;\r
+ \r
+ git_get_commit_first_parent(commit,&list);\r
+ while(git_get_commit_next_parent(&list,parent)==0)\r
+ {\r
+ m_ParentHash.push_back(CGitHash((char *)parent));\r
+ }\r
+ return 0;\r
+}\r
+\r
+int GitRev::ParserFromCommit(GIT_COMMIT *commit)\r
+{\r
+ int encode =CP_UTF8;\r
+ \r
+ if(commit->m_Encode != 0 && commit->m_EncodeSize != 0)\r
+ {\r
+ CString str;\r
+ g_Git.StringAppend(&str, (BYTE*)commit->m_Encode, CP_UTF8, commit->m_EncodeSize);\r
+ encode = CUnicodeUtils::GetCPCode(str);\r
+ }\r
+\r
+ this->m_AuthorDate = commit->m_Author.Date;\r
+ \r
+ this->m_AuthorEmail.Empty();\r
+ g_Git.StringAppend(&m_AuthorEmail,(BYTE*)commit->m_Author.Email,CP_UTF8,commit->m_Author.EmailSize);\r
+\r
+ this->m_AuthorName.Empty();\r
+ g_Git.StringAppend(&m_AuthorName,(BYTE*)commit->m_Author.Name,CP_UTF8,commit->m_Author.NameSize);\r
+ \r
+ this->m_Body.Empty();\r
+ g_Git.StringAppend(&m_Body,(BYTE*)commit->m_Body,encode,commit->m_BodySize);\r
+\r
+ this->m_CommitterDate = commit->m_Committer.Date;\r
+ \r
+ this->m_CommitterEmail.Empty();\r
+ g_Git.StringAppend(&m_CommitterEmail, (BYTE*)commit->m_Committer.Email,CP_UTF8, commit->m_Committer.EmailSize);\r
+\r
+ this->m_CommitterName.Empty();\r
+ g_Git.StringAppend(&m_CommitterName, (BYTE*)commit->m_Committer.Name,CP_UTF8, commit->m_Committer.NameSize);\r
+\r
+ this->m_Subject.Empty();\r
+ g_Git.StringAppend(&m_Subject, (BYTE*)commit->m_Subject,encode,commit->m_SubjectSize);\r
+ \r
+ return 0;\r
+}\r
+#ifndef TRACE\r
+#define TRACE(x) 1?0:(x)\r
+#endif\r
+void GitRev::DbgPrint()\r
+{\r
+ TRACE(_T("Commit %s\r\n"), this->m_CommitHash.ToString());\r
+ for(int i=0;i<this->m_ParentHash.size();i++)\r
+ {\r
+ TRACE(_T("Parent %i %s"),i, m_ParentHash[i].ToString());\r
+ }\r
+ TRACE(_T("\n"));\r
+}\r
+\r
+int GitRev::GetCommitFromHash(CGitHash &hash)\r
+{\r
+ g_Git.CheckAndInitDll();\r
+\r
+ GIT_COMMIT commit;\r
+ if(git_get_commit_from_hash( &commit, hash.m_hash))\r
+ return -1;\r
+\r
+ this->ParserFromCommit(&commit);\r
+ git_free_commit(&commit);\r
+\r
+ this->m_CommitHash=hash;\r
+\r
+ return 0;\r
+ \r
+}\r
+\r
+int GitRev::GetCommit(CString &refname)\r
+{\r
+ g_Git.CheckAndInitDll();\r
+ CStringA rev;\r
+ rev= CUnicodeUtils::GetUTF8(refname);\r
+ GIT_HASH sha;\r
+\r
+ if(git_get_sha1(rev.GetBuffer(),sha))\r
+ return -1;\r
+\r
+ GetCommitFromHash(CGitHash((char*)sha));\r
}
\ No newline at end of file