CString SVNPatch::CheckPatchPath( const CString& path ) { // first check if the path already matches if (CountMatches(path) > (GetNumberOfFiles()/3)) return path; CProgressDlg progress; CString tmp; progress.SetTitle(IDS_PATCH_SEARCHPATHTITLE); progress.SetShowProgressBar(false); tmp.LoadString(IDS_PATCH_SEARCHPATHLINE1); progress.SetLine(1, tmp); progress.ShowModeless(AfxGetMainWnd()); // now go up the tree and try again CString upperpath = path; while (upperpath.ReverseFind('\\')>0) { upperpath = upperpath.Left(upperpath.ReverseFind('\\')); progress.SetLine(2, upperpath, true); if (progress.HasUserCancelled()) return path; if (CountMatches(upperpath) > (GetNumberOfFiles()/3)) return upperpath; } // still no match found. So try sub folders bool isDir = false; CString subpath; CDirFileEnum filefinder(path); while (filefinder.NextFile(subpath, &isDir)) { if (progress.HasUserCancelled()) return path; if (!isDir) continue; if (g_SVNAdminDir.IsAdminDirPath(subpath)) continue; progress.SetLine(2, subpath, true); if (CountMatches(subpath) > (GetNumberOfFiles()/3)) return subpath; } // if a patch file only contains newly added files // we can't really find the correct path. // But: we can compare paths strings without the filenames // and check if at least those match upperpath = path; while (upperpath.ReverseFind('\\')>0) { upperpath = upperpath.Left(upperpath.ReverseFind('\\')); progress.SetLine(2, upperpath, true); if (progress.HasUserCancelled()) return path; if (CountDirMatches(upperpath) > (GetNumberOfFiles()/3)) return upperpath; } return path; }
void CEditPropExternals::OnBnClickedFindhead() { CProgressDlg progDlg; progDlg.ShowModal(m_hWnd, TRUE); progDlg.SetTitle(IDS_EDITPROPS_PROG_FINDHEADTITLE); progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_PROG_FINDHEADROOTS))); DWORD count = 0; DWORD total = (DWORD)m_externals.size()*4; SVN svn; svn.SetPromptParentWindow(m_hWnd); SVNInfo svnInfo; svnInfo.SetPromptParentWindow(m_hWnd); for (auto it = m_externals.begin(); it != m_externals.end(); ++it) { progDlg.SetProgress(count++, total); if (progDlg.HasUserCancelled()) break; if (it->root.IsEmpty()) { CTSVNPath p = it->path; p.AppendPathString(it->targetDir); it->root = svn.GetRepositoryRoot(p); } } progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_PROG_FINDHEADREVS))); SVNLogHelper logHelper; for (auto it = m_externals.begin(); it != m_externals.end(); ++it) { progDlg.SetProgress(count, total); progDlg.SetLine(2, it->url, true); if (progDlg.HasUserCancelled()) break; count += 4; if (!it->root.IsEmpty()) { auto youngestRev = logHelper.GetYoungestRev(CTSVNPath(it->fullurl)); if (!youngestRev.IsValid()) it->headrev = svn.GetHEADRevision(CTSVNPath(it->fullurl), true); else it->headrev = youngestRev; } } progDlg.Stop(); m_ExtList.Invalidate(); }
bool SVNDiff::ShowCompare( const CTSVNPath& url1, const SVNRev& rev1, const CTSVNPath& url2, const SVNRev& rev2, SVNRev peg, bool ignoreprops, const CString& options, bool ignoreancestry /*= false*/, bool blame /*= false*/, svn_node_kind_t nodekind /*= svn_node_unknown*/ ) { CTSVNPath tempfile; CString mimetype; CProgressDlg progDlg; progDlg.SetTitle(IDS_APPNAME); progDlg.SetTime(false); m_pSVN->SetAndClearProgressInfo(&progDlg); CAppUtils::DiffFlags diffFlags; diffFlags.ReadOnly().AlternativeTool(m_bAlternativeTool); if ((m_pSVN->PathIsURL(url1))||(!rev1.IsWorking())||(!url1.IsEquivalentTo(url2))) { // no working copy path! progDlg.ShowModeless(GetHWND()); tempfile = CTempFiles::Instance().GetTempFilePath(false, url1); // first find out if the url points to a file or dir CString sRepoRoot; if ((nodekind != svn_node_dir)&&(nodekind != svn_node_file)) { progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROGRESS_INFO))); SVNInfo info; const SVNInfoData * data = info.GetFirstFileInfo(url1, (peg.IsValid() ? peg : m_headPeg), rev1, svn_depth_empty); if (data == NULL) { data = info.GetFirstFileInfo(url1, (peg.IsValid() ? peg : rev1), rev1, svn_depth_empty); if (data == NULL) { data = info.GetFirstFileInfo(url1, (peg.IsValid() ? peg : rev2), rev1, svn_depth_empty); if (data == NULL) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); info.ShowErrorDialog(GetHWND()); return false; } else { sRepoRoot = data->reposRoot; nodekind = data->kind; peg = peg.IsValid() ? peg : rev2; } } else { sRepoRoot = data->reposRoot; nodekind = data->kind; peg = peg.IsValid() ? peg : rev1; } } else { sRepoRoot = data->reposRoot; nodekind = data->kind; peg = peg.IsValid() ? peg : m_headPeg; } } else { sRepoRoot = m_pSVN->GetRepositoryRoot(url1); peg = peg.IsValid() ? peg : m_headPeg; } if (nodekind == svn_node_dir) { if (rev1.IsWorking()) { if (UnifiedDiff(tempfile, url1, rev1, url2, rev2, (peg.IsValid() ? peg : SVNRev::REV_WC), options)) { CString sWC; sWC.LoadString(IDS_DIFF_WORKINGCOPY); progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); return !!CAppUtils::StartExtPatch(tempfile, url1.GetDirectory(), sWC, url2.GetSVNPathString(), TRUE); } } else { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); CFileDiffDlg fdlg; fdlg.DoBlame(blame); if (url1.IsEquivalentTo(url2)) { fdlg.SetDiff(url1, (peg.IsValid() ? peg : m_headPeg), rev1, rev2, svn_depth_infinity, ignoreancestry); fdlg.DoModal(); } else { fdlg.SetDiff(url1, rev1, url2, rev2, svn_depth_infinity, ignoreancestry); fdlg.DoModal(); } } } else { if (url1.IsEquivalentTo(url2) && !ignoreprops) { svn_revnum_t baseRev = 0; DiffProps(url1, rev2, rev1, baseRev); } // diffing two revs of a file, so export two files CTSVNPath tempfile1 = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, blame ? CTSVNPath() : url1, rev1); CTSVNPath tempfile2 = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, blame ? CTSVNPath() : url2, rev2); m_pSVN->SetAndClearProgressInfo(&progDlg, true); // activate progress bar progDlg.FormatPathLine(1, IDS_PROGRESSGETFILEREVISION, (LPCTSTR)url1.GetUIFileOrDirectoryName(), (LPCTSTR)rev1.ToString()); CAppUtils::GetMimeType(url1, mimetype, rev1); CBlame blamer; blamer.SetAndClearProgressInfo(&progDlg, true); if (blame) { if (!blamer.BlameToFile(url1, 1, rev1, peg.IsValid() ? peg : rev1, tempfile1, options, TRUE, TRUE)) { if ((peg.IsValid())&&(blamer.GetSVNError()->apr_err != SVN_ERR_CLIENT_IS_BINARY_FILE)) { if (!blamer.BlameToFile(url1, 1, rev1, rev1, tempfile1, options, TRUE, TRUE)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); blamer.ShowErrorDialog(GetHWND()); return false; } } else { if (blamer.GetSVNError()->apr_err != SVN_ERR_CLIENT_IS_BINARY_FILE) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); } blamer.ShowErrorDialog(GetHWND()); if (blamer.GetSVNError()->apr_err == SVN_ERR_CLIENT_IS_BINARY_FILE) blame = false; else return false; } } } if (!blame) { bool tryWorking = (!m_pSVN->PathIsURL(url1) && rev1.IsWorking() && PathFileExists(url1.GetWinPath())); if (!m_pSVN->Export(url1, tempfile1, peg.IsValid() && !tryWorking ? peg : rev1, rev1)) { if (peg.IsValid()) { if (!m_pSVN->Export(url1, tempfile1, rev1, rev1)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } else { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } } SetFileAttributes(tempfile1.GetWinPath(), FILE_ATTRIBUTE_READONLY); progDlg.FormatPathLine(1, IDS_PROGRESSGETFILEREVISION, (LPCTSTR)url2.GetUIFileOrDirectoryName(), (LPCTSTR)rev2.ToString()); progDlg.SetProgress(50,100); if (blame) { if (!blamer.BlameToFile(url2, 1, rev2, peg.IsValid() ? peg : rev2, tempfile2, options, TRUE, TRUE)) { if (peg.IsValid()) { if (!blamer.BlameToFile(url2, 1, rev2, rev2, tempfile2, options, TRUE, TRUE)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } else { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } } else { if (!m_pSVN->Export(url2, tempfile2, peg.IsValid() ? peg : rev2, rev2)) { if (peg.IsValid()) { if (!m_pSVN->Export(url2, tempfile2, rev2, rev2)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } else { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } } SetFileAttributes(tempfile2.GetWinPath(), FILE_ATTRIBUTE_READONLY); progDlg.SetProgress(100,100); progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); CString revname1, revname2; if (url1.IsEquivalentTo(url2)) { revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetUIFileOrDirectoryName(), (LPCTSTR)rev1.ToString()); revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetUIFileOrDirectoryName(), (LPCTSTR)rev2.ToString()); } else { if (sRepoRoot.IsEmpty()) { revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetSVNPathString(), (LPCTSTR)rev1.ToString()); revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetSVNPathString(), (LPCTSTR)rev2.ToString()); } else { if (url1.IsUrl()) revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetSVNPathString().Mid(sRepoRoot.GetLength()), (LPCTSTR)rev1.ToString()); else revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetSVNPathString(), (LPCTSTR)rev1.ToString()); if (url2.IsUrl() && (url2.GetSVNPathString().Left(sRepoRoot.GetLength()).Compare(sRepoRoot) == 0)) revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetSVNPathString().Mid(sRepoRoot.GetLength()), (LPCTSTR)rev2.ToString()); else revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetSVNPathString(), (LPCTSTR)rev2.ToString()); } } return CAppUtils::StartExtDiff(tempfile1, tempfile2, revname1, revname2, url1, url2, rev1, rev2, peg, diffFlags.Blame(blame), m_JumpLine, L"", mimetype); } } else { // compare with working copy if (PathIsDirectory(url1.GetWinPath())) { if (UnifiedDiff(tempfile, url1, rev1, url1, rev2, (peg.IsValid() ? peg : SVNRev::REV_WC), options)) { CString sWC, sRev; sWC.LoadString(IDS_DIFF_WORKINGCOPY); sRev.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev2); progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); return !!CAppUtils::StartExtPatch(tempfile, url1.GetDirectory(), sWC, sRev, TRUE); } } else { ASSERT(rev1.IsWorking()); if (url1.IsEquivalentTo(url2) && !ignoreprops) { svn_revnum_t baseRev = 0; DiffProps(url1, rev1, rev2, baseRev); } m_pSVN->SetAndClearProgressInfo(&progDlg, true); // activate progress bar progDlg.ShowModeless(GetHWND()); progDlg.FormatPathLine(1, IDS_PROGRESSGETFILEREVISION, (LPCTSTR)url1.GetUIFileOrDirectoryName(), (LPCTSTR)rev2.ToString()); tempfile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, url1, rev2); if (blame) { CBlame blamer; if (!blamer.BlameToFile(url1, 1, rev2, (peg.IsValid() ? peg : SVNRev::REV_WC), tempfile, options, TRUE, TRUE)) { if (peg.IsValid()) { if (!blamer.BlameToFile(url1, 1, rev2, SVNRev::REV_WC, tempfile, options, TRUE, TRUE)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } else { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); CTSVNPath tempfile2 = CTempFiles::Instance().GetTempFilePath(false, url1); if (!blamer.BlameToFile(url1, 1, SVNRev::REV_WC, SVNRev::REV_WC, tempfile2, options, TRUE, TRUE)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } CString revname, wcname; revname.Format(L"%s Revision %ld", (LPCTSTR)url1.GetFilename(), (LONG)rev2); wcname.Format(IDS_DIFF_WCNAME, (LPCTSTR)url1.GetFilename()); m_pSVN->SetAndClearProgressInfo((HWND)NULL); return CAppUtils::StartExtDiff(tempfile, tempfile2, revname, wcname, url1, url2, rev1, rev2, peg, diffFlags, m_JumpLine, url1.GetFileOrDirectoryName(), L""); } else { if (!m_pSVN->Export(url1, tempfile, (peg.IsValid() ? peg : SVNRev::REV_WC), rev2)) { if (peg.IsValid()) { if (!m_pSVN->Export(url1, tempfile, SVNRev::REV_WC, rev2)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } else { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); CString revname, wcname; revname.Format(L"%s Revision %s", (LPCTSTR)url1.GetFilename(), (LPCTSTR)rev2.ToString()); wcname.Format(IDS_DIFF_WCNAME, (LPCTSTR)url1.GetFilename()); return CAppUtils::StartExtDiff(tempfile, url1, revname, wcname, url1, url1, rev2, rev1, peg, diffFlags, m_JumpLine, url1.GetFileOrDirectoryName(), L""); } } } m_pSVN->SetAndClearProgressInfo((HWND)NULL); return false; }
bool SVNDiff::UnifiedDiff(CTSVNPath& tempfile, const CTSVNPath& url1, const SVNRev& rev1, const CTSVNPath& url2, const SVNRev& rev2, const SVNRev& peg, const CString& options, bool bIgnoreAncestry /* = false */, bool bIgnoreProperties /* = true */) { tempfile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, CTSVNPath(L"Test.diff")); bool bIsUrl = !!SVN::PathIsURL(url1); CProgressDlg progDlg; progDlg.SetTitle(IDS_APPNAME); progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROGRESS_UNIFIEDDIFF))); progDlg.SetTime(false); m_pSVN->SetAndClearProgressInfo(&progDlg); progDlg.ShowModeless(GetHWND()); // find the root of the files CTSVNPathList plist; plist.AddPath(url1); plist.AddPath(url2); CTSVNPath relativeTo = plist.GetCommonRoot(); if (!relativeTo.IsUrl()) { if (!relativeTo.IsDirectory()) relativeTo = relativeTo.GetContainingDirectory(); } if (relativeTo.IsEmpty() && url1.Exists() && url2.IsUrl()) { // the source path exists, i.e. it's a local path, so // use this as the relative url relativeTo = url1.GetDirectory(); } // the 'relativeTo' path must be a path: svn throws an error if it's used for urls. else if ((!url2.IsEquivalentTo(url1) && (relativeTo.IsEquivalentTo(url1) || relativeTo.IsEquivalentTo(url2))) || url1.IsUrl() || url2.IsUrl()) relativeTo.Reset(); if ((!url1.IsEquivalentTo(url2))||((rev1.IsWorking() || rev1.IsBase())&&(rev2.IsWorking() || rev2.IsBase()))) { if (!m_pSVN->Diff(url1, rev1, url2, rev2, relativeTo, svn_depth_infinity, true, false, false, false, false, false, bIgnoreProperties, false, options, bIgnoreAncestry, tempfile)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } else { if (!m_pSVN->PegDiff(url1, (peg.IsValid() ? peg : (bIsUrl ? m_headPeg : SVNRev::REV_WC)), rev1, rev2, relativeTo, svn_depth_infinity, true, false, false, false, false, false, bIgnoreProperties, false, options, false, tempfile)) { if (!m_pSVN->Diff(url1, rev1, url2, rev2, relativeTo, svn_depth_infinity, true, false, false, false, false, false, bIgnoreProperties, false, options, false, tempfile)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } } } if (CAppUtils::CheckForEmptyDiff(tempfile)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); TaskDialog(GetHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_ERR_ERROROCCURED), MAKEINTRESOURCE(IDS_ERR_EMPTYDIFF), TDCBF_OK_BUTTON, TD_ERROR_ICON, NULL); return false; } progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); return true; }
bool CleanupCommand::Execute() { bool bRet = false; CCleanTypeDlg dlg; if( dlg.DoModal() == IDOK) { bool quotepath = g_Git.GetConfigValueBool(_T("core.quotepath")); CString cmd; cmd.Format(_T("git.exe clean")); if (dlg.m_bDryRun || !dlg.m_bNoRecycleBin) cmd += _T(" -n "); if(dlg.m_bDir) cmd += _T(" -d "); switch(dlg.m_CleanType) { case 0: cmd += _T(" -fx"); break; case 1: cmd += _T(" -f"); break; case 2: cmd += _T(" -fX"); break; } STRING_VECTOR submoduleList; SubmodulePayload payload(submoduleList); if (dlg.m_bSubmodules) { payload.basePath = CTGitPath(g_Git.m_CurrentDir).GetGitPathString(); if (pathList.GetCount() != 1 || pathList.GetCount() == 1 && !pathList[0].IsEmpty()) { for (int i = 0; i < pathList.GetCount(); ++i) { CString path; if (pathList[i].IsDirectory()) payload.prefixList.push_back(pathList[i].GetGitPathString()); else payload.prefixList.push_back(pathList[i].GetContainingDirectory().GetGitPathString()); } } if (!GetSubmodulePathList(payload)) return FALSE; std::sort(submoduleList.begin(), submoduleList.end()); } if (dlg.m_bDryRun || dlg.m_bNoRecycleBin) { while (true) { CProgressDlg progress; for (int i = 0; i < this->pathList.GetCount(); ++i) { CString path; if (this->pathList[i].IsDirectory()) path = pathList[i].GetGitPathString(); else path = pathList[i].GetContainingDirectory().GetGitPathString(); progress.m_GitDirList.push_back(g_Git.m_CurrentDir); progress.m_GitCmdList.push_back(cmd + _T(" \"") + path + _T("\"")); } if (dlg.m_bSubmodules) { for (CString dir : submoduleList) { progress.m_GitDirList.push_back(CTGitPath(dir).GetWinPathString()); progress.m_GitCmdList.push_back(cmd); } } INT_PTR idRetry = -1; if (!dlg.m_bDryRun) idRetry = progress.m_PostFailCmdList.Add(CString(MAKEINTRESOURCE(IDS_MSGBOX_RETRY))); INT_PTR result = progress.DoModal(); if (result == IDOK) return TRUE; if (progress.m_GitStatus && result == IDC_PROGRESS_BUTTON1 + idRetry) continue; break; } } else { CSysProgressDlg sysProgressDlg; sysProgressDlg.SetAnimation(IDR_CLEANUPANI); sysProgressDlg.SetTitle(CString(MAKEINTRESOURCE(IDS_APPNAME))); sysProgressDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1))); sysProgressDlg.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROGRESSWAIT))); sysProgressDlg.SetShowProgressBar(false); sysProgressDlg.ShowModeless((HWND)NULL, true); CTGitPathList delList; for (size_t i = 0; i <= submoduleList.size(); ++i) { CGit git; CGit *pGit; if (i == 0) pGit = &g_Git; else { git.m_CurrentDir = submoduleList[i - 1]; pGit = &git; } CString cmdout, cmdouterr; if (pGit->Run(cmd, &cmdout, &cmdouterr, CP_UTF8)) { MessageBox(nullptr, cmdouterr, _T("TortoiseGit"), MB_ICONERROR); return FALSE; } if (sysProgressDlg.HasUserCancelled()) { CMessageBox::Show(nullptr, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK); return FALSE; } int pos = 0; CString token = cmdout.Tokenize(_T("\n"), pos); while (!token.IsEmpty()) { if (token.Mid(0, 13) == _T("Would remove ")) { CString tempPath = token.Mid(13).TrimRight(); if (quotepath) { tempPath = UnescapeQuotePath(tempPath.Trim(_T('"'))); } if (i == 0) delList.AddPath(CTGitPath(tempPath)); else delList.AddPath(CTGitPath(submoduleList[i - 1] + "/" + tempPath)); } token = cmdout.Tokenize(_T("\n"), pos); } if (sysProgressDlg.HasUserCancelled()) { CMessageBox::Show(nullptr, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK); return FALSE; } } delList.DeleteAllFiles(true, false); sysProgressDlg.Stop(); } } #if 0 CProgressDlg progress; progress.SetTitle(IDS_PROC_CLEANUP); progress.SetAnimation(IDR_CLEANUPANI); progress.SetShowProgressBar(false); progress.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1))); progress.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO2))); progress.ShowModeless(hwndExplorer); CString strSuccessfullPaths, strFailedPaths; for (int i=0; i<pathList.GetCount(); ++i) { SVN svn; if (!svn.CleanUp(pathList[i])) { strFailedPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n"); strFailedPaths += svn.GetLastErrorMessage() + _T("\n\n"); } else { strSuccessfullPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n"); // after the cleanup has finished, crawl the path downwards and send a change // notification for every directory to the shell. This will update the // overlays in the left tree view of the explorer. CDirFileEnum crawler(pathList[i].GetWinPathString()); CString sPath; bool bDir = false; CTSVNPathList updateList; while (crawler.NextFile(sPath, &bDir)) { if ((bDir) && (!g_SVNAdminDir.IsAdminDirPath(sPath))) { updateList.AddPath(CTSVNPath(sPath)); } } updateList.AddPath(pathList[i]); CShellUpdater::Instance().AddPathsForUpdate(updateList); CShellUpdater::Instance().Flush(); updateList.SortByPathname(true); for (INT_PTR i=0; i<updateList.GetCount(); ++i) { SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, updateList[i].GetWinPath(), NULL); CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": notify change for path %s\n"), updateList[i].GetWinPath()); } } } progress.Stop(); CString strMessage; if ( !strSuccessfullPaths.IsEmpty() ) { CString tmp; tmp.Format(IDS_PROC_CLEANUPFINISHED, (LPCTSTR)strSuccessfullPaths); strMessage += tmp; bRet = true; } if ( !strFailedPaths.IsEmpty() ) { if (!strMessage.IsEmpty()) strMessage += _T("\n"); CString tmp; tmp.Format(IDS_PROC_CLEANUPFINISHED_FAILED, (LPCTSTR)strFailedPaths); strMessage += tmp; bRet = false; } CMessageBox::Show(hwndExplorer, strMessage, _T("TortoiseGit"), MB_OK | (strFailedPaths.IsEmpty()?MB_ICONINFORMATION:MB_ICONERROR)); #endif CShellUpdater::Instance().Flush(); return bRet; }
void CEditPropExternals::OnContextMenu(CWnd* /*pWnd*/, CPoint point) { int selIndex = m_ExtList.GetSelectionMark(); if (selIndex < 0) return; // nothing selected, nothing to do with a context menu int selCount = m_ExtList.GetSelectedCount(); if (selCount <= 0) return; // nothing selected, nothing to do with a context menu // if the context menu is invoked through the keyboard, we have to use // a calculated position on where to anchor the menu on if ((point.x == -1) && (point.y == -1)) { CRect rect; m_ExtList.GetItemRect(selIndex, &rect, LVIR_LABEL); m_ExtList.ClientToScreen(&rect); point = rect.CenterPoint(); } bool haveHead = true; POSITION pos = m_ExtList.GetFirstSelectedItemPosition(); while (pos) { int index = m_ExtList.GetNextSelectedItem(pos); if ((index >= 0)&&(index < (int)m_externals.size())) { if (m_externals[index].headrev == SVN_INVALID_REVNUM) { haveHead = false; break; } } } CIconMenu popup; if (popup.CreatePopupMenu()) { if (haveHead) popup.AppendMenuIcon(CMD_ADJUST, IDS_EDITPROPS_ADJUST_TO_HEAD); else popup.AppendMenuIcon(CMD_FETCH_AND_ADJUST, IDS_EDITPROPS_FETCH_AND_ADJUST_TO_HEAD); int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON, point.x, point.y, this, 0); switch (cmd) { case CMD_FETCH_AND_ADJUST: { SVN svn; svn.SetPromptParentWindow(m_hWnd); SVNInfo svnInfo; svnInfo.SetPromptParentWindow(m_hWnd); SVNLogHelper logHelper; CProgressDlg progDlg; progDlg.ShowModal(m_hWnd, TRUE); progDlg.SetTitle(IDS_EDITPROPS_PROG_FINDHEADTITLE); progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_PROG_FINDHEADREVS))); DWORD count = 0; DWORD total = m_ExtList.GetSelectedCount(); POSITION p = m_ExtList.GetFirstSelectedItemPosition(); while (p) { int index = m_ExtList.GetNextSelectedItem(p); progDlg.SetProgress(count++, total); if ((index >= 0)&&(index < (int)m_externals.size())) { progDlg.SetLine(2, m_externals[index].url, true); if (m_externals[index].headrev == SVN_INVALID_REVNUM) { if (m_externals[index].root.IsEmpty()) { CTSVNPath path_ = m_externals[index].path; path_.AppendPathString(m_externals[index].targetDir); m_externals[index].root = svn.GetRepositoryRoot(path_); } auto fullurl = CTSVNPath(m_externals[index].fullurl); auto youngestRev = logHelper.GetYoungestRev(fullurl); if (!youngestRev.IsValid()) m_externals[index].headrev = svn.GetHEADRevision(fullurl, true); else m_externals[index].headrev = youngestRev; } } } progDlg.Stop(); } // intentional fall through case CMD_ADJUST: { POSITION p = m_ExtList.GetFirstSelectedItemPosition(); while (p) { int index = m_ExtList.GetNextSelectedItem(p); if ((index >= 0)&&(index < (int)m_externals.size())) { if (m_externals[index].headrev != SVN_INVALID_REVNUM) { if (m_externals[index].revision.kind == svn_opt_revision_number) { m_externals[index].revision.value.number = -1; m_externals[index].revision.kind = svn_opt_revision_unspecified; } m_externals[index].pegrevision.value.number = m_externals[index].headrev; m_externals[index].pegrevision.kind = svn_opt_revision_number; } } } m_ExtList.Invalidate(); } break; } } }
bool CleanupCommand::Execute() { bool bRet = false; CCleanTypeDlg dlg; if( dlg.DoModal() == IDOK) { bool quotepath = g_Git.GetConfigValueBool(_T("core.quotepath")); CString cmd; cmd.Format(_T("git clean")); if (dlg.m_bDryRun || !dlg.m_bNoRecycleBin) cmd += _T(" -n "); if(dlg.m_bDir) cmd += _T(" -d "); switch(dlg.m_CleanType) { case 0: cmd += _T(" -fx"); break; case 1: cmd += _T(" -f"); break; case 2: cmd += _T(" -fX"); break; } if (dlg.m_bDryRun || dlg.m_bNoRecycleBin) { CProgressDlg progress; for (int i = 0; i < this->pathList.GetCount(); ++i) { CString path; if (this->pathList[i].IsDirectory()) path = pathList[i].GetGitPathString(); else path = pathList[i].GetContainingDirectory().GetGitPathString(); progress.m_GitCmdList.push_back(cmd + _T(" \"") + path + _T("\"")); } if (progress.DoModal()==IDOK) return TRUE; } else { CSysProgressDlg sysProgressDlg; sysProgressDlg.SetAnimation(IDR_CLEANUPANI); sysProgressDlg.SetTitle(CString(MAKEINTRESOURCE(IDS_APPNAME))); sysProgressDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1))); sysProgressDlg.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROGRESSWAIT))); sysProgressDlg.SetShowProgressBar(false); sysProgressDlg.ShowModeless((HWND)NULL, true); CString cmdout, cmdouterr; if (g_Git.Run(cmd, &cmdout, &cmdouterr, CP_UTF8)) { MessageBox(NULL, cmdouterr, _T("TortoiseGit"), MB_ICONERROR); return FALSE; } if (sysProgressDlg.HasUserCancelled()) { CMessageBox::Show(NULL, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK); return FALSE; } int pos = 0; CString token = cmdout.Tokenize(_T("\n"), pos); CTGitPathList delList; while (!token.IsEmpty()) { if (token.Mid(0, 13) == _T("Would remove ")) { CString tempPath = token.Mid(13).TrimRight(); if (quotepath) { tempPath = UnescapeQuotePath(tempPath.Trim(_T('"'))); } delList.AddPath(CTGitPath(tempPath)); } token = cmdout.Tokenize(_T("\n"), pos); } if (sysProgressDlg.HasUserCancelled()) { CMessageBox::Show(NULL, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK); return FALSE; } delList.DeleteAllFiles(true, false); sysProgressDlg.Stop(); } } #if 0 CProgressDlg progress; progress.SetTitle(IDS_PROC_CLEANUP); progress.SetAnimation(IDR_CLEANUPANI); progress.SetShowProgressBar(false); progress.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1))); progress.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO2))); progress.ShowModeless(hwndExplorer); CString strSuccessfullPaths, strFailedPaths; for (int i=0; i<pathList.GetCount(); ++i) { SVN svn; if (!svn.CleanUp(pathList[i])) { strFailedPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n"); strFailedPaths += svn.GetLastErrorMessage() + _T("\n\n"); } else { strSuccessfullPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n"); // after the cleanup has finished, crawl the path downwards and send a change // notification for every directory to the shell. This will update the // overlays in the left tree view of the explorer. CDirFileEnum crawler(pathList[i].GetWinPathString()); CString sPath; bool bDir = false; CTSVNPathList updateList; while (crawler.NextFile(sPath, &bDir)) { if ((bDir) && (!g_SVNAdminDir.IsAdminDirPath(sPath))) { updateList.AddPath(CTSVNPath(sPath)); } } updateList.AddPath(pathList[i]); CShellUpdater::Instance().AddPathsForUpdate(updateList); CShellUpdater::Instance().Flush(); updateList.SortByPathname(true); for (INT_PTR i=0; i<updateList.GetCount(); ++i) { SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, updateList[i].GetWinPath(), NULL); ATLTRACE(_T("notify change for path %s\n"), updateList[i].GetWinPath()); } } } progress.Stop(); CString strMessage; if ( !strSuccessfullPaths.IsEmpty() ) { CString tmp; tmp.Format(IDS_PROC_CLEANUPFINISHED, (LPCTSTR)strSuccessfullPaths); strMessage += tmp; bRet = true; } if ( !strFailedPaths.IsEmpty() ) { if (!strMessage.IsEmpty()) strMessage += _T("\n"); CString tmp; tmp.Format(IDS_PROC_CLEANUPFINISHED_FAILED, (LPCTSTR)strFailedPaths); strMessage += tmp; bRet = false; } CMessageBox::Show(hwndExplorer, strMessage, _T("TortoiseGit"), MB_OK | (strFailedPaths.IsEmpty()?MB_ICONINFORMATION:MB_ICONERROR)); #endif CShellUpdater::Instance().Flush(); return bRet; }
bool ConflictEditorCommand::Execute() { CTSVNPath merge = cmdLinePath; CTSVNPath directory = merge.GetDirectory(); bool bRet = false; bool bAlternativeTool = !!parser.HasKey(L"alternative"); // Use Subversion 1.10 API to resolve possible tree conlifcts. SVNConflictInfo conflict; if (!conflict.Get(merge)) { conflict.ShowErrorDialog(GetExplorerHWND()); return false; } // Resolve tree conflicts first. if (conflict.HasTreeConflict()) { CProgressDlg progressDlg; progressDlg.SetTitle(IDS_PROC_EDIT_TREE_CONFLICTS); CString sProgressLine; sProgressLine.LoadString(IDS_PROGRS_FETCHING_TREE_CONFLICT_INFO); progressDlg.SetLine(1, sProgressLine); progressDlg.SetShowProgressBar(false); progressDlg.ShowModal(GetExplorerHWND(), FALSE); conflict.SetProgressDlg(&progressDlg); if (!conflict.FetchTreeDetails()) { // Ignore errors while fetching additional tree conflict information. // Use still may want to resolve it manually. conflict.ClearSVNError(); } progressDlg.Stop(); conflict.SetProgressDlg(NULL); CNewTreeConflictEditorDlg dlg; dlg.SetConflictInfo(&conflict); dlg.DoModal(GetExplorerHWND()); if (dlg.IsCancelled()) return false; if (dlg.GetResult() == svn_client_conflict_option_postpone) return false; // Send notififcation that status may be changed. We cannot use // '/resolvemsghwnd' here because satus of multiple files may be changed // during tree conflict resolution. if (parser.HasVal(L"refreshmsghwnd")) { HWND refreshMsgWnd = (HWND)parser.GetLongLongVal(L"refreshmsghwnd"); UINT WM_REFRESH_STATUS_MSG = RegisterWindowMessage(L"TORTOISESVN_REFRESH_STATUS_MSG"); ::PostMessage(refreshMsgWnd, WM_REFRESH_STATUS_MSG, 0, 0); } } // we have the conflicted file (%merged) // now look for the other required files SVNInfo info; const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev()); if (pInfoData == NULL) return false; for (auto conflIt = pInfoData->conflicts.cbegin(); conflIt != pInfoData->conflicts.cend(); ++conflIt) { switch (conflIt->kind) { case svn_wc_conflict_kind_text: { // we have a text conflict, use our merge tool to resolve the conflict CTSVNPath theirs = CTSVNPath(conflIt->conflict_new); CTSVNPath mine = CTSVNPath(conflIt->conflict_wrk); CTSVNPath base = CTSVNPath(conflIt->conflict_old); if (mine.IsEmpty()) mine = merge; bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), base, theirs, mine, merge, true, CString(), CString(), CString(), CString(), merge.GetFileOrDirectoryName()); } break; case svn_wc_conflict_kind_property: { // we have a property conflict CTSVNPath prej(conflIt->prejfile); CEditPropConflictDlg dlg; dlg.SetPrejFile(prej); dlg.SetConflictedItem(merge); dlg.SetPropertyName(conflIt->propname); dlg.SetPropValues(conflIt->propvalue_base, conflIt->propvalue_working, conflIt->propvalue_incoming_old, conflIt->propvalue_incoming_new); bRet = (dlg.DoModal() != IDCANCEL); } break; case svn_wc_conflict_kind_tree: { CTSVNPath treeConflictPath = CTSVNPath(conflIt->treeconflict_path); CTreeConflictEditorDlg dlg; dlg.SetPath(treeConflictPath); dlg.SetConflictLeftSources(conflIt->src_left_version_url, conflIt->src_left_version_path, conflIt->src_left_version_rev, conflIt->src_left_version_kind); dlg.SetConflictRightSources(conflIt->src_right_version_url, conflIt->src_right_version_path, conflIt->src_right_version_rev, conflIt->src_right_version_kind); dlg.SetConflictReason(conflIt->treeconflict_reason); dlg.SetConflictAction(conflIt->treeconflict_action); dlg.SetConflictOperation(conflIt->treeconflict_operation); dlg.SetKind(conflIt->treeconflict_nodekind); INT_PTR dlgRet = dlg.DoModal(); bRet = (dlgRet != IDCANCEL); } break; } } return bRet; }