bool RemoveCommand::Execute() { bool bRet = false; // removing items from a working copy is done item-by-item so we // have a chance to show a progress bar // // removing items from an URL in the repository requires that we // ask the user for a log message. #if 0 BOOL bForce = FALSE; SVN svn; if ((!pathList.IsEmpty())&&(SVN::PathIsURL(pathList[0]))) { // Delete using URL's, not wc paths svn.SetPromptApp(&theApp); CInputLogDlg dlg; CString sUUID; svn.GetRepositoryRootAndUUID(pathList[0], sUUID); dlg.SetUUID(sUUID); CString sHint; if (pathList.GetCount() == 1) sHint.Format(IDS_INPUT_REMOVEONE, (LPCTSTR)pathList[0].GetSVNPathString()); else sHint.Format(IDS_INPUT_REMOVEMORE, pathList.GetCount()); dlg.SetActionText(sHint); if (dlg.DoModal()==IDOK) { if (!svn.Remove(pathList, TRUE, parser.HasKey(_T("keep")), dlg.GetLogMessage())) { CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); return FALSE; } return true; } return FALSE; } else { for (int nPath = 0; nPath < pathList.GetCount(); ++nPath) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": remove file %s\n"), (LPCTSTR)pathList[nPath].GetUIPathString()); // even though SVN::Remove takes a list of paths to delete at once // we delete each item individually so we can prompt the user // if something goes wrong or unversioned/modified items are // to be deleted CTSVNPathList removePathList(pathList[nPath]); if (bForce) { CTSVNPath delPath = removePathList[0]; delPath.Delete(true); } if (!svn.Remove(removePathList, bForce, parser.HasKey(_T("keep")))) { if ((svn.Err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) || (svn.Err->apr_err == SVN_ERR_CLIENT_MODIFIED)) { CString msg, yes, no, yestoall; if (pathList[nPath].IsDirectory()) { msg.Format(IDS_PROC_REMOVEFORCEFOLDER, pathList[nPath].GetWinPath()); } else { msg.Format(IDS_PROC_REMOVEFORCE, (LPCTSTR)svn.GetLastErrorMessage()); } yes.LoadString(IDS_MSGBOX_YES); no.LoadString(IDS_MSGBOX_NO); yestoall.LoadString(IDS_PROC_YESTOALL); UINT ret = CMessageBox::Show(hwndExplorer, msg, _T("TortoiseGit"), 2, IDI_ERROR, yes, no, yestoall); if (ret == 3) bForce = TRUE; if ((ret == 1)||(ret==3)) { CTSVNPath delPath = removePathList[0]; delPath.Delete(true); if (!svn.Remove(removePathList, TRUE, parser.HasKey(_T("keep")))) { CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); } else bRet = true; } } else CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); } } } if (bRet) CShellUpdater::Instance().AddPathsForUpdate(pathList); #endif //we don't ask user about if keep local copy. //because there are command "Delete(keep local copy)" at explore context menu //int key=CMessageBox::Show(hwndExplorer, _T("File will removed from version control\r\n Do you want to keep local copy"), _T("TortoiseGit"), MB_ICONINFORMATION|MB_YESNOCANCEL); //if(key == IDCANCEL) CString format; BOOL keepLocal = parser.HasKey(_T("keep")); if (pathList.GetCount() > 1) format.Format(keepLocal ? IDS_WARN_DELETE_MANY_FROM_INDEX : IDS_WARN_DELETE_MANY, pathList.GetCount()); else format.Format(keepLocal ? IDS_WARN_DELETE_ONE_FROM_INDEX : IDS_WARN_REMOVE, pathList[0].GetGitPathString()); if (CMessageBox::Show(hwndExplorer, format, _T("TortoiseGit"), 2, IDI_QUESTION, CString(MAKEINTRESOURCE(IDS_REMOVEBUTTON)), CString(MAKEINTRESOURCE(IDS_MSGBOX_ABORT))) == 2) return false; if (keepLocal) { format= _T("git.exe rm -r -f --cached -- \"%s\""); } else { format=_T("git.exe rm -r -f -- \"%s\""); } CString output; CString cmd; int nPath; for (nPath = 0; nPath < pathList.GetCount(); ++nPath) { cmd.Format(format, (LPCTSTR)pathList[nPath].GetGitPathString()); if (g_Git.Run(cmd, &output, CP_UTF8)) { if (CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), 2, IDI_ERROR, CString(MAKEINTRESOURCE(IDS_IGNOREBUTTON)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON))) == 2) return FALSE; } } output.Format(IDS_PROC_FILESREMOVED, nPath); CShellUpdater::Instance().AddPathsForUpdate(pathList); CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_ICONINFORMATION|MB_OK); CShellUpdater::Instance().Flush(); return bRet; }
bool RenameCommand::Execute() { bool bRet = false; CString filename = cmdLinePath.GetFileOrDirectoryName(); CString basePath = cmdLinePath.GetContainingDirectory().GetGitPathString(); //::SetCurrentDirectory(basePath); // show the rename dialog until the user either cancels or enters a new // name (one that's different to the original name CString sNewName; do { CRenameDlg dlg; dlg.m_name = filename; if (dlg.DoModal() != IDOK) return FALSE; sNewName = dlg.m_name; } while(PathIsRelative(sNewName) && !PathIsURL(sNewName) && (sNewName.IsEmpty() || (sNewName.Compare(filename)==0))); if(!basePath.IsEmpty()) sNewName=basePath+"/"+sNewName; CString cmd; CString output; cmd.Format(_T("git.exe mv -- \"%s\" \"%s\""), cmdLinePath.GetGitPathString(), sNewName); if(g_Git.Run(cmd,&output,CP_ACP)) { CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_OK); } CTGitPath newpath; newpath.SetFromGit(sNewName); CShellUpdater::Instance().AddPathForUpdate(newpath); #if 0 TRACE(_T("rename file %s to %s\n"), (LPCTSTR)cmdLinePath.GetWinPathString(), (LPCTSTR)sNewName); CTSVNPath destinationPath(basePath); if (PathIsRelative(sNewName) && !PathIsURL(sNewName)) destinationPath.AppendPathString(sNewName); else destinationPath.SetFromWin(sNewName); // check if a rename just with case is requested: that's not possible on windows file systems // and we have to show an error. if (cmdLinePath.GetWinPathString().CompareNoCase(destinationPath.GetWinPathString())==0) { //rename to the same file! CString sHelpPath = theApp.m_pszHelpFilePath; sHelpPath += _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase"); CMessageBox::Show(hwndExplorer, IDS_PROC_CASERENAME, IDS_APPNAME, MB_OK|MB_HELP, sHelpPath); } else { CString sMsg; if (SVN::PathIsURL(cmdLinePath)) { // rename an URL. // Ask for a commit message, then rename directly in // the repository CInputLogDlg input; CString sUUID; SVN svn; svn.GetRepositoryRootAndUUID(cmdLinePath, sUUID); input.SetUUID(sUUID); CString sHint; sHint.Format(IDS_INPUT_MOVE, (LPCTSTR)cmdLinePath.GetSVNPathString(), (LPCTSTR)destinationPath.GetSVNPathString()); input.SetActionText(sHint); if (input.DoModal() == IDOK) { sMsg = input.GetLogMessage(); } else { return FALSE; } } if ((cmdLinePath.IsDirectory())||(pathList.GetCount() > 1)) { // renaming a directory can take a while: use the // progress dialog to show the progress of the renaming // operation. CSVNProgressDlg progDlg; progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Rename); if (parser.HasVal(_T("closeonend"))) progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend"))); progDlg.SetPathList(pathList); progDlg.SetUrl(destinationPath.GetWinPathString()); progDlg.SetCommitMessage(sMsg); progDlg.SetRevision(SVNRev::REV_WC); progDlg.DoModal(); bRet = !progDlg.DidErrorsOccur(); } else { SVN svn; CString sFilemask = cmdLinePath.GetFilename(); if (sFilemask.ReverseFind('.')>=0) { sFilemask = sFilemask.Left(sFilemask.ReverseFind('.')); } else sFilemask.Empty(); CString sNewMask = sNewName; if (sNewMask.ReverseFind('.'>=0)) { sNewMask = sNewMask.Left(sNewMask.ReverseFind('.')); } else sNewMask.Empty(); if (((!sFilemask.IsEmpty()) && (parser.HasKey(_T("noquestion")))) || (cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0)) { if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg)) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); } else bRet = true; } else { // when refactoring, multiple files have to be renamed // at once because those files belong together. // e.g. file.aspx, file.aspx.cs, file.aspx.resx CTSVNPathList renlist; CSimpleFileFind filefind(cmdLinePath.GetDirectory().GetWinPathString(), sFilemask+_T(".*")); while (filefind.FindNextFileNoDots()) { if (!filefind.IsDirectory()) renlist.AddPath(CTSVNPath(filefind.GetFilePath())); } if (renlist.GetCount()<=1) { // we couldn't find any other matching files // just do the default... if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg)) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); } else { bRet = true; CShellUpdater::Instance().AddPathForUpdate(destinationPath); } } else { std::map<CString, CString> renmap; CString sTemp; CString sRenList; for (int i=0; i<renlist.GetCount(); ++i) { CString sFilename = renlist[i].GetFilename(); CString sNewFilename = sNewMask + sFilename.Mid(sFilemask.GetLength()); sTemp.Format(_T("\n%s -> %s"), (LPCTSTR)sFilename, (LPCTSTR)sNewFilename); if (!renlist[i].IsEquivalentTo(cmdLinePath)) sRenList += sTemp; renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename; } CString sRenameMultipleQuestion; sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList); UINT idret = CMessageBox::Show(hwndExplorer, sRenameMultipleQuestion, _T("TortoiseGit"), MB_ICONQUESTION|MB_YESNOCANCEL); if (idret == IDYES) { CProgressDlg progress; progress.SetTitle(IDS_PROC_MOVING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); DWORD count = 1; for (std::map<CString, CString>::iterator it=renmap.begin(); it != renmap.end(); ++it) { progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, (LPCTSTR)it->first); progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, (LPCTSTR)it->second); progress.SetProgress(count, renmap.size()); if (!svn.Move(CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), TRUE, sMsg)) { if (svn.Err->apr_err == SVN_ERR_ENTRY_NOT_FOUND) { bRet = !!MoveFile(it->first, it->second); } else { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); bRet = false; } } else { bRet = true; CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it->second)); } } progress.Stop(); } else if (idret == IDNO) { // no, user wants to just rename the file he selected if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg)) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); } else { bRet = true; CShellUpdater::Instance().AddPathForUpdate(destinationPath); } } else if (idret == IDCANCEL) { // nothing } } } } } #endif CShellUpdater::Instance().Flush(); return bRet; }
bool DropExportCommand::Execute() { bool bRet = true; #if 0 CString droppath = parser.GetVal(_T("droptarget")); if (CTGitPath(droppath).IsAdminDir()) return false; SVN svn; if ((pathList.GetCount() == 1)&& (pathList[0].IsEquivalentTo(CTSVNPath(droppath)))) { // exporting to itself: // remove all svn admin dirs, effectively unversion the 'exported' folder. CString msg; msg.Format(IDS_PROC_EXPORTUNVERSION, (LPCTSTR)droppath); if (CMessageBox::Show(hwndExplorer, msg, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNO) == IDYES) { CProgressDlg progress; progress.SetTitle(IDS_PROC_UNVERSION); progress.SetAnimation(IDR_MOVEANI); progress.FormatNonPathLine(1, IDS_SVNPROGRESS_EXPORTINGWAIT); progress.SetTime(true); progress.ShowModeless(hwndExplorer); std::vector<CTSVNPath> removeVector; CDirFileEnum lister(droppath); CString srcFile; bool bFolder = false; while (lister.NextFile(srcFile, &bFolder)) { CTSVNPath item(srcFile); if ((bFolder)&&(g_SVNAdminDir.IsAdminDirName(item.GetFileOrDirectoryName()))) { removeVector.push_back(item); } } DWORD count = 0; for (std::vector<CTSVNPath>::iterator it = removeVector.begin(); (it != removeVector.end()) && (!progress.HasUserCancelled()); ++it) { progress.FormatPathLine(1, IDS_SVNPROGRESS_UNVERSION, (LPCTSTR)it->GetWinPath()); progress.SetProgress(count, removeVector.size()); count++; it->Delete(false); } progress.Stop(); } else return false; } else { for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { CString dropper = droppath + _T("\\") + pathList[nPath].GetFileOrDirectoryName(); if (PathFileExists(dropper)) { CString sMsg; CString sBtn1(MAKEINTRESOURCE(IDS_PROC_OVERWRITEEXPORT_OVERWRITE)); CString sBtn2(MAKEINTRESOURCE(IDS_PROC_OVERWRITEEXPORT_RENAME)); CString sBtn3(MAKEINTRESOURCE(IDS_PROC_OVERWRITEEXPORT_CANCEL)); sMsg.Format(IDS_PROC_OVERWRITEEXPORT, (LPCTSTR)dropper); UINT ret = CMessageBox::Show(hwndExplorer, sMsg, _T("TortoiseSVN"), MB_DEFBUTTON1, IDI_QUESTION, sBtn1, sBtn2, sBtn3); if (ret==2) { dropper.Format(IDS_PROC_EXPORTFOLDERNAME, (LPCTSTR)droppath, (LPCTSTR)pathList[nPath].GetFileOrDirectoryName()); int exportcount = 1; while (PathFileExists(dropper)) { dropper.Format(IDS_PROC_EXPORTFOLDERNAME2, (LPCTSTR)droppath, exportcount++, (LPCTSTR)pathList[nPath].GetFileOrDirectoryName()); } } else if (ret == 3) return false; } if (!svn.Export(pathList[nPath], CTSVNPath(dropper), SVNRev::REV_WC ,SVNRev::REV_WC, FALSE, FALSE, svn_depth_infinity, hwndExplorer, parser.HasKey(_T("extended")))) { CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_OK | MB_ICONERROR); bRet = false; } } } #endif return bRet; }
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; }
bool RemoveCommand::Execute() { bool bRet = false; // removing items from a working copy is done item-by-item so we // have a chance to show a progress bar // // removing items from an URL in the repository requires that we // ask the user for a log message. SVN svn; if ((pathList.GetCount())&&(SVN::PathIsURL(pathList[0]))) { // Delete using URL's, not wc paths svn.SetPromptApp(&theApp); CInputLogDlg dlg; CString sUUID; svn.GetRepositoryRootAndUUID(pathList[0], true, sUUID); dlg.SetUUID(sUUID); CString sHint; if (pathList.GetCount() == 1) sHint.Format(IDS_INPUT_REMOVEONE, (LPCTSTR)pathList[0].GetSVNPathString()); else sHint.Format(IDS_INPUT_REMOVEMORE, pathList.GetCount()); dlg.SetActionText(sHint); if (dlg.DoModal()==IDOK) { if (!svn.Remove(pathList, true, !!parser.HasKey(L"keep"), dlg.GetLogMessage())) { svn.ShowErrorDialog(GetExplorerHWND(), pathList.GetCommonDirectory()); return false; } return true; } return false; } else { bool bForce = false; for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": remove file %s\n", (LPCTSTR)pathList[nPath].GetUIPathString()); // even though SVN::Remove takes a list of paths to delete at once // we delete each item individually so we can prompt the user // if something goes wrong or unversioned/modified items are // to be deleted CTSVNPathList removePathList(pathList[nPath]); if ((bForce)&&(!parser.HasKey(L"keep"))) { CTSVNPath delPath = removePathList[0]; if (!delPath.IsDirectory()) delPath.Delete(true); // note: we don't move folders to the trash bin, so they can't // get restored anymore - svn removes *all* files in a removed // folder, even modified and unversioned ones // We could move the folders here to the trash bin too, but then // the folder would be gone and will require a recursive commit. // Of course: a solution would be to first create a copy of the folder, // move the original folder to the trash, then rename the copied folder // to the original name, then let svn delete the folder - but // that would just take too much time for bigger folders... } if (!svn.Remove(removePathList, bForce, !!parser.HasKey(L"keep"))) { if ((svn.GetSVNError()->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) || (svn.GetSVNError()->apr_err == SVN_ERR_CLIENT_MODIFIED)) { UINT ret = 0; CString msg; if (pathList[nPath].IsDirectory()) msg.Format(IDS_PROC_REMOVEFORCE_TASK1_2, (LPCTSTR)svn.GetLastErrorMessage(0), (LPCTSTR)pathList[nPath].GetFileOrDirectoryName()); else msg.Format(IDS_PROC_REMOVEFORCE_TASK1, (LPCTSTR)svn.GetLastErrorMessage(0), (LPCTSTR)pathList[nPath].GetFileOrDirectoryName()); CTaskDialog taskdlg(msg, CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK2)), L"TortoiseSVN", 0, TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW); taskdlg.AddCommandControl(IDYES, CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK3))); taskdlg.AddCommandControl(IDNO, CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK4))); taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON); taskdlg.SetVerificationCheckboxText(CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK5))); taskdlg.SetDefaultCommandControl(IDNO); taskdlg.SetMainIcon(TD_WARNING_ICON); ret = (UINT)taskdlg.DoModal(GetExplorerHWND()); if (taskdlg.GetVerificationCheckboxState()) bForce = true; if (ret == IDYESTOALL) bForce = true; if ((ret == IDYES)||(ret==IDYESTOALL)) { if (!parser.HasKey(L"keep")) { CTSVNPath delPath = removePathList[0]; if (!delPath.IsDirectory()) delPath.Delete(true); // note: see comment for the delPath.Delete() above } if (!svn.Remove(removePathList, true, !!parser.HasKey(L"keep"))) { svn.ShowErrorDialog(GetExplorerHWND(), removePathList.GetCommonDirectory()); } else bRet = true; } } else svn.ShowErrorDialog(GetExplorerHWND(), removePathList.GetCommonDirectory()); } } } if (bRet) CShellUpdater::Instance().AddPathsForUpdate(pathList); return bRet; }
bool PasteCopyCommand::Execute() { CString sDroppath = parser.GetVal(_T("droptarget")); CTSVNPath dropPath(sDroppath); ProjectProperties props; props.ReadProps(dropPath); if (dropPath.IsAdminDir()) return FALSE; SVN svn; SVNStatus status; unsigned long count = 0; CString sNewName; pathList.RemoveAdminPaths(); CProgressDlg progress; progress.SetTitle(IDS_PROC_COPYING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { const CTSVNPath& sourcePath = pathList[nPath]; CTSVNPath fullDropPath = dropPath; if (sNewName.IsEmpty()) fullDropPath.AppendPathString(sourcePath.GetFileOrDirectoryName()); else fullDropPath.AppendPathString(sNewName); // Check for a drop-on-to-ourselves if (sourcePath.IsEquivalentTo(fullDropPath)) { // Offer a rename progress.Stop(); CRenameDlg dlg; dlg.m_windowtitle.Format(IDS_PROC_NEWNAMECOPY, (LPCTSTR)sourcePath.GetUIFileOrDirectoryName()); if (dlg.DoModal() != IDOK) { return FALSE; } // rebuild the progress dialog progress.EnsureValid(); progress.SetTitle(IDS_PROC_COPYING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.SetProgress(count, pathList.GetCount()); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); // Rebuild the destination path, with the new name fullDropPath.SetFromUnknown(sDroppath); fullDropPath.AppendPathString(dlg.m_name); } svn_wc_status_kind s = status.GetAllStatus(sourcePath); if ((s == svn_wc_status_none)||(s == svn_wc_status_unversioned)||(s == svn_wc_status_ignored)) { // source file is unversioned: move the file to the target, then add it CopyFile(sourcePath.GetWinPath(), fullDropPath.GetWinPath(), FALSE); if (!svn.Add(CTSVNPathList(fullDropPath), &props, svn_depth_infinity, true, false, true)) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); return FALSE; //get out of here } else CShellUpdater::Instance().AddPathForUpdate(fullDropPath); } else { if (!svn.Copy(CTSVNPathList(sourcePath), fullDropPath, SVNRev::REV_WC, SVNRev())) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); return FALSE; //get out of here } else CShellUpdater::Instance().AddPathForUpdate(fullDropPath); } count++; if (progress.IsValid()) { progress.FormatPathLine(1, IDS_PROC_COPYINGPROG, sourcePath.GetWinPath()); progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, fullDropPath.GetWinPath()); progress.SetProgress(count, pathList.GetCount()); } if ((progress.IsValid())&&(progress.HasUserCancelled())) { CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION); return false; } } 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 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 RemoveCommand::Execute() { bool bRet = false; // removing items from a working copy is done item-by-item so we // have a chance to show a progress bar // // removing items from an URL in the repository requires that we // ask the user for a log message. bool bForce = false; SVN svn; if ((pathList.GetCount())&&(SVN::PathIsURL(pathList[0]))) { // Delete using URL's, not wc paths svn.SetPromptApp(&theApp); CInputLogDlg dlg; CString sUUID; svn.GetRepositoryRootAndUUID(pathList[0], true, sUUID); dlg.SetUUID(sUUID); CString sHint; if (pathList.GetCount() == 1) sHint.Format(IDS_INPUT_REMOVEONE, (LPCTSTR)pathList[0].GetSVNPathString()); else sHint.Format(IDS_INPUT_REMOVEMORE, pathList.GetCount()); dlg.SetActionText(sHint); if (dlg.DoModal()==IDOK) { if (!svn.Remove(pathList, true, !!parser.HasKey(_T("keep")), dlg.GetLogMessage())) { CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); return false; } return true; } return false; } else { for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { TRACE(_T("remove file %s\n"), (LPCTSTR)pathList[nPath].GetUIPathString()); // even though SVN::Remove takes a list of paths to delete at once // we delete each item individually so we can prompt the user // if something goes wrong or unversioned/modified items are // to be deleted CTSVNPathList removePathList(pathList[nPath]); if ((bForce)&&(!parser.HasKey(_T("keep")))) { CTSVNPath delPath = removePathList[0]; if (!delPath.IsDirectory()) delPath.Delete(true); // note: we don't move folders to the trash bin, so they can't // get restored anymore - svn removes *all* files in a removed // folder, even modified and unversioned ones // We could move the folders here to the trash bin too, but then // the folder would be gone and will require a recursive commit. // Of course: a solution would be to first create a copy of the folder, // move the original folder to the trash, then rename the copied folder // to the original name, then let svn delete the folder - but // that would just take too much time for bigger folders... } if (!svn.Remove(removePathList, bForce, !!parser.HasKey(_T("keep")))) { if ((svn.Err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) || (svn.Err->apr_err == SVN_ERR_CLIENT_MODIFIED)) { CString msg, yes, no, yestoall; if (pathList[nPath].IsDirectory()) { msg.Format(IDS_PROC_REMOVEFORCEFOLDER, pathList[nPath].GetWinPath()); } else { msg.Format(IDS_PROC_REMOVEFORCE, (LPCTSTR)svn.GetLastErrorMessage()); } yes.LoadString(IDS_MSGBOX_YES); no.LoadString(IDS_MSGBOX_NO); yestoall.LoadString(IDS_PROC_YESTOALL); UINT ret = CMessageBox::Show(hwndExplorer, msg, _T("TortoiseSVN"), 2, IDI_ERROR, yes, no, yestoall); if (ret == 3) bForce = true; if ((ret == 1)||(ret==3)) { if (!parser.HasKey(_T("keep"))) { CTSVNPath delPath = removePathList[0]; if (!delPath.IsDirectory()) delPath.Delete(true); // note: see comment for the delPath.Delete() above } if (!svn.Remove(removePathList, true, !!parser.HasKey(_T("keep")))) { CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); } else bRet = true; } } else CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); } } } if (bRet) CShellUpdater::Instance().AddPathsForUpdate(pathList); return bRet; }