1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2007-2008 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "RenameCommand.h"
22 #include "MessageBox.h"
23 //#include "SVNProgressDlg.h"
24 //#include "ProgressDlg.h"
25 #include "RenameDlg.h"
26 #include "InputLogDlg.h"
28 #include "DirFileEnum.h"
29 #include "ShellUpdater.h"
31 bool RenameCommand::Execute()
34 CString filename
= cmdLinePath
.GetFileOrDirectoryName();
35 CString basePath
= cmdLinePath
.GetContainingDirectory().GetGitPathString();
36 //::SetCurrentDirectory(basePath);
38 // show the rename dialog until the user either cancels or enters a new
39 // name (one that's different to the original name
44 dlg
.m_name
= filename
;
45 if (dlg
.DoModal() != IDOK
)
47 sNewName
= dlg
.m_name
;
48 } while(PathIsRelative(sNewName
) && !PathIsURL(sNewName
) && (sNewName
.IsEmpty() || (sNewName
.Compare(filename
)==0)));
50 if(!basePath
.IsEmpty())
51 sNewName
=basePath
+"/"+sNewName
;
55 cmd
.Format(_T("git.exe mv \"%s\" \"%s\""),
56 cmdLinePath
.GetGitPathString(),
59 if(g_Git
.Run(cmd
,&output
,CP_ACP
))
61 CMessageBox::Show(hwndExplorer
, output
, _T("TortoiseGit"), MB_OK
);
65 newpath
.SetFromGit(sNewName
);
67 CShellUpdater::Instance().AddPathForUpdate(newpath
);
69 TRACE(_T("rename file %s to %s\n"), (LPCTSTR
)cmdLinePath
.GetWinPathString(), (LPCTSTR
)sNewName
);
70 CTSVNPath
destinationPath(basePath
);
71 if (PathIsRelative(sNewName
) && !PathIsURL(sNewName
))
72 destinationPath
.AppendPathString(sNewName
);
74 destinationPath
.SetFromWin(sNewName
);
75 // check if a rename just with case is requested: that's not possible on windows file systems
76 // and we have to show an error.
77 if (cmdLinePath
.GetWinPathString().CompareNoCase(destinationPath
.GetWinPathString())==0)
79 //rename to the same file!
80 CString sHelpPath
= theApp
.m_pszHelpFilePath
;
81 sHelpPath
+= _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase");
82 CMessageBox::Show(hwndExplorer
, IDS_PROC_CASERENAME
, IDS_APPNAME
, MB_OK
|MB_HELP
, sHelpPath
);
87 if (SVN::PathIsURL(cmdLinePath
))
90 // Ask for a commit message, then rename directly in
95 svn
.GetRepositoryRootAndUUID(cmdLinePath
, sUUID
);
98 sHint
.Format(IDS_INPUT_MOVE
, (LPCTSTR
)cmdLinePath
.GetSVNPathString(), (LPCTSTR
)destinationPath
.GetSVNPathString());
99 input
.SetActionText(sHint
);
100 if (input
.DoModal() == IDOK
)
102 sMsg
= input
.GetLogMessage();
109 if ((cmdLinePath
.IsDirectory())||(pathList
.GetCount() > 1))
111 // renaming a directory can take a while: use the
112 // progress dialog to show the progress of the renaming
114 CSVNProgressDlg progDlg
;
115 progDlg
.SetCommand(CSVNProgressDlg::SVNProgress_Rename
);
116 if (parser
.HasVal(_T("closeonend")))
117 progDlg
.SetAutoClose(parser
.GetLongVal(_T("closeonend")));
118 progDlg
.SetPathList(pathList
);
119 progDlg
.SetUrl(destinationPath
.GetWinPathString());
120 progDlg
.SetCommitMessage(sMsg
);
121 progDlg
.SetRevision(SVNRev::REV_WC
);
123 bRet
= !progDlg
.DidErrorsOccur();
128 CString sFilemask
= cmdLinePath
.GetFilename();
129 if (sFilemask
.ReverseFind('.')>=0)
131 sFilemask
= sFilemask
.Left(sFilemask
.ReverseFind('.'));
135 CString sNewMask
= sNewName
;
136 if (sNewMask
.ReverseFind('.'>=0))
138 sNewMask
= sNewMask
.Left(sNewMask
.ReverseFind('.'));
143 if (((!sFilemask
.IsEmpty()) && (parser
.HasKey(_T("noquestion")))) ||
144 (cmdLinePath
.GetFileExtension().Compare(destinationPath
.GetFileExtension())!=0))
146 if (!svn
.Move(CTSVNPathList(cmdLinePath
), destinationPath
, TRUE
, sMsg
))
148 TRACE(_T("%s\n"), (LPCTSTR
)svn
.GetLastErrorMessage());
149 CMessageBox::Show(hwndExplorer
, svn
.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR
);
156 // when refactoring, multiple files have to be renamed
157 // at once because those files belong together.
158 // e.g. file.aspx, file.aspx.cs, file.aspx.resx
159 CTSVNPathList renlist
;
160 CSimpleFileFind
filefind(cmdLinePath
.GetDirectory().GetWinPathString(), sFilemask
+_T(".*"));
161 while (filefind
.FindNextFileNoDots())
163 if (!filefind
.IsDirectory())
164 renlist
.AddPath(CTSVNPath(filefind
.GetFilePath()));
166 if (renlist
.GetCount()<=1)
168 // we couldn't find any other matching files
169 // just do the default...
170 if (!svn
.Move(CTSVNPathList(cmdLinePath
), destinationPath
, TRUE
, sMsg
))
172 TRACE(_T("%s\n"), (LPCTSTR
)svn
.GetLastErrorMessage());
173 CMessageBox::Show(hwndExplorer
, svn
.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR
);
178 CShellUpdater::Instance().AddPathForUpdate(destinationPath
);
183 std::map
<CString
, CString
> renmap
;
186 for (int i
=0; i
<renlist
.GetCount(); ++i
)
188 CString sFilename
= renlist
[i
].GetFilename();
189 CString sNewFilename
= sNewMask
+ sFilename
.Mid(sFilemask
.GetLength());
190 sTemp
.Format(_T("\n%s -> %s"), (LPCTSTR
)sFilename
, (LPCTSTR
)sNewFilename
);
191 if (!renlist
[i
].IsEquivalentTo(cmdLinePath
))
193 renmap
[renlist
[i
].GetWinPathString()] = renlist
[i
].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename
;
195 CString sRenameMultipleQuestion
;
196 sRenameMultipleQuestion
.Format(IDS_PROC_MULTIRENAME
, (LPCTSTR
)sRenList
);
197 UINT idret
= CMessageBox::Show(hwndExplorer
, sRenameMultipleQuestion
, _T("TortoiseSVN"), MB_ICONQUESTION
|MB_YESNOCANCEL
);
200 CProgressDlg progress
;
201 progress
.SetTitle(IDS_PROC_MOVING
);
202 progress
.SetAnimation(IDR_MOVEANI
);
203 progress
.SetTime(true);
204 progress
.ShowModeless(CWnd::FromHandle(hwndExplorer
));
206 for (std::map
<CString
, CString
>::iterator it
=renmap
.begin(); it
!= renmap
.end(); ++it
)
208 progress
.FormatPathLine(1, IDS_PROC_MOVINGPROG
, (LPCTSTR
)it
->first
);
209 progress
.FormatPathLine(2, IDS_PROC_CPYMVPROG2
, (LPCTSTR
)it
->second
);
210 progress
.SetProgress(count
, renmap
.size());
211 if (!svn
.Move(CTSVNPathList(CTSVNPath(it
->first
)), CTSVNPath(it
->second
), TRUE
, sMsg
))
213 if (svn
.Err
->apr_err
== SVN_ERR_ENTRY_NOT_FOUND
)
215 bRet
= !!MoveFile(it
->first
, it
->second
);
219 TRACE(_T("%s\n"), (LPCTSTR
)svn
.GetLastErrorMessage());
220 CMessageBox::Show(hwndExplorer
, svn
.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR
);
227 CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it
->second
));
232 else if (idret
== IDNO
)
234 // no, user wants to just rename the file he selected
235 if (!svn
.Move(CTSVNPathList(cmdLinePath
), destinationPath
, TRUE
, sMsg
))
237 TRACE(_T("%s\n"), (LPCTSTR
)svn
.GetLastErrorMessage());
238 CMessageBox::Show(hwndExplorer
, svn
.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR
);
243 CShellUpdater::Instance().AddPathForUpdate(destinationPath
);
246 else if (idret
== IDCANCEL
)
255 CShellUpdater::Instance().Flush();