1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2007-2008 - TortoiseSVN
\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
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
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
20 #include "RenameCommand.h"
\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
28 #include "DirFileEnum.h"
\r
29 #include "ShellUpdater.h"
\r
31 bool RenameCommand::Execute()
\r
34 CString filename = cmdLinePath.GetFileOrDirectoryName();
\r
35 CString basePath = cmdLinePath.GetContainingDirectory().GetGitPathString();
\r
36 //::SetCurrentDirectory(basePath);
\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
44 dlg.m_name = filename;
\r
45 if (dlg.DoModal() != IDOK)
\r
47 sNewName = dlg.m_name;
\r
48 } while(PathIsRelative(sNewName) && !PathIsURL(sNewName) && (sNewName.IsEmpty() || (sNewName.Compare(filename)==0)));
\r
50 if(!basePath.IsEmpty())
\r
51 sNewName=basePath+"/"+sNewName;
\r
55 cmd.Format(_T("git.exe mv \"%s\" \"%s\""),
\r
56 cmdLinePath.GetGitPathString(),
\r
59 if(g_Git.Run(cmd,&output,CP_ACP))
\r
61 CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_OK);
\r
65 newpath.SetFromGit(sNewName);
\r
67 CShellUpdater::Instance().AddPathForUpdate(newpath);
\r
69 TRACE(_T("rename file %s to %s\n"), (LPCTSTR)cmdLinePath.GetWinPathString(), (LPCTSTR)sNewName);
\r
70 CTSVNPath destinationPath(basePath);
\r
71 if (PathIsRelative(sNewName) && !PathIsURL(sNewName))
\r
72 destinationPath.AppendPathString(sNewName);
\r
74 destinationPath.SetFromWin(sNewName);
\r
75 // check if a rename just with case is requested: that's not possible on windows file systems
\r
76 // and we have to show an error.
\r
77 if (cmdLinePath.GetWinPathString().CompareNoCase(destinationPath.GetWinPathString())==0)
\r
79 //rename to the same file!
\r
80 CString sHelpPath = theApp.m_pszHelpFilePath;
\r
81 sHelpPath += _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase");
\r
82 CMessageBox::Show(hwndExplorer, IDS_PROC_CASERENAME, IDS_APPNAME, MB_OK|MB_HELP, sHelpPath);
\r
87 if (SVN::PathIsURL(cmdLinePath))
\r
90 // Ask for a commit message, then rename directly in
\r
95 svn.GetRepositoryRootAndUUID(cmdLinePath, sUUID);
\r
96 input.SetUUID(sUUID);
\r
98 sHint.Format(IDS_INPUT_MOVE, (LPCTSTR)cmdLinePath.GetSVNPathString(), (LPCTSTR)destinationPath.GetSVNPathString());
\r
99 input.SetActionText(sHint);
\r
100 if (input.DoModal() == IDOK)
\r
102 sMsg = input.GetLogMessage();
\r
109 if ((cmdLinePath.IsDirectory())||(pathList.GetCount() > 1))
\r
111 // renaming a directory can take a while: use the
\r
112 // progress dialog to show the progress of the renaming
\r
114 CSVNProgressDlg progDlg;
\r
115 progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Rename);
\r
116 if (parser.HasVal(_T("closeonend")))
\r
117 progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));
\r
118 progDlg.SetPathList(pathList);
\r
119 progDlg.SetUrl(destinationPath.GetWinPathString());
\r
120 progDlg.SetCommitMessage(sMsg);
\r
121 progDlg.SetRevision(SVNRev::REV_WC);
\r
123 bRet = !progDlg.DidErrorsOccur();
\r
128 CString sFilemask = cmdLinePath.GetFilename();
\r
129 if (sFilemask.ReverseFind('.')>=0)
\r
131 sFilemask = sFilemask.Left(sFilemask.ReverseFind('.'));
\r
135 CString sNewMask = sNewName;
\r
136 if (sNewMask.ReverseFind('.'>=0))
\r
138 sNewMask = sNewMask.Left(sNewMask.ReverseFind('.'));
\r
143 if (((!sFilemask.IsEmpty()) && (parser.HasKey(_T("noquestion")))) ||
\r
144 (cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0))
\r
146 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
\r
148 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
149 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
156 // when refactoring, multiple files have to be renamed
\r
157 // at once because those files belong together.
\r
158 // e.g. file.aspx, file.aspx.cs, file.aspx.resx
\r
159 CTSVNPathList renlist;
\r
160 CSimpleFileFind filefind(cmdLinePath.GetDirectory().GetWinPathString(), sFilemask+_T(".*"));
\r
161 while (filefind.FindNextFileNoDots())
\r
163 if (!filefind.IsDirectory())
\r
164 renlist.AddPath(CTSVNPath(filefind.GetFilePath()));
\r
166 if (renlist.GetCount()<=1)
\r
168 // we couldn't find any other matching files
\r
169 // just do the default...
\r
170 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
\r
172 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
173 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
178 CShellUpdater::Instance().AddPathForUpdate(destinationPath);
\r
183 std::map<CString, CString> renmap;
\r
186 for (int i=0; i<renlist.GetCount(); ++i)
\r
188 CString sFilename = renlist[i].GetFilename();
\r
189 CString sNewFilename = sNewMask + sFilename.Mid(sFilemask.GetLength());
\r
190 sTemp.Format(_T("\n%s -> %s"), (LPCTSTR)sFilename, (LPCTSTR)sNewFilename);
\r
191 if (!renlist[i].IsEquivalentTo(cmdLinePath))
\r
193 renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename;
\r
195 CString sRenameMultipleQuestion;
\r
196 sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList);
\r
197 UINT idret = CMessageBox::Show(hwndExplorer, sRenameMultipleQuestion, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNOCANCEL);
\r
198 if (idret == IDYES)
\r
200 CProgressDlg progress;
\r
201 progress.SetTitle(IDS_PROC_MOVING);
\r
202 progress.SetAnimation(IDR_MOVEANI);
\r
203 progress.SetTime(true);
\r
204 progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
\r
206 for (std::map<CString, CString>::iterator it=renmap.begin(); it != renmap.end(); ++it)
\r
208 progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, (LPCTSTR)it->first);
\r
209 progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, (LPCTSTR)it->second);
\r
210 progress.SetProgress(count, renmap.size());
\r
211 if (!svn.Move(CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), TRUE, sMsg))
\r
213 if (svn.Err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
\r
215 bRet = !!MoveFile(it->first, it->second);
\r
219 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
220 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
227 CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it->second));
\r
232 else if (idret == IDNO)
\r
234 // no, user wants to just rename the file he selected
\r
235 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
\r
237 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
238 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
243 CShellUpdater::Instance().AddPathForUpdate(destinationPath);
\r
246 else if (idret == IDCANCEL)
\r
255 CShellUpdater::Instance().Flush();
\r