1 // TortoiseMerge - a Diff/Patch program
\r
3 // Copyright (C) 2006-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 "Registry.h"
\r
21 #include "AppUtils.h"
\r
22 #include "UnicodeUtils.h"
\r
23 #include "ProgressDlg.h"
\r
25 #include "svn_pools.h"
\r
27 #include "svn_path.h"
\r
28 #include "svn_diff.h"
\r
29 #include "svn_string.h"
\r
30 #include "svn_utf.h"
\r
32 CAppUtils::CAppUtils(void)
\r
36 CAppUtils::~CAppUtils(void)
\r
40 BOOL CAppUtils::GetVersionedFile(CString sPath, CString sVersion, CString sSavePath, CProgressDlg * progDlg, HWND hWnd /*=NULL*/)
\r
42 CString sSCMPath = CRegString(_T("Software\\TortoiseMerge\\SCMPath"), _T(""));
\r
43 if (sSCMPath.IsEmpty())
\r
45 // no path set, so use TortoiseSVN as default
\r
46 sSCMPath = CRegString(_T("Software\\TortoiseSVN\\ProcPath"), _T(""), false, HKEY_LOCAL_MACHINE);
\r
47 if (sSCMPath.IsEmpty())
\r
49 TCHAR pszSCMPath[MAX_PATH];
\r
50 GetModuleFileName(NULL, pszSCMPath, MAX_PATH);
\r
51 sSCMPath = pszSCMPath;
\r
52 sSCMPath = sSCMPath.Left(sSCMPath.ReverseFind('\\'));
\r
53 sSCMPath += _T("\\TortoiseProc.exe");
\r
55 sSCMPath += _T(" /command:cat /path:\"%1\" /revision:%2 /savepath:\"%3\" /hwnd:%4");
\r
58 sTemp.Format(_T("%d"), hWnd);
\r
59 sSCMPath.Replace(_T("%1"), sPath);
\r
60 sSCMPath.Replace(_T("%2"), sVersion);
\r
61 sSCMPath.Replace(_T("%3"), sSavePath);
\r
62 sSCMPath.Replace(_T("%4"), sTemp);
\r
63 // start the external SCM program to fetch the specific version of the file
\r
64 STARTUPINFO startup;
\r
65 PROCESS_INFORMATION process;
\r
66 memset(&startup, 0, sizeof(startup));
\r
67 startup.cb = sizeof(startup);
\r
68 memset(&process, 0, sizeof(process));
\r
69 if (CreateProcess(NULL, (LPTSTR)(LPCTSTR)sSCMPath, NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)
\r
72 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
\r
73 FORMAT_MESSAGE_FROM_SYSTEM |
\r
74 FORMAT_MESSAGE_IGNORE_INSERTS,
\r
77 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
\r
82 MessageBox(NULL, (LPCTSTR)lpMsgBuf, _T("TortoiseMerge"), MB_OK | MB_ICONERROR);
\r
83 LocalFree( lpMsgBuf );
\r
88 ret = WaitForSingleObject(process.hProcess, 100);
\r
89 } while ((ret == WAIT_TIMEOUT) && (!progDlg->HasUserCancelled()));
\r
90 CloseHandle(process.hThread);
\r
91 CloseHandle(process.hProcess);
\r
93 if (progDlg->HasUserCancelled())
\r
97 if (!PathFileExists(sSavePath))
\r
102 bool CAppUtils::CreateUnifiedDiff(const CString& orig, const CString& modified, const CString& output, bool bShowError)
\r
104 apr_file_t * outfile = NULL;
\r
105 apr_pool_t * pool = svn_pool_create(NULL);
\r
107 svn_error_t * err = svn_io_file_open (&outfile, svn_path_canonicalize(CUnicodeUtils::GetUTF8(output), pool),
\r
108 APR_WRITE | APR_CREATE | APR_BINARY | APR_TRUNCATE,
\r
109 APR_OS_DEFAULT, pool);
\r
112 svn_stream_t * stream = svn_stream_from_aprfile2(outfile, false, pool);
\r
115 svn_diff_t * diff = NULL;
\r
116 svn_diff_file_options_t * opts = svn_diff_file_options_create(pool);
\r
117 opts->ignore_eol_style = false;
\r
118 opts->ignore_space = svn_diff_file_ignore_space_none;
\r
119 err = svn_diff_file_diff_2(&diff, svn_path_canonicalize(CUnicodeUtils::GetUTF8(orig), pool),
\r
120 svn_path_canonicalize(CUnicodeUtils::GetUTF8(modified), pool), opts, pool);
\r
123 err = svn_diff_file_output_unified(stream, diff, svn_path_canonicalize(CUnicodeUtils::GetUTF8(orig), pool),
\r
124 svn_path_canonicalize(CUnicodeUtils::GetUTF8(modified), pool),
\r
126 svn_stream_close(stream);
\r
129 apr_file_close(outfile);
\r
134 AfxMessageBox(CAppUtils::GetErrorString(err), MB_ICONERROR);
\r
135 svn_error_clear(err);
\r
136 svn_pool_destroy(pool);
\r
139 svn_pool_destroy(pool);
\r
143 CString CAppUtils::GetErrorString(svn_error_t * Err)
\r
151 svn_error_t * ErrPtr = Err;
\r
152 if (ErrPtr->message)
\r
153 msg = CUnicodeUtils::GetUnicode(ErrPtr->message);
\r
156 /* Is this a Subversion-specific error code? */
\r
157 if ((ErrPtr->apr_err > APR_OS_START_USEERR)
\r
158 && (ErrPtr->apr_err <= APR_OS_START_CANONERR))
\r
159 msg = svn_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf));
\r
160 /* Otherwise, this must be an APR error code. */
\r
163 svn_error_t *temp_err = NULL;
\r
164 const char * err_string = NULL;
\r
165 temp_err = svn_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);
\r
168 svn_error_clear (temp_err);
\r
169 msg = _T("Can't recode error string from APR");
\r
173 msg = CUnicodeUtils::GetUnicode(err_string);
\r
177 while (ErrPtr->child)
\r
179 ErrPtr = ErrPtr->child;
\r
181 if (ErrPtr->message)
\r
182 temp = CUnicodeUtils::GetUnicode(ErrPtr->message);
\r
185 /* Is this a Subversion-specific error code? */
\r
186 if ((ErrPtr->apr_err > APR_OS_START_USEERR)
\r
187 && (ErrPtr->apr_err <= APR_OS_START_CANONERR))
\r
188 temp = svn_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf));
\r
189 /* Otherwise, this must be an APR error code. */
\r
192 svn_error_t *temp_err = NULL;
\r
193 const char * err_string = NULL;
\r
194 temp_err = svn_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);
\r
197 svn_error_clear (temp_err);
\r
198 temp = _T("Can't recode error string from APR");
\r
202 temp = CUnicodeUtils::GetUnicode(err_string);
\r
213 bool CAppUtils::HasClipboardFormat(UINT format)
\r
215 if (OpenClipboard(NULL))
\r
217 UINT enumFormat = 0;
\r
220 if (enumFormat == format)
\r
225 } while((enumFormat = EnumClipboardFormats(enumFormat))!=0);
\r