OSDN Git Service

Cppcheck: The scope of the variable '...' can be reduced.
[winmerge-jp/winmerge-jp.git] / Src / PatchTool.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 //    License (GPLv2+):
3 //    This program is free software; you can redistribute it and/or modify
4 //    it under the terms of the GNU General Public License as published by
5 //    the Free Software Foundation; either version 2 of the License, or (at
6 //    your option) any later version.
7 //    
8 //    This program is distributed in the hope that it will be useful, but
9 //    WITHOUT ANY WARRANTY; without even the implied warranty of
10 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //    GNU General Public License for more details.
12 //
13 //    You should have received a copy of the GNU General Public License
14 //    along with this program; if not, write to the Free Software
15 //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 /////////////////////////////////////////////////////////////////////////////
17 /** 
18  * @file  PatchTool.cpp
19  *
20  * @brief Code file routines
21  */
22
23 #include "StdAfx.h"
24 #include "PatchTool.h"
25 #include "UnicodeString.h"
26 #include "DiffWrapper.h"
27 #include "PathContext.h"
28 #include "PatchDlg.h"
29 #include "paths.h"
30
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #endif
34
35 /**
36  * @brief Default constructor.
37  */
38 CPatchTool::CPatchTool() : m_bOpenToEditor(false)
39 {
40 }
41
42 /**
43  * @brief Default destructor.
44  */
45 CPatchTool::~CPatchTool()
46 {
47 }
48
49 /** 
50  * @brief Adds files to list for patching.
51  * @param [in] file1 First file to add.
52  * @param [in] file2 Second file to add.
53  */
54 void CPatchTool::AddFiles(const String &file1, const String &file2)
55 {
56         PATCHFILES files;
57         files.lfile = file1;
58         files.rfile = file2;
59
60         // TODO: Read and add file's timestamps
61         m_fileList.push_back(files);
62 }
63
64 /**
65  * @brief Add files with alternative paths.
66  * This function adds files with alternative paths. Alternative path is the
67  * one that is added to the patch file. So while @p file1 and @p file2 are
68  * paths in disk (can be temp file names), @p altPath1 and @p altPath2 are
69  * "visible " paths printed to the patch file.
70  * @param [in] file1 First path in disk.
71  * @param [in] altPath1 First path as printed to the patch file.
72  * @param [in] file2 Second path in disk.
73  * @param [in] altPath2 Second path as printed to the patch file.
74  */
75 void CPatchTool::AddFiles(const String &file1, const String &altPath1,
76                 const String &file2, const String &altPath2)
77 {
78         PATCHFILES files;
79         files.lfile = file1;
80         files.rfile = file2;
81         files.pathLeft = altPath1;
82         files.pathRight = altPath2;
83
84         // TODO: Read and add file's timestamps
85         m_fileList.push_back(files);
86 }
87
88 /** 
89  * @brief Create a patch from files given.
90  * @note Files can be given using AddFiles() or selecting using
91  * CPatchDlg.
92  */
93 int CPatchTool::CreatePatch()
94 {
95         DIFFSTATUS status;
96         int retVal = 0;
97
98         CPatchDlg dlgPatch;
99
100         // If files already inserted, add them to dialog
101     for(std::vector<PATCHFILES>::iterator iter = m_fileList.begin(); iter != m_fileList.end(); ++iter)
102     {
103         dlgPatch.AddItem(*iter);
104         }
105
106         if (ShowDialog(&dlgPatch))
107         {
108                 bool bResult = true;
109
110                 if (!paths_CreateIfNeeded(paths_GetPathOnly(dlgPatch.m_fileResult)))
111                 {
112                         LangMessageBox(IDS_FOLDER_NOTEXIST, MB_OK | MB_ICONSTOP);
113                         return 0;
114                 }
115
116                 // Select patch create -mode
117                 m_diffWrapper.SetCreatePatchFile(dlgPatch.m_fileResult);
118                 m_diffWrapper.SetAppendFiles(dlgPatch.m_appendFile);
119                 m_diffWrapper.SetPrediffer(NULL);
120
121                 size_t fileCount = dlgPatch.GetItemCount();
122
123                 m_diffWrapper.WritePatchFileHeader(dlgPatch.m_outputStyle, dlgPatch.m_appendFile);
124                 m_diffWrapper.SetAppendFiles(true);
125
126                 for (size_t index = 0; index < fileCount; index++)
127                 {
128                         const PATCHFILES& files = dlgPatch.GetItemAt(index);
129                         String filename1 = files.lfile.length() == 0 ? _T("NUL") : files.lfile;
130                         String filename2 = files.rfile.length() == 0 ? _T("NUL") : files.rfile;
131                         
132                         // Set up DiffWrapper
133                         m_diffWrapper.SetPaths(PathContext(filename1, filename2), false);
134                         m_diffWrapper.SetAlternativePaths(PathContext(files.pathLeft, files.pathRight));
135                         m_diffWrapper.SetCompareFiles(PathContext(files.lfile, files.rfile));
136                         bool bDiffSuccess = m_diffWrapper.RunFileDiff();
137                         m_diffWrapper.GetDiffStatus(&status);
138
139                         if (!bDiffSuccess)
140                         {
141                                 LangMessageBox(IDS_FILEERROR, MB_ICONSTOP);
142                                 bResult = false;
143                                 break;
144                         }
145                         else if (status.bBinaries)
146                         {
147                                 LangMessageBox(IDS_CANNOT_CREATE_BINARYPATCH, MB_ICONSTOP);
148                                 bResult = false;
149                                 break;
150                         }
151                         else if (status.bPatchFileFailed)
152                         {
153                                 String errMsg = string_format_string1(_("Could not write to file %1."), dlgPatch.m_fileResult);
154                                 AfxMessageBox(errMsg.c_str(), MB_ICONSTOP);
155                                 bResult = false;
156                                 break;
157                         }
158                 }
159                 
160                 m_diffWrapper.WritePatchFileTerminator(dlgPatch.m_outputStyle);
161
162                 if (bResult && fileCount > 0)
163                 {
164                         LangMessageBox(IDS_DIFF_SUCCEEDED, MB_ICONINFORMATION|MB_DONT_DISPLAY_AGAIN,
165                                             IDS_DIFF_SUCCEEDED);
166                         
167                         m_sPatchFile = dlgPatch.m_fileResult;
168                         m_bOpenToEditor = dlgPatch.m_openToEditor;
169                         retVal = 1;
170                 }
171         }
172         dlgPatch.ClearItems();
173         return retVal;
174 }
175
176 /** 
177  * @brief Show patch options dialog and check options selected.
178  * @return TRUE if user wants to create a patch (didn't cancel dialog).
179  */
180 bool CPatchTool::ShowDialog(CPatchDlg *pDlgPatch)
181 {
182         DIFFOPTIONS diffOptions = {0};
183         PATCHOPTIONS patchOptions;
184         bool bRetVal = true;
185
186         if (pDlgPatch->DoModal() == IDOK)
187         {
188                 // There must be one filepair
189                 if (pDlgPatch->GetItemCount() < 1)
190                         bRetVal = false;
191
192                 // These two are from dropdown list - can't be wrong
193                 patchOptions.outputStyle = pDlgPatch->m_outputStyle;
194                 patchOptions.nContext = pDlgPatch->m_contextLines;
195
196                 // Checkbox - can't be wrong
197                 patchOptions.bAddCommandline = !!pDlgPatch->m_includeCmdLine;
198                 m_diffWrapper.SetPatchOptions(&patchOptions);
199
200                 // These are from checkboxes and radiobuttons - can't be wrong
201                 diffOptions.nIgnoreWhitespace = pDlgPatch->m_whitespaceCompare;
202                 diffOptions.bIgnoreBlankLines = pDlgPatch->m_ignoreBlanks;
203                 m_diffWrapper.SetAppendFiles(pDlgPatch->m_appendFile);
204
205                 // Use this because non-sensitive setting can't write
206                 // patch file EOLs correctly
207                 diffOptions.bIgnoreEol = pDlgPatch->m_ignoreEOLDifference;
208                 
209                 diffOptions.bIgnoreCase = pDlgPatch->m_caseSensitive == false;
210                 m_diffWrapper.SetOptions(&diffOptions);
211         }
212         else
213                 return false;
214
215         return bRetVal;
216 }
217
218 /** 
219  * @brief Returns filename and path for patch-file
220  */
221 String CPatchTool::GetPatchFile() const
222 {
223         return m_sPatchFile;
224 }
225
226 /** 
227  * @brief Returns TRUE if user wants to open patch file
228  * to external editor (specified in WinMerge options).
229  */
230 bool CPatchTool::GetOpenToEditor() const
231 {
232         return m_bOpenToEditor;
233 }