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