int CGitDiff::SubmoduleDiff(const CTGitPath * pPath, const CTGitPath * /*pPath2*/, const git_revnum_t &rev1, const git_revnum_t &rev2, bool /*blame*/, bool /*unified*/) { CString oldhash; CString newhash; bool dirty = false; CString cmd; bool isWorkingCopy = false; if( rev2 == GIT_REV_ZERO || rev1 == GIT_REV_ZERO ) { oldhash = GIT_REV_ZERO; newhash = GIT_REV_ZERO; CString rev; if( rev2 != GIT_REV_ZERO ) rev = rev2; if( rev1 != GIT_REV_ZERO ) rev = rev1; isWorkingCopy = true; cmd.Format(_T("git.exe diff %s -- \"%s\""), rev,pPath->GetGitPathString()); CString output, err; if (g_Git.Run(cmd, &output, &err, CP_UTF8)) { CMessageBox::Show(NULL, output + L"\n" + err, _T("TortoiseGit"), MB_OK|MB_ICONERROR); return -1; } if (output.IsEmpty()) { output.Empty(); err.Empty(); // also compare against index cmd.Format(_T("git.exe diff -- \"%s\""), pPath->GetGitPathString()); if (g_Git.Run(cmd, &output, &err, CP_UTF8)) { CMessageBox::Show(NULL, output + _T("\n") + err, _T("TortoiseGit"), MB_OK | MB_ICONERROR); return -1; } if (output.IsEmpty()) { CMessageBox::Show(NULL, CString(MAKEINTRESOURCE(IDS_ERR_EMPTYDIFF)), _T("TortoiseGit"), MB_OK | MB_ICONERROR); return -1; } else if (CMessageBox::Show(NULL, CString(MAKEINTRESOURCE(IDS_SUBMODULE_EMPTYDIFF)), _T("TortoiseGit"), 1, IDI_QUESTION, CString(MAKEINTRESOURCE(IDS_MSGBOX_YES)), CString(MAKEINTRESOURCE(IDS_MSGBOX_NO))) == 1) { CString sCmd; sCmd.Format(_T("/command:subupdate /bkpath:\"%s\""), g_Git.m_CurrentDir); CAppUtils::RunTortoiseGitProc(sCmd); } return -1; } int start =0; int oldstart = output.Find(_T("-Subproject commit"),start); if(oldstart<0) { CMessageBox::Show(NULL,_T("Subproject Diff Format error") ,_T("TortoiseGit"),MB_OK|MB_ICONERROR); return -1; } oldhash = output.Mid(oldstart+ CString(_T("-Subproject commit")).GetLength()+1,40); start = 0; int newstart = output.Find(_T("+Subproject commit"),start); if(oldstart<0) { CMessageBox::Show(NULL,_T("Subproject Diff Format error") ,_T("TortoiseGit"),MB_OK|MB_ICONERROR); return -1; } newhash = output.Mid(newstart+ CString(_T("+Subproject commit")).GetLength()+1,40); dirty = output.Mid(newstart + CString(_T("+Subproject commit")).GetLength() + 41) == _T("-dirty\n"); } else { cmd.Format(_T("git.exe diff-tree -r -z %s %s -- \"%s\""), rev2,rev1,pPath->GetGitPathString()); BYTE_VECTOR bytes, errBytes; if(g_Git.Run(cmd, &bytes, &errBytes)) { CString err; g_Git.StringAppend(&err, &errBytes[0], CP_UTF8); CMessageBox::Show(NULL,err,_T("TortoiseGit"),MB_OK|MB_ICONERROR); return -1; } g_Git.StringAppend(&oldhash, &bytes[15], CP_UTF8, 40); g_Git.StringAppend(&newhash, &bytes[15+41], CP_UTF8, 40); } CString oldsub; CString newsub; bool oldOK = false, newOK = false; CGit subgit; subgit.m_CurrentDir=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString(); CSubmoduleDiffDlg::ChangeType changeType = CSubmoduleDiffDlg::Unknown; if(pPath->HasAdminDir()) { int encode=CAppUtils::GetLogOutputEncode(&subgit); int oldTime = 0, newTime = 0; if(oldhash != GIT_REV_ZERO) { CString cmdout, cmderr; cmd.Format(_T("git.exe log -n1 --pretty=format:\"%%ct %%s\" %s --"), oldhash); oldOK = !subgit.Run(cmd, &cmdout, &cmderr, encode); if (oldOK) { int pos = cmdout.Find(_T(" ")); oldTime = _ttoi(cmdout.Left(pos)); oldsub = cmdout.Mid(pos + 1); } else oldsub = cmderr; } if (newhash != GIT_REV_ZERO) { CString cmdout, cmderr; cmd.Format(_T("git.exe log -n1 --pretty=format:\"%%ct %%s\" %s --"), newhash); newOK = !subgit.Run(cmd, &cmdout, &cmderr, encode); if (newOK) { int pos = cmdout.Find(_T(" ")); newTime = _ttoi(cmdout.Left(pos)); newsub = cmdout.Mid(pos + 1); } else newsub = cmderr; } if (oldhash == GIT_REV_ZERO) { oldOK = true; changeType = CSubmoduleDiffDlg::NewSubmodule; } else if (newhash == GIT_REV_ZERO) { newOK = true; changeType = CSubmoduleDiffDlg::DeleteSubmodule; } else if (oldhash != newhash) { bool ffNewer = false, ffOlder = false; ffNewer = subgit.IsFastForward(oldhash, newhash); if (!ffNewer) { ffOlder = subgit.IsFastForward(newhash, oldhash); if (!ffOlder) { if (newTime > oldTime) changeType = CSubmoduleDiffDlg::NewerTime; else if (newTime < oldTime) changeType = CSubmoduleDiffDlg::OlderTime; else changeType = CSubmoduleDiffDlg::SameTime; } else changeType = CSubmoduleDiffDlg::Rewind; } else changeType = CSubmoduleDiffDlg::FastForward; } } if (!oldOK || !newOK) changeType = CSubmoduleDiffDlg::Unknown; CSubmoduleDiffDlg submoduleDiffDlg; submoduleDiffDlg.SetDiff(pPath->GetWinPath(), isWorkingCopy, oldhash, oldsub, oldOK, newhash, newsub, newOK, dirty, changeType); submoduleDiffDlg.DoModal(); if (submoduleDiffDlg.IsRefresh()) return 1; return 0; }
void CGitDiff::GetSubmoduleChangeType(CGit& subgit, const CString& oldhash, const CString& newhash, bool& oldOK, bool& newOK, ChangeType& changeType, CString& oldsub, CString& newsub) { CString cmd; int encode = CAppUtils::GetLogOutputEncode(&subgit); int oldTime = 0, newTime = 0; if (oldhash != GIT_REV_ZERO) { CString cmdout, cmderr; cmd.Format(_T("git.exe log -n1 --pretty=format:\"%%ct %%s\" %s --"), (LPCTSTR)oldhash); oldOK = !subgit.Run(cmd, &cmdout, &cmderr, encode); if (oldOK) { int pos = cmdout.Find(_T(" ")); oldTime = _ttoi(cmdout.Left(pos)); oldsub = cmdout.Mid(pos + 1); } else oldsub = cmderr; } if (newhash != GIT_REV_ZERO) { CString cmdout, cmderr; cmd.Format(_T("git.exe log -n1 --pretty=format:\"%%ct %%s\" %s --"), (LPCTSTR)newhash); newOK = !subgit.Run(cmd, &cmdout, &cmderr, encode); if (newOK) { int pos = cmdout.Find(_T(" ")); newTime = _ttoi(cmdout.Left(pos)); newsub = cmdout.Mid(pos + 1); } else newsub = cmderr; } if (oldhash == GIT_REV_ZERO) { oldOK = true; changeType = NewSubmodule; } else if (newhash == GIT_REV_ZERO) { newOK = true; changeType = DeleteSubmodule; } else if (oldhash != newhash) { bool ffNewer = false, ffOlder = false; ffNewer = subgit.IsFastForward(oldhash, newhash); if (!ffNewer) { ffOlder = subgit.IsFastForward(newhash, oldhash); if (!ffOlder) { if (newTime > oldTime) changeType = NewerTime; else if (newTime < oldTime) changeType = OlderTime; else changeType = SameTime; } else changeType = Rewind; } else changeType = FastForward; } else if (oldhash == newhash) changeType = Identical; if (!oldOK || !newOK) changeType = Unknown; }