OSDN Git Service

Fixed issue #112: (7) Low hanging GUI fruits during Commit and Push
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / SVNProgressDlg.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-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 "TortoiseProc.h"\r
21 #include "messagebox.h"\r
22 #include "SVNProgressDlg.h"\r
23 #include "LogDlg.h"\r
24 #include "TGitPath.h"\r
25 #include "Registry.h"\r
26 #include "GitStatus.h"\r
27 #include "AppUtils.h"\r
28 #include "PathUtils.h"\r
29 #include "StringUtils.h"\r
30 #include "TempFile.h"\r
31 #include "UnicodeUtils.h"\r
32 #include "SoundUtils.h"\r
33 #include "GitDiff.h"\r
34 #include "Hooks.h"\r
35 #include "DropFiles.h"\r
36 //#include "GitLogHelper.h"\r
37 #include "RegHistory.h"\r
38 //#include "ConflictResolveDlg.h"\r
39 #include "LogFile.h"\r
40 #include "ShellUpdater.h"\r
41 #include "IconMenu.h"\r
42 #include "BugTraqAssociations.h"\r
43 #include "patch.h"\r
44 \r
45 static UINT WM_GITPROGRESS = RegisterWindowMessage(_T("TORTOISEGIT_GITPROGRESS_MSG"));\r
46 \r
47 BOOL    CGitProgressDlg::m_bAscending = FALSE;\r
48 int             CGitProgressDlg::m_nSortedColumn = -1;\r
49 \r
50 #define TRANSFERTIMER   100\r
51 #define VISIBLETIMER    101\r
52 \r
53 enum SVNProgressDlgContextMenuCommands\r
54 {\r
55         // needs to start with 1, since 0 is the return value if *nothing* is clicked on in the context menu\r
56         ID_COMPARE = 1,\r
57         ID_EDITCONFLICT,\r
58         ID_CONFLICTRESOLVE,\r
59         ID_CONFLICTUSETHEIRS,\r
60         ID_CONFLICTUSEMINE,\r
61         ID_LOG,\r
62         ID_OPEN,\r
63         ID_OPENWITH,\r
64         ID_EXPLORE,\r
65         ID_COPY\r
66 };\r
67 \r
68 IMPLEMENT_DYNAMIC(CGitProgressDlg, CResizableStandAloneDialog)\r
69 CGitProgressDlg::CGitProgressDlg(CWnd* pParent /*=NULL*/)\r
70         : CResizableStandAloneDialog(CGitProgressDlg::IDD, pParent)\r
71         , m_bCancelled(FALSE)\r
72         , m_pThread(NULL)\r
73 #if 0\r
74         , m_Revision(_T("HEAD"))\r
75         //, m_RevisionEnd(0)\r
76         , m_bLockWarning(false)\r
77         , m_bLockExists(false)\r
78         , m_bThreadRunning(FALSE)\r
79         , m_nConflicts(0)\r
80         , m_bErrorsOccurred(FALSE)\r
81         , m_bMergesAddsDeletesOccurred(FALSE)\r
82         \r
83         , m_options(ProgOptNone)\r
84         , m_dwCloseOnEnd((DWORD)-1)\r
85         , m_bFinishedItemAdded(false)\r
86         , m_bLastVisible(false)\r
87 //      , m_depth(svn_depth_unknown)\r
88         , m_itemCount(-1)\r
89         , m_itemCountTotal(-1)\r
90         , m_AlwaysConflicted(false)\r
91         , m_BugTraqProvider(NULL)\r
92         , sIgnoredIncluded(MAKEINTRESOURCE(IDS_PROGRS_IGNOREDINCLUDED))\r
93         , sExtExcluded(MAKEINTRESOURCE(IDS_PROGRS_EXTERNALSEXCLUDED))\r
94         , sExtIncluded(MAKEINTRESOURCE(IDS_PROGRS_EXTERNALSINCLUDED))\r
95         , sIgnoreAncestry(MAKEINTRESOURCE(IDS_PROGRS_IGNOREANCESTRY))\r
96         , sRespectAncestry(MAKEINTRESOURCE(IDS_PROGRS_RESPECTANCESTRY))\r
97         , sDryRun(MAKEINTRESOURCE(IDS_PROGRS_DRYRUN))\r
98         , sRecordOnly(MAKEINTRESOURCE(IDS_MERGE_RECORDONLY))\r
99 #endif\r
100 {\r
101 }\r
102 \r
103 CGitProgressDlg::~CGitProgressDlg()\r
104 {\r
105         for (size_t i=0; i<m_arData.size(); i++)\r
106         {\r
107                 delete m_arData[i];\r
108         } \r
109         if(m_pThread != NULL)\r
110         {\r
111                 delete m_pThread;\r
112         }\r
113 }\r
114 \r
115 void CGitProgressDlg::DoDataExchange(CDataExchange* pDX)\r
116 {\r
117         CResizableStandAloneDialog::DoDataExchange(pDX);\r
118         DDX_Control(pDX, IDC_SVNPROGRESS, m_ProgList);\r
119 }\r
120 \r
121 BEGIN_MESSAGE_MAP(CGitProgressDlg, CResizableStandAloneDialog)\r
122         ON_BN_CLICKED(IDC_LOGBUTTON, OnBnClickedLogbutton)\r
123         ON_NOTIFY(NM_CUSTOMDRAW, IDC_SVNPROGRESS, OnNMCustomdrawSvnprogress)\r
124         ON_WM_CLOSE()\r
125         ON_NOTIFY(NM_DBLCLK, IDC_SVNPROGRESS, OnNMDblclkSvnprogress)\r
126         ON_NOTIFY(HDN_ITEMCLICK, 0, OnHdnItemclickSvnprogress)\r
127         ON_WM_SETCURSOR()\r
128         ON_WM_CONTEXTMENU()\r
129         ON_REGISTERED_MESSAGE(WM_GITPROGRESS, OnGitProgress)\r
130         ON_WM_TIMER()\r
131         ON_EN_SETFOCUS(IDC_INFOTEXT, &CGitProgressDlg::OnEnSetfocusInfotext)\r
132         ON_NOTIFY(LVN_BEGINDRAG, IDC_SVNPROGRESS, &CGitProgressDlg::OnLvnBegindragSvnprogress)\r
133         ON_WM_SIZE()\r
134         ON_NOTIFY(LVN_GETDISPINFO, IDC_SVNPROGRESS, &CGitProgressDlg::OnLvnGetdispinfoSvnprogress)\r
135         ON_BN_CLICKED(IDC_NONINTERACTIVE, &CGitProgressDlg::OnBnClickedNoninteractive)\r
136         ON_MESSAGE(WM_SHOWCONFLICTRESOLVER, OnShowConflictResolver)\r
137 END_MESSAGE_MAP()\r
138 \r
139 BOOL CGitProgressDlg::Cancel()\r
140 {\r
141         return m_bCancelled;\r
142 }\r
143 \r
144 LRESULT CGitProgressDlg::OnShowConflictResolver(WPARAM /*wParam*/, LPARAM lParam)\r
145 {\r
146 #if 0\r
147         CConflictResolveDlg dlg(this);\r
148         const svn_wc_conflict_description_t *description = (svn_wc_conflict_description_t *)lParam;\r
149         if (description)\r
150         {\r
151                 dlg.SetConflictDescription(description);\r
152                 if (dlg.DoModal() == IDOK)\r
153                 {\r
154                         if (dlg.GetResult() == svn_wc_conflict_choose_postpone)\r
155                         {\r
156                                 // if the result is conflicted and the dialog returned IDOK,\r
157                                 // that means we should not ask again in case of a conflict\r
158                                 m_AlwaysConflicted = true;\r
159                                 ::SendMessage(GetDlgItem(IDC_NONINTERACTIVE)->GetSafeHwnd(), BM_SETCHECK, BST_CHECKED, 0);\r
160                         }\r
161                 }\r
162                 m_mergedfile = dlg.GetMergedFile();\r
163                 m_bCancelled = dlg.IsCancelled();\r
164                 return dlg.GetResult();\r
165         }\r
166 \r
167         return svn_wc_conflict_choose_postpone;\r
168 #endif\r
169         return 0;\r
170 }\r
171 #if 0\r
172 svn_wc_conflict_choice_t CGitProgressDlg::ConflictResolveCallback(const svn_wc_conflict_description_t *description, CString& mergedfile)\r
173 {\r
174         // we only bother the user when merging\r
175         if (((m_Command == GitProgress_Merge)||(m_Command == GitProgress_MergeAll)||(m_Command == GitProgress_MergeReintegrate))&&(!m_AlwaysConflicted)&&(description))\r
176         {\r
177                 // we're in a worker thread here. That means we must not show a dialog from the thread\r
178                 // but let the UI thread do it.\r
179                 // To do that, we send a message to the UI thread and let it show the conflict resolver dialog.\r
180                 LRESULT dlgResult = ::SendMessage(GetSafeHwnd(), WM_SHOWCONFLICTRESOLVER, 0, (LPARAM)description);\r
181                 mergedfile = m_mergedfile;\r
182                 return (svn_wc_conflict_choice_t)dlgResult;\r
183         }\r
184 \r
185         return svn_wc_conflict_choose_postpone;\r
186 }\r
187 #endif\r
188 void CGitProgressDlg::AddItemToList()\r
189 {\r
190         int totalcount = m_ProgList.GetItemCount();\r
191 \r
192         m_ProgList.SetItemCountEx(totalcount+1, LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL);\r
193         // make columns width fit\r
194         if (iFirstResized < 30)\r
195         {\r
196                 // only resize the columns for the first 30 or so entries.\r
197                 // after that, don't resize them anymore because that's an\r
198                 // expensive function call and the columns will be sized\r
199                 // close enough already.\r
200                 ResizeColumns();\r
201                 iFirstResized++;\r
202         }\r
203 \r
204         // Make sure the item is *entirely* visible even if the horizontal\r
205         // scroll bar is visible.\r
206         int count = m_ProgList.GetCountPerPage();\r
207         if (totalcount <= (m_ProgList.GetTopIndex() + count + nEnsureVisibleCount + 2))\r
208         {\r
209                 nEnsureVisibleCount++;\r
210                 m_bLastVisible = true;\r
211         }\r
212         else\r
213         {\r
214                 nEnsureVisibleCount = 0;\r
215                 if (IsIconic() == 0)\r
216                         m_bLastVisible = false;\r
217         }\r
218 }\r
219 \r
220 \r
221 BOOL CGitProgressDlg::Notify(const CTGitPath& path, git_wc_notify_action_t action,\r
222                                                          int status ,\r
223                                                          CString *strErr \r
224                                                          /*\r
225                                                          svn_node_kind_t kind, const CString& mime_type, \r
226                                                          svn_wc_notify_state_t content_state, \r
227                                                          svn_wc_notify_state_t prop_state, LONG rev,\r
228                                                          const svn_lock_t * lock, svn_wc_notify_lock_state_t lock_state,\r
229                                                          const CString& changelistname,\r
230                                                          svn_merge_range_t * range,\r
231                                                          svn_error_t * err, apr_pool_t * pool\r
232                                                          */)\r
233 {\r
234         bool bNoNotify = false;\r
235         bool bDoAddData = true;\r
236         NotificationData * data = new NotificationData();\r
237         data->path = path;\r
238         data->action = action;\r
239         data->sPathColumnText=path.GetGitPathString();\r
240         data->bAuxItem = false;\r
241 #if 0\r
242         data->kind = kind;\r
243         data->mime_type = mime_type;\r
244         data->content_state = content_state;\r
245         data->prop_state = prop_state;\r
246         data->rev = rev;\r
247         data->lock_state = lock_state;\r
248         data->changelistname = changelistname;\r
249         if ((lock)&&(lock->owner))\r
250                 data->owner = CUnicodeUtils::GetUnicode(lock->owner);\r
251         data->sPathColumnText = path.GetUIPathString();\r
252         if (!m_basePath.IsEmpty())\r
253                 data->basepath = m_basePath;\r
254         if (range)\r
255                 data->merge_range = *range;\r
256 #endif\r
257         switch (data->action)\r
258         {\r
259         case git_wc_notify_add:\r
260         //case svn_wc_notify_update_add:\r
261         //      if ((data->content_state == svn_wc_notify_state_conflicted) || (data->prop_state == svn_wc_notify_state_conflicted))\r
262         //      {\r
263         //              data->color = m_Colors.GetColor(CColors::Conflict);\r
264         //              data->bConflictedActionItem = true;\r
265         //              data->sActionColumnText.LoadString(IDS_SVNACTION_CONFLICTED);\r
266         //              m_nConflicts++;\r
267         //      }\r
268         //      else\r
269         //      {\r
270         //              m_bMergesAddsDeletesOccurred = true;\r
271                         data->sActionColumnText.LoadString(IDS_SVNACTION_ADD);\r
272                         data->color = m_Colors.GetColor(CColors::Added);\r
273         //      }\r
274                 break;\r
275         case git_wc_notify_sendmail_start:\r
276                 data->bAuxItem = true;\r
277                 data->sActionColumnText.LoadString(IDS_SVNACTION_SENDMAIL_START);\r
278                 data->color = m_Colors.GetColor(CColors::Modified);\r
279                 break;\r
280         \r
281         case git_wc_notify_sendmail_error:\r
282                 data->bAuxItem = true;\r
283                 data->sActionColumnText.LoadString(IDS_SVNACTION_SENDMAIL_ERROR);\r
284                 if(strErr)\r
285                         data->sPathColumnText = *strErr;\r
286                 else\r
287                         data->sPathColumnText.Empty();\r
288                 data->color = m_Colors.GetColor(CColors::Modified);\r
289                 break;\r
290 \r
291         case git_wc_notify_sendmail_done:\r
292                 \r
293                 data->sActionColumnText.LoadString(IDS_SVNACTION_SENDMAIL_DONE);\r
294                 data->sPathColumnText.Empty();\r
295                 data->color = m_Colors.GetColor(CColors::Modified);\r
296                 break;\r
297 \r
298         case git_wc_notify_sendmail_retry:\r
299                 data->sActionColumnText.LoadString(IDS_SVNACTION_SENDMAIL_RETRY);\r
300                 data->sPathColumnText.Empty();\r
301                 data->color = m_Colors.GetColor(CColors::Modified);\r
302                 break;\r
303 \r
304 \r
305         case git_wc_notify_resolved:\r
306                 data->sActionColumnText.LoadString(IDS_SVNACTION_RESOLVE);\r
307                 break;\r
308 \r
309         case git_wc_notify_revert:\r
310                 data->sActionColumnText.LoadString(IDS_SVNACTION_REVERT);\r
311                 break;\r
312 \r
313 #if 0\r
314         case svn_wc_notify_commit_added:\r
315                 data->sActionColumnText.LoadString(IDS_SVNACTION_ADDING);\r
316                 data->color = m_Colors.GetColor(CColors::Added);\r
317                 break;\r
318         case svn_wc_notify_copy:\r
319                 data->sActionColumnText.LoadString(IDS_SVNACTION_COPY);\r
320                 break;\r
321         case svn_wc_notify_commit_modified:\r
322                 data->sActionColumnText.LoadString(IDS_SVNACTION_MODIFIED);\r
323                 data->color = m_Colors.GetColor(CColors::Modified);\r
324                 break;\r
325         case svn_wc_notify_delete:\r
326         case svn_wc_notify_update_delete:\r
327                 data->sActionColumnText.LoadString(IDS_SVNACTION_DELETE);\r
328                 m_bMergesAddsDeletesOccurred = true;\r
329                 data->color = m_Colors.GetColor(CColors::Deleted);\r
330                 break;\r
331         case svn_wc_notify_commit_deleted:\r
332                 data->sActionColumnText.LoadString(IDS_SVNACTION_DELETING);\r
333                 data->color = m_Colors.GetColor(CColors::Deleted);\r
334                 break;\r
335         case svn_wc_notify_restore:\r
336                 data->sActionColumnText.LoadString(IDS_SVNACTION_RESTORE);\r
337                 break;\r
338 \r
339         case svn_wc_notify_update_replace:\r
340         case svn_wc_notify_commit_replaced:\r
341                 data->sActionColumnText.LoadString(IDS_SVNACTION_REPLACED);\r
342                 data->color = m_Colors.GetColor(CColors::Deleted);\r
343                 break;\r
344         case svn_wc_notify_exists:\r
345                 if ((data->content_state == svn_wc_notify_state_conflicted) || (data->prop_state == svn_wc_notify_state_conflicted))\r
346                 {\r
347                         data->color = m_Colors.GetColor(CColors::Conflict);\r
348                         data->bConflictedActionItem = true;\r
349                         m_nConflicts++;\r
350                         data->sActionColumnText.LoadString(IDS_SVNACTION_CONFLICTED);\r
351                 }\r
352                 else if ((data->content_state == svn_wc_notify_state_merged) || (data->prop_state == svn_wc_notify_state_merged))\r
353                 {\r
354                         data->color = m_Colors.GetColor(CColors::Merged);\r
355                         m_bMergesAddsDeletesOccurred = true;\r
356                         data->sActionColumnText.LoadString(IDS_SVNACTION_MERGED);\r
357                 }\r
358                 else\r
359                         data->sActionColumnText.LoadString(IDS_SVNACTION_EXISTS);\r
360                 break;\r
361         case svn_wc_notify_update_update:\r
362                 // if this is an inoperative dir change, don't show the notification.\r
363                 // an inoperative dir change is when a directory gets updated without\r
364                 // any real change in either text or properties.\r
365                 if ((kind == svn_node_dir)\r
366                         && ((prop_state == svn_wc_notify_state_inapplicable)\r
367                         || (prop_state == svn_wc_notify_state_unknown)\r
368                         || (prop_state == svn_wc_notify_state_unchanged)))\r
369                 {\r
370                         bNoNotify = true;\r
371                         break;\r
372                 }\r
373                 if ((data->content_state == svn_wc_notify_state_conflicted) || (data->prop_state == svn_wc_notify_state_conflicted))\r
374                 {\r
375                         data->color = m_Colors.GetColor(CColors::Conflict);\r
376                         data->bConflictedActionItem = true;\r
377                         m_nConflicts++;\r
378                         data->sActionColumnText.LoadString(IDS_SVNACTION_CONFLICTED);\r
379                 }\r
380                 else if ((data->content_state == svn_wc_notify_state_merged) || (data->prop_state == svn_wc_notify_state_merged))\r
381                 {\r
382                         data->color = m_Colors.GetColor(CColors::Merged);\r
383                         m_bMergesAddsDeletesOccurred = true;\r
384                         data->sActionColumnText.LoadString(IDS_SVNACTION_MERGED);\r
385                 }\r
386                 else if (((data->content_state != svn_wc_notify_state_unchanged)&&(data->content_state != svn_wc_notify_state_unknown)) || \r
387                         ((data->prop_state != svn_wc_notify_state_unchanged)&&(data->prop_state != svn_wc_notify_state_unknown)))\r
388                 {\r
389                         data->sActionColumnText.LoadString(IDS_SVNACTION_UPDATE);\r
390                 }\r
391                 else\r
392                 {\r
393                         bNoNotify = true;\r
394                         break;\r
395                 }\r
396                 if (lock_state == svn_wc_notify_lock_state_unlocked)\r
397                 {\r
398                         CString temp(MAKEINTRESOURCE(IDS_SVNACTION_UNLOCKED));\r
399                         data->sActionColumnText += _T(", ") + temp;\r
400                 }\r
401                 break;\r
402 \r
403         case svn_wc_notify_update_external:\r
404                 // For some reason we build a list of externals...\r
405                 m_ExtStack.AddHead(path.GetUIPathString());\r
406                 data->sActionColumnText.LoadString(IDS_SVNACTION_EXTERNAL);\r
407                 data->bAuxItem = true;\r
408                 break;\r
409 \r
410         case svn_wc_notify_update_completed:\r
411                 {\r
412                         data->sActionColumnText.LoadString(IDS_SVNACTION_COMPLETED);\r
413                         data->bAuxItem = true;\r
414                         bool bEmpty = !!m_ExtStack.IsEmpty();\r
415                         if (!bEmpty)\r
416                                 data->sPathColumnText.Format(IDS_PROGRS_PATHATREV, (LPCTSTR)m_ExtStack.RemoveHead(), rev);\r
417                         else\r
418                                 data->sPathColumnText.Format(IDS_PROGRS_ATREV, rev);\r
419 \r
420                         if ((m_nConflicts>0)&&(bEmpty))\r
421                         {\r
422                                 // We're going to add another aux item - let's shove this current onto the list first\r
423                                 // I don't really like this, but it will do for the moment.\r
424                                 m_arData.push_back(data);\r
425                                 AddItemToList();\r
426 \r
427                                 data = new NotificationData();\r
428                                 data->bAuxItem = true;\r
429                                 data->sActionColumnText.LoadString(IDS_PROGRS_CONFLICTSOCCURED_WARNING);\r
430                                 data->sPathColumnText.LoadString(IDS_PROGRS_CONFLICTSOCCURED);\r
431                                 data->color = m_Colors.GetColor(CColors::Conflict);\r
432                                 CSoundUtils::PlayTSVNWarning();\r
433                                 // This item will now be added after the switch statement\r
434                         }\r
435                         if (!m_basePath.IsEmpty())\r
436                                 m_FinishedRevMap[m_basePath.GetSVNApiPath(pool)] = rev;\r
437                         m_RevisionEnd = rev;\r
438                         m_bFinishedItemAdded = true;\r
439                 }\r
440                 break;\r
441         case svn_wc_notify_commit_postfix_txdelta:\r
442                 data->sActionColumnText.LoadString(IDS_SVNACTION_POSTFIX);\r
443                 break;\r
444         case svn_wc_notify_failed_revert:\r
445                 data->sActionColumnText.LoadString(IDS_SVNACTION_FAILEDREVERT);\r
446                 break;\r
447         case svn_wc_notify_status_completed:\r
448         case svn_wc_notify_status_external:\r
449                 data->sActionColumnText.LoadString(IDS_SVNACTION_STATUS);\r
450                 break;\r
451         case svn_wc_notify_skip:\r
452                 if ((content_state == svn_wc_notify_state_missing)||(content_state == svn_wc_notify_state_obstructed)||(content_state == svn_wc_notify_state_conflicted))\r
453                 {\r
454                         data->sActionColumnText.LoadString(IDS_SVNACTION_SKIPMISSING);\r
455 \r
456                         // The color settings dialog describes the red color with\r
457                         // "possible or real conflict / obstructed" which also applies to\r
458                         // skipped targets during a merge. So we just use the same color.\r
459                         data->color = m_Colors.GetColor(CColors::Conflict);\r
460                 }\r
461                 else\r
462                         data->sActionColumnText.LoadString(IDS_SVNACTION_SKIP);\r
463                 break;\r
464         case svn_wc_notify_locked:\r
465                 if ((lock)&&(lock->owner))\r
466                         data->sActionColumnText.Format(IDS_SVNACTION_LOCKEDBY, (LPCTSTR)CUnicodeUtils::GetUnicode(lock->owner));\r
467                 break;\r
468         case svn_wc_notify_unlocked:\r
469                 data->sActionColumnText.LoadString(IDS_SVNACTION_UNLOCKED);\r
470                 break;\r
471         case svn_wc_notify_failed_lock:\r
472                 data->sActionColumnText.LoadString(IDS_SVNACTION_FAILEDLOCK);\r
473                 m_arData.push_back(data);\r
474                 AddItemToList();\r
475                 ReportError(SVN::GetErrorString(err));\r
476                 bDoAddData = false;\r
477                 if (err->apr_err == SVN_ERR_FS_OUT_OF_DATE)\r
478                         m_bLockWarning = true;\r
479                 if (err->apr_err == SVN_ERR_FS_PATH_ALREADY_LOCKED)\r
480                         m_bLockExists = true;\r
481                 break;\r
482         case svn_wc_notify_failed_unlock:\r
483                 data->sActionColumnText.LoadString(IDS_SVNACTION_FAILEDUNLOCK);\r
484                 m_arData.push_back(data);\r
485                 AddItemToList();\r
486                 ReportError(SVN::GetErrorString(err));\r
487                 bDoAddData = false;\r
488                 if (err->apr_err == SVN_ERR_FS_OUT_OF_DATE)\r
489                         m_bLockWarning = true;\r
490                 break;\r
491         case svn_wc_notify_changelist_set:\r
492                 data->sActionColumnText.Format(IDS_SVNACTION_CHANGELISTSET, (LPCTSTR)data->changelistname);\r
493                 break;\r
494         case svn_wc_notify_changelist_clear:\r
495                 data->sActionColumnText.LoadString(IDS_SVNACTION_CHANGELISTCLEAR);\r
496                 break;\r
497         case svn_wc_notify_changelist_moved:\r
498                 data->sActionColumnText.Format(IDS_SVNACTION_CHANGELISTMOVED, (LPCTSTR)data->changelistname);\r
499                 break;\r
500         case svn_wc_notify_foreign_merge_begin:\r
501         case svn_wc_notify_merge_begin:\r
502                 if (range == NULL)\r
503                         data->sActionColumnText.LoadString(IDS_SVNACTION_MERGEBEGINNONE);\r
504                 else if ((data->merge_range.start == data->merge_range.end) || (data->merge_range.start == data->merge_range.end - 1))\r
505                         data->sActionColumnText.Format(IDS_SVNACTION_MERGEBEGINSINGLE, data->merge_range.end);\r
506                 else if (data->merge_range.start - 1 == data->merge_range.end)\r
507                         data->sActionColumnText.Format(IDS_SVNACTION_MERGEBEGINSINGLEREVERSE, data->merge_range.start);\r
508                 else if (data->merge_range.start < data->merge_range.end)\r
509                         data->sActionColumnText.Format(IDS_SVNACTION_MERGEBEGINMULTIPLE, data->merge_range.start + 1, data->merge_range.end);\r
510                 else\r
511                         data->sActionColumnText.Format(IDS_SVNACTION_MERGEBEGINMULTIPLEREVERSE, data->merge_range.start, data->merge_range.end + 1);\r
512                 data->bAuxItem = true;\r
513                 break;\r
514 #endif\r
515         default:\r
516                 break;\r
517         } // switch (data->action)\r
518 \r
519         if (bNoNotify)\r
520                 delete data;\r
521         else\r
522         {\r
523                 if (bDoAddData)\r
524                 {\r
525                         m_arData.push_back(data);\r
526                         AddItemToList();\r
527                         if ((!data->bAuxItem) && (m_itemCount > 0))\r
528                         {\r
529                                 m_itemCount--;\r
530 \r
531                                 CProgressCtrl * progControl = (CProgressCtrl *)GetDlgItem(IDC_PROGRESSBAR);\r
532                                 progControl->ShowWindow(SW_SHOW);\r
533                                 progControl->SetPos(m_itemCountTotal - m_itemCount);\r
534                                 progControl->SetRange32(0, m_itemCountTotal);\r
535                         }\r
536                 }\r
537                 //if ((action == svn_wc_notify_commit_postfix_txdelta)&&(bSecondResized == FALSE))\r
538                 //{\r
539                 //      ResizeColumns();\r
540                 //      bSecondResized = TRUE;\r
541                 //}\r
542         }\r
543 \r
544         return TRUE;\r
545 }\r
546 \r
547 \r
548 CString CGitProgressDlg::BuildInfoString()\r
549 {\r
550         CString infotext;\r
551 #if 0\r
552         \r
553         CString temp;\r
554         int added = 0;\r
555         int copied = 0;\r
556         int deleted = 0;\r
557         int restored = 0;\r
558         int reverted = 0;\r
559         int resolved = 0;\r
560         int conflicted = 0;\r
561         int updated = 0;\r
562         int merged = 0;\r
563         int modified = 0;\r
564         int skipped = 0;\r
565         int replaced = 0;\r
566 \r
567         for (size_t i=0; i<m_arData.size(); ++i)\r
568         {\r
569                 const NotificationData * dat = m_arData[i];\r
570                 switch (dat->action)\r
571                 {\r
572                 case svn_wc_notify_add:\r
573                 case svn_wc_notify_update_add:\r
574                 case svn_wc_notify_commit_added:\r
575                         if (dat->bConflictedActionItem)\r
576                                 conflicted++;\r
577                         else\r
578                                 added++;\r
579                         break;\r
580                 case svn_wc_notify_copy:\r
581                         copied++;\r
582                         break;\r
583                 case svn_wc_notify_delete:\r
584                 case svn_wc_notify_update_delete:\r
585                 case svn_wc_notify_commit_deleted:\r
586                         deleted++;\r
587                         break;\r
588                 case svn_wc_notify_restore:\r
589                         restored++;\r
590                         break;\r
591                 case svn_wc_notify_revert:\r
592                         reverted++;\r
593                         break;\r
594                 case svn_wc_notify_resolved:\r
595                         resolved++;\r
596                         break;\r
597                 case svn_wc_notify_update_update:\r
598                         if (dat->bConflictedActionItem)\r
599                                 conflicted++;\r
600                         else if ((dat->content_state == svn_wc_notify_state_merged) || (dat->prop_state == svn_wc_notify_state_merged))\r
601                                 merged++;\r
602                         else\r
603                                 updated++;\r
604                         break;\r
605                 case svn_wc_notify_commit_modified:\r
606                         modified++;\r
607                         break;\r
608                 case svn_wc_notify_skip:\r
609                         skipped++;\r
610                         break;\r
611                 case svn_wc_notify_commit_replaced:\r
612                         replaced++;\r
613                         break;\r
614                 }\r
615         }\r
616         if (conflicted)\r
617         {\r
618                 temp.LoadString(IDS_SVNACTION_CONFLICTED);\r
619                 infotext += temp;\r
620                 temp.Format(_T(":%d "), conflicted);\r
621                 infotext += temp;\r
622         }\r
623         if (skipped)\r
624         {\r
625                 temp.LoadString(IDS_SVNACTION_SKIP);\r
626                 infotext += temp;\r
627                 infotext.AppendFormat(_T(":%d "), skipped);\r
628         }\r
629         if (merged)\r
630         {\r
631                 temp.LoadString(IDS_SVNACTION_MERGED);\r
632                 infotext += temp;\r
633                 infotext.AppendFormat(_T(":%d "), merged);\r
634         }\r
635         if (added)\r
636         {\r
637                 temp.LoadString(IDS_SVNACTION_ADD);\r
638                 infotext += temp;\r
639                 infotext.AppendFormat(_T(":%d "), added);\r
640         }\r
641         if (deleted)\r
642         {\r
643                 temp.LoadString(IDS_SVNACTION_DELETE);\r
644                 infotext += temp;\r
645                 infotext.AppendFormat(_T(":%d "), deleted);\r
646         }\r
647         if (modified)\r
648         {\r
649                 temp.LoadString(IDS_SVNACTION_MODIFIED);\r
650                 infotext += temp;\r
651                 infotext.AppendFormat(_T(":%d "), modified);\r
652         }\r
653         if (copied)\r
654         {\r
655                 temp.LoadString(IDS_SVNACTION_COPY);\r
656                 infotext += temp;\r
657                 infotext.AppendFormat(_T(":%d "), copied);\r
658         }\r
659         if (replaced)\r
660         {\r
661                 temp.LoadString(IDS_SVNACTION_REPLACED);\r
662                 infotext += temp;\r
663                 infotext.AppendFormat(_T(":%d "), replaced);\r
664         }\r
665         if (updated)\r
666         {\r
667                 temp.LoadString(IDS_SVNACTION_UPDATE);\r
668                 infotext += temp;\r
669                 infotext.AppendFormat(_T(":%d "), updated);\r
670         }\r
671         if (restored)\r
672         {\r
673                 temp.LoadString(IDS_SVNACTION_RESTORE);\r
674                 infotext += temp;\r
675                 infotext.AppendFormat(_T(":%d "), restored);\r
676         }\r
677         if (reverted)\r
678         {\r
679                 temp.LoadString(IDS_SVNACTION_REVERT);\r
680                 infotext += temp;\r
681                 infotext.AppendFormat(_T(":%d "), reverted);\r
682         }\r
683         if (resolved)\r
684         {\r
685                 temp.LoadString(IDS_SVNACTION_RESOLVE);\r
686                 infotext += temp;\r
687                 infotext.AppendFormat(_T(":%d "), resolved);\r
688         }\r
689 #endif\r
690         return infotext;\r
691 }\r
692 \r
693 void CGitProgressDlg::SetSelectedList(const CTGitPathList& selPaths)\r
694 {\r
695         m_selectedPaths = selPaths;\r
696 }\r
697 \r
698 void CGitProgressDlg::ResizeColumns()\r
699 {\r
700         m_ProgList.SetRedraw(FALSE);\r
701 \r
702         TCHAR textbuf[MAX_PATH];\r
703 \r
704         int maxcol = ((CHeaderCtrl*)(m_ProgList.GetDlgItem(0)))->GetItemCount()-1;\r
705         for (int col = 0; col <= maxcol; col++)\r
706         {\r
707                 // find the longest width of all items\r
708                 int count = m_ProgList.GetItemCount();\r
709                 HDITEM hdi = {0};\r
710                 hdi.mask = HDI_TEXT;\r
711                 hdi.pszText = textbuf;\r
712                 hdi.cchTextMax = sizeof(textbuf);\r
713                 ((CHeaderCtrl*)(m_ProgList.GetDlgItem(0)))->GetItem(col, &hdi);\r
714                 int cx = m_ProgList.GetStringWidth(hdi.pszText)+20; // 20 pixels for col separator and margin\r
715 \r
716                 for (int index = 0; index<count; ++index)\r
717                 {\r
718                         // get the width of the string and add 12 pixels for the column separator and margins\r
719                         int linewidth = cx;\r
720                         switch (col)\r
721                         {\r
722                         case 0:\r
723                                 linewidth = m_ProgList.GetStringWidth(m_arData[index]->sActionColumnText) + 12;\r
724                                 break;\r
725                         case 1:\r
726                                 linewidth = m_ProgList.GetStringWidth(m_arData[index]->sPathColumnText) + 12;\r
727                                 break;\r
728                         case 2:\r
729                                 linewidth = m_ProgList.GetStringWidth(m_arData[index]->mime_type) + 12;\r
730                                 break;\r
731                         }\r
732                         if (cx < linewidth)\r
733                                 cx = linewidth;\r
734                 }\r
735                 m_ProgList.SetColumnWidth(col, cx);\r
736         }\r
737 \r
738         m_ProgList.SetRedraw(TRUE);     \r
739 }\r
740 \r
741 BOOL CGitProgressDlg::OnInitDialog()\r
742 {\r
743         __super::OnInitDialog();\r
744 \r
745         m_ProgList.SetExtendedStyle (LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);\r
746 \r
747         m_ProgList.DeleteAllItems();\r
748         int c = ((CHeaderCtrl*)(m_ProgList.GetDlgItem(0)))->GetItemCount()-1;\r
749         while (c>=0)\r
750                 m_ProgList.DeleteColumn(c--);\r
751         CString temp;\r
752         temp.LoadString(IDS_PROGRS_ACTION);\r
753         m_ProgList.InsertColumn(0, temp);\r
754         temp.LoadString(IDS_PROGRS_PATH);\r
755         m_ProgList.InsertColumn(1, temp);\r
756         temp.LoadString(IDS_PROGRS_MIMETYPE);\r
757         m_ProgList.InsertColumn(2, temp);\r
758 \r
759         m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);\r
760         if (m_pThread==NULL)\r
761         {\r
762                 ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));\r
763         }\r
764         else\r
765         {\r
766                 m_pThread->m_bAutoDelete = FALSE;\r
767                 m_pThread->ResumeThread();\r
768         }\r
769 \r
770         UpdateData(FALSE);\r
771 \r
772         // Call this early so that the column headings aren't hidden before any\r
773         // text gets added.\r
774         ResizeColumns();\r
775 \r
776         SetTimer(VISIBLETIMER, 300, NULL);\r
777 \r
778         AddAnchor(IDC_SVNPROGRESS, TOP_LEFT, BOTTOM_RIGHT);\r
779         AddAnchor(IDC_PROGRESSLABEL, BOTTOM_LEFT, BOTTOM_CENTER);\r
780         AddAnchor(IDC_PROGRESSBAR, BOTTOM_CENTER, BOTTOM_RIGHT);\r
781         AddAnchor(IDC_INFOTEXT, BOTTOM_LEFT, BOTTOM_RIGHT);\r
782         AddAnchor(IDC_NONINTERACTIVE, BOTTOM_LEFT, BOTTOM_RIGHT);\r
783         AddAnchor(IDCANCEL, BOTTOM_RIGHT);\r
784         AddAnchor(IDOK, BOTTOM_RIGHT);\r
785         AddAnchor(IDC_LOGBUTTON, BOTTOM_RIGHT);\r
786         //SetPromptParentWindow(this->m_hWnd);\r
787         if (hWndExplorer)\r
788                 CenterWindow(CWnd::FromHandle(hWndExplorer));\r
789         EnableSaveRestore(_T("SVNProgressDlg"));\r
790         return TRUE;\r
791 }\r
792 \r
793 bool CGitProgressDlg::SetBackgroundImage(UINT nID)\r
794 {\r
795         return CAppUtils::SetListCtrlBackgroundImage(m_ProgList.GetSafeHwnd(), nID);\r
796 }\r
797 \r
798 #if 0\r
799 void CGitProgressDlg::ReportSVNError()\r
800 {\r
801         ReportError(GetLastErrorMessage());\r
802 }\r
803 #endif\r
804 \r
805 void CGitProgressDlg::ReportError(const CString& sError)\r
806 {\r
807         CSoundUtils::PlayTGitError();\r
808         ReportString(sError, CString(MAKEINTRESOURCE(IDS_ERR_ERROR)), m_Colors.GetColor(CColors::Conflict));\r
809         m_bErrorsOccurred = true;\r
810 }\r
811 \r
812 void CGitProgressDlg::ReportWarning(const CString& sWarning)\r
813 {\r
814         CSoundUtils::PlayTGitWarning();\r
815         ReportString(sWarning, CString(MAKEINTRESOURCE(IDS_WARN_WARNING)), m_Colors.GetColor(CColors::Conflict));\r
816 }\r
817 \r
818 void CGitProgressDlg::ReportNotification(const CString& sNotification)\r
819 {\r
820         CSoundUtils::PlayTGitNotification();\r
821         ReportString(sNotification, CString(MAKEINTRESOURCE(IDS_WARN_NOTE)));\r
822 }\r
823 \r
824 void CGitProgressDlg::ReportCmd(const CString& sCmd)\r
825 {\r
826         ReportString(sCmd, CString(MAKEINTRESOURCE(IDS_PROGRS_CMDINFO)), m_Colors.GetColor(CColors::Cmd));\r
827 }\r
828 \r
829 void CGitProgressDlg::ReportString(CString sMessage, const CString& sMsgKind, COLORREF color)\r
830 {\r
831         // instead of showing a dialog box with the error message or notification,\r
832         // just insert the error text into the list control.\r
833         // that way the user isn't 'interrupted' by a dialog box popping up!\r
834 \r
835         // the message may be split up into different lines\r
836         // so add a new entry for each line of the message\r
837         while (!sMessage.IsEmpty())\r
838         {\r
839                 NotificationData * data = new NotificationData();\r
840                 data->bAuxItem = true;\r
841                 data->sActionColumnText = sMsgKind;\r
842                 if (sMessage.Find('\n')>=0)\r
843                         data->sPathColumnText = sMessage.Left(sMessage.Find('\n'));\r
844                 else\r
845                         data->sPathColumnText = sMessage;               \r
846                 data->sPathColumnText.Trim(_T("\n\r"));\r
847                 data->color = color;\r
848                 if (sMessage.Find('\n')>=0)\r
849                 {\r
850                         sMessage = sMessage.Mid(sMessage.Find('\n'));\r
851                         sMessage.Trim(_T("\n\r"));\r
852                 }\r
853                 else\r
854                         sMessage.Empty();\r
855                 m_arData.push_back(data);\r
856                 AddItemToList();\r
857         }\r
858 }\r
859 \r
860 UINT CGitProgressDlg::ProgressThreadEntry(LPVOID pVoid)\r
861 {\r
862         return ((CGitProgressDlg*)pVoid)->ProgressThread();\r
863 }\r
864 \r
865 UINT CGitProgressDlg::ProgressThread()\r
866 {\r
867         // The SetParams function should have loaded something for us\r
868 \r
869         CString temp;\r
870         CString sWindowTitle;\r
871         bool localoperation = false;\r
872         bool bSuccess = false;\r
873         m_AlwaysConflicted = false;\r
874 \r
875         DialogEnableWindow(IDOK, FALSE);\r
876         DialogEnableWindow(IDCANCEL, TRUE);\r
877 //      SetAndClearProgressInfo(m_hWnd);\r
878         m_itemCount = m_itemCountTotal;\r
879 \r
880         InterlockedExchange(&m_bThreadRunning, TRUE);\r
881         iFirstResized = 0;\r
882         bSecondResized = FALSE;\r
883         m_bFinishedItemAdded = false;\r
884         CTime startTime = CTime::GetCurrentTime();\r
885         switch (m_Command)\r
886         {\r
887         case GitProgress_Add:\r
888                 bSuccess = CmdAdd(sWindowTitle, localoperation);\r
889                 break;\r
890         case GitProgress_Checkout:\r
891                 bSuccess = CmdCheckout(sWindowTitle, localoperation);\r
892                 break;\r
893         case GitProgress_Commit:\r
894                 bSuccess = CmdCommit(sWindowTitle, localoperation);\r
895                 break;\r
896         case GitProgress_Copy:\r
897                 bSuccess = CmdCopy(sWindowTitle, localoperation);\r
898                 break;\r
899         case GitProgress_Export:\r
900                 bSuccess = CmdExport(sWindowTitle, localoperation);\r
901                 break;\r
902         case GitProgress_Import:\r
903                 bSuccess = CmdImport(sWindowTitle, localoperation);\r
904                 break;\r
905         case GitProgress_Lock:\r
906                 bSuccess = CmdLock(sWindowTitle, localoperation);\r
907                 break;\r
908         case GitProgress_Merge:\r
909                 bSuccess = CmdMerge(sWindowTitle, localoperation);\r
910                 break;\r
911         case GitProgress_MergeAll:\r
912                 bSuccess = CmdMergeAll(sWindowTitle, localoperation);\r
913                 break;\r
914         case GitProgress_MergeReintegrate:\r
915                 bSuccess = CmdMergeReintegrate(sWindowTitle, localoperation);\r
916                 break;\r
917         case GitProgress_Rename:\r
918                 bSuccess = CmdRename(sWindowTitle, localoperation);\r
919                 break;\r
920         case GitProgress_Resolve:\r
921                 bSuccess = CmdResolve(sWindowTitle, localoperation);\r
922                 break;\r
923         case GitProgress_Revert:\r
924                 bSuccess = CmdRevert(sWindowTitle, localoperation);\r
925                 break;\r
926         case GitProgress_Switch:\r
927                 bSuccess = CmdSwitch(sWindowTitle, localoperation);\r
928                 break;\r
929         case GitProgress_Unlock:\r
930                 bSuccess = CmdUnlock(sWindowTitle, localoperation);\r
931                 break;\r
932         case GitProgress_Update:\r
933                 bSuccess = CmdUpdate(sWindowTitle, localoperation);\r
934                 break;\r
935         case GitProgress_SendMail:\r
936                 bSuccess = CmdSendMail(sWindowTitle, localoperation);\r
937                 break;\r
938         }\r
939         if (!bSuccess)\r
940                 temp.LoadString(IDS_PROGRS_TITLEFAILED);\r
941         else\r
942                 temp.LoadString(IDS_PROGRS_TITLEFIN);\r
943         sWindowTitle = sWindowTitle + _T(" ") + temp;\r
944         SetWindowText(sWindowTitle);\r
945 \r
946         KillTimer(TRANSFERTIMER);\r
947         KillTimer(VISIBLETIMER);\r
948 \r
949         DialogEnableWindow(IDCANCEL, FALSE);\r
950         DialogEnableWindow(IDOK, TRUE);\r
951 \r
952         CString info = BuildInfoString();\r
953         if (!bSuccess)\r
954                 info.LoadString(IDS_PROGRS_INFOFAILED);\r
955         SetDlgItemText(IDC_INFOTEXT, info);\r
956         ResizeColumns();\r
957         SendMessage(DM_SETDEFID, IDOK);\r
958         GetDlgItem(IDOK)->SetFocus();   \r
959 \r
960         CString sFinalInfo;\r
961         if (!m_sTotalBytesTransferred.IsEmpty())\r
962         {\r
963                 CTimeSpan time = CTime::GetCurrentTime() - startTime;\r
964                 temp.Format(IDS_PROGRS_TIME, (LONG)time.GetTotalMinutes(), (LONG)time.GetSeconds());\r
965                 sFinalInfo.Format(IDS_PROGRS_FINALINFO, m_sTotalBytesTransferred, (LPCTSTR)temp);\r
966                 SetDlgItemText(IDC_PROGRESSLABEL, sFinalInfo);\r
967         }\r
968         else\r
969                 GetDlgItem(IDC_PROGRESSLABEL)->ShowWindow(SW_HIDE);\r
970 \r
971         GetDlgItem(IDC_PROGRESSBAR)->ShowWindow(SW_HIDE);\r
972 \r
973         if (!m_bFinishedItemAdded)\r
974         {\r
975                 // there's no "finished: xxx" line at the end. We add one here to make\r
976                 // sure the user sees that the command is actually finished.\r
977                 NotificationData * data = new NotificationData();\r
978                 data->bAuxItem = true;\r
979                 data->sActionColumnText.LoadString(IDS_PROGRS_FINISHED);\r
980                 m_arData.push_back(data);\r
981                 AddItemToList();\r
982         }\r
983 \r
984         int count = m_ProgList.GetItemCount();\r
985         if ((count > 0)&&(m_bLastVisible))\r
986                 m_ProgList.EnsureVisible(count-1, FALSE);\r
987 \r
988         CLogFile logfile;\r
989         if (logfile.Open())\r
990         {\r
991                 logfile.AddTimeLine();\r
992                 for (size_t i=0; i<m_arData.size(); i++)\r
993                 {\r
994                         NotificationData * data = m_arData[i];\r
995                         temp.Format(_T("%-20s : %s"), (LPCTSTR)data->sActionColumnText, (LPCTSTR)data->sPathColumnText);\r
996                         logfile.AddLine(temp);\r
997                 }\r
998                 if (!sFinalInfo.IsEmpty())\r
999                         logfile.AddLine(sFinalInfo);\r
1000                 logfile.Close();\r
1001         }\r
1002 \r
1003         m_bCancelled = TRUE;\r
1004         InterlockedExchange(&m_bThreadRunning, FALSE);\r
1005         RefreshCursor();\r
1006 \r
1007         DWORD dwAutoClose = CRegStdWORD(_T("Software\\TortoiseGit\\AutoClose"));\r
1008         if (m_options & ProgOptDryRun)\r
1009                 dwAutoClose = 0;                // dry run means progress dialog doesn't auto close at all\r
1010         if (!m_bLastVisible)\r
1011                 dwAutoClose = 0;\r
1012         if (m_dwCloseOnEnd != (DWORD)-1)\r
1013                 dwAutoClose = m_dwCloseOnEnd;           // command line value has priority over setting value\r
1014         if ((dwAutoClose == CLOSE_NOERRORS)&&(!m_bErrorsOccurred))\r
1015                 PostMessage(WM_COMMAND, 1, (LPARAM)GetDlgItem(IDOK)->m_hWnd);\r
1016         if ((dwAutoClose == CLOSE_NOCONFLICTS)&&(!m_bErrorsOccurred)&&(m_nConflicts==0))\r
1017                 PostMessage(WM_COMMAND, 1, (LPARAM)GetDlgItem(IDOK)->m_hWnd);\r
1018         if ((dwAutoClose == CLOSE_NOMERGES)&&(!m_bErrorsOccurred)&&(m_nConflicts==0)&&(!m_bMergesAddsDeletesOccurred))\r
1019                 PostMessage(WM_COMMAND, 1, (LPARAM)GetDlgItem(IDOK)->m_hWnd);\r
1020         if ((dwAutoClose == CLOSE_LOCAL)&&(!m_bErrorsOccurred)&&(m_nConflicts==0)&&(localoperation))\r
1021                 PostMessage(WM_COMMAND, 1, (LPARAM)GetDlgItem(IDOK)->m_hWnd);\r
1022 \r
1023         //Don't do anything here which might cause messages to be sent to the window\r
1024         //The window thread is probably now blocked in OnOK if we've done an auto close\r
1025         return 0;\r
1026 }\r
1027 \r
1028 void CGitProgressDlg::OnBnClickedLogbutton()\r
1029 {\r
1030 #if 0\r
1031         if (m_targetPathList.GetCount() != 1)\r
1032                 return;\r
1033         StringRevMap::iterator it = m_UpdateStartRevMap.begin();\r
1034         svn_revnum_t rev = -1;\r
1035         if (it != m_UpdateStartRevMap.end())\r
1036         {\r
1037                 rev = it->second;\r
1038         }\r
1039         CLogDlg dlg;\r
1040         dlg.SetParams(m_targetPathList[0], m_RevisionEnd, m_RevisionEnd, rev, 0, TRUE);\r
1041         dlg.DoModal();\r
1042 #endif\r
1043 }\r
1044 \r
1045 \r
1046 void CGitProgressDlg::OnClose()\r
1047 {\r
1048         if (m_bCancelled)\r
1049         {\r
1050                 TerminateThread(m_pThread->m_hThread, (DWORD)-1);\r
1051                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
1052         }\r
1053         else\r
1054         {\r
1055                 m_bCancelled = TRUE;\r
1056                 return;\r
1057         }\r
1058         DialogEnableWindow(IDCANCEL, TRUE);\r
1059         __super::OnClose();\r
1060 }\r
1061 \r
1062 void CGitProgressDlg::OnOK()\r
1063 {\r
1064         if ((m_bCancelled)&&(!m_bThreadRunning))\r
1065         {\r
1066                 // I have made this wait a sensible amount of time (10 seconds) for the thread to finish\r
1067                 // You must be careful in the thread that after posting the WM_COMMAND/IDOK message, you \r
1068                 // don't do any more operations on the window which might require message passing\r
1069                 // If you try to send windows messages once we're waiting here, then the thread can't finished\r
1070                 // because the Window's message loop is blocked at this wait\r
1071                 WaitForSingleObject(m_pThread->m_hThread, 10000);\r
1072                 __super::OnOK();\r
1073         }\r
1074         m_bCancelled = TRUE;\r
1075 }\r
1076 \r
1077 void CGitProgressDlg::OnCancel()\r
1078 {\r
1079         if ((m_bCancelled)&&(!m_bThreadRunning))\r
1080                 __super::OnCancel();\r
1081         m_bCancelled = TRUE;\r
1082 }\r
1083 \r
1084 void CGitProgressDlg::OnLvnGetdispinfoSvnprogress(NMHDR *pNMHDR, LRESULT *pResult)\r
1085 {\r
1086         NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);\r
1087 \r
1088         if (pDispInfo)\r
1089         {\r
1090                 if (pDispInfo->item.mask & LVIF_TEXT)\r
1091                 {\r
1092                         if (pDispInfo->item.iItem < (int)m_arData.size())\r
1093                         {\r
1094                                 const NotificationData * data = m_arData[pDispInfo->item.iItem];\r
1095                                 switch (pDispInfo->item.iSubItem)\r
1096                                 {\r
1097                                 case 0:\r
1098                                         lstrcpyn(m_columnbuf, data->sActionColumnText, MAX_PATH);\r
1099                                         break;\r
1100                                 case 1:\r
1101                                         lstrcpyn(m_columnbuf, data->sPathColumnText, pDispInfo->item.cchTextMax);\r
1102                                         if (!data->bAuxItem)\r
1103                                         {\r
1104                                                 int cWidth = m_ProgList.GetColumnWidth(1);\r
1105                                                 cWidth = max(12, cWidth-12);\r
1106                                                 CDC * pDC = m_ProgList.GetDC();\r
1107                         if (pDC != NULL)\r
1108                         {\r
1109                                                     CFont * pFont = pDC->SelectObject(m_ProgList.GetFont());\r
1110                                                     PathCompactPath(pDC->GetSafeHdc(), m_columnbuf, cWidth);\r
1111                                                     pDC->SelectObject(pFont);\r
1112                                                         ReleaseDC(pDC);\r
1113                         }\r
1114                                         }\r
1115                                         break;\r
1116                                 case 2:\r
1117                                         lstrcpyn(m_columnbuf, data->mime_type, MAX_PATH);\r
1118                                         break;\r
1119                                 default:\r
1120                                         m_columnbuf[0] = 0;\r
1121                                 }\r
1122                                 pDispInfo->item.pszText = m_columnbuf;\r
1123                         }\r
1124                 }\r
1125         }\r
1126         *pResult = 0;\r
1127 }\r
1128 \r
1129 void CGitProgressDlg::OnNMCustomdrawSvnprogress(NMHDR *pNMHDR, LRESULT *pResult)\r
1130 {\r
1131         NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );\r
1132 \r
1133         // Take the default processing unless we set this to something else below.\r
1134         *pResult = CDRF_DODEFAULT;\r
1135 \r
1136         // First thing - check the draw stage. If it's the control's prepaint\r
1137         // stage, then tell Windows we want messages for every item.\r
1138 \r
1139         if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )\r
1140         {\r
1141                 *pResult = CDRF_NOTIFYITEMDRAW;\r
1142         }\r
1143         else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )\r
1144         {\r
1145                 // This is the prepaint stage for an item. Here's where we set the\r
1146                 // item's text color. Our return value will tell Windows to draw the\r
1147                 // item itself, but it will use the new color we set here.\r
1148 \r
1149                 // Tell Windows to paint the control itself.\r
1150                 *pResult = CDRF_DODEFAULT;\r
1151 \r
1152                 ASSERT(pLVCD->nmcd.dwItemSpec <  m_arData.size());\r
1153                 if(pLVCD->nmcd.dwItemSpec >= m_arData.size())\r
1154                 {\r
1155                         return;\r
1156                 }\r
1157                 const NotificationData * data = m_arData[pLVCD->nmcd.dwItemSpec];\r
1158                 ASSERT(data != NULL);\r
1159                 if (data == NULL)\r
1160                         return;\r
1161 \r
1162                 // Store the color back in the NMLVCUSTOMDRAW struct.\r
1163                 pLVCD->clrText = data->color;\r
1164         }\r
1165 }\r
1166 \r
1167 void CGitProgressDlg::OnNMDblclkSvnprogress(NMHDR *pNMHDR, LRESULT *pResult)\r
1168 {\r
1169 #if 0\r
1170         LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);\r
1171         *pResult = 0;\r
1172         if (pNMLV->iItem < 0)\r
1173                 return;\r
1174         if (m_options & ProgOptDryRun)\r
1175                 return; //don't do anything in a dry-run.\r
1176 \r
1177         const NotificationData * data = m_arData[pNMLV->iItem];\r
1178         if (data == NULL)\r
1179                 return;\r
1180 \r
1181         if (data->bConflictedActionItem)\r
1182         {\r
1183                 // We've double-clicked on a conflicted item - do a three-way merge on it\r
1184                 SVNDiff::StartConflictEditor(data->path);\r
1185         }\r
1186         else if ((data->action == svn_wc_notify_update_update) && ((data->content_state == svn_wc_notify_state_merged)||(GitProgress_Merge == m_Command)) || (data->action == svn_wc_notify_resolved))\r
1187         {\r
1188                 // This is a modified file which has been merged on update. Diff it against base\r
1189                 CTGitPath temporaryFile;\r
1190                 SVNDiff diff(this, this->m_hWnd, true);\r
1191                 diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));\r
1192                 svn_revnum_t baseRev = 0;\r
1193                 diff.DiffFileAgainstBase(data->path, baseRev);\r
1194         }\r
1195         else if ((!data->bAuxItem)&&(data->path.Exists())&&(!data->path.IsDirectory()))\r
1196         {\r
1197                 bool bOpenWith = false;\r
1198                 int ret = (int)ShellExecute(m_hWnd, NULL, data->path.GetWinPath(), NULL, NULL, SW_SHOWNORMAL);\r
1199                 if (ret <= HINSTANCE_ERROR)\r
1200                         bOpenWith = true;\r
1201                 if (bOpenWith)\r
1202                 {\r
1203                         CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ");\r
1204                         cmd += data->path.GetWinPathString() + _T(" ");\r
1205                         CAppUtils::LaunchApplication(cmd, NULL, false);\r
1206                 }\r
1207         }\r
1208 #endif\r
1209 }\r
1210 \r
1211 void CGitProgressDlg::OnHdnItemclickSvnprogress(NMHDR *pNMHDR, LRESULT *pResult)\r
1212 {\r
1213         LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);\r
1214         if (m_bThreadRunning)\r
1215                 return;\r
1216         if (m_nSortedColumn == phdr->iItem)\r
1217                 m_bAscending = !m_bAscending;\r
1218         else\r
1219                 m_bAscending = TRUE;\r
1220         m_nSortedColumn = phdr->iItem;\r
1221         Sort();\r
1222 \r
1223         CString temp;\r
1224         m_ProgList.SetRedraw(FALSE);\r
1225         m_ProgList.DeleteAllItems();\r
1226         m_ProgList.SetItemCountEx (static_cast<int>(m_arData.size()));\r
1227 \r
1228         m_ProgList.SetRedraw(TRUE);\r
1229 \r
1230         *pResult = 0;\r
1231 }\r
1232 \r
1233 bool CGitProgressDlg::NotificationDataIsAux(const NotificationData* pData)\r
1234 {\r
1235         return pData->bAuxItem;\r
1236 }\r
1237 \r
1238 LRESULT CGitProgressDlg::OnGitProgress(WPARAM /*wParam*/, LPARAM lParam)\r
1239 {\r
1240 #if 0\r
1241         SVNProgress * pProgressData = (SVNProgress *)lParam;\r
1242         CProgressCtrl * progControl = (CProgressCtrl *)GetDlgItem(IDC_PROGRESSBAR);\r
1243         if ((pProgressData->total > 1000)&&(!progControl->IsWindowVisible()))\r
1244         {\r
1245                 progControl->ShowWindow(SW_SHOW);\r
1246         }\r
1247         if (((pProgressData->total < 0)&&(pProgressData->progress > 1000)&&(progControl->IsWindowVisible()))&&(m_itemCountTotal<0))\r
1248         {\r
1249                 progControl->ShowWindow(SW_HIDE);\r
1250         }\r
1251         if (!GetDlgItem(IDC_PROGRESSLABEL)->IsWindowVisible())\r
1252                 GetDlgItem(IDC_PROGRESSLABEL)->ShowWindow(SW_SHOW);\r
1253         SetTimer(TRANSFERTIMER, 2000, NULL);\r
1254         if ((pProgressData->total > 0)&&(pProgressData->progress > 1000))\r
1255         {\r
1256                 progControl->SetPos((int)pProgressData->progress);\r
1257                 progControl->SetRange32(0, (int)pProgressData->total);\r
1258         }\r
1259         CString progText;\r
1260         if (pProgressData->overall_total < 1024)\r
1261                 m_sTotalBytesTransferred.Format(IDS_SVN_PROGRESS_TOTALBYTESTRANSFERRED, pProgressData->overall_total);  \r
1262         else if (pProgressData->overall_total < 1200000)\r
1263                 m_sTotalBytesTransferred.Format(IDS_SVN_PROGRESS_TOTALTRANSFERRED, pProgressData->overall_total / 1024);\r
1264         else\r
1265                 m_sTotalBytesTransferred.Format(IDS_SVN_PROGRESS_TOTALMBTRANSFERRED, (double)((double)pProgressData->overall_total / 1024000.0));\r
1266         progText.Format(IDS_SVN_PROGRESS_TOTALANDSPEED, (LPCTSTR)m_sTotalBytesTransferred, (LPCTSTR)pProgressData->SpeedString);\r
1267         SetDlgItemText(IDC_PROGRESSLABEL, progText);\r
1268 #endif\r
1269         return 0;\r
1270 }\r
1271 \r
1272 void CGitProgressDlg::OnTimer(UINT_PTR nIDEvent)\r
1273 {\r
1274         if (nIDEvent == TRANSFERTIMER)\r
1275         {\r
1276                 CString progText;\r
1277                 CString progSpeed;\r
1278                 progSpeed.Format(IDS_SVN_PROGRESS_BYTES_SEC, 0);\r
1279                 progText.Format(IDS_SVN_PROGRESS_TOTALANDSPEED, (LPCTSTR)m_sTotalBytesTransferred, (LPCTSTR)progSpeed);\r
1280                 SetDlgItemText(IDC_PROGRESSLABEL, progText);\r
1281                 KillTimer(TRANSFERTIMER);\r
1282         }\r
1283         if (nIDEvent == VISIBLETIMER)\r
1284         {\r
1285                 if (nEnsureVisibleCount)\r
1286                         m_ProgList.EnsureVisible(m_ProgList.GetItemCount()-1, false);\r
1287                 nEnsureVisibleCount = 0;\r
1288         }\r
1289 }\r
1290 \r
1291 void CGitProgressDlg::Sort()\r
1292 {\r
1293         if(m_arData.size() < 2)\r
1294         {\r
1295                 return;\r
1296         }\r
1297 \r
1298         // We need to sort the blocks which lie between the auxiliary entries\r
1299         // This is so that any aux data stays where it was\r
1300         NotificationDataVect::iterator actionBlockBegin;\r
1301         NotificationDataVect::iterator actionBlockEnd = m_arData.begin();       // We start searching from here\r
1302 \r
1303         for(;;)\r
1304         {\r
1305                 // Search to the start of the non-aux entry in the next block\r
1306                 actionBlockBegin = std::find_if(actionBlockEnd, m_arData.end(), std::not1(std::ptr_fun(&CGitProgressDlg::NotificationDataIsAux)));\r
1307                 if(actionBlockBegin == m_arData.end())\r
1308                 {\r
1309                         // There are no more actions\r
1310                         break;\r
1311                 }\r
1312                 // Now search to find the end of the block\r
1313                 actionBlockEnd = std::find_if(actionBlockBegin+1, m_arData.end(), std::ptr_fun(&CGitProgressDlg::NotificationDataIsAux));\r
1314                 // Now sort the block\r
1315                 std::sort(actionBlockBegin, actionBlockEnd, &CGitProgressDlg::SortCompare);\r
1316         }\r
1317 }\r
1318 \r
1319 bool CGitProgressDlg::SortCompare(const NotificationData * pData1, const NotificationData * pData2)\r
1320 {\r
1321         int result = 0;\r
1322         switch (m_nSortedColumn)\r
1323         {\r
1324         case 0:         //action column\r
1325                 result = pData1->sActionColumnText.Compare(pData2->sActionColumnText);\r
1326                 break;\r
1327         case 1:         //path column\r
1328                 // Compare happens after switch()\r
1329                 break;\r
1330         case 2:         //mime-type column\r
1331                 result = pData1->mime_type.Compare(pData2->mime_type);\r
1332                 break;\r
1333         default:\r
1334                 break;\r
1335         }\r
1336 \r
1337         // Sort by path if everything else is equal\r
1338         if (result == 0)\r
1339         {\r
1340                 result = CTGitPath::Compare(pData1->path, pData2->path);\r
1341         }\r
1342 \r
1343         if (!m_bAscending)\r
1344                 result = -result;\r
1345         return result < 0;\r
1346 }\r
1347 \r
1348 BOOL CGitProgressDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)\r
1349 {\r
1350         if (!GetDlgItem(IDOK)->IsWindowEnabled())\r
1351         {\r
1352                 // only show the wait cursor over the list control\r
1353                 if ((pWnd)&&(pWnd == GetDlgItem(IDC_SVNPROGRESS)))\r
1354                 {\r
1355                         HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));\r
1356                         SetCursor(hCur);\r
1357                         return TRUE;\r
1358                 }\r
1359         }\r
1360         HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));\r
1361         SetCursor(hCur);\r
1362         return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);\r
1363 }\r
1364 \r
1365 BOOL CGitProgressDlg::PreTranslateMessage(MSG* pMsg)\r
1366 {\r
1367         if (pMsg->message == WM_KEYDOWN)\r
1368         {\r
1369                 if (pMsg->wParam == VK_ESCAPE)\r
1370                 {\r
1371                         // pressing the ESC key should close the dialog. But since we disabled the escape\r
1372                         // key (so the user doesn't get the idea that he could simply undo an e.g. update)\r
1373                         // this won't work.\r
1374                         // So if the user presses the ESC key, change it to VK_RETURN so the dialog gets\r
1375                         // the impression that the OK button was pressed.\r
1376                         if ((!m_bThreadRunning)&&(!GetDlgItem(IDCANCEL)->IsWindowEnabled())\r
1377                                 &&(GetDlgItem(IDOK)->IsWindowEnabled())&&(GetDlgItem(IDOK)->IsWindowVisible()))\r
1378                         {\r
1379                                 // since we convert ESC to RETURN, make sure the OK button has the focus.\r
1380                                 GetDlgItem(IDOK)->SetFocus();\r
1381                                 pMsg->wParam = VK_RETURN;\r
1382                         }\r
1383                 }\r
1384                 if (pMsg->wParam == 'A')\r
1385                 {\r
1386                         if (GetKeyState(VK_CONTROL)&0x8000)\r
1387                         {\r
1388                                 // Ctrl-A -> select all\r
1389                                 m_ProgList.SetSelectionMark(0);\r
1390                                 for (int i=0; i<m_ProgList.GetItemCount(); ++i)\r
1391                                 {\r
1392                                         m_ProgList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);\r
1393                                 }\r
1394                         }\r
1395                 }\r
1396                 if ((pMsg->wParam == 'C')||(pMsg->wParam == VK_INSERT))\r
1397                 {\r
1398                         int selIndex = m_ProgList.GetSelectionMark();\r
1399                         if (selIndex >= 0)\r
1400                         {\r
1401                                 if (GetKeyState(VK_CONTROL)&0x8000)\r
1402                                 {\r
1403                                         //Ctrl-C -> copy to clipboard\r
1404                                         CString sClipdata;\r
1405                                         POSITION pos = m_ProgList.GetFirstSelectedItemPosition();\r
1406                                         if (pos != NULL)\r
1407                                         {\r
1408                                                 while (pos)\r
1409                                                 {\r
1410                                                         int nItem = m_ProgList.GetNextSelectedItem(pos);\r
1411                                                         CString sAction = m_ProgList.GetItemText(nItem, 0);\r
1412                                                         CString sPath = m_ProgList.GetItemText(nItem, 1);\r
1413                                                         CString sMime = m_ProgList.GetItemText(nItem, 2);\r
1414                                                         CString sLogCopyText;\r
1415                                                         sLogCopyText.Format(_T("%s: %s  %s\r\n"),\r
1416                                                                 (LPCTSTR)sAction, (LPCTSTR)sPath, (LPCTSTR)sMime);\r
1417                                                         sClipdata +=  sLogCopyText;\r
1418                                                 }\r
1419                                                 CStringUtils::WriteAsciiStringToClipboard(sClipdata);\r
1420                                         }\r
1421                                 }\r
1422                         }\r
1423                 } \r
1424         } // if (pMsg->message == WM_KEYDOWN)\r
1425         return __super::PreTranslateMessage(pMsg);\r
1426 }\r
1427 \r
1428 void CGitProgressDlg::OnContextMenu(CWnd* pWnd, CPoint point)\r
1429 {\r
1430 #if 0\r
1431         if (m_options & ProgOptDryRun)\r
1432                 return; // don't do anything in a dry-run.\r
1433 \r
1434         if (pWnd == &m_ProgList)\r
1435         {\r
1436                 int selIndex = m_ProgList.GetSelectionMark();\r
1437                 if ((point.x == -1) && (point.y == -1))\r
1438                 {\r
1439                         // Menu was invoked from the keyboard rather than by right-clicking\r
1440                         CRect rect;\r
1441                         m_ProgList.GetItemRect(selIndex, &rect, LVIR_LABEL);\r
1442                         m_ProgList.ClientToScreen(&rect);\r
1443                         point = rect.CenterPoint();\r
1444                 }\r
1445 \r
1446                 if ((selIndex >= 0)&&(!m_bThreadRunning))\r
1447                 {\r
1448                         // entry is selected, thread has finished with updating so show the popup menu\r
1449                         CIconMenu popup;\r
1450                         if (popup.CreatePopupMenu())\r
1451                         {\r
1452                                 bool bAdded = false;\r
1453                                 NotificationData * data = m_arData[selIndex];\r
1454                                 if ((data)&&(!data->path.IsDirectory()))\r
1455                                 {\r
1456                                         if (data->action == svn_wc_notify_update_update || data->action == svn_wc_notify_resolved)\r
1457                                         {\r
1458                                                 if (m_ProgList.GetSelectedCount() == 1)\r
1459                                                 {\r
1460                                                         popup.AppendMenuIcon(ID_COMPARE, IDS_LOG_POPUP_COMPARE, IDI_DIFF);\r
1461                                                         bAdded = true;\r
1462                                                 }\r
1463                                         }\r
1464                                                 if (data->bConflictedActionItem)\r
1465                                                 {\r
1466                                                         if (m_ProgList.GetSelectedCount() == 1)\r
1467                                                         {\r
1468                                                                 popup.AppendMenuIcon(ID_EDITCONFLICT, IDS_MENUCONFLICT,IDI_CONFLICT);\r
1469                                                                 popup.SetDefaultItem(ID_EDITCONFLICT, FALSE);\r
1470                                                                 popup.AppendMenuIcon(ID_CONFLICTRESOLVE, IDS_SVNPROGRESS_MENUMARKASRESOLVED,IDI_RESOLVE);\r
1471                                                         }\r
1472                                                         popup.AppendMenuIcon(ID_CONFLICTUSETHEIRS, IDS_SVNPROGRESS_MENUUSETHEIRS,IDI_RESOLVE);\r
1473                                                         popup.AppendMenuIcon(ID_CONFLICTUSEMINE, IDS_SVNPROGRESS_MENUUSEMINE,IDI_RESOLVE);\r
1474                                                 }\r
1475                                                 else if ((data->content_state == svn_wc_notify_state_merged)||(GitProgress_Merge == m_Command)||(data->action == svn_wc_notify_resolved))\r
1476                                                         popup.SetDefaultItem(ID_COMPARE, FALSE);\r
1477                                         \r
1478                                         if (m_ProgList.GetSelectedCount() == 1)\r
1479                                         {\r
1480                                                 if ((data->action == svn_wc_notify_add)||\r
1481                                                         (data->action == svn_wc_notify_update_add)||\r
1482                                                         (data->action == svn_wc_notify_commit_added)||\r
1483                                                         (data->action == svn_wc_notify_commit_modified)||\r
1484                                                         (data->action == svn_wc_notify_restore)||\r
1485                                                         (data->action == svn_wc_notify_revert)||\r
1486                                                         (data->action == svn_wc_notify_resolved)||\r
1487                                                         (data->action == svn_wc_notify_commit_replaced)||\r
1488                                                         (data->action == svn_wc_notify_commit_modified)||\r
1489                                                         (data->action == svn_wc_notify_commit_postfix_txdelta)||\r
1490                                                         (data->action == svn_wc_notify_update_update))\r
1491                                                 {\r
1492                                                         popup.AppendMenuIcon(ID_LOG, IDS_MENULOG,IDI_LOG);\r
1493                                                         if (data->action == svn_wc_notify_update_update)\r
1494                                                                 popup.AppendMenu(MF_SEPARATOR, NULL);\r
1495                                                         popup.AppendMenuIcon(ID_OPEN, IDS_LOG_POPUP_OPEN, IDI_OPEN);\r
1496                                                         popup.AppendMenuIcon(ID_OPENWITH, IDS_LOG_POPUP_OPENWITH, IDI_OPEN);\r
1497                                                         bAdded = true;\r
1498                                                 }\r
1499                                         }\r
1500                                 } // if ((data)&&(!data->path.IsDirectory()))\r
1501                                 if (m_ProgList.GetSelectedCount() == 1)\r
1502                                 {\r
1503                                         if (data)\r
1504                                         {\r
1505                                                 CString sPath = GetPathFromColumnText(data->sPathColumnText);\r
1506                                                 if ((!sPath.IsEmpty())&&(!SVN::PathIsURL(CTGitPath(sPath))))\r
1507                                                 {\r
1508                                                         CTGitPath path = CTGitPath(sPath);\r
1509                                                         if (path.GetDirectory().Exists())\r
1510                                                         {\r
1511                                                                 popup.AppendMenuIcon(ID_EXPLORE, IDS_SVNPROGRESS_MENUOPENPARENT, IDI_EXPLORER);\r
1512                                                                 bAdded = true;\r
1513                                                         }\r
1514                                                 }\r
1515                                         }\r
1516                                 }\r
1517                                 if (m_ProgList.GetSelectedCount() > 0)\r
1518                                 {\r
1519                                         if (bAdded)\r
1520                                                 popup.AppendMenu(MF_SEPARATOR, NULL);\r
1521                                         popup.AppendMenuIcon(ID_COPY, IDS_LOG_POPUP_COPYTOCLIPBOARD,IDI_COPYCLIP);\r
1522                                         bAdded = true;\r
1523                                 }\r
1524                                 if (bAdded)\r
1525                                 {\r
1526                                         int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);\r
1527                                         DialogEnableWindow(IDOK, FALSE);\r
1528                                         this->SetPromptApp(&theApp);\r
1529                                         theApp.DoWaitCursor(1);\r
1530                                         bool bOpenWith = false;\r
1531                                         switch (cmd)\r
1532                                         {\r
1533                                         case ID_COPY:\r
1534                                                 {\r
1535                                                         CString sLines;\r
1536                                                         POSITION pos = m_ProgList.GetFirstSelectedItemPosition();\r
1537                                                         while (pos)\r
1538                                                         {\r
1539                                                                 int nItem = m_ProgList.GetNextSelectedItem(pos);\r
1540                                                                 NotificationData * data = m_arData[nItem];\r
1541                                                                 if (data)\r
1542                                                                 {\r
1543                                                                         sLines += data->sPathColumnText;\r
1544                                                                         sLines += _T("\r\n");\r
1545                                                                 }\r
1546                                                         }\r
1547                                                         sLines.TrimRight();\r
1548                                                         if (!sLines.IsEmpty())\r
1549                                                         {\r
1550                                                                 CStringUtils::WriteAsciiStringToClipboard(sLines, GetSafeHwnd());\r
1551                                                         }\r
1552                                                 }\r
1553                                                 break;\r
1554                                         case ID_EXPLORE:\r
1555                                                 {\r
1556                                                         CString sPath = GetPathFromColumnText(data->sPathColumnText);\r
1557 \r
1558                                                         CTGitPath path = CTGitPath(sPath);\r
1559                                                         ShellExecute(m_hWnd, _T("explore"), path.GetDirectory().GetWinPath(), NULL, path.GetDirectory().GetWinPath(), SW_SHOW);\r
1560                                                 }\r
1561                                                 break;\r
1562                                         case ID_COMPARE:\r
1563                                                 {\r
1564                                                         svn_revnum_t rev = -1;\r
1565                                                         StringRevMap::iterator it = m_UpdateStartRevMap.end();\r
1566                                                         if (data->basepath.IsEmpty())\r
1567                                                                 it = m_UpdateStartRevMap.begin();\r
1568                                                         else\r
1569                                                                 it = m_UpdateStartRevMap.find(data->basepath.GetSVNApiPath(pool));\r
1570                                                         if (it != m_UpdateStartRevMap.end())\r
1571                                                                 rev = it->second;\r
1572                                                         // if the file was merged during update, do a three way diff between OLD, MINE, THEIRS\r
1573                                                         if (data->content_state == svn_wc_notify_state_merged)\r
1574                                                         {\r
1575                                                                 CTGitPath basefile = CTempFiles::Instance().GetTempFilePath(false, data->path, rev);\r
1576                                                                 CTGitPath newfile = CTempFiles::Instance().GetTempFilePath(false, data->path, SVNRev::REV_HEAD);\r
1577                                                                 SVN svn;\r
1578                                                                 if (!svn.Cat(data->path, SVNRev(SVNRev::REV_WC), rev, basefile))\r
1579                                                                 {\r
1580                                                                         CMessageBox::Show(m_hWnd, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
1581                                                                         DialogEnableWindow(IDOK, TRUE);\r
1582                                                                         break;\r
1583                                                                 }\r
1584                                                                 // If necessary, convert the line-endings on the file before diffing\r
1585                                                                 if ((DWORD)CRegDWORD(_T("Software\\TortoiseGit\\ConvertBase"), TRUE))\r
1586                                                                 {\r
1587                                                                         CTGitPath temporaryFile = CTempFiles::Instance().GetTempFilePath(false, data->path, SVNRev::REV_BASE);\r
1588                                                                         if (!svn.Cat(data->path, SVNRev(SVNRev::REV_BASE), SVNRev(SVNRev::REV_BASE), temporaryFile))\r
1589                                                                         {\r
1590                                                                                 temporaryFile.Reset();\r
1591                                                                                 break;\r
1592                                                                         }\r
1593                                                                         else\r
1594                                                                         {\r
1595                                                                                 newfile = temporaryFile;\r
1596                                                                         }\r
1597                                                                 }\r
1598 \r
1599                                                                 SetFileAttributes(newfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);\r
1600                                                                 SetFileAttributes(basefile.GetWinPath(), FILE_ATTRIBUTE_READONLY);\r
1601                                                                 CString revname, wcname, basename;\r
1602                                                                 revname.Format(_T("%s Revision %ld"), (LPCTSTR)data->path.GetUIFileOrDirectoryName(), rev);\r
1603                                                                 wcname.Format(IDS_DIFF_WCNAME, (LPCTSTR)data->path.GetUIFileOrDirectoryName());\r
1604                                                                 basename.Format(IDS_DIFF_BASENAME, (LPCTSTR)data->path.GetUIFileOrDirectoryName());\r
1605                                                                 CAppUtils::StartExtMerge(basefile, newfile, data->path, data->path, basename, revname, wcname, CString(), true);\r
1606                                                         }\r
1607                                                         else\r
1608                                                         {\r
1609                                                                 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, data->path, rev);\r
1610                                                                 SVN svn;\r
1611                                                                 if (!svn.Cat(data->path, SVNRev(SVNRev::REV_WC), rev, tempfile))\r
1612                                                                 {\r
1613                                                                         CMessageBox::Show(m_hWnd, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
1614                                                                         DialogEnableWindow(IDOK, TRUE);\r
1615                                                                         break;\r
1616                                                                 }\r
1617                                                                 else\r
1618                                                                 {\r
1619                                                                         SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);\r
1620                                                                         CString revname, wcname;\r
1621                                                                         revname.Format(_T("%s Revision %ld"), (LPCTSTR)data->path.GetUIFileOrDirectoryName(), rev);\r
1622                                                                         wcname.Format(IDS_DIFF_WCNAME, (LPCTSTR)data->path.GetUIFileOrDirectoryName());\r
1623                                                                         CAppUtils::StartExtDiff(\r
1624                                                                                 tempfile, data->path, revname, wcname,\r
1625                                                                                 CAppUtils::DiffFlags().AlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000)));\r
1626                                                                 }\r
1627                                                         }\r
1628                                                 }\r
1629                                                 break;\r
1630                                         case ID_EDITCONFLICT:\r
1631                                                 {\r
1632                                                         CString sPath = GetPathFromColumnText(data->sPathColumnText);\r
1633                                                         SVNDiff::StartConflictEditor(CTGitPath(sPath));\r
1634                                                 }\r
1635                                                 break;\r
1636                                         case ID_CONFLICTUSETHEIRS:\r
1637                                         case ID_CONFLICTUSEMINE:\r
1638                                         case ID_CONFLICTRESOLVE:\r
1639                                                 {\r
1640                                                         svn_wc_conflict_choice_t result = svn_wc_conflict_choose_merged;\r
1641                                                         switch (cmd)\r
1642                                                         {\r
1643                                                         case ID_CONFLICTUSETHEIRS:\r
1644                                                                 result = svn_wc_conflict_choose_theirs_full;\r
1645                                                                 break;\r
1646                                                         case ID_CONFLICTUSEMINE:\r
1647                                                                 result = svn_wc_conflict_choose_mine_full;\r
1648                                                                 break;\r
1649                                                         case ID_CONFLICTRESOLVE:\r
1650                                                                 result = svn_wc_conflict_choose_merged;\r
1651                                                                 break;\r
1652                                                         }\r
1653                                                         SVN svn;\r
1654                                                         POSITION pos = m_ProgList.GetFirstSelectedItemPosition();\r
1655                                                         CString sResolvedPaths;\r
1656                                                         while (pos)\r
1657                                                         {\r
1658                                                                 int nItem = m_ProgList.GetNextSelectedItem(pos);\r
1659                                                                 NotificationData * data = m_arData[nItem];\r
1660                                                                 if (data)\r
1661                                                                 {\r
1662                                                                         if (data->bConflictedActionItem)\r
1663                                                                         {\r
1664                                                                                 if (!svn.Resolve(data->path, result, FALSE))\r
1665                                                                                 {\r
1666                                                                                         CMessageBox::Show(m_hWnd, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);\r
1667                                                                                         DialogEnableWindow(IDOK, TRUE);\r
1668                                                                                         break;\r
1669                                                                                 }\r
1670                                                                                 else\r
1671                                                                                 {\r
1672                                                                                         data->color = ::GetSysColor(COLOR_WINDOWTEXT);\r
1673                                                                                         data->action = svn_wc_notify_resolved;\r
1674                                                                                         data->sActionColumnText.LoadString(IDS_SVNACTION_RESOLVE);\r
1675                                                                                         data->bConflictedActionItem = false;\r
1676                                                                                         m_nConflicts--;\r
1677 \r
1678                                                                                         if (m_nConflicts==0)\r
1679                                                                                         {\r
1680                                                                                                 // When the last conflict is resolved we remove\r
1681                                                                                                 // the warning which we assume is in the last line.\r
1682                                                                                                 int nIndex = m_ProgList.GetItemCount()-1;\r
1683                                                                                                 VERIFY(m_ProgList.DeleteItem(nIndex));\r
1684 \r
1685                                                                                                 delete m_arData[nIndex];\r
1686                                                                                                 m_arData.pop_back();\r
1687                                                                                         }\r
1688                                                                                         sResolvedPaths += data->path.GetWinPathString() + _T("\n");\r
1689                                                                                 }\r
1690                                                                         }\r
1691                                                                 }\r
1692                                                         }\r
1693                                                         m_ProgList.Invalidate();\r
1694                                                         CString info = BuildInfoString();\r
1695                                                         SetDlgItemText(IDC_INFOTEXT, info);\r
1696 \r
1697                                                         if (!sResolvedPaths.IsEmpty())\r
1698                                                         {\r
1699                                                                 CString msg;\r
1700                                                                 msg.Format(IDS_SVNPROGRESS_RESOLVED, (LPCTSTR)sResolvedPaths);\r
1701                                                                 CMessageBox::Show(m_hWnd, msg, _T("TortoiseSVN"), MB_OK | MB_ICONINFORMATION);\r
1702                                                         }\r
1703                                                 }\r
1704                                                 break;\r
1705                                         case ID_LOG:\r
1706                                                 {\r
1707                                                         CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseGit\\NumberOfLogs"), 100);\r
1708                                                         int limit = (int)(DWORD)reg;\r
1709                                                         svn_revnum_t rev = m_RevisionEnd;\r
1710                                                         if (!data->basepath.IsEmpty())\r
1711                                                         {\r
1712                                                                 StringRevMap::iterator it = m_FinishedRevMap.find(data->basepath.GetSVNApiPath(pool));\r
1713                                                                 if (it != m_FinishedRevMap.end())\r
1714                                                                         rev = it->second;\r
1715                                                         }\r
1716                                                         CLogDlg dlg;\r
1717                                                         // fetch the log from HEAD, not the revision we updated to:\r
1718                                                         // the path might be inside an external folder which has its own\r
1719                                                         // revisions.\r
1720                                                         CString sPath = GetPathFromColumnText(data->sPathColumnText);\r
1721                                                         dlg.SetParams(CTGitPath(sPath), SVNRev(), SVNRev::REV_HEAD, 1, limit, TRUE);\r
1722                                                         dlg.DoModal();\r
1723                                                 }\r
1724                                                 break;\r
1725                                         case ID_OPENWITH:\r
1726                                                 bOpenWith = true;\r
1727                                         case ID_OPEN:\r
1728                                                 {\r
1729                                                         int ret = 0;\r
1730                                                         CString sWinPath = GetPathFromColumnText(data->sPathColumnText);\r
1731                                                         if (!bOpenWith)\r
1732                                                                 ret = (int)ShellExecute(this->m_hWnd, NULL, (LPCTSTR)sWinPath, NULL, NULL, SW_SHOWNORMAL);\r
1733                                                         if ((ret <= HINSTANCE_ERROR)||bOpenWith)\r
1734                                                         {\r
1735                                                                 CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ");\r
1736                                                                 cmd += sWinPath + _T(" ");\r
1737                                                                 CAppUtils::LaunchApplication(cmd, NULL, false);\r
1738                                                         }\r
1739                                                 }\r
1740                                         }\r
1741                                         DialogEnableWindow(IDOK, TRUE);\r
1742                                         theApp.DoWaitCursor(-1);\r
1743                                 } // if (bAdded)\r
1744                         }\r
1745                 }\r
1746         }\r
1747 #endif\r
1748 }\r
1749 \r
1750 void CGitProgressDlg::OnEnSetfocusInfotext()\r
1751 {\r
1752         CString sTemp;\r
1753         GetDlgItemText(IDC_INFOTEXT, sTemp);\r
1754         if (sTemp.IsEmpty())\r
1755                 GetDlgItem(IDC_INFOTEXT)->HideCaret();\r
1756 }\r
1757 \r
1758 void CGitProgressDlg::OnLvnBegindragSvnprogress(NMHDR* , LRESULT *pResult)\r
1759 {\r
1760         //LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);\r
1761 #if 0\r
1762         int selIndex = m_ProgList.GetSelectionMark();\r
1763         if (selIndex < 0)\r
1764                 return;\r
1765 \r
1766         CDropFiles dropFiles; // class for creating DROPFILES struct\r
1767 \r
1768         int index;\r
1769         POSITION pos = m_ProgList.GetFirstSelectedItemPosition();\r
1770         while ( (index = m_ProgList.GetNextSelectedItem(pos)) >= 0 )\r
1771         {\r
1772                 NotificationData * data = m_arData[index];\r
1773 \r
1774                 if ( data->kind==svn_node_file || data->kind==svn_node_dir )\r
1775                 {\r
1776                         CString sPath = GetPathFromColumnText(data->sPathColumnText);\r
1777 \r
1778                         dropFiles.AddFile( sPath );\r
1779                 }\r
1780         }\r
1781 \r
1782         if ( dropFiles.GetCount()>0 )\r
1783         {\r
1784                 dropFiles.CreateStructure();\r
1785         }\r
1786 #endif\r
1787         *pResult = 0;\r
1788 }\r
1789 \r
1790 void CGitProgressDlg::OnSize(UINT nType, int cx, int cy)\r
1791 {\r
1792         CResizableStandAloneDialog::OnSize(nType, cx, cy);\r
1793         if ((nType == SIZE_RESTORED)&&(m_bLastVisible))\r
1794         {\r
1795                 if(!m_ProgList.m_hWnd)\r
1796                         return;\r
1797 \r
1798                 int count = m_ProgList.GetItemCount();\r
1799                 if (count > 0)\r
1800                         m_ProgList.EnsureVisible(count-1, false);\r
1801         }\r
1802 }\r
1803 \r
1804 //////////////////////////////////////////////////////////////////////////\r
1805 /// commands\r
1806 //////////////////////////////////////////////////////////////////////////\r
1807 bool CGitProgressDlg::CmdAdd(CString& sWindowTitle, bool& localoperation)\r
1808 {\r
1809 \r
1810         localoperation = true;\r
1811         sWindowTitle.LoadString(IDS_PROGRS_TITLE_ADD);\r
1812         SetWindowText(sWindowTitle);\r
1813         SetBackgroundImage(IDI_ADD_BKG);\r
1814         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_ADD)));\r
1815 \r
1816         for(int i=0;i<m_targetPathList.GetCount();i++)\r
1817         {\r
1818                 CString cmd,out;\r
1819                 cmd.Format(_T("git.exe add -f \"%s\""),m_targetPathList[i].GetGitPathString());\r
1820                 if(g_Git.Run(cmd,&out,CP_ACP))\r
1821                 {\r
1822                         CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
1823                         m_bErrorsOccurred=true;\r
1824                         return false;\r
1825                 }\r
1826                 Notify(m_targetPathList[i],git_wc_notify_add);\r
1827         }\r
1828 #if 0\r
1829         if (!Add(m_targetPathList, &m_ProjectProperties, svn_depth_empty, FALSE, TRUE, TRUE))\r
1830         {\r
1831                 ReportSVNError();\r
1832                 return false;\r
1833         }\r
1834 #endif\r
1835         //CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);\r
1836         m_bErrorsOccurred=false;\r
1837         return true;\r
1838 }\r
1839 \r
1840 bool CGitProgressDlg::CmdCheckout(CString& sWindowTitle, bool& /*localoperation*/)\r
1841 {\r
1842 #if 0\r
1843         ASSERT(m_targetPathList.GetCount() == 1);\r
1844         sWindowTitle.LoadString(IDS_PROGRS_TITLE_CHECKOUT);\r
1845         SetBackgroundImage(IDI_CHECKOUT_BKG);\r
1846         CTGitPathList urls;\r
1847         urls.LoadFromAsteriskSeparatedString(m_url.GetSVNPathString());\r
1848         CTGitPath checkoutdir = m_targetPathList[0];\r
1849         for (int i=0; i<urls.GetCount(); ++i)\r
1850         {\r
1851                 sWindowTitle = urls[i].GetUIFileOrDirectoryName()+_T(" - ")+sWindowTitle;\r
1852                 SetWindowText(sWindowTitle);\r
1853                 checkoutdir = m_targetPathList[0];\r
1854                 if (urls.GetCount() > 1)\r
1855                 {\r
1856                         CString fileordir = urls[i].GetFileOrDirectoryName();\r
1857                         fileordir = CPathUtils::PathUnescape(fileordir);\r
1858                         checkoutdir.AppendPathString(fileordir);\r
1859                 }\r
1860                 CString sCmdInfo;\r
1861                 sCmdInfo.Format(IDS_PROGRS_CMD_CHECKOUT, \r
1862                         (LPCTSTR)urls[i].GetSVNPathString(), (LPCTSTR)m_Revision.ToString(), \r
1863                         (LPCTSTR)SVNStatus::GetDepthString(m_depth), \r
1864                         m_options & ProgOptIgnoreExternals ? (LPCTSTR)sExtExcluded : (LPCTSTR)sExtIncluded);\r
1865                 ReportCmd(sCmdInfo);\r
1866 \r
1867                 if (!Checkout(urls[i], checkoutdir, m_Revision, m_Revision, m_depth, m_options & ProgOptIgnoreExternals))\r
1868                 {\r
1869                         if (m_ProgList.GetItemCount()!=0)\r
1870                         {\r
1871                                 ReportSVNError();\r
1872                                 return false;\r
1873                         }\r
1874                         // if the checkout fails with the peg revision set to the checkout revision,\r
1875                         // try again with HEAD as the peg revision.\r
1876                         else\r
1877                         {\r
1878                                 if (!Checkout(urls[i], checkoutdir, SVNRev::REV_HEAD, m_Revision, m_depth, m_options & ProgOptIgnoreExternals))\r
1879                                 {\r
1880                                         ReportSVNError();\r
1881                                         return false;\r
1882                                 }\r
1883                         }\r
1884                 }\r
1885         }\r
1886 #endif\r
1887         return true;\r
1888 }\r
1889 \r
1890 bool CGitProgressDlg::CmdCommit(CString& sWindowTitle, bool& /*localoperation*/)\r
1891 {\r
1892 #if 0\r
1893         sWindowTitle.LoadString(IDS_PROGRS_TITLE_COMMIT);\r
1894         SetWindowText(sWindowTitle);\r
1895         SetBackgroundImage(IDI_COMMIT_BKG);\r
1896         if (m_targetPathList.GetCount()==0)\r
1897         {\r
1898                 SetWindowText(sWindowTitle);\r
1899 \r
1900                 DialogEnableWindow(IDCANCEL, FALSE);\r
1901                 DialogEnableWindow(IDOK, TRUE);\r
1902 \r
1903                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
1904                 return true;\r
1905         }\r
1906         if (m_targetPathList.GetCount()==1)\r
1907         {\r
1908                 sWindowTitle = m_targetPathList[0].GetUIFileOrDirectoryName()+_T(" - ")+sWindowTitle;\r
1909                 SetWindowText(sWindowTitle);\r
1910         }\r
1911         BOOL isTag = FALSE;\r
1912         BOOL bURLFetched = FALSE;\r
1913         CString url;\r
1914         for (int i=0; i<m_targetPathList.GetCount(); ++i)\r
1915         {\r
1916                 if (bURLFetched == FALSE)\r
1917                 {\r
1918                         url = GetURLFromPath(m_targetPathList[i]);\r
1919                         if (!url.IsEmpty())\r
1920                                 bURLFetched = TRUE;\r
1921                         CString urllower = url;\r
1922                         urllower.MakeLower();\r
1923                         // test if the commit goes to a tag.\r
1924                         // now since Subversion doesn't force users to\r
1925                         // create tags in the recommended /tags/ folder\r
1926                         // only a warning is shown. This won't work if the tags\r
1927                         // are stored in a non-recommended place, but the check\r
1928                         // still helps those who do.\r
1929                         if (urllower.Find(_T("/tags/"))>=0)\r
1930                                 isTag = TRUE;\r
1931                         break;\r
1932                 }\r
1933         }\r
1934         if (isTag)\r
1935         {\r
1936                 if (CMessageBox::Show(m_hWnd, IDS_PROGRS_COMMITT_TRUNK, IDS_APPNAME, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION)==IDNO)\r
1937                         return false;\r
1938         }\r
1939         DWORD exitcode = 0;\r
1940         CString error;\r
1941         if (CHooks::Instance().PreCommit(m_selectedPaths, m_depth, m_sMessage, exitcode, error))\r
1942         {\r
1943                 if (exitcode)\r
1944                 {\r
1945                         CString temp;\r
1946                         temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);\r
1947                         ReportError(temp);\r
1948                         return false;\r
1949                 }\r
1950         }\r
1951 \r
1952         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_COMMIT)));\r
1953         CStringArray changelists;\r
1954     if (!m_changelist.IsEmpty())\r
1955             changelists.Add(m_changelist);\r
1956         bool commitSuccessful = true;\r
1957         if (!Commit(m_targetPathList, m_sMessage, changelists, m_keepchangelist, \r
1958                 m_depth, m_options & ProgOptKeeplocks))\r
1959         {\r
1960                 ReportSVNError();\r
1961                 error = GetLastErrorMessage();\r
1962                 // if a non-recursive commit failed with SVN_ERR_UNSUPPORTED_FEATURE,\r
1963                 // that means a folder deletion couldn't be committed.\r
1964                 if ((m_Revision != 0)&&(Err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))\r
1965                 {\r
1966                         ReportError(CString(MAKEINTRESOURCE(IDS_PROGRS_NONRECURSIVEHINT)));\r
1967                 }\r
1968                 commitSuccessful = false;\r
1969                 return false;\r
1970         }\r
1971         if (!PostCommitErr.IsEmpty())\r
1972         {\r
1973                 ReportWarning(PostCommitErr);\r
1974         }\r
1975         if (commitSuccessful)\r
1976         {\r
1977                 if (m_BugTraqProvider)\r
1978                 {\r
1979                         CComPtr<IBugTraqProvider2> pProvider = NULL;\r
1980                         HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider);\r
1981                         if (SUCCEEDED(hr))\r
1982                         {\r
1983                                 BSTR commonRoot = SysAllocString(m_targetPathList.GetCommonRoot().GetDirectory().GetWinPath());\r
1984                                 SAFEARRAY *pathList = SafeArrayCreateVector(VT_BSTR, 0, m_targetPathList.GetCount());\r
1985 \r
1986                                 for (LONG index = 0; index < m_targetPathList.GetCount(); ++index)\r
1987                                         SafeArrayPutElement(pathList, &index, m_targetPathList[index].GetSVNPathString().AllocSysString());\r
1988 \r
1989                                 BSTR logMessage = m_sMessage.AllocSysString();\r
1990 \r
1991                                 BSTR temp = NULL;\r
1992                                 if (FAILED(hr = pProvider->OnCommitFinished(GetSafeHwnd(), \r
1993                                         commonRoot,\r
1994                                         pathList,\r
1995                                         logMessage,\r
1996                                         (LONG)m_RevisionEnd,\r
1997                                         &temp)))\r
1998                                 {\r
1999                                         CString sErr = temp;\r
2000                                         if (!sErr.IsEmpty())\r
2001                                                 ReportError(temp);\r
2002                                 }\r
2003 \r
2004                                 SysFreeString(temp);\r
2005                         }\r
2006                 }\r
2007         }\r
2008         if (CHooks::Instance().PostCommit(m_selectedPaths, m_depth, m_RevisionEnd, m_sMessage, exitcode, error))\r
2009         {\r
2010                 if (exitcode)\r
2011                 {\r
2012                         CString temp;\r
2013                         temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);\r
2014                         ReportError(temp);\r
2015                         return false;\r
2016                 }\r
2017         }\r
2018 #endif\r
2019         return true;\r
2020 }\r
2021 \r
2022 bool CGitProgressDlg::CmdCopy(CString& sWindowTitle, bool& /*localoperation*/)\r
2023 {\r
2024 #if 0\r
2025         ASSERT(m_targetPathList.GetCount() == 1);\r
2026         sWindowTitle.LoadString(IDS_PROGRS_TITLE_COPY);\r
2027         SetWindowText(sWindowTitle);\r
2028         SetBackgroundImage(IDI_COPY_BKG);\r
2029 \r
2030         CString sCmdInfo;\r
2031         sCmdInfo.Format(IDS_PROGRS_CMD_COPY, \r
2032                 m_targetPathList[0].IsUrl() ? (LPCTSTR)m_targetPathList[0].GetSVNPathString() : m_targetPathList[0].GetWinPath(),\r
2033                 (LPCTSTR)m_url.GetSVNPathString(), (LPCTSTR)m_Revision.ToString());\r
2034         ReportCmd(sCmdInfo);\r
2035 \r
2036         if (!Copy(m_targetPathList, m_url, m_Revision, m_pegRev, m_sMessage))\r
2037         {\r
2038                 ReportSVNError();\r
2039                 return false;\r
2040         }\r
2041         if (m_options & ProgOptSwitchAfterCopy)\r
2042         {\r
2043                 sCmdInfo.Format(IDS_PROGRS_CMD_SWITCH, \r
2044                         m_targetPathList[0].GetWinPath(),\r
2045                         (LPCTSTR)m_url.GetSVNPathString(), (LPCTSTR)m_Revision.ToString());\r
2046                 ReportCmd(sCmdInfo);\r
2047                 if (!Switch(m_targetPathList[0], m_url, SVNRev::REV_HEAD, SVNRev::REV_HEAD, m_depth, TRUE, m_options & ProgOptIgnoreExternals))\r
2048                 {\r
2049                         if (!Switch(m_targetPathList[0], m_url, SVNRev::REV_HEAD, m_Revision, m_depth, TRUE, m_options & ProgOptIgnoreExternals))\r
2050                         {\r
2051                                 ReportSVNError();\r
2052                                 return false;\r
2053                         }\r
2054                 }\r
2055         }\r
2056         else\r
2057         {\r
2058                 if (SVN::PathIsURL(m_url))\r
2059                 {\r
2060                         CString sMsg(MAKEINTRESOURCE(IDS_PROGRS_COPY_WARNING));\r
2061                         ReportNotification(sMsg);\r
2062                 }\r
2063         }\r
2064 #endif\r
2065         return true;\r
2066 }\r
2067 \r
2068 bool CGitProgressDlg::CmdExport(CString& sWindowTitle, bool& /*localoperation*/)\r
2069 {\r
2070 #if 0\r
2071         ASSERT(m_targetPathList.GetCount() == 1);\r
2072         sWindowTitle.LoadString(IDS_PROGRS_TITLE_EXPORT);\r
2073         sWindowTitle = m_url.GetUIFileOrDirectoryName()+_T(" - ")+sWindowTitle;\r
2074         SetWindowText(sWindowTitle);\r
2075         SetBackgroundImage(IDI_EXPORT_BKG);\r
2076         CString eol;\r
2077         if (m_options & ProgOptEolCRLF)\r
2078                 eol = _T("CRLF");\r
2079         if (m_options & ProgOptEolLF)\r
2080                 eol = _T("LF");\r
2081         if (m_options & ProgOptEolCR)\r
2082                 eol = _T("CR");\r
2083         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_EXPORT)));\r
2084         if (!Export(m_url, m_targetPathList[0], m_Revision, m_Revision, TRUE, m_options & ProgOptIgnoreExternals, m_depth, NULL, FALSE, eol))\r
2085         {\r
2086                 ReportSVNError();\r
2087                 return false;\r
2088         }\r
2089 #endif\r
2090         return true;\r
2091 }\r
2092 \r
2093 bool CGitProgressDlg::CmdImport(CString& sWindowTitle, bool& /*localoperation*/)\r
2094 {\r
2095 #if 0\r
2096         ASSERT(m_targetPathList.GetCount() == 1);\r
2097         sWindowTitle.LoadString(IDS_PROGRS_TITLE_IMPORT);\r
2098         sWindowTitle = m_targetPathList[0].GetUIFileOrDirectoryName()+_T(" - ")+sWindowTitle;\r
2099         SetWindowText(sWindowTitle);\r
2100         SetBackgroundImage(IDI_IMPORT_BKG);\r
2101         CString sCmdInfo;\r
2102         sCmdInfo.Format(IDS_PROGRS_CMD_IMPORT, \r
2103                 m_targetPathList[0].GetWinPath(), (LPCTSTR)m_url.GetSVNPathString(), \r
2104                 m_options & ProgOptIncludeIgnored ? (LPCTSTR)(_T(", ") + sIgnoredIncluded) : _T(""));\r
2105         ReportCmd(sCmdInfo);\r
2106         if (!Import(m_targetPathList[0], m_url, m_sMessage, &m_ProjectProperties, svn_depth_infinity, m_options & ProgOptIncludeIgnored ? true : false, false))\r
2107         {\r
2108                 ReportSVNError();\r
2109                 return false;\r
2110         }\r
2111 #endif\r
2112         return true;\r
2113 }\r
2114 \r
2115 bool CGitProgressDlg::CmdLock(CString& sWindowTitle, bool& /*localoperation*/)\r
2116 {\r
2117 #if 0\r
2118         sWindowTitle.LoadString(IDS_PROGRS_TITLE_LOCK);\r
2119         SetWindowText(sWindowTitle);\r
2120         SetBackgroundImage(IDI_LOCK_BKG);\r
2121         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_LOCK)));\r
2122         if (!Lock(m_targetPathList, m_options & ProgOptLockForce, m_sMessage))\r
2123         {\r
2124                 ReportSVNError();\r
2125                 return false;\r
2126         }\r
2127         CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);\r
2128         if (m_bLockWarning)\r
2129         {\r
2130                 // the lock failed, because the file was outdated.\r
2131                 // ask the user whether to update the file and try again\r
2132                 if (CMessageBox::Show(m_hWnd, IDS_WARN_LOCKOUTDATED, IDS_APPNAME, MB_ICONQUESTION|MB_YESNO)==IDYES)\r
2133                 {\r
2134                         ReportString(CString(MAKEINTRESOURCE(IDS_SVNPROGRESS_UPDATEANDRETRY)), CString(MAKEINTRESOURCE(IDS_WARN_NOTE)));\r
2135                         if (!Update(m_targetPathList, SVNRev::REV_HEAD, svn_depth_files, false, true))\r
2136                         {\r
2137                                 ReportSVNError();\r
2138                                 return false;\r
2139                         }\r
2140                         if (!Lock(m_targetPathList, m_options & ProgOptLockForce, m_sMessage))\r
2141                         {\r
2142                                 ReportSVNError();\r
2143                                 return false;\r
2144                         }\r
2145                 }\r
2146         }\r
2147         if (m_bLockExists)\r
2148         {\r
2149                 // the locking failed because there already is a lock.\r
2150                 // if the locking-dialog is skipped in the settings, tell the\r
2151                 // user how to steal the lock anyway (i.e., how to get the lock\r
2152                 // dialog back without changing the settings)\r
2153                 if (!DWORD(CRegDWORD(_T("Software\\TortoiseGit\\ShowLockDlg"), TRUE)))\r
2154                 {\r
2155                         ReportString(CString(MAKEINTRESOURCE(IDS_SVNPROGRESS_LOCKHINT)), CString(MAKEINTRESOURCE(IDS_WARN_NOTE)));\r
2156                 }\r
2157                 return false;\r
2158         }\r
2159 #endif\r
2160         return true;\r
2161 }\r
2162 \r
2163 bool CGitProgressDlg::CmdMerge(CString& sWindowTitle, bool& /*localoperation*/)\r
2164 {\r
2165 #if 0\r
2166         bool bFailed = false;\r
2167         ASSERT(m_targetPathList.GetCount() == 1);\r
2168         sWindowTitle.LoadString(IDS_PROGRS_TITLE_MERGE);\r
2169         SetBackgroundImage(IDI_MERGE_BKG);\r
2170         if (m_options & ProgOptDryRun)\r
2171         {\r
2172                 sWindowTitle += _T(" ") + sDryRun;\r
2173         }\r
2174         if (m_options & ProgOptRecordOnly)\r
2175         {\r
2176                 sWindowTitle += _T(" ") + sRecordOnly;\r
2177         }\r
2178         SetWindowText(sWindowTitle);\r
2179 \r
2180         GetDlgItem(IDC_INFOTEXT)->ShowWindow(SW_HIDE);\r
2181         GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_SHOW);\r
2182         CRegDWORD nonint = CRegDWORD(_T("Software\\TortoiseGit\\MergeNonInteractive"), FALSE);\r
2183         if (DWORD(nonint))\r
2184         {\r
2185                 ::SendMessage(GetDlgItem(IDC_NONINTERACTIVE)->GetSafeHwnd(), BM_SETCHECK, BST_CHECKED, 0);\r
2186                 m_AlwaysConflicted = true;\r
2187         }\r
2188         // we only accept a revision list to merge for peg merges\r
2189         ATLASSERT((m_revisionArray.GetCount()==0) || (m_revisionArray.GetCount() && (m_url.IsEquivalentTo(m_url2))));\r
2190 \r
2191         if (m_url.IsEquivalentTo(m_url2))\r
2192         {\r
2193                 CString sSuggestedMessage;\r
2194                 CString sMergedLogMessage;\r
2195                 CString sSeparator = CRegString(_T("Software\\TortoiseGit\\MergeLogSeparator"), _T("........"));\r
2196                 CString temp;\r
2197 \r
2198                 // Merging revisions %s of %s to %s into %s, %s%s\r
2199                 CString sCmdInfo;\r
2200                 sCmdInfo.Format(IDS_PROGRS_CMD_MERGEPEG, \r
2201                         (LPCTSTR)m_revisionArray.ToListString(),\r
2202                         (LPCTSTR)m_url.GetSVNPathString(),\r
2203                         m_targetPathList[0].GetWinPath(),\r
2204                         m_options & ProgOptIgnoreAncestry ? (LPCTSTR)sIgnoreAncestry : (LPCTSTR)sRespectAncestry,\r
2205                         m_options & ProgOptDryRun ? ((LPCTSTR)_T(", ") + sDryRun) : _T(""));\r
2206                 ReportCmd(sCmdInfo);\r
2207 \r
2208                 if (!PegMerge(m_url, m_revisionArray, \r
2209                         m_pegRev.IsValid() ? m_pegRev : (m_url.IsUrl() ? SVNRev::REV_HEAD : SVNRev(SVNRev::REV_WC)),\r
2210                         m_targetPathList[0], true, m_depth, m_diffoptions, !!(m_options & ProgOptIgnoreAncestry), !!(m_options & ProgOptDryRun), !!(m_options & ProgOptRecordOnly)))\r
2211                 {\r
2212                         // if the merge fails with the peg revision set,\r
2213                         // try again with HEAD as the peg revision.\r
2214                         if (!PegMerge(m_url, m_revisionArray, SVNRev::REV_HEAD,\r
2215                                 m_targetPathList[0], true, m_depth, m_diffoptions, !!(m_options & ProgOptIgnoreAncestry), !!(m_options & ProgOptDryRun), !!(m_options & ProgOptRecordOnly)))\r
2216                         {\r
2217                                 ReportSVNError();\r
2218                                 bFailed = true;\r
2219                         }\r
2220                 }\r
2221         }\r
2222         else\r
2223         {\r
2224                 CString sCmdInfo;\r
2225                 sCmdInfo.Format(IDS_PROGRS_CMD_MERGEURL, \r
2226                         (LPCTSTR)m_url.GetSVNPathString(), (LPCTSTR)m_Revision.ToString(), \r
2227                         (LPCTSTR)m_url2.GetSVNPathString(), (LPCTSTR)m_RevisionEnd.ToString(),\r
2228                         m_targetPathList[0].GetWinPath(),\r
2229                         m_options & ProgOptIgnoreAncestry ? (LPCTSTR)sIgnoreAncestry : (LPCTSTR)sRespectAncestry,\r
2230                         m_options & ProgOptDryRun ? ((LPCTSTR)_T(", ") + sDryRun) : _T(""));\r
2231                 ReportCmd(sCmdInfo);\r
2232 \r
2233                 if (!Merge(m_url, m_Revision, m_url2, m_RevisionEnd, m_targetPathList[0], \r
2234                         true, m_depth, m_diffoptions, !!(m_options & ProgOptIgnoreAncestry), !!(m_options & ProgOptDryRun), !!(m_options & ProgOptRecordOnly)))\r
2235                 {\r
2236                         ReportSVNError();\r
2237                         bFailed = true;\r
2238                 }\r
2239         }\r
2240         GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_HIDE);\r
2241         GetDlgItem(IDC_INFOTEXT)->ShowWindow(SW_SHOW);\r
2242         return !bFailed;\r
2243 #endif\r
2244         return true;\r
2245 }\r
2246 \r
2247 bool CGitProgressDlg::CmdMergeAll(CString& sWindowTitle, bool& /*localoperation*/)\r
2248 {\r
2249 #if 0\r
2250         ASSERT(m_targetPathList.GetCount() == 1);\r
2251         sWindowTitle.LoadString(IDS_PROGRS_TITLE_MERGE);\r
2252         SetBackgroundImage(IDI_MERGE_BKG);\r
2253         SetWindowText(sWindowTitle);\r
2254 \r
2255         ATLASSERT(m_targetPathList.GetCount() == 1);\r
2256 \r
2257         CString sCmdInfo;\r
2258         sCmdInfo.LoadString(IDS_PROGRS_INFOGETTINGINFO);\r
2259         ReportCmd(sCmdInfo);\r
2260         CTGitPathList suggestedSources;\r
2261         if (!SuggestMergeSources(m_targetPathList[0], m_Revision, suggestedSources))\r
2262         {\r
2263                 ReportSVNError();\r
2264                 return false;\r
2265         }\r
2266 \r
2267         if (suggestedSources.GetCount() == 0)\r
2268         {\r
2269                 CString sErr;\r
2270                 sErr.Format(IDS_PROGRS_MERGEALLNOSOURCES, m_targetPathList[0].GetWinPath());\r
2271                 ReportError(sErr);\r
2272                 return false;\r
2273         }\r
2274         sCmdInfo.Format(IDS_PROGRS_CMD_MERGEALL, \r
2275                 (LPCTSTR)suggestedSources[0].GetSVNPathString(),\r
2276                 m_targetPathList[0].GetWinPath(),\r
2277                 m_options & ProgOptIgnoreAncestry ? (LPCTSTR)sIgnoreAncestry : (LPCTSTR)sRespectAncestry);\r
2278         ReportCmd(sCmdInfo);\r
2279 \r
2280         GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_SHOW);\r
2281         CRegDWORD nonint = CRegDWORD(_T("Software\\TortoiseGit\\MergeNonInteractive"), FALSE);\r
2282         if (DWORD(nonint))\r
2283         {\r
2284                 ::SendMessage(GetDlgItem(IDC_NONINTERACTIVE)->GetSafeHwnd(), BM_SETCHECK, BST_CHECKED, 0);\r
2285                 m_AlwaysConflicted = true;\r
2286         }\r
2287 \r
2288         SVNRevRangeArray revarray;\r
2289         if (!PegMerge(suggestedSources[0], revarray, \r
2290                 SVNRev::REV_HEAD,\r
2291                 m_targetPathList[0], true, m_depth, m_diffoptions, !!(m_options & ProgOptIgnoreAncestry), FALSE))\r
2292         {\r
2293                 GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_HIDE);\r
2294                 ReportSVNError();\r
2295                 return false;\r
2296         }\r
2297 \r
2298         GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_HIDE);\r
2299 #endif\r
2300         return true;\r
2301 }\r
2302 \r
2303 bool CGitProgressDlg::CmdMergeReintegrate(CString& sWindowTitle, bool& /*localoperation*/)\r
2304 {\r
2305 #if 0\r
2306         ASSERT(m_targetPathList.GetCount() == 1);\r
2307         sWindowTitle.LoadString(IDS_PROGRS_TITLE_MERGEREINTEGRATE);\r
2308         SetBackgroundImage(IDI_MERGE_BKG);\r
2309         SetWindowText(sWindowTitle);\r
2310 \r
2311         CString sCmdInfo;\r
2312         sCmdInfo.Format(IDS_PROGRS_CMD_MERGEREINTEGRATE, \r
2313                 (LPCTSTR)m_url.GetSVNPathString(),\r
2314                 m_targetPathList[0].GetWinPath());\r
2315         ReportCmd(sCmdInfo);\r
2316 \r
2317         GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_SHOW);\r
2318         CRegDWORD nonint = CRegDWORD(_T("Software\\TortoiseGit\\MergeNonInteractive"), FALSE);\r
2319         if (DWORD(nonint))\r
2320         {\r
2321                 ::SendMessage(GetDlgItem(IDC_NONINTERACTIVE)->GetSafeHwnd(), BM_SETCHECK, BST_CHECKED, 0);\r
2322                 m_AlwaysConflicted = true;\r
2323         }\r
2324 \r
2325         if (!MergeReintegrate(m_url, SVNRev::REV_HEAD, m_targetPathList[0], !!(m_options & ProgOptDryRun), m_diffoptions))\r
2326         {\r
2327                 ReportSVNError();\r
2328                 GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_HIDE);\r
2329                 return false;\r
2330         }\r
2331 \r
2332         GetDlgItem(IDC_NONINTERACTIVE)->ShowWindow(SW_HIDE);\r
2333 #endif\r
2334         return true;\r
2335 }\r
2336 \r
2337 bool CGitProgressDlg::CmdRename(CString& sWindowTitle, bool& localoperation)\r
2338 {\r
2339 #if 0\r
2340         ASSERT(m_targetPathList.GetCount() == 1);\r
2341         if ((!m_targetPathList[0].IsUrl())&&(!m_url.IsUrl()))\r
2342                 localoperation = true;\r
2343         sWindowTitle.LoadString(IDS_PROGRS_TITLE_RENAME);\r
2344         SetWindowText(sWindowTitle);\r
2345         SetBackgroundImage(IDI_RENAME_BKG);\r
2346         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_RENAME)));\r
2347         if (!Move(m_targetPathList, m_url, m_Revision, m_sMessage))\r
2348         {\r
2349                 ReportSVNError();\r
2350                 return false;\r
2351         }\r
2352 #endif\r
2353         return true;\r
2354 }\r
2355 \r
2356 bool CGitProgressDlg::CmdResolve(CString& sWindowTitle, bool& localoperation)\r
2357 {\r
2358 \r
2359         localoperation = true;\r
2360         ASSERT(m_targetPathList.GetCount() == 1);\r
2361         sWindowTitle.LoadString(IDS_PROGRS_TITLE_RESOLVE);\r
2362         SetWindowText(sWindowTitle);\r
2363         SetBackgroundImage(IDI_RESOLVE_BKG);\r
2364         // check if the file may still have conflict markers in it.\r
2365         BOOL bMarkers = FALSE;\r
2366 \r
2367         for(int i=0;i<m_targetPathList.GetCount();i++)\r
2368         {\r
2369                 CString cmd,out,tempmergefile;\r
2370                 cmd.Format(_T("git.exe add -f \"%s\""),m_targetPathList[i].GetGitPathString());\r
2371                 if(g_Git.Run(cmd,&out,CP_ACP))\r
2372                 {\r
2373                         CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
2374                         m_bErrorsOccurred=true;\r
2375                         return false;\r
2376                 }\r
2377                 \r
2378 \r
2379                 try\r
2380                 {\r
2381                         tempmergefile = CAppUtils::GetMergeTempFile(_T("LOCAL"),(CTGitPath &)m_targetPathList[i]);\r
2382                         CFile::Remove(tempmergefile);\r
2383                 }catch(...)\r
2384                 {\r
2385                 }\r
2386                 \r
2387                 try\r
2388                 {\r
2389                         tempmergefile = CAppUtils::GetMergeTempFile(_T("REMOTE"),(CTGitPath &)m_targetPathList[i]);\r
2390                         CFile::Remove(tempmergefile);\r
2391                 }catch(...)\r
2392                 {\r
2393                 }\r
2394 \r
2395                 try\r
2396                 {\r
2397                         tempmergefile = CAppUtils::GetMergeTempFile(_T("BASE"),(CTGitPath &)m_targetPathList[i]);\r
2398                         CFile::Remove(tempmergefile);\r
2399                 }catch(...)\r
2400                 {\r
2401                 }\r
2402                 \r
2403 \r
2404                 Notify(m_targetPathList[i],git_wc_notify_resolved);\r
2405         }\r
2406 #if 0\r
2407         if ((m_options & ProgOptSkipConflictCheck) == 0)\r
2408         {\r
2409                 try\r
2410                 {\r
2411                         for (INT_PTR fileindex=0; (fileindex<m_targetPathList.GetCount()) && (bMarkers==FALSE); ++fileindex)\r
2412                         {\r
2413                                 if (!m_targetPathList[fileindex].IsDirectory())\r
2414                                 {\r
2415                                         CStdioFile file(m_targetPathList[fileindex].GetWinPath(), CFile::typeBinary | CFile::modeRead);\r
2416                                         CString strLine = _T("");\r
2417                                         while (file.ReadString(strLine))\r
2418                                         {\r
2419                                                 if (strLine.Find(_T("<<<<<<<"))==0)\r
2420                                                 {\r
2421                                                         bMarkers = TRUE;\r
2422                                                         break;\r
2423                                                 }\r
2424                                         }\r
2425                                         file.Close();\r
2426                                 }\r
2427                         }\r
2428                 } \r
2429                 catch (CFileException* pE)\r
2430                 {\r
2431                         TRACE(_T("CFileException in Resolve!\n"));\r
2432                         TCHAR error[10000] = {0};\r
2433                         pE->GetErrorMessage(error, 10000);\r
2434                         ReportError(error);\r
2435                         pE->Delete();\r
2436                         return false;\r
2437                 }\r
2438         }\r
2439         if (bMarkers)\r
2440         {\r
2441                 if (CMessageBox::Show(m_hWnd, IDS_PROGRS_REVERTMARKERS, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION)==IDYES)\r
2442                 {\r
2443                         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_RESOLVE)));\r
2444                         for (INT_PTR fileindex=0; fileindex<m_targetPathList.GetCount(); ++fileindex)\r
2445                                 Resolve(m_targetPathList[fileindex], svn_wc_conflict_choose_merged, true);\r
2446                 }\r
2447         }\r
2448         else\r
2449         {\r
2450                 ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_RESOLVE)));\r
2451                 for (INT_PTR fileindex=0; fileindex<m_targetPathList.GetCount(); ++fileindex)\r
2452                         Resolve(m_targetPathList[fileindex], svn_wc_conflict_choose_merged, true);\r
2453         }\r
2454 #endif\r
2455         CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);\r
2456 \r
2457         return true;\r
2458 }\r
2459 \r
2460 bool CGitProgressDlg::CmdRevert(CString& sWindowTitle, bool& localoperation)\r
2461 {\r
2462 \r
2463         localoperation = true;\r
2464         sWindowTitle.LoadString(IDS_PROGRS_TITLE_REVERT);\r
2465         SetWindowText(sWindowTitle);\r
2466         SetBackgroundImage(IDI_REVERT_BKG);\r
2467 \r
2468         CTGitPathList delList = m_selectedPaths;\r
2469         if (DWORD(CRegDWORD(_T("Software\\TortoiseGit\\RevertWithRecycleBin"), TRUE)))\r
2470                 delList.DeleteAllFiles(true);\r
2471 \r
2472         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_REVERT)));\r
2473         for(int i=0;i<m_selectedPaths.GetCount();i++)\r
2474         {\r
2475                 if(g_Git.Revert((CTGitPath&)m_selectedPaths[i],true))\r
2476                 {\r
2477                         CMessageBox::Show(NULL,_T("Revert Fail"),_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
2478                         m_bErrorsOccurred=true;\r
2479                         return false;\r
2480                 }\r
2481                 Notify(m_selectedPaths[i],git_wc_notify_revert);\r
2482         }\r
2483 \r
2484         CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);\r
2485 \r
2486         return true;\r
2487 }\r
2488 \r
2489 bool CGitProgressDlg::CmdSwitch(CString& sWindowTitle, bool& /*localoperation*/)\r
2490 {\r
2491 #if 0\r
2492         ASSERT(m_targetPathList.GetCount() == 1);\r
2493         SVNStatus st;\r
2494         sWindowTitle.LoadString(IDS_PROGRS_TITLE_SWITCH);\r
2495         SetWindowText(sWindowTitle);\r
2496         SetBackgroundImage(IDI_SWITCH_BKG);\r
2497         LONG rev = 0;\r
2498         if (st.GetStatus(m_targetPathList[0]) != (-2))\r
2499         {\r
2500                 if (st.status->entry != NULL)\r
2501                 {\r
2502                         rev = st.status->entry->revision;\r
2503                 }\r
2504         }\r
2505 \r
2506         CString sCmdInfo;\r
2507         sCmdInfo.Format(IDS_PROGRS_CMD_SWITCH, \r
2508                 m_targetPathList[0].GetWinPath(), (LPCTSTR)m_url.GetSVNPathString(),\r
2509                 (LPCTSTR)m_Revision.ToString());\r
2510         ReportCmd(sCmdInfo);\r
2511 \r
2512         bool depthIsSticky = true;\r
2513         if (m_depth == svn_depth_unknown)\r
2514                 depthIsSticky = false;\r
2515         if (!Switch(m_targetPathList[0], m_url, m_Revision, m_Revision, m_depth, depthIsSticky, m_options & ProgOptIgnoreExternals))\r
2516         {\r
2517                 ReportSVNError();\r
2518                 return false;\r
2519         }\r
2520         m_UpdateStartRevMap[m_targetPathList[0].GetSVNApiPath(pool)] = rev;\r
2521         if ((m_RevisionEnd >= 0)&&(rev >= 0)\r
2522                 &&((LONG)m_RevisionEnd > (LONG)rev))\r
2523         {\r
2524                 GetDlgItem(IDC_LOGBUTTON)->ShowWindow(SW_SHOW);\r
2525         }\r
2526 #endif\r
2527         return true;\r
2528 }\r
2529 \r
2530 bool CGitProgressDlg::CmdUnlock(CString& sWindowTitle, bool& /*localoperation*/)\r
2531 {\r
2532 #if 0\r
2533         sWindowTitle.LoadString(IDS_PROGRS_TITLE_UNLOCK);\r
2534         SetWindowText(sWindowTitle);\r
2535         SetBackgroundImage(IDI_UNLOCK_BKG);\r
2536         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_UNLOCK)));\r
2537         if (!Unlock(m_targetPathList, m_options & ProgOptLockForce))\r
2538         {\r
2539                 ReportSVNError();\r
2540                 return false;\r
2541         }\r
2542         CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);\r
2543 #endif\r
2544         return true;\r
2545 }\r
2546 \r
2547 bool CGitProgressDlg::CmdUpdate(CString& sWindowTitle, bool& /*localoperation*/)\r
2548 {\r
2549 #if 0\r
2550         sWindowTitle.LoadString(IDS_PROGRS_TITLE_UPDATE);\r
2551         SetWindowText(sWindowTitle);\r
2552         SetBackgroundImage(IDI_UPDATE_BKG);\r
2553 \r
2554         int targetcount = m_targetPathList.GetCount();\r
2555         CString sfile;\r
2556         CStringA uuid;\r
2557         StringRevMap uuidmap;\r
2558         SVNRev revstore = m_Revision;\r
2559         int nUUIDs = 0;\r
2560         for(int nItem = 0; nItem < targetcount; nItem++)\r
2561         {\r
2562                 const CTGitPath& targetPath = m_targetPathList[nItem];\r
2563                 SVNStatus st;\r
2564                 LONG headrev = -1;\r
2565                 m_Revision = revstore;\r
2566                 if (m_Revision.IsHead())\r
2567                 {\r
2568                         if ((targetcount > 1)&&((headrev = st.GetStatus(targetPath, true)) != (-2)))\r
2569                         {\r
2570                                 if (st.status->entry != NULL)\r
2571                                 {\r
2572 \r
2573                                         m_UpdateStartRevMap[targetPath.GetSVNApiPath(pool)] = st.status->entry->cmt_rev;\r
2574                                         if (st.status->entry->uuid)\r
2575                                         {\r
2576                                                 uuid = st.status->entry->uuid;\r
2577                                                 StringRevMap::iterator iter = uuidmap.lower_bound(uuid);\r
2578                                                 if (iter == uuidmap.end() || iter->first != uuid)\r
2579                                                 {\r
2580                                                         uuidmap.insert(iter, std::make_pair(uuid, headrev));\r
2581                                                         nUUIDs++;\r
2582                                                 }\r
2583                                                 else\r
2584                                                         headrev = iter->second;\r
2585                                                 m_Revision = headrev;\r
2586                                         }\r
2587                                         else\r
2588                                                 m_Revision = headrev;\r
2589                                 }\r
2590                         }\r
2591                         else\r
2592                         {\r
2593                                 if ((headrev = st.GetStatus(targetPath, FALSE)) != (-2))\r
2594                                 {\r
2595                                         if (st.status->entry != NULL)\r
2596                                                 m_UpdateStartRevMap[targetPath.GetSVNApiPath(pool)] = st.status->entry->cmt_rev;\r
2597                                 }\r
2598                         }\r
2599                         if (uuidmap.size() > 1)\r
2600                                 m_Revision = SVNRev::REV_HEAD;\r
2601                 } // if (m_Revision.IsHead()) \r
2602         } // for(int nItem = 0; nItem < targetcount; nItem++) \r
2603         sWindowTitle = m_targetPathList.GetCommonRoot().GetWinPathString()+_T(" - ")+sWindowTitle;\r
2604         SetWindowText(sWindowTitle);\r
2605 \r
2606         DWORD exitcode = 0;\r
2607         CString error;\r
2608         if (CHooks::Instance().PreUpdate(m_targetPathList, m_depth, nUUIDs > 1 ? revstore : m_Revision, exitcode, error))\r
2609         {\r
2610                 if (exitcode)\r
2611                 {\r
2612                         CString temp;\r
2613                         temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);\r
2614                         ReportError(temp);\r
2615                         return false;\r
2616                 }\r
2617         }\r
2618         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_UPDATE)));\r
2619         if (nUUIDs > 1)\r
2620         {\r
2621                 // the selected items are from different repositories,\r
2622                 // so we have to update them separately\r
2623                 for(int nItem = 0; nItem < targetcount; nItem++)\r
2624                 {\r
2625                         const CTGitPath& targetPath = m_targetPathList[nItem];\r
2626                         m_basePath = targetPath;\r
2627                         CString sNotify;\r
2628                         sNotify.Format(IDS_PROGRS_UPDATEPATH, m_basePath.GetWinPath());\r
2629                         ReportString(sNotify, CString(MAKEINTRESOURCE(IDS_WARN_NOTE)));\r
2630                         if (!Update(CTGitPathList(targetPath), revstore, m_depth, TRUE, m_options & ProgOptIgnoreExternals))\r
2631                         {\r
2632                                 ReportSVNError();\r
2633                                 return false;\r
2634                         }\r
2635                 }\r
2636         }\r
2637         else \r
2638         {\r
2639                 // if we have only one target path, but that target path does not exist,\r
2640                 // we have to check whether at least the parent path exists. If not,\r
2641                 // then we have to update all paths in between the first path that exists and the\r
2642                 // parent path of the one we want to update\r
2643                 // This is required so a user can create a sparse checkout without having\r
2644                 // to update all intermediate folders manually\r
2645                 if ((m_targetPathList.GetCount() == 1) && (!m_targetPathList[0].Exists()))\r
2646                 {\r
2647                         CTGitPath wcPath = m_targetPathList[0].GetContainingDirectory();\r
2648                         CTGitPath existingParentPath = wcPath.GetContainingDirectory();\r
2649                         while (!existingParentPath.Exists() && (existingParentPath.GetWinPathString().GetLength() > 2))\r
2650                         {\r
2651                                 existingParentPath = existingParentPath.GetContainingDirectory();\r
2652                         }\r
2653                         if (existingParentPath.GetWinPathString().GetLength() && !existingParentPath.IsEquivalentTo(wcPath))\r
2654                         {\r
2655                                 // update all intermediate directories with depth 'empty'\r
2656                                 CTGitPath intermediatepath = existingParentPath;\r
2657                                 bool bSuccess = true;\r
2658                                 while (bSuccess && intermediatepath.IsAncestorOf(wcPath) && !intermediatepath.IsEquivalentTo(wcPath))\r
2659                                 {\r
2660                                         CString childname = wcPath.GetWinPathString().Mid(intermediatepath.GetWinPathString().GetLength(),\r
2661                                                 wcPath.GetWinPathString().Find('\\', intermediatepath.GetWinPathString().GetLength()+1)-intermediatepath.GetWinPathString().GetLength());\r
2662                                         if (childname.IsEmpty())\r
2663                                                 intermediatepath = wcPath;\r
2664                                         else\r
2665                                                 intermediatepath.AppendPathString(childname);\r
2666                                         bSuccess = !!Update(CTGitPathList(intermediatepath), m_Revision, svn_depth_empty, false, true);\r
2667                                 }\r
2668 \r
2669                                 if (!bSuccess)\r
2670                                 {\r
2671                                         ReportSVNError();\r
2672                                         return false;\r
2673                                 }\r
2674                         }\r
2675                 }\r
2676                 if (!Update(m_targetPathList, m_Revision, m_depth, TRUE, m_options & ProgOptIgnoreExternals))\r
2677                 {\r
2678                         ReportSVNError();\r
2679                         return false;\r
2680                 }\r
2681         }\r
2682         if (CHooks::Instance().PostUpdate(m_targetPathList, m_depth, m_RevisionEnd, exitcode, error))\r
2683         {\r
2684                 if (exitcode)\r
2685                 {\r
2686                         CString temp;\r
2687                         temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);\r
2688                         ReportError(temp);\r
2689                         return false;\r
2690                 }\r
2691         }\r
2692 \r
2693         // after an update, show the user the log button, but only if only one single item was updated\r
2694         // (either a file or a directory)\r
2695         if ((m_targetPathList.GetCount() == 1)&&(m_UpdateStartRevMap.size()>0))\r
2696                 GetDlgItem(IDC_LOGBUTTON)->ShowWindow(SW_SHOW);\r
2697 #endif\r
2698         return true;\r
2699 }\r
2700 \r
2701 void CGitProgressDlg::OnBnClickedNoninteractive()\r
2702 {\r
2703         LRESULT res = ::SendMessage(GetDlgItem(IDC_NONINTERACTIVE)->GetSafeHwnd(), BM_GETCHECK, 0, 0);\r
2704         m_AlwaysConflicted = (res == BST_CHECKED);\r
2705         CRegDWORD nonint = CRegDWORD(_T("Software\\TortoiseGit\\MergeNonInteractive"), FALSE);\r
2706         nonint = m_AlwaysConflicted;\r
2707 }\r
2708 \r
2709 CString CGitProgressDlg::GetPathFromColumnText(const CString& sColumnText)\r
2710 {\r
2711         CString sPath = CPathUtils::ParsePathInString(sColumnText);\r
2712         if (sPath.Find(':')<0)\r
2713         {\r
2714                 // the path is not absolute: add the common root of all paths to it\r
2715                 sPath = m_targetPathList.GetCommonRoot().GetDirectory().GetWinPathString() + _T("\\") + CPathUtils::ParsePathInString(sColumnText);\r
2716         }\r
2717         return sPath;\r
2718 }\r
2719 \r
2720 bool CGitProgressDlg::CmdSendMail(CString& sWindowTitle, bool& /*localoperation*/)\r
2721 {\r
2722         sWindowTitle.LoadString(IDS_PROGRS_TITLE_SENDMAIL);\r
2723         SetWindowText(sWindowTitle);\r
2724         //SetBackgroundImage(IDI_ADD_BKG);\r
2725         ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_SENDMAIL)));\r
2726         bool ret=true;\r
2727         if(this->m_SendMailFlags&SENDMAIL_COMBINED)\r
2728         {\r
2729                 CString error;\r
2730                 CTGitPath path;\r
2731                 Notify(path,git_wc_notify_sendmail_start);\r
2732                 CString err;\r
2733                 int retry=0;\r
2734                 while(retry <3)\r
2735                 {\r
2736                         if(CPatch::Send(m_targetPathList,m_SendMailTO,m_SendMailCC,m_SendMailSubject,this->m_SendMailFlags&SENDMAIL_ATTACHMENT,&err))\r
2737                         {\r
2738                                 Notify(path,git_wc_notify_sendmail_error,ret,&err);\r
2739                                 ret = false;\r
2740                         }\r
2741                         else\r
2742                         {\r
2743                                 break;          \r
2744                         }\r
2745 \r
2746                         retry++;\r
2747                         Sleep(2000);\r
2748                         if(m_bCancelled)\r
2749                         {\r
2750                                 Notify(path,git_wc_notify_sendmail_retry,ret,&CString("User Canceled"));\r
2751                             return false;\r
2752                         }\r
2753                 }\r
2754                 Notify(path,git_wc_notify_sendmail_done,ret);\r
2755 \r
2756         }else\r
2757         {\r
2758                 for(int i=0;i<m_targetPathList.GetCount();i++)\r
2759                 {\r
2760                         CPatch patch;\r
2761                         Notify(m_targetPathList[i],git_wc_notify_sendmail_start);\r
2762 \r
2763                         int retry=0;\r
2764                         while(retry<3)\r
2765                         {\r
2766                                 int ret=patch.Send((CString&)m_targetPathList[i].GetWinPathString(),this->m_SendMailTO,\r
2767                                          this->m_SendMailCC,this->m_SendMailFlags&SENDMAIL_ATTACHMENT);\r
2768                                 if(ret)\r
2769                                 {\r
2770                                         Notify(m_targetPathList[i],git_wc_notify_sendmail_error,ret,&patch.m_LastError);\r
2771                                         ret = false;\r
2772 \r
2773                                 }else\r
2774                                 {\r
2775                                         break;\r
2776                                 }\r
2777                                 Notify(m_targetPathList[i],git_wc_notify_sendmail_retry,ret,&patch.m_LastError);\r
2778 \r
2779                                 retry++;\r
2780                                 Sleep(2000);\r
2781                                 if(m_bCancelled)\r
2782                                 {\r
2783                                         Notify(m_targetPathList[i],git_wc_notify_sendmail_retry,ret,&CString("User Canceled"));\r
2784                                     return false;\r
2785                                 }\r
2786                         }\r
2787                         Notify(m_targetPathList[i],git_wc_notify_sendmail_done,ret);\r
2788                         \r
2789                 }\r
2790         }\r
2791         return ret;\r
2792 }