OSDN Git Service

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