1 // TortoiseMerge - a Diff/Patch program
3 // Copyright (C) 2006-2009 - 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.
22 #include "PathUtils.h"
23 #include "UnicodeUtils.h"
24 #include "SysProgressDlg.h"
26 #include "svn_pools.h"
30 #include "svn_string.h"
33 CAppUtils::CAppUtils(void)
37 CAppUtils::~CAppUtils(void)
41 BOOL
CAppUtils::GetVersionedFile(CString sPath
, CString sVersion
, CString sSavePath
, CSysProgressDlg
* progDlg
, HWND hWnd
/*=NULL*/)
43 CString sSCMPath
= CRegString(_T("Software\\TortoiseMerge\\SCMPath"), _T(""));
44 if (sSCMPath
.IsEmpty())
46 // no path set, so use TortoiseSVN as default
47 sSCMPath
= CPathUtils::GetAppDirectory() + _T("TortoiseProc.exe");
48 sSCMPath
+= _T(" /command:cat /path:\"%1\" /revision:%2 /savepath:\"%3\" /hwnd:%4");
51 sTemp
.Format(_T("%d"), hWnd
);
52 sSCMPath
.Replace(_T("%1"), sPath
);
53 sSCMPath
.Replace(_T("%2"), sVersion
);
54 sSCMPath
.Replace(_T("%3"), sSavePath
);
55 sSCMPath
.Replace(_T("%4"), sTemp
);
56 // start the external SCM program to fetch the specific version of the file
58 PROCESS_INFORMATION process
;
59 memset(&startup
, 0, sizeof(startup
));
60 startup
.cb
= sizeof(startup
);
61 memset(&process
, 0, sizeof(process
));
62 if (CreateProcess(NULL
, (LPTSTR
)(LPCTSTR
)sSCMPath
, NULL
, NULL
, FALSE
, 0, 0, 0, &startup
, &process
)==0)
65 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
66 FORMAT_MESSAGE_FROM_SYSTEM
|
67 FORMAT_MESSAGE_IGNORE_INSERTS
,
70 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
75 MessageBox(NULL
, (LPCTSTR
)lpMsgBuf
, _T("TortoiseMerge"), MB_OK
| MB_ICONERROR
);
76 LocalFree( lpMsgBuf
);
81 ret
= WaitForSingleObject(process
.hProcess
, 100);
82 } while ((ret
== WAIT_TIMEOUT
) && (!progDlg
->HasUserCancelled()));
83 CloseHandle(process
.hThread
);
84 CloseHandle(process
.hProcess
);
86 if (progDlg
->HasUserCancelled())
90 if (!PathFileExists(sSavePath
))
95 bool CAppUtils::CreateUnifiedDiff(const CString
& orig
, const CString
& modified
, const CString
& output
, bool bShowError
)
98 apr_file_t
* outfile
= NULL
;
99 apr_pool_t
* pool
= svn_pool_create(NULL
);
101 svn_error_t
* err
= svn_io_file_open (&outfile
, svn_path_internal_style(CUnicodeUtils::GetUTF8(output
), pool
),
102 APR_WRITE
| APR_CREATE
| APR_BINARY
| APR_TRUNCATE
,
103 APR_OS_DEFAULT
, pool
);
106 svn_stream_t
* stream
= svn_stream_from_aprfile2(outfile
, false, pool
);
109 svn_diff_t
* diff
= NULL
;
110 svn_diff_file_options_t
* opts
= svn_diff_file_options_create(pool
);
111 opts
->ignore_eol_style
= false;
112 opts
->ignore_space
= svn_diff_file_ignore_space_none
;
113 err
= svn_diff_file_diff_2(&diff
, svn_path_internal_style(CUnicodeUtils::GetUTF8(orig
), pool
),
114 svn_path_internal_style(CUnicodeUtils::GetUTF8(modified
), pool
), opts
, pool
);
117 err
= svn_diff_file_output_unified(stream
, diff
, svn_path_internal_style(CUnicodeUtils::GetUTF8(orig
), pool
),
118 svn_path_internal_style(CUnicodeUtils::GetUTF8(modified
), pool
),
120 svn_stream_close(stream
);
123 apr_file_close(outfile
);
128 AfxMessageBox(CAppUtils::GetErrorString(err
), MB_ICONERROR
);
129 svn_error_clear(err
);
130 svn_pool_destroy(pool
);
133 svn_pool_destroy(pool
);
138 CString
CAppUtils::GetErrorString(svn_error_t
* Err
)
146 svn_error_t
* ErrPtr
= Err
;
148 msg
= CUnicodeUtils::GetUnicode(ErrPtr
->message
);
151 /* Is this a Subversion-specific error code? */
152 if ((ErrPtr
->apr_err
> APR_OS_START_USEERR
)
153 && (ErrPtr
->apr_err
<= APR_OS_START_CANONERR
))
154 msg
= svn_strerror (ErrPtr
->apr_err
, errbuf
, sizeof (errbuf
));
155 /* Otherwise, this must be an APR error code. */
158 svn_error_t
*temp_err
= NULL
;
159 const char * err_string
= NULL
;
160 temp_err
= svn_utf_cstring_to_utf8(&err_string
, apr_strerror (ErrPtr
->apr_err
, errbuf
, sizeof (errbuf
)-1), ErrPtr
->pool
);
163 svn_error_clear (temp_err
);
164 msg
= _T("Can't recode error string from APR");
168 msg
= CUnicodeUtils::GetUnicode(err_string
);
172 while (ErrPtr
->child
)
174 ErrPtr
= ErrPtr
->child
;
177 temp
= CUnicodeUtils::GetUnicode(ErrPtr
->message
);
180 /* Is this a Subversion-specific error code? */
181 if ((ErrPtr
->apr_err
> APR_OS_START_USEERR
)
182 && (ErrPtr
->apr_err
<= APR_OS_START_CANONERR
))
183 temp
= svn_strerror (ErrPtr
->apr_err
, errbuf
, sizeof (errbuf
));
184 /* Otherwise, this must be an APR error code. */
187 svn_error_t
*temp_err
= NULL
;
188 const char * err_string
= NULL
;
189 temp_err
= svn_utf_cstring_to_utf8(&err_string
, apr_strerror (ErrPtr
->apr_err
, errbuf
, sizeof (errbuf
)-1), ErrPtr
->pool
);
192 svn_error_clear (temp_err
);
193 temp
= _T("Can't recode error string from APR");
197 temp
= CUnicodeUtils::GetUnicode(err_string
);
208 bool CAppUtils::HasClipboardFormat(UINT format
)
210 if (OpenClipboard(NULL
))
215 if (enumFormat
== format
)
220 } while((enumFormat
= EnumClipboardFormats(enumFormat
))!=0);