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.cmd mv \"%s\" \"%s\""),
\r
56 cmdLinePath.GetGitPathString(),
\r
59 if(g_Git.Run(cmd,&output))
\r
61 CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_OK);
\r
65 TRACE(_T("rename file %s to %s\n"), (LPCTSTR)cmdLinePath.GetWinPathString(), (LPCTSTR)sNewName);
\r
66 CTSVNPath destinationPath(basePath);
\r
67 if (PathIsRelative(sNewName) && !PathIsURL(sNewName))
\r
68 destinationPath.AppendPathString(sNewName);
\r
70 destinationPath.SetFromWin(sNewName);
\r
71 // check if a rename just with case is requested: that's not possible on windows file systems
\r
72 // and we have to show an error.
\r
73 if (cmdLinePath.GetWinPathString().CompareNoCase(destinationPath.GetWinPathString())==0)
\r
75 //rename to the same file!
\r
76 CString sHelpPath = theApp.m_pszHelpFilePath;
\r
77 sHelpPath += _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase");
\r
78 CMessageBox::Show(hwndExplorer, IDS_PROC_CASERENAME, IDS_APPNAME, MB_OK|MB_HELP, sHelpPath);
\r
83 if (SVN::PathIsURL(cmdLinePath))
\r
86 // Ask for a commit message, then rename directly in
\r
91 svn.GetRepositoryRootAndUUID(cmdLinePath, sUUID);
\r
92 input.SetUUID(sUUID);
\r
94 sHint.Format(IDS_INPUT_MOVE, (LPCTSTR)cmdLinePath.GetSVNPathString(), (LPCTSTR)destinationPath.GetSVNPathString());
\r
95 input.SetActionText(sHint);
\r
96 if (input.DoModal() == IDOK)
\r
98 sMsg = input.GetLogMessage();
\r
105 if ((cmdLinePath.IsDirectory())||(pathList.GetCount() > 1))
\r
107 // renaming a directory can take a while: use the
\r
108 // progress dialog to show the progress of the renaming
\r
110 CSVNProgressDlg progDlg;
\r
111 progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Rename);
\r
112 if (parser.HasVal(_T("closeonend")))
\r
113 progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));
\r
114 progDlg.SetPathList(pathList);
\r
115 progDlg.SetUrl(destinationPath.GetWinPathString());
\r
116 progDlg.SetCommitMessage(sMsg);
\r
117 progDlg.SetRevision(SVNRev::REV_WC);
\r
119 bRet = !progDlg.DidErrorsOccur();
\r
124 CString sFilemask = cmdLinePath.GetFilename();
\r
125 if (sFilemask.ReverseFind('.')>=0)
\r
127 sFilemask = sFilemask.Left(sFilemask.ReverseFind('.'));
\r
131 CString sNewMask = sNewName;
\r
132 if (sNewMask.ReverseFind('.'>=0))
\r
134 sNewMask = sNewMask.Left(sNewMask.ReverseFind('.'));
\r
139 if (((!sFilemask.IsEmpty()) && (parser.HasKey(_T("noquestion")))) ||
\r
140 (cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0))
\r
142 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
\r
144 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
145 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
152 // when refactoring, multiple files have to be renamed
\r
153 // at once because those files belong together.
\r
154 // e.g. file.aspx, file.aspx.cs, file.aspx.resx
\r
155 CTSVNPathList renlist;
\r
156 CSimpleFileFind filefind(cmdLinePath.GetDirectory().GetWinPathString(), sFilemask+_T(".*"));
\r
157 while (filefind.FindNextFileNoDots())
\r
159 if (!filefind.IsDirectory())
\r
160 renlist.AddPath(CTSVNPath(filefind.GetFilePath()));
\r
162 if (renlist.GetCount()<=1)
\r
164 // we couldn't find any other matching files
\r
165 // just do the default...
\r
166 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
\r
168 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
169 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
174 CShellUpdater::Instance().AddPathForUpdate(destinationPath);
\r
179 std::map<CString, CString> renmap;
\r
182 for (int i=0; i<renlist.GetCount(); ++i)
\r
184 CString sFilename = renlist[i].GetFilename();
\r
185 CString sNewFilename = sNewMask + sFilename.Mid(sFilemask.GetLength());
\r
186 sTemp.Format(_T("\n%s -> %s"), (LPCTSTR)sFilename, (LPCTSTR)sNewFilename);
\r
187 if (!renlist[i].IsEquivalentTo(cmdLinePath))
\r
189 renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename;
\r
191 CString sRenameMultipleQuestion;
\r
192 sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList);
\r
193 UINT idret = CMessageBox::Show(hwndExplorer, sRenameMultipleQuestion, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNOCANCEL);
\r
194 if (idret == IDYES)
\r
196 CProgressDlg progress;
\r
197 progress.SetTitle(IDS_PROC_MOVING);
\r
198 progress.SetAnimation(IDR_MOVEANI);
\r
199 progress.SetTime(true);
\r
200 progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
\r
202 for (std::map<CString, CString>::iterator it=renmap.begin(); it != renmap.end(); ++it)
\r
204 progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, (LPCTSTR)it->first);
\r
205 progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, (LPCTSTR)it->second);
\r
206 progress.SetProgress(count, renmap.size());
\r
207 if (!svn.Move(CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), TRUE, sMsg))
\r
209 if (svn.Err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
\r
211 bRet = !!MoveFile(it->first, it->second);
\r
215 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
216 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
223 CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it->second));
\r
228 else if (idret == IDNO)
\r
230 // no, user wants to just rename the file he selected
\r
231 if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
\r
233 TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
\r
234 CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
239 CShellUpdater::Instance().AddPathForUpdate(destinationPath);
\r
242 else if (idret == IDCANCEL)
\r