int CGitDiff::SubmoduleDiffNull(const CTGitPath * pPath, const git_revnum_t &rev1) { CString oldhash = GIT_REV_ZERO; CString oldsub ; CString newsub; CString newhash; CString cmd; if (rev1 != GIT_REV_ZERO) cmd.Format(_T("git.exe ls-tree \"%s\" -- \"%s\""), rev1, pPath->GetGitPathString()); else cmd.Format(_T("git.exe ls-files -s -- \"%s\""), 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; } int start=0; start=output.Find(_T(' '),start); if(start>0) { if (rev1 != GIT_REV_ZERO) // in ls-files the hash is in the second column; in ls-tree it's in the third one start = output.Find(_T(' '), start + 1); if(start>0) newhash=output.Mid(start+1, 40); CGit subgit; subgit.m_CurrentDir=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString(); int encode=CAppUtils::GetLogOutputEncode(&subgit); cmd.Format(_T("git.exe log -n1 --pretty=format:\"%%s\" %s --"), newhash); bool toOK = !subgit.Run(cmd,&newsub,encode); bool dirty = false; if (rev1 == GIT_REV_ZERO) { CString dirtyList; subgit.Run(_T("git.exe status --porcelain"), &dirtyList, encode); dirty = !dirtyList.IsEmpty(); } CSubmoduleDiffDlg submoduleDiffDlg; submoduleDiffDlg.SetDiff(pPath->GetWinPath(), false, oldhash, oldsub, true, newhash, newsub, toOK, dirty, CSubmoduleDiffDlg::NewSubmodule); submoduleDiffDlg.DoModal(); if (submoduleDiffDlg.IsRefresh()) return 1; return 0; } if (rev1 != GIT_REV_ZERO) CMessageBox::Show(NULL, _T("ls-tree output format error"), _T("TortoiseGit"), MB_OK | MB_ICONERROR); else CMessageBox::Show(NULL, _T("ls-files output format error"), _T("TortoiseGit"), MB_OK | MB_ICONERROR); return -1; }
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\""), (LPCTSTR)rev, (LPCTSTR)pPath->GetGitPathString()); CString output, err; if (g_Git.Run(cmd, &output, &err, CP_UTF8)) { CMessageBox::Show(nullptr, 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\""), (LPCTSTR)pPath->GetGitPathString()); if (g_Git.Run(cmd, &output, &err, CP_UTF8)) { CMessageBox::Show(nullptr, output + _T("\n") + err, _T("TortoiseGit"), MB_OK | MB_ICONERROR); return -1; } if (output.IsEmpty()) { CMessageBox::Show(nullptr, IDS_ERR_EMPTYDIFF, IDS_APPNAME, MB_OK | MB_ICONERROR); return -1; } else if (CMessageBox::Show(nullptr, IDS_SUBMODULE_EMPTYDIFF, IDS_APPNAME, 1, IDI_QUESTION, IDS_MSGBOX_YES, IDS_MSGBOX_NO) == 1) { CString sCmd; sCmd.Format(_T("/command:subupdate /bkpath:\"%s\""), (LPCTSTR)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(nullptr, _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 (newstart < 0) { CMessageBox::Show(nullptr, _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\""), (LPCTSTR)rev2, (LPCTSTR)rev1, (LPCTSTR)pPath->GetGitPathString()); BYTE_VECTOR bytes, errBytes; if(g_Git.Run(cmd, &bytes, &errBytes)) { CString err; CGit::StringAppend(&err, &errBytes[0], CP_UTF8); CMessageBox::Show(nullptr, err, _T("TortoiseGit"), MB_OK | MB_ICONERROR); return -1; } if (bytes.size() < 15 + 2 * GIT_HASH_SIZE + 1 + 2 * GIT_HASH_SIZE) { CMessageBox::Show(nullptr, _T("git diff-tree gives invalid output"), _T("TortoiseGit"), MB_OK | MB_ICONERROR); return -1; } CGit::StringAppend(&oldhash, &bytes[15], CP_UTF8, 2 * GIT_HASH_SIZE); CGit::StringAppend(&newhash, &bytes[15 + 2 * GIT_HASH_SIZE + 1], CP_UTF8, 2 * GIT_HASH_SIZE); } CString oldsub; CString newsub; bool oldOK = false, newOK = false; CGit subgit; subgit.m_CurrentDir = g_Git.CombinePath(pPath); ChangeType changeType = Unknown; if (pPath->HasAdminDir()) GetSubmoduleChangeType(subgit, oldhash, newhash, oldOK, newOK, changeType, oldsub, newsub); CSubmoduleDiffDlg submoduleDiffDlg; submoduleDiffDlg.SetDiff(pPath->GetWinPath(), isWorkingCopy, oldhash, oldsub, oldOK, newhash, newsub, newOK, dirty, changeType); submoduleDiffDlg.DoModal(); if (submoduleDiffDlg.IsRefresh()) return 1; return 0; }
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; }
int CGitDiff::SubmoduleDiffNull(const CTGitPath * pPath, const git_revnum_t &rev1) { CString oldhash = GIT_REV_ZERO; CString oldsub ; CString newsub; CString newhash; CString cmd; if (rev1 != GIT_REV_ZERO) cmd.Format(L"git.exe ls-tree \"%s\" -- \"%s\"", (LPCTSTR)rev1, (LPCTSTR)pPath->GetGitPathString()); else cmd.Format(L"git.exe ls-files -s -- \"%s\"", (LPCTSTR)pPath->GetGitPathString()); CString output, err; if (g_Git.Run(cmd, &output, &err, CP_UTF8)) { CMessageBox::Show(nullptr, output + L'\n' + err, L"TortoiseGit", MB_OK | MB_ICONERROR); return -1; } int start = output.Find(L' '); if(start>0) { if (rev1 != GIT_REV_ZERO) // in ls-files the hash is in the second column; in ls-tree it's in the third one start = output.Find(L' ', start + 1); if(start>0) newhash=output.Mid(start+1, 40); CGit subgit; subgit.m_CurrentDir = g_Git.CombinePath(pPath); int encode=CAppUtils::GetLogOutputEncode(&subgit); cmd.Format(L"git.exe log -n1 --pretty=format:\"%%s\" %s --", (LPCTSTR)newhash); bool toOK = !subgit.Run(cmd,&newsub,encode); bool dirty = false; if (rev1 == GIT_REV_ZERO && !(pPath->m_Action & CTGitPath::LOGACTIONS_DELETED)) { CString dirtyList; subgit.Run(L"git.exe status --porcelain", &dirtyList, encode); dirty = !dirtyList.IsEmpty(); } CSubmoduleDiffDlg submoduleDiffDlg; if (pPath->m_Action & CTGitPath::LOGACTIONS_DELETED) submoduleDiffDlg.SetDiff(pPath->GetWinPath(), false, newhash, newsub, toOK, oldhash, oldsub, false, dirty, DeleteSubmodule); else submoduleDiffDlg.SetDiff(pPath->GetWinPath(), false, oldhash, oldsub, true, newhash, newsub, toOK, dirty, NewSubmodule); submoduleDiffDlg.DoModal(); if (submoduleDiffDlg.IsRefresh()) return 1; return 0; } if (rev1 != GIT_REV_ZERO) CMessageBox::Show(nullptr, L"ls-tree output format error", L"TortoiseGit", MB_OK | MB_ICONERROR); else CMessageBox::Show(nullptr, L"ls-files output format error", L"TortoiseGit", MB_OK | MB_ICONERROR); return -1; }