OSDN Git Service

Fixed issue #155: Fix SVN Rebase sets upstream as remotes/trunk
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / Commands / CreatePatchCommand.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 "CreatePatchCommand.h"\r
21 \r
22 #include "PathUtils.h"\r
23 #include "StringUtils.h"\r
24 #include "AppUtils.h"\r
25 #include "CreatePatchDlg.h"\r
26 #include "SVN.h"\r
27 #include "TempFile.h"\r
28 #include "ProgressDlg.h"\r
29 \r
30 #define PATCH_TO_CLIPBOARD_PSEUDO_FILENAME              _T(".TSVNPatchToClipboard")\r
31 \r
32 \r
33 bool CreatePatchCommand::Execute()\r
34 {\r
35         bool bRet = false;\r
36         CString savepath = CPathUtils::GetLongPathname(parser.GetVal(_T("savepath")));\r
37         CCreatePatch dlg;\r
38         dlg.m_pathList = pathList;\r
39         if (dlg.DoModal()==IDOK)\r
40         {\r
41                 if (cmdLinePath.IsEmpty())\r
42                 {\r
43                         cmdLinePath = pathList.GetCommonRoot();\r
44                 }\r
45                 bRet = CreatePatch(cmdLinePath.GetDirectory(), dlg.m_pathList, CTSVNPath(savepath));\r
46                 SVN svn;\r
47                 svn.Revert(dlg.m_filesToRevert, CStringArray(), false);\r
48         }\r
49         return bRet;\r
50 }\r
51 \r
52 UINT_PTR CALLBACK CreatePatchCommand::CreatePatchFileOpenHook(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM /*lParam*/)\r
53 {\r
54         if(uiMsg ==     WM_COMMAND && LOWORD(wParam) == IDC_PATCH_TO_CLIPBOARD)\r
55         {\r
56                 HWND hFileDialog = GetParent(hDlg);\r
57 \r
58                 CString strFilename = CTempFiles::Instance().GetTempFilePath(false).GetWinPathString() + PATCH_TO_CLIPBOARD_PSEUDO_FILENAME;\r
59 \r
60                 CommDlg_OpenSave_SetControlText(hFileDialog, edt1, (LPCTSTR)strFilename);   \r
61 \r
62                 PostMessage(hFileDialog, WM_COMMAND, MAKEWPARAM(IDOK, BM_CLICK), (LPARAM)(GetDlgItem(hDlg, IDOK)));\r
63         }\r
64         return 0;\r
65 }\r
66 \r
67 bool CreatePatchCommand::CreatePatch(const CTSVNPath& root, const CTSVNPathList& path, const CTSVNPath& cmdLineSavePath)\r
68 {\r
69         OPENFILENAME ofn = {0};                         // common dialog box structure\r
70         CString temp;\r
71         CTSVNPath savePath;\r
72 \r
73         if (cmdLineSavePath.IsEmpty())\r
74         {\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
82 \r
83                 temp.LoadString(IDS_REPOBROWSE_SAVEAS);\r
84                 CStringUtils::RemoveAccelerators(temp);\r
85                 if (temp.IsEmpty())\r
86                         ofn.lpstrTitle = NULL;\r
87                 else\r
88                         ofn.lpstrTitle = temp;\r
89                 ofn.Flags = OFN_OVERWRITEPROMPT | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK;\r
90 \r
91                 ofn.hInstance = AfxGetResourceHandle();\r
92                 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_PATCH_FILE_OPEN_CUSTOM);\r
93                 ofn.lpfnHook = CreatePatchFileOpenHook;\r
94 \r
95                 CString sFilter;\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
102                 {\r
103                         if (*ptr == '|')\r
104                                 *ptr = '\0';\r
105                         ptr--;\r
106                 }\r
107                 ofn.lpstrFilter = pszFilters;\r
108                 ofn.nFilterIndex = 1;\r
109                 // Display the Open dialog box. \r
110                 if (GetSaveFileName(&ofn)==FALSE)\r
111                 {\r
112                         delete [] pszFilters;\r
113                         return FALSE;\r
114                 }\r
115                 delete [] pszFilters;\r
116                 savePath = CTSVNPath(ofn.lpstrFile);\r
117                 if (ofn.nFilterIndex == 1)\r
118                 {\r
119                         if (savePath.GetFileExtension().IsEmpty())\r
120                                 savePath.AppendRawString(_T(".patch"));\r
121                 }\r
122         }\r
123         else\r
124         {\r
125                 savePath = cmdLineSavePath;\r
126         }\r
127 \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
132 \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
138         if(bToClipboard)\r
139         {\r
140                 progDlg.FormatNonPathLine(2, IDS_CLIPBOARD_PROGRESS_DEST);\r
141         }\r
142         else\r
143         {\r
144                 progDlg.SetLine(2, savePath.GetUIPathString(), true);\r
145         }\r
146         //progDlg.SetAnimation(IDR_ANIMATION);\r
147 \r
148         CTSVNPath tempPatchFilePath;\r
149         if (bToClipboard)\r
150                 tempPatchFilePath = CTempFiles::Instance().GetTempFilePath(true);\r
151         else\r
152                 tempPatchFilePath = savePath;\r
153 \r
154         ::DeleteFile(tempPatchFilePath.GetWinPath());\r
155 \r
156         CTSVNPath sDir = root;\r
157         if (sDir.IsEmpty())\r
158                 sDir = path.GetCommonRoot();\r
159 \r
160         SVN svn;\r
161         for (int fileindex = 0; fileindex < path.GetCount(); ++fileindex)\r
162         {\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
165                 {\r
166                         progDlg.Stop();\r
167                         ::MessageBox(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
168                         return FALSE;\r
169                 }\r
170         }\r
171 \r
172         if(bToClipboard)\r
173         {\r
174                 // The user actually asked for the patch to be written to the clipboard\r
175                 CStringA sClipdata;\r
176                 FILE * inFile;\r
177                 _tfopen_s(&inFile, tempPatchFilePath.GetWinPath(), _T("rb"));\r
178                 if(inFile)\r
179                 {\r
180                         char chunkBuffer[16384];\r
181                         while(!feof(inFile))\r
182                         {\r
183                                 size_t readLength = fread(chunkBuffer, 1, sizeof(chunkBuffer), inFile);\r
184                                 sClipdata.Append(chunkBuffer, (int)readLength);\r
185                         }\r
186                         fclose(inFile);\r
187 \r
188                         CStringUtils::WriteDiffToClipboard(sClipdata);\r
189                 }\r
190         }\r
191         else\r
192                 CAppUtils::StartUnifiedDiffViewer(tempPatchFilePath, tempPatchFilePath.GetFilename());\r
193 \r
194         progDlg.Stop();\r
195         return TRUE;\r
196 }\r