BOOL CCopyDlg::OnInitDialog() { CResizableStandAloneDialog::OnInitDialog(); CAppUtils::MarkWindowAsUnpinnable(m_hWnd); ExtendFrameIntoClientArea(IDC_EXTGROUP); m_aeroControls.SubclassControl(this, IDC_DOSWITCH); m_aeroControls.SubclassControl(this, IDC_MAKEPARENTS); m_aeroControls.SubclassOkCancelHelp(this); m_bCancelled = false; DWORD exStyle = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_CHECKBOXES; m_ExtList.SetExtendedStyle(exStyle); SetWindowTheme(m_ExtList.GetSafeHwnd(), L"Explorer", NULL); m_ExtList.ShowText(CString(MAKEINTRESOURCE(IDS_COPY_WAITFOREXTERNALS))); AdjustControlSize(IDC_COPYHEAD); AdjustControlSize(IDC_COPYREV); AdjustControlSize(IDC_COPYWC); AdjustControlSize(IDC_DOSWITCH); AdjustControlSize(IDC_MAKEPARENTS); CTSVNPath path(m_path); CString sWindowTitle; GetWindowText(sWindowTitle); CAppUtils::SetWindowTitle(m_hWnd, path.GetUIPathString(), sWindowTitle); m_History.SetMaxHistoryItems((LONG)CRegDWORD(L"Software\\TortoiseSVN\\MaxHistoryItems", 25)); SetRevision(m_CopyRev); m_tooltips.AddTool(IDC_HISTORY, IDS_COMMITDLG_HISTORY_TT); if (SVN::PathIsURL(path)) { DialogEnableWindow(IDC_COPYWC, FALSE); DialogEnableWindow(IDC_DOSWITCH, FALSE); SetDlgItemText(IDC_COPYSTARTLABEL, CString(MAKEINTRESOURCE(IDS_COPYDLG_FROMURL))); } SVN svn; CString sUUID; m_repoRoot = svn.GetRepositoryRootAndUUID(path, true, sUUID); m_repoRoot.TrimRight('/'); m_wcURL = svn.GetURLFromPath(path); if (m_wcURL.IsEmpty() || (!path.IsUrl() && !path.Exists())) { CString Wrong_URL=path.GetSVNPathString(); CString temp; temp.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)Wrong_URL); ::MessageBox(this->m_hWnd, temp, L"TortoiseSVN", MB_ICONERROR); this->EndDialog(IDCANCEL); //exit } m_URLCombo.LoadHistory(L"Software\\TortoiseSVN\\History\\repoPaths\\"+sUUID, L"url"); m_URLCombo.SetCurSel(0); CString relPath = m_wcURL.Mid(m_repoRoot.GetLength()); if (!m_URL.IsEmpty()) { // allow the use of urls relative to the repo root if (m_URL[0] != '^') relPath = m_URL.Mid(m_repoRoot.GetLength()); else relPath = m_URL.Mid(1); } CTSVNPath r = CTSVNPath(relPath); relPath = r.GetUIPathString(); relPath.Replace('\\', '/'); m_URLCombo.AddString(relPath, 0); m_URLCombo.SelectString(-1, relPath); m_URL = m_wcURL; SetDlgItemText(IDC_DESTURL, CPathUtils::CombineUrls(m_repoRoot, relPath)); SetDlgItemText(IDC_FROMURL, m_wcURL); CString reg; reg.Format(L"Software\\TortoiseSVN\\History\\commit%s", (LPCTSTR)sUUID); m_History.Load(reg, L"logmsgs"); m_ProjectProperties.ReadProps(m_path); if (CRegDWORD(L"Software\\TortoiseSVN\\AlwaysWarnIfNoIssue", FALSE)) m_ProjectProperties.bWarnIfNoIssue = TRUE; m_cLogMessage.Init(m_ProjectProperties); m_cLogMessage.SetFont((CString)CRegString(L"Software\\TortoiseSVN\\LogFontName", L"Courier New"), (DWORD)CRegDWORD(L"Software\\TortoiseSVN\\LogFontSize", 8)); GetDlgItem(IDC_BUGTRAQBUTTON)->ShowWindow(SW_HIDE); GetDlgItem(IDC_BUGTRAQBUTTON)->EnableWindow(FALSE); CBugTraqAssociations bugtraq_associations; bugtraq_associations.Load(m_ProjectProperties.GetProviderUUID(), m_ProjectProperties.sProviderParams); if (bugtraq_associations.FindProvider(CTSVNPathList(m_path), &m_bugtraq_association)) { CComPtr<IBugTraqProvider> pProvider; HRESULT hr = pProvider.CoCreateInstance(m_bugtraq_association.GetProviderClass()); if (SUCCEEDED(hr)) { m_BugTraqProvider = pProvider; ATL::CComBSTR temp; ATL::CComBSTR parameters; parameters.Attach(m_bugtraq_association.GetParameters().AllocSysString()); hr = pProvider->GetLinkText(GetSafeHwnd(), parameters, &temp); if (SUCCEEDED(hr)) { SetDlgItemText(IDC_BUGTRAQBUTTON, temp == 0 ? L"" : temp); GetDlgItem(IDC_BUGTRAQBUTTON)->EnableWindow(TRUE); GetDlgItem(IDC_BUGTRAQBUTTON)->ShowWindow(SW_SHOW); } } GetDlgItem(IDC_LOGMESSAGE)->SetFocus(); } if (m_ProjectProperties.sMessage.IsEmpty()) { GetDlgItem(IDC_BUGID)->ShowWindow(SW_HIDE); GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_HIDE); GetDlgItem(IDC_LOGMESSAGE)->SetFocus(); } else { GetDlgItem(IDC_BUGID)->ShowWindow(SW_SHOW); GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_SHOW); if (!m_ProjectProperties.sLabel.IsEmpty()) SetDlgItemText(IDC_BUGIDLABEL, m_ProjectProperties.sLabel); GetDlgItem(IDC_BUGID)->SetFocus(); } if (!m_sLogMessage.IsEmpty()) m_cLogMessage.SetText(m_sLogMessage); else m_cLogMessage.SetText(m_ProjectProperties.GetLogMsgTemplate(PROJECTPROPNAME_LOGTEMPLATEBRANCH)); OnEnChangeLogmessage(); m_linkControl.ConvertStaticToLink(m_hWnd, IDC_CHECKALL); m_linkControl.ConvertStaticToLink(m_hWnd, IDC_CHECKNONE); // line up all controls and adjust their sizes. #define LINKSPACING 9 RECT rc = AdjustControlSize(IDC_SELECTLABEL); rc.right -= 15; // AdjustControlSize() adds 20 pixels for the checkbox/radio button bitmap, but this is a label... rc = AdjustStaticSize(IDC_CHECKALL, rc, LINKSPACING); rc = AdjustStaticSize(IDC_CHECKNONE, rc, LINKSPACING); CAppUtils::SetAccProperty(m_cLogMessage.GetSafeHwnd(), PROPID_ACC_ROLE, ROLE_SYSTEM_TEXT); CAppUtils::SetAccProperty(m_cLogMessage.GetSafeHwnd(), PROPID_ACC_HELP, CString(MAKEINTRESOURCE(IDS_INPUT_ENTERLOG))); CAppUtils::SetAccProperty(m_cLogMessage.GetSafeHwnd(), PROPID_ACC_KEYBOARDSHORTCUT, L"Alt+"+CString(CAppUtils::FindAcceleratorKey(this, IDC_INVISIBLE))); CAppUtils::SetAccProperty(GetDlgItem(IDC_CHECKALL)->GetSafeHwnd(), PROPID_ACC_ROLE, ROLE_SYSTEM_LINK); CAppUtils::SetAccProperty(GetDlgItem(IDC_CHECKNONE)->GetSafeHwnd(), PROPID_ACC_ROLE, ROLE_SYSTEM_LINK); CAppUtils::SetAccProperty(m_URLCombo.GetSafeHwnd(), PROPID_ACC_KEYBOARDSHORTCUT, L"Alt+"+CString(CAppUtils::FindAcceleratorKey(this, IDC_TOURLLABEL))); CAppUtils::SetAccProperty(GetDlgItem(IDC_FROMURL)->GetSafeHwnd(), PROPID_ACC_KEYBOARDSHORTCUT, L"Alt+"+CString(CAppUtils::FindAcceleratorKey(this, IDC_COPYSTARTLABEL))); CAppUtils::SetAccProperty(GetDlgItem(IDC_DESTURL)->GetSafeHwnd(), PROPID_ACC_KEYBOARDSHORTCUT, L"Alt+"+CString(CAppUtils::FindAcceleratorKey(this, IDC_DESTLABEL))); AddAnchor(IDC_REPOGROUP, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_COPYSTARTLABEL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_FROMURL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_TOURLLABEL, TOP_LEFT); AddAnchor(IDC_URLCOMBO, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_BROWSE, TOP_RIGHT); AddAnchor(IDC_DESTLABEL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_DESTURL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_MSGGROUP, TOP_LEFT, MIDDLE_RIGHT); AddAnchor(IDC_HISTORY, TOP_LEFT); AddAnchor(IDC_BUGTRAQBUTTON, TOP_LEFT); AddAnchor(IDC_BUGIDLABEL, TOP_RIGHT); AddAnchor(IDC_BUGID, TOP_RIGHT); AddAnchor(IDC_INVISIBLE, TOP_RIGHT); AddAnchor(IDC_LOGMESSAGE, TOP_LEFT, MIDDLE_RIGHT); AddAnchor(IDC_FROMGROUP, MIDDLE_LEFT, MIDDLE_RIGHT); AddAnchor(IDC_COPYHEAD, MIDDLE_LEFT); AddAnchor(IDC_COPYREV, MIDDLE_LEFT); AddAnchor(IDC_COPYREVTEXT, MIDDLE_RIGHT); AddAnchor(IDC_BROWSEFROM, MIDDLE_RIGHT); AddAnchor(IDC_COPYWC, MIDDLE_LEFT); AddAnchor(IDC_EXTGROUP, MIDDLE_LEFT, BOTTOM_RIGHT); AddAnchor(IDC_SELECTLABEL, MIDDLE_LEFT); AddAnchor(IDC_CHECKALL, MIDDLE_LEFT); AddAnchor(IDC_CHECKNONE, MIDDLE_LEFT); AddAnchor(IDC_EXTERNALSLIST, MIDDLE_LEFT, BOTTOM_RIGHT); AddAnchor(IDC_DOSWITCH, BOTTOM_LEFT); AddAnchor(IDC_MAKEPARENTS, BOTTOM_LEFT); AddAnchor(IDOK, BOTTOM_RIGHT); AddAnchor(IDCANCEL, BOTTOM_RIGHT); AddAnchor(IDHELP, BOTTOM_RIGHT); if ((m_pParentWnd==NULL)&&(GetExplorerHWND())) CenterWindow(CWnd::FromHandle(GetExplorerHWND())); EnableSaveRestore(L"CopyDlg"); m_bSettingChanged = false; if (!m_path.IsUrl()) { // start a thread to obtain the highest revision number of the working copy // without blocking the dialog if ((m_pThread = AfxBeginThread(FindRevThreadEntry, this))==NULL) { OnCantStartThread(); } } return TRUE; }
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 RenameCommand::Execute() { bool bRet = false; CString filename = cmdLinePath.GetFileOrDirectoryName(); CString basePath = cmdLinePath.GetContainingDirectory().GetWinPathString(); ::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 (!SVN::PathIsURL(cmdLinePath)) dlg.SetFileSystemAutoComplete(); if (dlg.DoModal() != IDOK) return FALSE; sNewName = dlg.m_name; } while(PathIsRelative(sNewName) && !PathIsURL(sNewName) && (sNewName.IsEmpty() || (sNewName.Compare(filename)==0))); CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": 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); 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, true, sUUID); input.SetUUID(sUUID); CString sHint; sHint.FormatMessage(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); progDlg.SetAutoClose (parser); progDlg.SetPathList(pathList); progDlg.SetUrl(destinationPath.GetWinPathString()); progDlg.SetCommitMessage(sMsg); progDlg.DoModal(); bRet = !progDlg.DidErrorsOccur(); } else { CString sFilemask = cmdLinePath.GetFilename(); int slashpos = 0; // find out up to which char sFilemask and sNewName are identical int minlen = min(sFilemask.GetLength(), sNewName.GetLength()); for (; slashpos < minlen; ++slashpos) { if (sFilemask[slashpos] != sNewName[slashpos]) break; } if (sFilemask.ReverseFind('.') >= slashpos) { while (sFilemask.ReverseFind('.') >= slashpos) sFilemask = sFilemask.Left(sFilemask.ReverseFind('.')); } else sFilemask.Empty(); CString sNewMask = sNewName; if (sNewMask.ReverseFind('.') >= slashpos) { while (sNewMask.ReverseFind('.') >= slashpos) sNewMask = sNewMask.Left(sNewMask.ReverseFind('.')); } else sNewMask.Empty(); CString sRightPartNew = sNewName.Mid(sNewMask.GetLength()); CString sRightPartOld = cmdLinePath.GetFilename().Mid(sFilemask.GetLength()); // if the file extension changed, or the old and new right parts are not the // same then we can not correctly guess the new names of similar files, so // just do the plain rename of the selected file and don't offer to rename similar ones. if (((!sFilemask.IsEmpty()) && (parser.HasKey(L"noquestion"))) || (cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0) || (sRightPartOld.CompareNoCase(sRightPartNew))) { if (RenameWithReplace(GetExplorerHWND(), CTSVNPathList(cmdLinePath), destinationPath, sMsg)) 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+L".*"); while (filefind.FindNextFileNoDots()) { if (!filefind.IsDirectory()) renlist.AddPath(CTSVNPath(filefind.GetFilePath())); } if ((renlist.GetCount() <= 1) || (renlist.GetCount() > 10)) // arbitrary value of ten { // Either no matching files to rename, or way too many of them: // just do the default... if (RenameWithReplace(GetExplorerHWND(), CTSVNPathList(cmdLinePath), destinationPath, sMsg)) { 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(L"\n%s -> %s", (LPCTSTR)sFilename, (LPCTSTR)sNewFilename); if (!renlist[i].IsEquivalentTo(cmdLinePath)) sRenList += sTemp; renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+L"\\"+sNewFilename; } CString sRenameMultipleQuestion; sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList); UINT idret = ::MessageBox(GetExplorerHWND(), sRenameMultipleQuestion, L"TortoiseSVN", MB_ICONQUESTION|MB_YESNOCANCEL); if (idret == IDYES) { CProgressDlg progress; progress.SetTitle(IDS_PROC_MOVING); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND())); 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.SetProgress64(count, renmap.size()); if (RenameWithReplace(GetExplorerHWND(), CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), sMsg)) { 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 (RenameWithReplace(GetExplorerHWND(), CTSVNPathList(cmdLinePath), destinationPath, sMsg)) { bRet = true; CShellUpdater::Instance().AddPathForUpdate(destinationPath); } } else if (idret == IDCANCEL) { // nothing } } } } 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 CSwitchDlg::OnInitDialog() { CResizableStandAloneDialog::OnInitDialog(); ExtendFrameIntoClientArea(IDC_REVGROUP); m_aeroControls.SubclassOkCancelHelp(this); CTSVNPath svnPath(m_path); SetDlgItemText(IDC_SWITCHPATH, m_path); m_bFolder = svnPath.IsDirectory(); SVN svn; CString sUUID; m_repoRoot = svn.GetRepositoryRootAndUUID(svnPath, true, sUUID); m_repoRoot.TrimRight('/'); CString url = svn.GetURLFromPath(svnPath); m_URLCombo.LoadHistory(_T("Software\\TortoiseSVN\\History\\repoPaths\\")+sUUID, _T("url")); m_URLCombo.SetCurSel(0); if (!url.IsEmpty()) { CString relPath = url.Mid(m_repoRoot.GetLength()); CTSVNPath r = CTSVNPath(relPath); relPath = r.GetUIPathString(); relPath.Replace('\\', '/'); m_URLCombo.AddString(relPath, 0); m_URLCombo.SelectString(-1, relPath); m_URL = url; SetDlgItemText(IDC_DESTURL, CPathUtils::CombineUrls(m_repoRoot, relPath)); } if (m_sTitle.IsEmpty()) GetWindowText(m_sTitle); SetWindowText(m_sTitle); if (m_sLabel.IsEmpty()) GetDlgItemText(IDC_URLLABEL, m_sLabel); SetDlgItemText(IDC_URLLABEL, m_sLabel); // set head revision as default revision SetRevision(SVNRev::REV_HEAD); m_depthCombo.AddString(CString(MAKEINTRESOURCE(IDS_SVN_DEPTH_WORKING))); m_depthCombo.AddString(CString(MAKEINTRESOURCE(IDS_SVN_DEPTH_INFINITE))); m_depthCombo.AddString(CString(MAKEINTRESOURCE(IDS_SVN_DEPTH_IMMEDIATE))); m_depthCombo.AddString(CString(MAKEINTRESOURCE(IDS_SVN_DEPTH_FILES))); m_depthCombo.AddString(CString(MAKEINTRESOURCE(IDS_SVN_DEPTH_EMPTY))); m_depthCombo.AddString(CString(MAKEINTRESOURCE(IDS_SVN_DEPTH_EXCLUDE))); m_depthCombo.SetCurSel(0); RECT rect; GetWindowRect(&rect); m_height = rect.bottom - rect.top; AddAnchor(IDC_SWITCHLABEL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_SWITCHPATH, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_URLLABEL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_URLCOMBO, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_BROWSE, TOP_RIGHT); AddAnchor(IDC_DESTLABEL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_DESTURL, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_REVGROUP, TOP_LEFT); AddAnchor(IDC_REVISION_HEAD, TOP_LEFT); AddAnchor(IDC_REVISION_N, TOP_LEFT); AddAnchor(IDC_REVISION_NUM, TOP_LEFT); AddAnchor(IDC_LOG, TOP_LEFT); AddAnchor(IDC_GROUPMIDDLE, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_DEPTH, TOP_LEFT, TOP_RIGHT); AddAnchor(IDC_NOEXTERNALS, TOP_LEFT, TOP_RIGHT); AddAnchor(IDOK, BOTTOM_RIGHT); AddAnchor(IDCANCEL, BOTTOM_RIGHT); AddAnchor(IDHELP, BOTTOM_RIGHT); if ((m_pParentWnd==NULL)&&(hWndExplorer)) CenterWindow(CWnd::FromHandle(hWndExplorer)); EnableSaveRestore(_T("SwitchDlg")); return TRUE; }
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; }