OSDN Git Service

Show Ignore Sub Menu
[tortoisegit/TortoiseGitJp.git] / TortoiseProc / Commands / RenameCommand.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2007-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "StdAfx.h"\r
20 #include "RenameCommand.h"\r
21 \r
22 #include "MessageBox.h"\r
23 #include "SVNProgressDlg.h"\r
24 #include "ProgressDlg.h"\r
25 #include "RenameDlg.h"\r
26 #include "InputLogDlg.h"\r
27 #include "SVN.h"\r
28 #include "DirFileEnum.h"\r
29 #include "ShellUpdater.h"\r
30 \r
31 bool RenameCommand::Execute()\r
32 {\r
33         bool bRet = false;\r
34         CString filename = cmdLinePath.GetFileOrDirectoryName();\r
35         CString basePath = cmdLinePath.GetContainingDirectory().GetWinPathString();\r
36         ::SetCurrentDirectory(basePath);\r
37 \r
38         // show the rename dialog until the user either cancels or enters a new\r
39         // name (one that's different to the original name\r
40         CString sNewName;\r
41         do \r
42         {\r
43                 CRenameDlg dlg;\r
44                 dlg.m_name = filename;\r
45                 if (dlg.DoModal() != IDOK)\r
46                         return FALSE;\r
47                 sNewName = dlg.m_name;\r
48         } while(PathIsRelative(sNewName) && !PathIsURL(sNewName) && (sNewName.IsEmpty() || (sNewName.Compare(filename)==0)));\r
49 \r
50         TRACE(_T("rename file %s to %s\n"), (LPCTSTR)cmdLinePath.GetWinPathString(), (LPCTSTR)sNewName);\r
51         CTSVNPath destinationPath(basePath);\r
52         if (PathIsRelative(sNewName) && !PathIsURL(sNewName))\r
53                 destinationPath.AppendPathString(sNewName);\r
54         else\r
55                 destinationPath.SetFromWin(sNewName);\r
56         // check if a rename just with case is requested: that's not possible on windows file systems\r
57         // and we have to show an error.\r
58         if (cmdLinePath.GetWinPathString().CompareNoCase(destinationPath.GetWinPathString())==0)\r
59         {\r
60                 //rename to the same file!\r
61                 CString sHelpPath = theApp.m_pszHelpFilePath;\r
62                 sHelpPath += _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase");\r
63                 CMessageBox::Show(hwndExplorer, IDS_PROC_CASERENAME, IDS_APPNAME, MB_OK|MB_HELP, sHelpPath);\r
64         }\r
65         else\r
66         {\r
67                 CString sMsg;\r
68                 if (SVN::PathIsURL(cmdLinePath))\r
69                 {\r
70                         // rename an URL.\r
71                         // Ask for a commit message, then rename directly in\r
72                         // the repository\r
73                         CInputLogDlg input;\r
74                         CString sUUID;\r
75                         SVN svn;\r
76                         svn.GetRepositoryRootAndUUID(cmdLinePath, sUUID);\r
77                         input.SetUUID(sUUID);\r
78                         CString sHint;\r
79                         sHint.Format(IDS_INPUT_MOVE, (LPCTSTR)cmdLinePath.GetSVNPathString(), (LPCTSTR)destinationPath.GetSVNPathString());\r
80                         input.SetActionText(sHint);\r
81                         if (input.DoModal() == IDOK)\r
82                         {\r
83                                 sMsg = input.GetLogMessage();\r
84                         }\r
85                         else\r
86                         {\r
87                                 return FALSE;\r
88                         }\r
89                 }\r
90                 if ((cmdLinePath.IsDirectory())||(pathList.GetCount() > 1))\r
91                 {\r
92                         // renaming a directory can take a while: use the\r
93                         // progress dialog to show the progress of the renaming\r
94                         // operation.\r
95                         CSVNProgressDlg progDlg;\r
96                         progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Rename);\r
97                         if (parser.HasVal(_T("closeonend")))\r
98                                 progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));\r
99                         progDlg.SetPathList(pathList);\r
100                         progDlg.SetUrl(destinationPath.GetWinPathString());\r
101                         progDlg.SetCommitMessage(sMsg);\r
102                         progDlg.SetRevision(SVNRev::REV_WC);\r
103                         progDlg.DoModal();\r
104                         bRet = !progDlg.DidErrorsOccur();\r
105                 }\r
106                 else\r
107                 {\r
108                         SVN svn;\r
109                         CString sFilemask = cmdLinePath.GetFilename();\r
110                         if (sFilemask.ReverseFind('.')>=0)\r
111                         {\r
112                                 sFilemask = sFilemask.Left(sFilemask.ReverseFind('.'));\r
113                         }\r
114                         else\r
115                                 sFilemask.Empty();\r
116                         CString sNewMask = sNewName;\r
117                         if (sNewMask.ReverseFind('.'>=0))\r
118                         {\r
119                                 sNewMask = sNewMask.Left(sNewMask.ReverseFind('.'));\r
120                         }\r
121                         else\r
122                                 sNewMask.Empty();\r
123 \r
124                         if (((!sFilemask.IsEmpty()) && (parser.HasKey(_T("noquestion")))) ||\r
125                                 (cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0))\r
126                         {\r
127                                 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))\r
128                                 {\r
129                                         TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
130                                         CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
131                                 }\r
132                                 else\r
133                                         bRet = true;\r
134                         }\r
135                         else\r
136                         {\r
137                                 // when refactoring, multiple files have to be renamed\r
138                                 // at once because those files belong together.\r
139                                 // e.g. file.aspx, file.aspx.cs, file.aspx.resx\r
140                                 CTSVNPathList renlist;\r
141                                 CSimpleFileFind filefind(cmdLinePath.GetDirectory().GetWinPathString(), sFilemask+_T(".*"));\r
142                                 while (filefind.FindNextFileNoDots())\r
143                                 {\r
144                                         if (!filefind.IsDirectory())\r
145                                                 renlist.AddPath(CTSVNPath(filefind.GetFilePath()));\r
146                                 }\r
147                                 if (renlist.GetCount()<=1)\r
148                                 {\r
149                                         // we couldn't find any other matching files\r
150                                         // just do the default...\r
151                                         if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))\r
152                                         {\r
153                                                 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
154                                                 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
155                                         }\r
156                                         else\r
157                                         {\r
158                                                 bRet = true;\r
159                                                 CShellUpdater::Instance().AddPathForUpdate(destinationPath);\r
160                                         }\r
161                                 }\r
162                                 else\r
163                                 {\r
164                                         std::map<CString, CString> renmap;\r
165                                         CString sTemp;\r
166                                         CString sRenList;\r
167                                         for (int i=0; i<renlist.GetCount(); ++i)\r
168                                         {\r
169                                                 CString sFilename = renlist[i].GetFilename();\r
170                                                 CString sNewFilename = sNewMask + sFilename.Mid(sFilemask.GetLength());\r
171                                                 sTemp.Format(_T("\n%s -> %s"), (LPCTSTR)sFilename, (LPCTSTR)sNewFilename);\r
172                                                 if (!renlist[i].IsEquivalentTo(cmdLinePath))\r
173                                                         sRenList += sTemp;\r
174                                                 renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename;\r
175                                         }\r
176                                         CString sRenameMultipleQuestion;\r
177                                         sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList);\r
178                                         UINT idret = CMessageBox::Show(hwndExplorer, sRenameMultipleQuestion, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNOCANCEL);\r
179                                         if (idret == IDYES)\r
180                                         {\r
181                                                 CProgressDlg progress;\r
182                                                 progress.SetTitle(IDS_PROC_MOVING);\r
183                                                 progress.SetAnimation(IDR_MOVEANI);\r
184                                                 progress.SetTime(true);\r
185                                                 progress.ShowModeless(CWnd::FromHandle(hwndExplorer));\r
186                                                 DWORD count = 1;\r
187                                                 for (std::map<CString, CString>::iterator it=renmap.begin(); it != renmap.end(); ++it)\r
188                                                 {\r
189                                                         progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, (LPCTSTR)it->first);\r
190                                                         progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, (LPCTSTR)it->second);\r
191                                                         progress.SetProgress(count, renmap.size());\r
192                                                         if (!svn.Move(CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), TRUE, sMsg))\r
193                                                         {\r
194                                                                 if (svn.Err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)\r
195                                                                 {\r
196                                                                         bRet = !!MoveFile(it->first, it->second);\r
197                                                                 }\r
198                                                                 else\r
199                                                                 {\r
200                                                                         TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
201                                                                         CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
202                                                                         bRet = false;\r
203                                                                 }\r
204                                                         }\r
205                                                         else\r
206                                                         {\r
207                                                                 bRet = true;\r
208                                                                 CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it->second));\r
209                                                         }\r
210                                                 }\r
211                                                 progress.Stop();\r
212                                         }\r
213                                         else if (idret == IDNO)\r
214                                         {\r
215                                                 // no, user wants to just rename the file he selected\r
216                                                 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))\r
217                                                 {\r
218                                                         TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());\r
219                                                         CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
220                                                 }\r
221                                                 else\r
222                                                 {\r
223                                                         bRet = true;\r
224                                                         CShellUpdater::Instance().AddPathForUpdate(destinationPath);\r
225                                                 }\r
226                                         }\r
227                                         else if (idret == IDCANCEL)\r
228                                         {\r
229                                                 // nothing\r
230                                         }\r
231                                 }\r
232                         }\r
233                 }\r
234         }\r
235         return bRet;\r
236 }\r