--- /dev/null
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2007-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "StdAfx.h"\r
+#include "RenameCommand.h"\r
+\r
+#include "MessageBox.h"\r
+#include "SVNProgressDlg.h"\r
+#include "ProgressDlg.h"\r
+#include "RenameDlg.h"\r
+#include "InputLogDlg.h"\r
+#include "SVN.h"\r
+#include "DirFileEnum.h"\r
+#include "ShellUpdater.h"\r
+\r
+bool RenameCommand::Execute()\r
+{\r
+ bool bRet = false;\r
+ CString filename = cmdLinePath.GetFileOrDirectoryName();\r
+ CString basePath = cmdLinePath.GetContainingDirectory().GetWinPathString();\r
+ ::SetCurrentDirectory(basePath);\r
+\r
+ // show the rename dialog until the user either cancels or enters a new\r
+ // name (one that's different to the original name\r
+ CString sNewName;\r
+ do \r
+ {\r
+ CRenameDlg dlg;\r
+ dlg.m_name = filename;\r
+ if (dlg.DoModal() != IDOK)\r
+ return FALSE;\r
+ sNewName = dlg.m_name;\r
+ } while(PathIsRelative(sNewName) && !PathIsURL(sNewName) && (sNewName.IsEmpty() || (sNewName.Compare(filename)==0)));\r
+\r
+ TRACE(_T("rename file %s to %s\n"), (LPCTSTR)cmdLinePath.GetWinPathString(), (LPCTSTR)sNewName);\r
+ CTSVNPath destinationPath(basePath);\r
+ if (PathIsRelative(sNewName) && !PathIsURL(sNewName))\r
+ destinationPath.AppendPathString(sNewName);\r
+ else\r
+ destinationPath.SetFromWin(sNewName);\r
+ // check if a rename just with case is requested: that's not possible on windows file systems\r
+ // and we have to show an error.\r
+ if (cmdLinePath.GetWinPathString().CompareNoCase(destinationPath.GetWinPathString())==0)\r
+ {\r
+ //rename to the same file!\r
+ CString sHelpPath = theApp.m_pszHelpFilePath;\r
+ sHelpPath += _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase");\r
+ CMessageBox::Show(hwndExplorer, IDS_PROC_CASERENAME, IDS_APPNAME, MB_OK|MB_HELP, sHelpPath);\r
+ }\r
+ else\r
+ {\r
+ CString sMsg;\r
+ if (SVN::PathIsURL(cmdLinePath))\r
+ {\r
+ // rename an URL.\r
+ // Ask for a commit message, then rename directly in\r
+ // the repository\r
+ CInputLogDlg input;\r
+ CString sUUID;\r
+ SVN svn;\r
+ svn.GetRepositoryRootAndUUID(cmdLinePath, sUUID);\r
+ input.SetUUID(sUUID);\r
+ CString sHint;\r
+ sHint.Format(IDS_INPUT_MOVE, (LPCTSTR)cmdLinePath.GetSVNPathString(), (LPCTSTR)destinationPath.GetSVNPathString());\r
+ input.SetActionText(sHint);\r
+ if (input.DoModal() == IDOK)\r
+ {\r
+ sMsg = input.GetLogMessage();\r
+ }\r
+ else\r
+ {\r
+ return FALSE;\r
+ }\r
+ }\r
+ if ((cmdLinePath.IsDirectory())||(pathList.GetCount() > 1))\r
+ {\r
+ // renaming a directory can take a while: use the\r
+ // progress dialog to show the progress of the renaming\r
+ // operation.\r
+ CSVNProgressDlg progDlg;\r
+ progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Rename);\r
+ if (parser.HasVal(_T("closeonend")))\r
+ progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));\r
+ progDlg.SetPathList(pathList);\r
+ progDlg.SetUrl(destinationPath.GetWinPathString());\r
+ progDlg.SetCommitMessage(sMsg);\r
+ progDlg.SetRevision(SVNRev::REV_WC);\r
+ progDlg.DoModal();\r
+ bRet = !progDlg.DidErrorsOccur();\r
+ }\r
+ else\r
+ {\r
+ SVN svn;\r
+ CString sFilemask = cmdLinePath.GetFilename();\r
+ if (sFilemask.ReverseFind('.')>=0)\r
+ {\r
+ sFilemask = sFilemask.Left(sFilemask.ReverseFind('.'));\r
+ }\r
+ else\r
+ sFilemask.Empty();\r
+ CString sNewMask = sNewName;\r
+ if (sNewMask.ReverseFind('.'>=0))\r
+ {\r
+ sNewMask = sNewMask.Left(sNewMask.ReverseFind('.'));\r
+ }\r
+ else\r
+ sNewMask.Empty();\r
+\r
+ if (((!sFilemask.IsEmpty()) && (parser.HasKey(_T("noquestion")))) ||\r
+ (cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0))\r
+ {\r
+ if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))\r
+ {\r
+ TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
+ CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
+ }\r
+ else\r
+ bRet = true;\r
+ }\r
+ else\r
+ {\r
+ // when refactoring, multiple files have to be renamed\r
+ // at once because those files belong together.\r
+ // e.g. file.aspx, file.aspx.cs, file.aspx.resx\r
+ CTSVNPathList renlist;\r
+ CSimpleFileFind filefind(cmdLinePath.GetDirectory().GetWinPathString(), sFilemask+_T(".*"));\r
+ while (filefind.FindNextFileNoDots())\r
+ {\r
+ if (!filefind.IsDirectory())\r
+ renlist.AddPath(CTSVNPath(filefind.GetFilePath()));\r
+ }\r
+ if (renlist.GetCount()<=1)\r
+ {\r
+ // we couldn't find any other matching files\r
+ // just do the default...\r
+ if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))\r
+ {\r
+ TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
+ CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
+ }\r
+ else\r
+ {\r
+ bRet = true;\r
+ CShellUpdater::Instance().AddPathForUpdate(destinationPath);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ std::map<CString, CString> renmap;\r
+ CString sTemp;\r
+ CString sRenList;\r
+ for (int i=0; i<renlist.GetCount(); ++i)\r
+ {\r
+ CString sFilename = renlist[i].GetFilename();\r
+ CString sNewFilename = sNewMask + sFilename.Mid(sFilemask.GetLength());\r
+ sTemp.Format(_T("\n%s -> %s"), (LPCTSTR)sFilename, (LPCTSTR)sNewFilename);\r
+ if (!renlist[i].IsEquivalentTo(cmdLinePath))\r
+ sRenList += sTemp;\r
+ renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename;\r
+ }\r
+ CString sRenameMultipleQuestion;\r
+ sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList);\r
+ UINT idret = CMessageBox::Show(hwndExplorer, sRenameMultipleQuestion, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNOCANCEL);\r
+ if (idret == IDYES)\r
+ {\r
+ CProgressDlg progress;\r
+ progress.SetTitle(IDS_PROC_MOVING);\r
+ progress.SetAnimation(IDR_MOVEANI);\r
+ progress.SetTime(true);\r
+ progress.ShowModeless(CWnd::FromHandle(hwndExplorer));\r
+ DWORD count = 1;\r
+ for (std::map<CString, CString>::iterator it=renmap.begin(); it != renmap.end(); ++it)\r
+ {\r
+ progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, (LPCTSTR)it->first);\r
+ progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, (LPCTSTR)it->second);\r
+ progress.SetProgress(count, renmap.size());\r
+ if (!svn.Move(CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), TRUE, sMsg))\r
+ {\r
+ if (svn.Err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)\r
+ {\r
+ bRet = !!MoveFile(it->first, it->second);\r
+ }\r
+ else\r
+ {\r
+ TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
+ CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
+ bRet = false;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ bRet = true;\r
+ CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it->second));\r
+ }\r
+ }\r
+ progress.Stop();\r
+ }\r
+ else if (idret == IDNO)\r
+ {\r
+ // no, user wants to just rename the file he selected\r
+ if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))\r
+ {\r
+ TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
+ CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
+ }\r
+ else\r
+ {\r
+ bRet = true;\r
+ CShellUpdater::Instance().AddPathForUpdate(destinationPath);\r
+ }\r
+ }\r
+ else if (idret == IDCANCEL)\r
+ {\r
+ // nothing\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return bRet;\r
+}\r