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 "CreatePatchCommand.h"
\r
22 #include "PathUtils.h"
\r
23 #include "StringUtils.h"
\r
24 #include "AppUtils.h"
\r
25 #include "CreatePatchDlg.h"
\r
27 #include "TempFile.h"
\r
28 #include "ProgressDlg.h"
\r
30 #define PATCH_TO_CLIPBOARD_PSEUDO_FILENAME _T(".TSVNPatchToClipboard")
\r
33 bool CreatePatchCommand::Execute()
\r
36 CString savepath = CPathUtils::GetLongPathname(parser.GetVal(_T("savepath")));
\r
38 dlg.m_pathList = pathList;
\r
39 if (dlg.DoModal()==IDOK)
\r
41 if (cmdLinePath.IsEmpty())
\r
43 cmdLinePath = pathList.GetCommonRoot();
\r
45 bRet = CreatePatch(cmdLinePath.GetDirectory(), dlg.m_pathList, CTSVNPath(savepath));
\r
47 svn.Revert(dlg.m_filesToRevert, CStringArray(), false);
\r
52 UINT_PTR CALLBACK CreatePatchCommand::CreatePatchFileOpenHook(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM /*lParam*/)
\r
54 if(uiMsg == WM_COMMAND && LOWORD(wParam) == IDC_PATCH_TO_CLIPBOARD)
\r
56 HWND hFileDialog = GetParent(hDlg);
\r
58 CString strFilename = CTempFiles::Instance().GetTempFilePath(false).GetWinPathString() + PATCH_TO_CLIPBOARD_PSEUDO_FILENAME;
\r
60 CommDlg_OpenSave_SetControlText(hFileDialog, edt1, (LPCTSTR)strFilename);
\r
62 PostMessage(hFileDialog, WM_COMMAND, MAKEWPARAM(IDOK, BM_CLICK), (LPARAM)(GetDlgItem(hDlg, IDOK)));
\r
67 bool CreatePatchCommand::CreatePatch(const CTSVNPath& root, const CTSVNPathList& path, const CTSVNPath& cmdLineSavePath)
\r
69 OPENFILENAME ofn = {0}; // common dialog box structure
\r
73 if (cmdLineSavePath.IsEmpty())
\r
75 TCHAR szFile[MAX_PATH] = {0}; // buffer for file name
\r
76 // Initialize OPENFILENAME
\r
77 ofn.lStructSize = sizeof(OPENFILENAME);
\r
78 ofn.hwndOwner = hwndExplorer;
\r
79 ofn.lpstrFile = szFile;
\r
80 ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);
\r
81 ofn.lpstrInitialDir = root.GetWinPath();
\r
83 temp.LoadString(IDS_REPOBROWSE_SAVEAS);
\r
84 CStringUtils::RemoveAccelerators(temp);
\r
86 ofn.lpstrTitle = NULL;
\r
88 ofn.lpstrTitle = temp;
\r
89 ofn.Flags = OFN_OVERWRITEPROMPT | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK;
\r
91 ofn.hInstance = AfxGetResourceHandle();
\r
92 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_PATCH_FILE_OPEN_CUSTOM);
\r
93 ofn.lpfnHook = CreatePatchFileOpenHook;
\r
96 sFilter.LoadString(IDS_PATCHFILEFILTER);
\r
97 TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];
\r
98 _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);
\r
99 // Replace '|' delimiters with '\0's
\r
100 TCHAR *ptr = pszFilters + _tcslen(pszFilters); //set ptr at the NULL
\r
101 while (ptr != pszFilters)
\r
107 ofn.lpstrFilter = pszFilters;
\r
108 ofn.nFilterIndex = 1;
\r
109 // Display the Open dialog box.
\r
110 if (GetSaveFileName(&ofn)==FALSE)
\r
112 delete [] pszFilters;
\r
115 delete [] pszFilters;
\r
116 savePath = CTSVNPath(ofn.lpstrFile);
\r
117 if (ofn.nFilterIndex == 1)
\r
119 if (savePath.GetFileExtension().IsEmpty())
\r
120 savePath.AppendRawString(_T(".patch"));
\r
125 savePath = cmdLineSavePath;
\r
128 // This is horrible and I should be ashamed of myself, but basically, the
\r
129 // the file-open dialog writes ".TSVNPatchToClipboard" to its file field if the user clicks
\r
130 // the "Save To Clipboard" button.
\r
131 bool bToClipboard = _tcsstr(savePath.GetWinPath(), PATCH_TO_CLIPBOARD_PSEUDO_FILENAME) != NULL;
\r
133 CProgressDlg progDlg;
\r
134 progDlg.SetTitle(IDS_PROC_PATCHTITLE);
\r
135 progDlg.SetShowProgressBar(false);
\r
136 progDlg.ShowModeless(CWnd::FromHandle(hwndExplorer));
\r
137 progDlg.FormatNonPathLine(1, IDS_PROC_SAVEPATCHTO);
\r
140 progDlg.FormatNonPathLine(2, IDS_CLIPBOARD_PROGRESS_DEST);
\r
144 progDlg.SetLine(2, savePath.GetUIPathString(), true);
\r
146 //progDlg.SetAnimation(IDR_ANIMATION);
\r
148 CTSVNPath tempPatchFilePath;
\r
150 tempPatchFilePath = CTempFiles::Instance().GetTempFilePath(true);
\r
152 tempPatchFilePath = savePath;
\r
154 ::DeleteFile(tempPatchFilePath.GetWinPath());
\r
156 CTSVNPath sDir = root;
\r
157 if (sDir.IsEmpty())
\r
158 sDir = path.GetCommonRoot();
\r
161 for (int fileindex = 0; fileindex < path.GetCount(); ++fileindex)
\r
163 svn_depth_t depth = path[fileindex].IsDirectory() ? svn_depth_empty : svn_depth_files;
\r
164 if (!svn.CreatePatch(path[fileindex], SVNRev::REV_BASE, path[fileindex], SVNRev::REV_WC, sDir.GetDirectory(), depth, FALSE, FALSE, FALSE, _T(""), true, tempPatchFilePath))
\r
167 ::MessageBox(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
\r
174 // The user actually asked for the patch to be written to the clipboard
\r
175 CStringA sClipdata;
\r
177 _tfopen_s(&inFile, tempPatchFilePath.GetWinPath(), _T("rb"));
\r
180 char chunkBuffer[16384];
\r
181 while(!feof(inFile))
\r
183 size_t readLength = fread(chunkBuffer, 1, sizeof(chunkBuffer), inFile);
\r
184 sClipdata.Append(chunkBuffer, (int)readLength);
\r
188 CStringUtils::WriteDiffToClipboard(sClipdata);
\r
192 CAppUtils::StartUnifiedDiffViewer(tempPatchFilePath, tempPatchFilePath.GetFilename());
\r