m_arFileDiffs.RemoveAll();\r
}\r
\r
+BOOL CPatch::ParserGitPatch(CFileTextLines &PatchLines,int nIndex)\r
+{\r
+ CString sLine;\r
+ EOL ending = EOL_NOENDING;\r
+\r
+ int state = 0;\r
+ Chunks * chunks = NULL;\r
+ Chunk * chunk = NULL;\r
+ int nAddLineCount = 0;\r
+ int nRemoveLineCount = 0;\r
+ int nContextLineCount = 0;\r
+ for ( ;nIndex<PatchLines.GetCount(); nIndex++)\r
+ {\r
+ sLine = PatchLines.GetAt(nIndex);\r
+ ending = PatchLines.GetLineEnding(nIndex);\r
+ if (ending != EOL_NOENDING)\r
+ ending = EOL_AUTOLINE;\r
+ \r
+ switch (state)\r
+ {\r
+ case 0: \r
+ {\r
+ // diff --git\r
+ if( sLine.Find(_T("diff --git"))==0)\r
+ {\r
+ if (chunks)\r
+ {\r
+ //this is a new file diff, so add the last one to \r
+ //our array.\r
+ m_arFileDiffs.Add(chunks);\r
+ }\r
+ chunks = new Chunks();\r
+\r
+ }\r
+ \r
+ //index\r
+ if( sLine.Find(_T("index"))==0 )\r
+ {\r
+ int dotstart=sLine.Find(_T(".."));\r
+ if(dotstart>=0)\r
+ {\r
+ chunks->sRevision = sLine.Mid(dotstart-7,7);\r
+ chunks->sRevision2 = sLine.Mid(dotstart+2,7);\r
+ }\r
+ }\r
+\r
+ //---\r
+ if( sLine.Find(_T("--- "))==0 )\r
+ {\r
+ if (sLine.Left(3).Compare(_T("---"))!=0)\r
+ {\r
+ //no starting "---" found\r
+ //seems to be either garbage or just\r
+ //a binary file. So start over...\r
+ state = 0;\r
+ nIndex--;\r
+ if (chunks)\r
+ {\r
+ delete chunks;\r
+ chunks = NULL;\r
+ }\r
+ break;\r
+ }\r
+ \r
+ sLine = sLine.Mid(3); //remove the "---"\r
+ sLine =sLine.Trim();\r
+ //at the end of the filepath there's a revision number...\r
+ int bracket = sLine.ReverseFind('(');\r
+ if (bracket < 0)\r
+ // some patch files can have another '(' char, especially ones created in Chinese OS\r
+ bracket = sLine.ReverseFind(0xff08);\r
+ \r
+ if (bracket < 0)\r
+ {\r
+ if (chunks->sFilePath.IsEmpty())\r
+ chunks->sFilePath = sLine.Trim();\r
+ }\r
+ else\r
+ chunks->sFilePath = sLine.Left(bracket-1).Trim();\r
+ \r
+ if (chunks->sFilePath.Find('\t')>=0)\r
+ {\r
+ chunks->sFilePath = chunks->sFilePath.Left(chunks->sFilePath.Find('\t'));\r
+ }\r
+ if( chunks->sFilePath.Find(_T("a/")) == 0 )\r
+ chunks->sFilePath=chunks->sFilePath.Mid(2);\r
+\r
+ chunks->sFilePath.Replace(_T('/'),_T('\\'));\r
+ }\r
+ \r
+ // +++\r
+ if( sLine.Find(_T("+++ ")) == 0 )\r
+ {\r
+ sLine = sLine.Mid(3); //remove the "---"\r
+ sLine =sLine.Trim();\r
+ \r
+ //at the end of the filepath there's a revision number...\r
+ int bracket = sLine.ReverseFind('(');\r
+ if (bracket < 0)\r
+ // some patch files can have another '(' char, especially ones created in Chinese OS\r
+ bracket = sLine.ReverseFind(0xff08);\r
+\r
+ if (bracket < 0)\r
+ chunks->sFilePath2 = sLine.Trim();\r
+ else\r
+ chunks->sFilePath2 = sLine.Left(bracket-1).Trim();\r
+ if (chunks->sFilePath2.Find('\t')>=0)\r
+ {\r
+ chunks->sFilePath2 = chunks->sFilePath2.Left(chunks->sFilePath2.Find('\t'));\r
+ }\r
+ if( chunks->sFilePath2.Find(_T("a/")) == 0 )\r
+ chunks->sFilePath2=chunks->sFilePath2.Mid(2);\r
+\r
+ chunks->sFilePath2.Replace(_T('/'),_T('\\'));\r
+ }\r
+ \r
+ //@@ -xxx,xxx +xxx,xxx @@\r
+ if( sLine.Find(_T("@@")) == 0 )\r
+ {\r
+ sLine = sLine.Mid(2);\r
+ sLine = sLine.Trim();\r
+ chunk = new Chunk();\r
+ CString sRemove = sLine.Left(sLine.Find(' '));\r
+ CString sAdd = sLine.Mid(sLine.Find(' '));\r
+ chunk->lRemoveStart = (-_ttol(sRemove));\r
+ if (sRemove.Find(',')>=0)\r
+ {\r
+ sRemove = sRemove.Mid(sRemove.Find(',')+1);\r
+ chunk->lRemoveLength = _ttol(sRemove);\r
+ }\r
+ else\r
+ {\r
+ chunk->lRemoveStart = 0;\r
+ chunk->lRemoveLength = (-_ttol(sRemove));\r
+ }\r
+ chunk->lAddStart = _ttol(sAdd);\r
+ if (sAdd.Find(',')>=0)\r
+ {\r
+ sAdd = sAdd.Mid(sAdd.Find(',')+1);\r
+ chunk->lAddLength = _ttol(sAdd);\r
+ }\r
+ else\r
+ {\r
+ chunk->lAddStart = 1;\r
+ chunk->lAddLength = _ttol(sAdd);\r
+ }\r
+ \r
+ state =5;\r
+ }\r
+ } \r
+ break;\r
+ \r
+ \r
+ case 5: //[ |+|-] <sourceline>\r
+ {\r
+ //this line is either a context line (with a ' ' in front)\r
+ //a line added (with a '+' in front)\r
+ //or a removed line (with a '-' in front)\r
+ TCHAR type;\r
+ if (sLine.IsEmpty())\r
+ type = ' ';\r
+ else\r
+ type = sLine.GetAt(0);\r
+ if (type == ' ')\r
+ {\r
+ //it's a context line - we don't use them here right now\r
+ //but maybe in the future the patch algorithm can be\r
+ //extended to use those in case the file to patch has\r
+ //already changed and no base file is around...\r
+ chunk->arLines.Add(RemoveUnicodeBOM(sLine.Mid(1)));\r
+ chunk->arLinesStates.Add(PATCHSTATE_CONTEXT);\r
+ chunk->arEOLs.push_back(ending);\r
+ nContextLineCount++;\r
+ }\r
+ else if (type == '\\')\r
+ {\r
+ //it's a context line (sort of): \r
+ //warnings start with a '\' char (e.g. "\ No newline at end of file")\r
+ //so just ignore this...\r
+ }\r
+ else if (type == '-')\r
+ {\r
+ //a removed line\r
+ chunk->arLines.Add(RemoveUnicodeBOM(sLine.Mid(1)));\r
+ chunk->arLinesStates.Add(PATCHSTATE_REMOVED);\r
+ chunk->arEOLs.push_back(ending);\r
+ nRemoveLineCount++;\r
+ }\r
+ else if (type == '+')\r
+ {\r
+ //an added line\r
+ chunk->arLines.Add(RemoveUnicodeBOM(sLine.Mid(1)));\r
+ chunk->arLinesStates.Add(PATCHSTATE_ADDED);\r
+ chunk->arEOLs.push_back(ending);\r
+ nAddLineCount++;\r
+ }\r
+ else\r
+ {\r
+ //none of those lines! what the hell happened here?\r
+ m_sErrorMessage.Format(IDS_ERR_PATCH_UNKOWNLINETYPE, nIndex);\r
+ goto errorcleanup;\r
+ }\r
+ if ((chunk->lAddLength == (nAddLineCount + nContextLineCount)) &&\r
+ chunk->lRemoveLength == (nRemoveLineCount + nContextLineCount))\r
+ {\r
+ //chunk is finished\r
+ if (chunks)\r
+ chunks->chunks.Add(chunk);\r
+ else\r
+ delete chunk;\r
+ chunk = NULL;\r
+ nAddLineCount = 0;\r
+ nContextLineCount = 0;\r
+ nRemoveLineCount = 0;\r
+ state = 0;\r
+ }\r
+ } \r
+ break;\r
+ default:\r
+ ASSERT(FALSE);\r
+ } // switch (state) \r
+ } // for ( ;nIndex<m_PatchLines.GetCount(); nIndex++) \r
+ if (chunk)\r
+ {\r
+ m_sErrorMessage.LoadString(IDS_ERR_PATCH_CHUNKMISMATCH);\r
+ goto errorcleanup;\r
+ }\r
+ if (chunks)\r
+ m_arFileDiffs.Add(chunks);\r
+ return TRUE;\r
+\r
+errorcleanup:\r
+ if (chunk)\r
+ delete chunk;\r
+ if (chunks)\r
+ {\r
+ for (int i=0; i<chunks->chunks.GetCount(); i++)\r
+ {\r
+ delete chunks->chunks.GetAt(i);\r
+ }\r
+ chunks->chunks.RemoveAll();\r
+ delete chunks;\r
+ }\r
+ FreeMemory();\r
+ return FALSE;\r
+}\r
+\r
BOOL CPatch::OpenUnifiedDiffFile(const CString& filename)\r
{\r
CString sLine;\r
//first, skip possible garbage at the beginning\r
//garbage is finished when a line starts with "Index: "\r
//and the next line consists of only "=" characters\r
- for (nIndex=0; nIndex<PatchLines.GetCount(); nIndex++)\r
+ if( !m_IsGitPatch )\r
{\r
- sLine = PatchLines.GetAt(nIndex);\r
- if (sLine.Left(4).Compare(_T("--- "))==0)\r
- break;\r
- if ((nIndex+1)<PatchLines.GetCount())\r
+ for (nIndex=0; nIndex<PatchLines.GetCount(); nIndex++)\r
{\r
- sLine = PatchLines.GetAt(nIndex+1);\r
-\r
- if(sLine.IsEmpty()&&m_IsGitPatch)\r
- continue;\r
+ sLine = PatchLines.GetAt(nIndex);\r
\r
- sLine.Replace(_T("="), _T(""));\r
- if (sLine.IsEmpty())\r
+ if (sLine.Left(4).Compare(_T("--- "))==0)\r
break;\r
+ if ((nIndex+1)<PatchLines.GetCount())\r
+ {\r
+ sLine = PatchLines.GetAt(nIndex+1);\r
+\r
+ if(sLine.IsEmpty()&&m_IsGitPatch)\r
+ continue;\r
+\r
+ sLine.Replace(_T("="), _T(""));\r
+ if (sLine.IsEmpty())\r
+ break;\r
+ }\r
}\r
}\r
+\r
if ((PatchLines.GetCount()-nIndex) < 2)\r
{\r
//no file entry found.\r
return FALSE;\r
}\r
\r
+ if( m_IsGitPatch )\r
+ return ParserGitPatch(PatchLines,nIndex);\r
+\r
//from this point on we have the real unified diff data\r
int state = 0;\r
Chunks * chunks = NULL;\r