Reduce C style casts
[TortoiseGit.git] / src / TortoiseProc / SyncDlg.cpp
blob400d6ec6bbcc6880c27f21957a4e0b00af780002
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2016 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 // SyncDlg.cpp : implementation file
23 #include "stdafx.h"
24 #include "TortoiseProc.h"
25 #include "SyncDlg.h"
26 #include "AppUtils.h"
27 #include "ProgressDlg.h"
28 #include "MessageBox.h"
29 #include "ImportPatchDlg.h"
30 #include "RebaseDlg.h"
31 #include "Hooks.h"
32 #include "SmartHandle.h"
33 #include "ProgressCommands/FetchProgressCommand.h"
35 // CSyncDlg dialog
37 IMPLEMENT_DYNAMIC(CSyncDlg, CResizableStandAloneDialog)
39 CSyncDlg::CSyncDlg(CWnd* pParent /*=nullptr*/)
40 : CResizableStandAloneDialog(CSyncDlg::IDD, pParent)
41 , m_iPullRebase(0)
43 m_CurrentCmd = 0;
44 m_pTooltip=&this->m_tooltips;
45 m_bInited=false;
46 m_CmdOutCurrentPos=0;
47 m_bAutoLoadPuttyKey = CAppUtils::IsSSHPutty();
48 m_bForce=false;
49 m_bBlock = false;
50 m_BufStart = 0;
51 m_pThread = nullptr;
52 m_bAbort = false;
53 m_bDone = false;
54 m_bWantToExit = false;
55 m_GitCmdStatus = -1;
56 m_startTick = GetTickCount64();
57 m_seq = 0;
60 CSyncDlg::~CSyncDlg()
64 void CSyncDlg::DoDataExchange(CDataExchange* pDX)
66 CDialog::DoDataExchange(pDX);
67 DDX_Check(pDX, IDC_CHECK_PUTTY_KEY, m_bAutoLoadPuttyKey);
68 DDX_Check(pDX, IDC_CHECK_FORCE,m_bForce);
69 DDX_Control(pDX, IDC_COMBOBOXEX_URL, m_ctrlURL);
70 DDX_Control(pDX, IDC_BUTTON_TABCTRL, m_ctrlDumyButton);
71 DDX_Control(pDX, IDC_BUTTON_PULL, m_ctrlPull);
72 DDX_Control(pDX, IDC_BUTTON_PUSH, m_ctrlPush);
73 DDX_Control(pDX, IDC_STATIC_STATUS, m_ctrlStatus);
74 DDX_Control(pDX, IDC_PROGRESS_SYNC, m_ctrlProgress);
75 DDX_Control(pDX, IDC_ANIMATE_SYNC, m_ctrlAnimate);
76 DDX_Control(pDX, IDC_BUTTON_SUBMODULE,m_ctrlSubmodule);
77 DDX_Control(pDX, IDC_BUTTON_STASH, m_ctrlStash);
78 DDX_Control(pDX, IDC_PROG_LABEL, m_ctrlProgLabel);
79 BRANCH_COMBOX_DDX;
82 BEGIN_MESSAGE_MAP(CSyncDlg, CResizableStandAloneDialog)
83 ON_BN_CLICKED(IDC_BUTTON_PULL, &CSyncDlg::OnBnClickedButtonPull)
84 ON_BN_CLICKED(IDC_BUTTON_PUSH, &CSyncDlg::OnBnClickedButtonPush)
85 ON_BN_CLICKED(IDC_BUTTON_APPLY, &CSyncDlg::OnBnClickedButtonApply)
86 ON_BN_CLICKED(IDC_BUTTON_EMAIL, &CSyncDlg::OnBnClickedButtonEmail)
87 ON_BN_CLICKED(IDC_BUTTON_MANAGE, &CSyncDlg::OnBnClickedButtonManage)
88 BRANCH_COMBOX_EVENT
89 ON_CBN_EDITCHANGE(IDC_COMBOBOXEX_URL, &CSyncDlg::OnCbnEditchangeComboboxex)
90 ON_CBN_EDITCHANGE(IDC_COMBOBOXEX_REMOTE_BRANCH, &CSyncDlg::OnCbnEditchangeComboboxex)
91 ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)
92 ON_MESSAGE(WM_PROG_CMD_FINISH, OnProgCmdFinish)
93 ON_NOTIFY(LVN_COLUMNCLICK, IDC_IN_LOGLIST, OnLvnInLogListColumnClick)
94 ON_BN_CLICKED(IDC_BUTTON_COMMIT, &CSyncDlg::OnBnClickedButtonCommit)
95 ON_BN_CLICKED(IDC_BUTTON_SUBMODULE, &CSyncDlg::OnBnClickedButtonSubmodule)
96 ON_BN_CLICKED(IDC_BUTTON_STASH, &CSyncDlg::OnBnClickedButtonStash)
97 ON_WM_TIMER()
98 ON_REGISTERED_MESSAGE(TaskBarButtonCreated, OnTaskbarBtnCreated)
99 ON_BN_CLICKED(IDC_CHECK_FORCE, &CSyncDlg::OnBnClickedCheckForce)
100 ON_BN_CLICKED(IDC_LOG, &CSyncDlg::OnBnClickedLog)
101 ON_WM_DESTROY()
102 END_MESSAGE_MAP()
104 void CSyncDlg::EnableControlButton(bool bEnabled)
106 GetDlgItem(IDC_BUTTON_PULL)->EnableWindow(bEnabled);
107 GetDlgItem(IDC_BUTTON_PUSH)->EnableWindow(bEnabled);
108 GetDlgItem(IDC_BUTTON_APPLY)->EnableWindow(bEnabled);
109 GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(bEnabled);
110 GetDlgItem(IDOK)->EnableWindow(bEnabled);
111 GetDlgItem(IDC_BUTTON_SUBMODULE)->EnableWindow(bEnabled);
112 GetDlgItem(IDC_BUTTON_STASH)->EnableWindow(bEnabled);
114 // CSyncDlg message handlers
116 bool CSyncDlg::AskSetTrackedBranch()
118 CString remote, remoteBranch;
119 g_Git.GetRemoteTrackedBranch(m_strLocalBranch, remote, remoteBranch);
120 if (remoteBranch.IsEmpty())
122 remoteBranch = m_strRemoteBranch;
123 if (remoteBranch.IsEmpty())
124 remoteBranch = m_strLocalBranch;
125 CString temp;
126 temp.Format(IDS_NOTYET_SETTRACKEDBRANCH, (LPCTSTR)m_strLocalBranch, (LPCTSTR)remoteBranch);
127 BOOL dontShowAgain = FALSE;
128 auto ret = CMessageBox::ShowCheck(GetSafeHwnd(), temp, L"TortoiseGit", MB_ICONQUESTION | MB_YESNOCANCEL, nullptr, CString(MAKEINTRESOURCE(IDS_MSGBOX_DONOTSHOW)), &dontShowAgain);
129 if (dontShowAgain)
130 CRegDWORD(L"Software\\TortoiseGit\\AskSetTrackedBranch") = FALSE;
131 if (ret == IDCANCEL)
132 return false;
133 if (ret == IDYES)
135 CString key;
136 key.Format(L"branch.%s.remote", (LPCTSTR)m_strLocalBranch);
137 g_Git.SetConfigValue(key, m_strURL);
138 key.Format(L"branch.%s.merge", (LPCTSTR)m_strLocalBranch);
139 g_Git.SetConfigValue(key, L"refs/heads/" + g_Git.StripRefName(remoteBranch));
142 return true;
145 void CSyncDlg::OnBnClickedButtonPull()
147 int CurrentEntry;
148 CurrentEntry = (int)this->m_ctrlPull.GetCurrentEntry();
149 this->m_regPullButton = CurrentEntry;
151 this->m_bAbort=false;
152 this->m_GitCmdList.clear();
153 m_ctrlCmdOut.SetWindowTextW(_T(""));
154 m_LogText.Empty();
156 this->UpdateData();
157 UpdateCombox();
159 if (g_Git.GetHash(m_oldHash, _T("HEAD")))
161 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR);
162 return;
165 m_refList.Clear();
166 m_newHashMap.clear();
167 m_oldHashMap.clear();
169 if( CurrentEntry == 0)
171 CGitHash localBranchHash;
172 if (g_Git.GetHash(localBranchHash, m_strLocalBranch))
174 MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + m_strLocalBranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
175 return;
177 if (localBranchHash != m_oldHash)
179 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_SYNC_PULLWRONGBRANCH, IDS_APPNAME, MB_OK | MB_ICONERROR);
180 return;
184 if(this->m_strURL.IsEmpty())
186 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_GITCONFIG_URLEMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
187 return;
190 if (!IsURL() && !m_strRemoteBranch.IsEmpty() && CurrentEntry == 0 && CRegDWORD(L"Software\\TortoiseGit\\AskSetTrackedBranch", TRUE) == TRUE)
192 if (!AskSetTrackedBranch())
193 return;
196 if (m_bAutoLoadPuttyKey && CurrentEntry != 4) // CurrentEntry (Remote Update) handles this on its own)
198 CAppUtils::LaunchPAgent(nullptr, &m_strURL);
201 if (g_Git.GetMapHashToFriendName(m_oldHashMap))
202 MessageBox(g_Git.GetGitLastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR);
204 CString force;
205 if(this->m_bForce)
206 force = _T(" --force");
208 CString cmd;
210 m_iPullRebase = 0;
211 if (CurrentEntry == 0 && CRegDWORD(L"Software\\TortoiseGit\\PullRebaseBehaviorLike1816", FALSE) == FALSE) // check whether we need to override Pull if pull.rebase is set
213 CAutoRepository repo(g_Git.GetGitRepository());
214 if (!repo)
215 MessageBox(CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
217 // Check config branch.<name>.rebase and pull.reabse
220 if (!repo)
221 break;
223 if (git_repository_head_detached(repo) == 1)
224 break;
226 CAutoConfig config(true);
227 if (git_repository_config(config.GetPointer(), repo))
228 break;
230 // branch.<name>.rebase overrides pull.rebase
231 if (config.GetBOOL(_T("branch.") + g_Git.GetCurrentBranch() + _T(".rebase"), m_iPullRebase) == GIT_ENOTFOUND)
233 if (config.GetBOOL(_T("pull.rebase"), m_iPullRebase) == GIT_ENOTFOUND)
234 break;
235 else
237 CString value;
238 config.GetString(_T("pull.rebase"), value);
239 if (value == _T("preserve"))
241 m_iPullRebase = 2;
242 break;
246 else
248 CString value;
249 config.GetString(_T("branch.") + g_Git.GetCurrentBranch() + _T(".rebase"), value);
250 if (value == _T("preserve"))
252 m_iPullRebase = 2;
253 break;
256 } while (0);
257 if (m_iPullRebase > 0)
259 CurrentEntry = 1;
260 if (m_strRemoteBranch.IsEmpty())
262 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_PULL_EMPTYBRANCH, IDS_APPNAME, MB_ICONEXCLAMATION);
263 return;
268 SwitchToRun();
270 ShowTab(IDC_CMD_LOG);
272 m_ctrlTabCtrl.ShowTab(IDC_REFLIST - 1, true);
273 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST - 1, false);
274 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST - 1, false);
275 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT - 1, false);
277 ///Pull
278 if(CurrentEntry == 0) //Pull
280 CString remotebranch;
281 remotebranch = m_strRemoteBranch;
283 if(!IsURL())
285 CString pullRemote, pullBranch;
286 g_Git.GetRemoteTrackedBranch(m_strLocalBranch, pullRemote, pullBranch);
287 if(pullBranch == remotebranch && pullRemote == this->m_strURL)
288 remotebranch.Empty();
291 cmd.Format(_T("git.exe pull -v --progress%s \"%s\" %s"),
292 (LPCTSTR)force,
293 (LPCTSTR)m_strURL,
294 (LPCTSTR)remotebranch);
296 m_CurrentCmd = GIT_COMMAND_PULL;
297 m_GitCmdList.push_back(cmd);
299 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
300 if (!m_pThread)
302 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
304 else
306 m_pThread->m_bAutoDelete = TRUE;
307 m_pThread->ResumeThread();
312 ///Fetch
313 if (CurrentEntry == 1 || CurrentEntry == 2 || CurrentEntry == 3)
315 m_oldRemoteHash.Empty();
316 CString remotebranch;
317 if (CurrentEntry == 3)
318 m_strRemoteBranch.Empty();
319 else if (IsURL() || m_strRemoteBranch.IsEmpty())
321 remotebranch=this->m_strRemoteBranch;
324 else
326 remotebranch.Format(_T("remotes/%s/%s"), (LPCTSTR)m_strURL, (LPCTSTR)m_strRemoteBranch);
327 g_Git.GetHash(m_oldRemoteHash, remotebranch);
328 if (m_oldRemoteHash.IsEmpty())
329 remotebranch=m_strRemoteBranch;
330 else
331 remotebranch=m_strRemoteBranch+_T(":")+remotebranch;
334 if (CurrentEntry == 1 || CurrentEntry == 3)
335 m_CurrentCmd = GIT_COMMAND_FETCH;
336 else
337 m_CurrentCmd = GIT_COMMAND_FETCHANDREBASE;
339 if (g_Git.UsingLibGit2(CGit::GIT_CMD_FETCH))
341 CString refspec;
342 if (!remotebranch.IsEmpty())
343 refspec.Format(_T("refs/heads/%s:refs/remotes/%s/%s"), (LPCTSTR)m_strRemoteBranch, (LPCTSTR)m_strURL, (LPCTSTR)m_strRemoteBranch);
345 progressCommand = std::make_unique<FetchProgressCommand>();
346 FetchProgressCommand* fetchProgressCommand = static_cast<FetchProgressCommand*>(progressCommand.get());
347 fetchProgressCommand->SetUrl(m_strURL);
348 fetchProgressCommand->SetRefSpec(refspec);
349 m_GitProgressList.SetCommand(progressCommand.get());
350 m_GitProgressList.Init();
351 ShowTab(IDC_CMD_GIT_PROG);
353 else
355 cmd.Format(_T("git.exe fetch --progress -v%s \"%s\" %s"),
356 (LPCTSTR)force,
357 (LPCTSTR)m_strURL,
358 (LPCTSTR)remotebranch);
360 m_GitCmdList.push_back(cmd);
362 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
363 if (!m_pThread)
365 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
367 else
369 m_pThread->m_bAutoDelete = TRUE;
370 m_pThread->ResumeThread();
375 ///Remote Update
376 if (CurrentEntry == 4)
378 if (m_bAutoLoadPuttyKey)
380 STRING_VECTOR list;
381 if (!g_Git.GetRemoteList(list))
383 for (size_t i = 0; i < list.size(); ++i)
384 CAppUtils::LaunchPAgent(nullptr, &list[i]);
388 m_CurrentCmd = GIT_COMMAND_REMOTE;
389 cmd=_T("git.exe remote update");
390 m_GitCmdList.push_back(cmd);
392 InterlockedExchange(&m_bBlock, TRUE);
394 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
395 if (!m_pThread)
397 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
398 InterlockedExchange(&m_bBlock, FALSE);
400 else
402 m_pThread->m_bAutoDelete = TRUE;
403 m_pThread->ResumeThread();
407 ///Cleanup stale remote banches
408 if (CurrentEntry == 5)
410 m_CurrentCmd = GIT_COMMAND_REMOTE;
411 cmd.Format(_T("git.exe remote prune \"%s\""), (LPCTSTR)m_strURL);
412 m_GitCmdList.push_back(cmd);
414 InterlockedExchange(&m_bBlock, TRUE);
416 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
417 if (!m_pThread)
419 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
420 InterlockedExchange(&m_bBlock, FALSE);
422 else
424 m_pThread->m_bAutoDelete = TRUE;
425 m_pThread->ResumeThread();
430 void CSyncDlg::ShowInCommits(const CString& friendname)
432 CGitHash newHash;
434 if (g_Git.GetHash(newHash, friendname))
436 MessageBox(g_Git.GetGitLastErr(L"Could not get " + friendname + L" hash."), L"TortoiseGit", MB_ICONERROR);
437 return;
440 if (newHash == m_oldHash)
442 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST - 1, false);
443 m_InLogList.ShowText(CString(MAKEINTRESOURCE(IDS_UPTODATE)));
444 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST - 1, true);
445 ShowTab(IDC_REFLIST);
447 else
449 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST - 1, true);
450 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST - 1, true);
452 AddDiffFileList(&m_InChangeFileList, &m_arInChangeList, newHash.ToString(), m_oldHash.ToString());
454 CString range;
455 range.Format(L"%s..%s", (LPCTSTR)m_oldHash.ToString(), (LPCTSTR)newHash.ToString());
456 m_InLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT | CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
457 ShowTab(IDC_IN_LOGLIST);
461 void CSyncDlg::PullComplete()
463 EnableControlButton(true);
464 SwitchToInput();
465 this->FetchOutList(true);
467 if( this ->m_GitCmdStatus )
469 int hasConflicts = g_Git.HasWorkingTreeConflicts();
470 if (hasConflicts < 0)
472 this->m_ctrlCmdOut.SetSel(-1,-1);
473 this->m_ctrlCmdOut.ReplaceSel(g_Git.GetGitLastErr(L"Checking for conflicts failed.", CGit::GIT_CMD_CHECKCONFLICTS));
475 this->ShowTab(IDC_CMD_LOG);
476 return;
479 if (hasConflicts)
481 this->m_ConflictFileList.Clear();
482 CTGitPathList list;
483 CTGitPath path;
484 list.AddPath(path);
486 this->m_ConflictFileList.GetStatus(&list,true);
487 this->m_ConflictFileList.Show(CTGitPath::LOGACTIONS_UNMERGED,
488 CTGitPath::LOGACTIONS_UNMERGED);
490 this->ShowTab(IDC_IN_CONFLICT);
492 else
493 this->ShowTab(IDC_CMD_LOG);
496 else
497 ShowInCommits(L"HEAD");
500 void CSyncDlg::FetchComplete()
502 EnableControlButton(true);
503 SwitchToInput();
505 if (g_Git.UsingLibGit2(CGit::GIT_CMD_FETCH))
506 ShowTab(IDC_CMD_GIT_PROG);
507 else
508 ShowTab(IDC_REFLIST);
510 if (m_GitCmdStatus || (m_CurrentCmd != GIT_COMMAND_FETCHANDREBASE && m_iPullRebase == 0))
512 FetchOutList(true);
513 return;
516 CString remote;
517 CString remotebranch;
518 CString upstream = _T("FETCH_HEAD");
519 m_ctrlURL.GetWindowText(remote);
520 if (!remote.IsEmpty())
522 STRING_VECTOR remotes;
523 g_Git.GetRemoteList(remotes);
524 if (std::find(remotes.cbegin(), remotes.cend(), remote) == remotes.cend())
525 remote.Empty();
527 m_ctrlRemoteBranch.GetWindowText(remotebranch);
528 if (!remote.IsEmpty() && !remotebranch.IsEmpty())
529 upstream = _T("remotes/") + remote + _T("/") + remotebranch;
531 if (m_iPullRebase > 0)
533 CAppUtils::RebaseAfterFetch(upstream, m_iPullRebase ? 2 : 0, m_iPullRebase == 2);
534 FillNewRefMap();
535 FetchOutList(true);
537 ShowInCommits(L"HEAD");
539 return;
542 CGitHash remoteBranchHash;
543 g_Git.GetHash(remoteBranchHash, upstream);
544 if (remoteBranchHash == m_oldRemoteHash && !m_oldRemoteHash.IsEmpty() && CMessageBox::ShowCheck(this->GetSafeHwnd(), IDS_REBASE_BRANCH_UNCHANGED, IDS_APPNAME, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _T("OpenRebaseRemoteBranchUnchanged"), IDS_MSGBOX_DONOTSHOWAGAIN) == IDNO)
546 ShowInCommits(upstream);
547 return;
550 if (g_Git.IsFastForward(_T("HEAD"), upstream))
552 UINT ret = CMessageBox::ShowCheck(GetSafeHwnd(), IDS_REBASE_BRANCH_FF, IDS_APPNAME, 2, IDI_QUESTION, IDS_MERGEBUTTON, IDS_REBASEBUTTON, IDS_ABORTBUTTON, L"OpenRebaseRemoteBranchFastForwards", IDS_MSGBOX_DONOTSHOWAGAIN);
553 if (ret == 3)
554 return;
555 if (ret == 1)
557 CProgressDlg mergeProgress;
558 mergeProgress.m_GitCmd = _T("git.exe merge --ff-only ") + upstream;
559 mergeProgress.m_AutoClose = AUTOCLOSE_IF_NO_ERRORS;
560 mergeProgress.m_PostCmdCallback = [](DWORD status, PostCmdList& postCmdList)
562 if (status && g_Git.HasWorkingTreeConflicts())
564 // there are conflict files
565 postCmdList.emplace_back(IDI_RESOLVE, IDS_PROGRS_CMD_RESOLVE, []
567 CString sCmd;
568 sCmd.Format(_T("/command:commit /path:\"%s\""), g_Git.m_CurrentDir);
569 CAppUtils::RunTortoiseGitProc(sCmd);
573 mergeProgress.DoModal();
574 FillNewRefMap();
575 FetchOutList(true);
577 ShowInCommits(L"HEAD");
579 return;
583 CAppUtils::RebaseAfterFetch(upstream);
584 FillNewRefMap();
585 FetchOutList(true);
587 ShowInCommits(L"HEAD");
590 void CSyncDlg::StashComplete()
592 EnableControlButton(true);
593 INT_PTR entry = m_ctrlStash.GetCurrentEntry();
594 if (entry != 1 && entry != 2)
595 return;
597 SwitchToInput();
598 if (m_GitCmdStatus)
600 int hasConflicts = g_Git.HasWorkingTreeConflicts();
601 if (hasConflicts < 0)
603 m_ctrlCmdOut.SetSel(-1, -1);
604 m_ctrlCmdOut.ReplaceSel(g_Git.GetGitLastErr(L"Checking for conflicts failed.", CGit::GIT_CMD_CHECKCONFLICTS));
606 ShowTab(IDC_CMD_LOG);
607 return;
610 if (hasConflicts)
612 m_ConflictFileList.Clear();
613 CTGitPathList list;
614 CTGitPath path;
615 list.AddPath(path);
617 m_ConflictFileList.GetStatus(&list,true);
618 m_ConflictFileList.Show(CTGitPath::LOGACTIONS_UNMERGED, CTGitPath::LOGACTIONS_UNMERGED);
620 ShowTab(IDC_IN_CONFLICT);
622 else
623 ShowTab(IDC_CMD_LOG);
627 void CSyncDlg::OnBnClickedButtonPush()
629 this->UpdateData();
630 UpdateCombox();
631 m_ctrlCmdOut.SetWindowTextW(_T(""));
632 m_LogText.Empty();
634 if(this->m_strURL.IsEmpty())
636 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_GITCONFIG_URLEMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
637 return;
640 if (!IsURL() && m_ctrlPush.GetCurrentEntry() == 0 && CRegDWORD(L"Software\\TortoiseGit\\AskSetTrackedBranch", TRUE) == TRUE)
642 if (!AskSetTrackedBranch())
643 return;
646 this->m_regPushButton=(DWORD)this->m_ctrlPush.GetCurrentEntry();
647 this->SwitchToRun();
648 this->m_bAbort=false;
649 this->m_GitCmdList.clear();
651 ShowTab(IDC_CMD_LOG);
653 CString cmd;
654 CString arg;
656 CString error;
657 DWORD exitcode = 0xFFFFFFFF;
658 if (CHooks::Instance().PrePush(g_Git.m_CurrentDir, exitcode, error))
660 if (exitcode)
662 CString temp;
663 temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);
664 CMessageBox::Show(GetSafeHwnd(), temp, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
665 return ;
669 CString refName = g_Git.FixBranchName(m_strLocalBranch);
670 switch (m_ctrlPush.GetCurrentEntry())
672 case 1:
673 arg += _T(" --tags");
674 break;
675 case 2:
676 refName = _T("refs/notes/commits"); //default ref for notes
677 break;
680 if(this->m_bForce)
681 arg += _T(" --force");
683 cmd.Format(_T("git.exe push -v --progress%s \"%s\" %s"),
684 (LPCTSTR)arg,
685 (LPCTSTR)m_strURL,
686 (LPCTSTR)refName);
688 if (!m_strRemoteBranch.IsEmpty() && m_ctrlPush.GetCurrentEntry() != 2)
690 cmd += _T(":") + m_strRemoteBranch;
693 m_GitCmdList.push_back(cmd);
695 m_CurrentCmd = GIT_COMMAND_PUSH;
697 if(this->m_bAutoLoadPuttyKey)
699 CAppUtils::LaunchPAgent(nullptr, &m_strURL);
702 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
703 if (!m_pThread)
705 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
707 else
709 m_pThread->m_bAutoDelete = TRUE;
710 m_pThread->ResumeThread();
714 void CSyncDlg::OnBnClickedButtonApply()
716 CGitHash oldhash;
717 if (g_Git.GetHash(oldhash, _T("HEAD")))
719 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR);
720 return;
723 CImportPatchDlg dlg;
724 CString cmd,output;
726 if(dlg.DoModal() == IDOK)
728 int err=0;
729 for (int i = 0; i < dlg.m_PathList.GetCount(); ++i)
731 cmd.Format(_T("git.exe am \"%s\""), (LPCTSTR)dlg.m_PathList[i].GetGitPathString());
733 if (g_Git.Run(cmd, &output, CP_UTF8))
735 CMessageBox::Show(GetSafeHwnd(), output, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
737 err=1;
738 break;
740 this->m_ctrlCmdOut.SetSel(-1,-1);
741 this->m_ctrlCmdOut.ReplaceSel(cmd+_T("\n"));
742 this->m_ctrlCmdOut.SetSel(-1,-1);
743 this->m_ctrlCmdOut.ReplaceSel(output);
746 CGitHash newhash;
747 if (g_Git.GetHash(newhash, _T("HEAD")))
749 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash after applying patches.")), _T("TortoiseGit"), MB_ICONERROR);
750 return;
753 this->m_InLogList.Clear();
754 this->m_InChangeFileList.Clear();
756 if(newhash == oldhash)
758 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
759 this->m_InLogList.ShowText(_T("No commits get from patch"));
760 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true);
763 else
765 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,true);
766 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true);
768 CString range;
769 range.Format(_T("%s..%s"), (LPCTSTR)m_oldHash.ToString(), (LPCTSTR)newhash.ToString());
770 this->AddDiffFileList(&m_InChangeFileList, &m_arInChangeList, newhash.ToString(), oldhash.ToString());
771 m_InLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
773 this->FetchOutList(true);
776 this->m_ctrlTabCtrl.ShowTab(IDC_CMD_LOG-1,true);
778 if(err)
780 this->ShowTab(IDC_CMD_LOG);
782 else
784 this->ShowTab(IDC_IN_LOGLIST);
789 void CSyncDlg::OnBnClickedButtonEmail()
791 CString cmd, out, err;
793 this->m_strLocalBranch = this->m_ctrlLocalBranch.GetString();
794 this->m_ctrlRemoteBranch.GetWindowText(this->m_strRemoteBranch);
795 this->m_ctrlURL.GetWindowText(this->m_strURL);
796 m_strURL=m_strURL.Trim();
797 m_strRemoteBranch=m_strRemoteBranch.Trim();
799 cmd.Format(_T("git.exe format-patch -o \"%s\" %s..%s"),
800 (LPCTSTR)g_Git.m_CurrentDir,
801 (LPCTSTR)(m_strURL + _T('/') + m_strRemoteBranch), (LPCTSTR)g_Git.FixBranchName(m_strLocalBranch));
803 if (g_Git.Run(cmd, &out, &err, CP_UTF8))
805 CMessageBox::Show(GetSafeHwnd(), out + L"\n" + err, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
806 return ;
809 CAppUtils::SendPatchMail(cmd,out);
811 void CSyncDlg::ShowProgressCtrl(bool bShow)
813 int b=bShow?SW_NORMAL:SW_HIDE;
814 this->m_ctrlAnimate.ShowWindow(b);
815 this->m_ctrlProgress.ShowWindow(b);
816 this->m_ctrlProgLabel.ShowWindow(b);
817 this->m_ctrlAnimate.Open(IDR_DOWNLOAD);
818 if(b == SW_NORMAL)
819 this->m_ctrlAnimate.Play(0, UINT_MAX, UINT_MAX);
820 else
821 this->m_ctrlAnimate.Stop();
823 void CSyncDlg::ShowInputCtrl(bool bShow)
825 int b=bShow?SW_NORMAL:SW_HIDE;
826 this->m_ctrlURL.ShowWindow(b);
827 this->m_ctrlLocalBranch.ShowWindow(b);
828 this->m_ctrlRemoteBranch.ShowWindow(b);
829 this->GetDlgItem(IDC_BUTTON_LOCAL_BRANCH)->ShowWindow(b);
830 this->GetDlgItem(IDC_BUTTON_REMOTE_BRANCH)->ShowWindow(b);
831 this->GetDlgItem(IDC_STATIC_LOCAL_BRANCH)->ShowWindow(b);
832 this->GetDlgItem(IDC_STATIC_REMOTE_BRANCH)->ShowWindow(b);
833 this->GetDlgItem(IDC_BUTTON_MANAGE)->ShowWindow(b);
834 this->GetDlgItem(IDC_CHECK_PUTTY_KEY)->ShowWindow(b);
835 this->GetDlgItem(IDC_CHECK_FORCE)->ShowWindow(b);
836 this->GetDlgItem(IDC_STATIC_REMOTE_URL)->ShowWindow(b);
838 BOOL CSyncDlg::OnInitDialog()
840 CResizableStandAloneDialog::OnInitDialog();
841 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
843 // Let the TaskbarButtonCreated message through the UIPI filter. If we don't
844 // do this, Explorer would be unable to send that message to our window if we
845 // were running elevated. It's OK to make the call all the time, since if we're
846 // not elevated, this is a no-op.
847 CHANGEFILTERSTRUCT cfs = { sizeof(CHANGEFILTERSTRUCT) };
848 typedef BOOL STDAPICALLTYPE ChangeWindowMessageFilterExDFN(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct);
849 CAutoLibrary hUser = AtlLoadSystemLibraryUsingFullPath(_T("user32.dll"));
850 if (hUser)
852 ChangeWindowMessageFilterExDFN *pfnChangeWindowMessageFilterEx = (ChangeWindowMessageFilterExDFN*)GetProcAddress(hUser, "ChangeWindowMessageFilterEx");
853 if (pfnChangeWindowMessageFilterEx)
855 pfnChangeWindowMessageFilterEx(m_hWnd, TaskBarButtonCreated, MSGFLT_ALLOW, &cfs);
858 m_pTaskbarList.Release();
859 if (FAILED(m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList)))
860 m_pTaskbarList = nullptr;
862 this->GetDlgItem(IDC_CHECK_PUTTY_KEY)->EnableWindow(CAppUtils::IsSSHPutty());
865 this->m_ctrlAnimate.ShowWindow(SW_NORMAL);
866 this->m_ctrlAnimate.Open(IDR_DOWNLOAD);
867 this->m_ctrlAnimate.Play(0,-1,-1);
870 // ------------------ Create Tabctrl -----------
871 CWnd *pwnd=this->GetDlgItem(IDC_BUTTON_TABCTRL);
872 CRect rectDummy;
873 pwnd->GetWindowRect(&rectDummy);
874 this->ScreenToClient(rectDummy);
876 if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_SYNC_TAB))
878 TRACE0("Failed to create output tab window\n");
879 return FALSE; // fail to create
881 m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);
883 // -------------Create Command Log Ctrl ---------
884 DWORD dwStyle;
885 dwStyle= ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL |WS_VSCROLL ;
887 if( !m_ctrlCmdOut.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_CMD_LOG))
889 TRACE0("Failed to create Log commits window\n");
890 return FALSE; // fail to create
893 // set the font to use in the log message view, configured in the settings dialog
894 CFont m_logFont;
895 CAppUtils::CreateFontForLogs(m_logFont);
896 //GetDlgItem(IDC_CMD_LOG)->SetFont(&m_logFont);
897 m_ctrlCmdOut.SetFont(&m_logFont);
898 m_ctrlTabCtrl.InsertTab(&m_ctrlCmdOut, CString(MAKEINTRESOURCE(IDS_LOG)), -1);
900 //m_ctrlCmdOut.ReplaceSel(_T("Hello"));
902 //---------- Create in coming list ctrl -----------
903 dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;;
905 if( !m_InLogList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_IN_LOGLIST))
907 TRACE0("Failed to create output commits window\n");
908 return FALSE; // fail to create
911 m_ctrlTabCtrl.InsertTab(&m_InLogList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_INCOMMITS)), -1);
913 m_InLogList.m_ColumnRegKey=_T("SyncIn");
914 m_InLogList.InsertGitColumn();
916 //----------- Create In Change file list -----------
917 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;
919 if( !m_InChangeFileList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_IN_CHANGELIST))
921 TRACE0("Failed to create output change files window\n");
922 return FALSE; // fail to create
924 m_ctrlTabCtrl.InsertTab(&m_InChangeFileList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_INCHANGELIST)), -1);
926 m_InChangeFileList.Init(GITSLC_COLEXT | GITSLC_COLSTATUS |GITSLC_COLADD|GITSLC_COLDEL , _T("InSyncDlg"),
927 (CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWOREVISIONS) |
928 CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF2REVISIONS)), false, true, GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD| GITSLC_COLDEL);
931 //---------- Create Conflict List Ctrl -----------------
932 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;
934 if( !m_ConflictFileList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_IN_CONFLICT))
936 TRACE0("Failed to create output change files window\n");
937 return FALSE; // fail to create
939 m_ctrlTabCtrl.InsertTab(&m_ConflictFileList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_CONFLICTS)), -1);
941 m_ConflictFileList.Init(GITSLC_COLEXT | GITSLC_COLSTATUS |GITSLC_COLADD|GITSLC_COLDEL , _T("ConflictSyncDlg"),
942 (CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWOREVISIONS) |
943 CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF2REVISIONS) |
944 GITSLC_POPCONFLICT|GITSLC_POPRESOLVE),false);
947 //---------- Create Commit Out List Ctrl---------------
949 dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;;
951 if( !m_OutLogList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_OUT_LOGLIST))
953 TRACE0("Failed to create output commits window\n");
954 return FALSE; // fail to create
958 m_ctrlTabCtrl.InsertTab(&m_OutLogList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_OUTCOMMITS)), -1);
960 m_OutLogList.m_ColumnRegKey = _T("SyncOut");
961 m_OutLogList.InsertGitColumn();
963 //------------- Create Change File List Control ----------------
965 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;
967 if( !m_OutChangeFileList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_OUT_CHANGELIST))
969 TRACE0("Failed to create output change files window\n");
970 return FALSE; // fail to create
972 m_ctrlTabCtrl.InsertTab(&m_OutChangeFileList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_OUTCHANGELIST)), -1);
974 m_OutChangeFileList.Init(GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD | GITSLC_COLDEL, _T("OutSyncDlg"),
975 (CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWOREVISIONS) |
976 CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF2REVISIONS)), false, true, GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD | GITSLC_COLDEL);
978 if (!m_GitProgressList.Create(dwStyle | LVS_OWNERDATA, rectDummy, &m_ctrlTabCtrl, IDC_CMD_GIT_PROG))
980 TRACE0("Failed to create Git Progress List Window\n");
981 return FALSE; // fail to create
983 m_ctrlTabCtrl.InsertTab(&m_GitProgressList, CString(MAKEINTRESOURCE(IDS_LOG)), -1);
984 m_GitProgressList.m_pAnimate = &m_ctrlAnimate;
985 m_GitProgressList.m_pPostWnd = this;
986 m_GitProgressList.m_pProgressLabelCtrl = &m_ctrlProgLabel;
987 m_GitProgressList.m_pProgControl = &m_ctrlProgress;
988 m_GitProgressList.m_pTaskbarList = m_pTaskbarList;
990 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;
991 DWORD exStyle = LVS_EX_HEADERDRAGDROP | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP;
992 if (CRegDWORD(L"Software\\TortoiseGit\\FullRowSelect", TRUE))
993 exStyle |= LVS_EX_FULLROWSELECT;
994 if (g_Git.m_IsUseLibGit2)
996 m_refList.Create(dwStyle, rectDummy, &m_ctrlTabCtrl, IDC_REFLIST);
997 m_refList.SetExtendedStyle(exStyle);
998 m_refList.Init();
999 m_ctrlTabCtrl.InsertTab(&m_refList, CString(MAKEINTRESOURCE(IDS_REFLIST)), -1);
1002 AddAnchor(IDC_SYNC_TAB,TOP_LEFT,BOTTOM_RIGHT);
1004 AddAnchor(IDC_GROUP_INFO,TOP_LEFT,TOP_RIGHT);
1005 AddAnchor(IDC_COMBOBOXEX_URL,TOP_LEFT,TOP_RIGHT);
1006 AddAnchor(IDC_BUTTON_MANAGE,TOP_RIGHT);
1007 AddAnchor(IDC_BUTTON_PULL,BOTTOM_LEFT);
1008 AddAnchor(IDC_BUTTON_PUSH,BOTTOM_LEFT);
1009 AddAnchor(IDC_BUTTON_SUBMODULE,BOTTOM_LEFT);
1010 AddAnchor(IDC_BUTTON_STASH,BOTTOM_LEFT);
1011 AddAnchor(IDC_BUTTON_APPLY,BOTTOM_RIGHT);
1012 AddAnchor(IDC_BUTTON_EMAIL,BOTTOM_RIGHT);
1013 AddAnchor(IDC_PROGRESS_SYNC,TOP_LEFT,TOP_RIGHT);
1014 AddAnchor(IDOK,BOTTOM_RIGHT);
1015 AddAnchor(IDHELP,BOTTOM_RIGHT);
1016 AddAnchor(IDC_STATIC_STATUS, BOTTOM_LEFT, BOTTOM_RIGHT);
1017 AddAnchor(IDC_ANIMATE_SYNC,TOP_LEFT);
1018 AddAnchor(IDC_BUTTON_COMMIT,BOTTOM_LEFT);
1019 AddAnchor(IDC_LOG, BOTTOM_LEFT);
1021 // do not use BRANCH_COMBOX_ADD_ANCHOR here, we want to have different stylings
1022 AddAnchor(IDC_COMBOBOXEX_LOCAL_BRANCH, TOP_LEFT,TOP_CENTER);
1023 AddAnchor(IDC_COMBOBOXEX_REMOTE_BRANCH, TOP_CENTER, TOP_RIGHT);
1024 AddAnchor(IDC_BUTTON_LOCAL_BRANCH, TOP_CENTER);
1025 AddAnchor(IDC_BUTTON_REMOTE_BRANCH, TOP_RIGHT);
1026 AddAnchor(IDC_STATIC_REMOTE_BRANCH, TOP_CENTER);
1027 AddAnchor(IDC_PROG_LABEL, TOP_LEFT);
1029 AdjustControlSize(IDC_CHECK_PUTTY_KEY);
1030 AdjustControlSize(IDC_CHECK_FORCE);
1032 CString WorkingDir=g_Git.m_CurrentDir;
1033 WorkingDir.Replace(_T(':'),_T('_'));
1034 m_RegKeyRemoteBranch = CString(_T("Software\\TortoiseGit\\History\\SyncBranch\\"))+WorkingDir;
1037 this->AddOthersToAnchor();
1039 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSH)));
1040 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSHTAGS)));
1041 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSHNOTES)));
1043 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PULL)));
1044 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCH)));
1045 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCHREBASE)));
1046 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCHALL)));
1047 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_REMOTEUPDATE)));
1048 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_CLEANUPSTALEBRANCHES)));
1050 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULEUPDATE)));
1051 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULEINIT)));
1052 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULESYNC)));
1054 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHSAVE)));
1055 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHPOP)));
1056 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHAPPLY)));
1058 WorkingDir.Replace(_T(':'),_T('_'));
1060 CString regkey ;
1061 regkey.Format(_T("Software\\TortoiseGit\\TortoiseProc\\Sync\\%s"), (LPCTSTR)WorkingDir);
1063 this->m_regPullButton = CRegDWORD(regkey+_T("\\Pull"),0);
1064 this->m_regPushButton = CRegDWORD(regkey+_T("\\Push"),0);
1065 this->m_regSubmoduleButton = CRegDWORD(regkey+_T("\\Submodule"));
1066 this->m_regAutoLoadPutty = CRegDWORD(regkey + _T("\\AutoLoadPutty"), CAppUtils::IsSSHPutty());
1068 this->UpdateData();
1069 this->m_bAutoLoadPuttyKey = m_regAutoLoadPutty;
1070 if(!CAppUtils::IsSSHPutty())
1071 m_bAutoLoadPuttyKey = false;
1072 this->UpdateData(FALSE);
1074 this->m_ctrlPull.SetCurrentEntry(this->m_regPullButton);
1075 this->m_ctrlPush.SetCurrentEntry(this->m_regPushButton);
1076 this->m_ctrlSubmodule.SetCurrentEntry(this->m_regSubmoduleButton);
1078 CString sWindowTitle;
1079 GetWindowText(sWindowTitle);
1080 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
1082 EnableSaveRestore(_T("SyncDlg"));
1084 m_ctrlURL.SetCaseSensitive(TRUE);
1085 m_ctrlURL.SetURLHistory(true);
1086 m_ctrlURL.SetMaxHistoryItems(0x7FFFFFFF);
1087 this->m_ctrlURL.LoadHistory(CString(_T("Software\\TortoiseGit\\History\\SyncURL\\"))+WorkingDir, _T("url"));
1089 STRING_VECTOR list;
1091 if(!g_Git.GetRemoteList(list))
1093 for (unsigned int i = 0; i < list.size(); ++i)
1095 m_ctrlURL.AddString(list[i]);
1098 m_ctrlURL.SetCurSel(0);
1099 m_ctrlRemoteBranch.SetCurSel(0);
1101 this->LoadBranchInfo();
1103 this->m_bInited=true;
1104 FetchOutList();
1106 m_ctrlTabCtrl.ShowTab(IDC_CMD_LOG-1,false);
1107 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,false);
1108 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
1109 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT-1,false);
1110 m_ctrlTabCtrl.ShowTab(IDC_CMD_GIT_PROG-1, false);
1111 m_ctrlTabCtrl.ShowTab(IDC_REFLIST-1, false);
1113 m_ctrlRemoteBranch.m_bWantReturn = TRUE;
1114 m_ctrlURL.m_bWantReturn = TRUE;
1116 if (m_seq > 0 && (DWORD)CRegDWORD(_T("Software\\TortoiseGit\\SyncDialogRandomPos")))
1118 m_seq %= 5;
1119 RECT rect;
1120 GetWindowRect(&rect);
1121 rect.top -= m_seq * 30;
1122 rect.bottom -= m_seq * 30;
1123 if (rect.top < 0)
1125 rect.top += 150;
1126 rect.bottom += 150;
1128 MoveWindow(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
1131 return TRUE; // return TRUE unless you set the focus to a control
1132 // EXCEPTION: OCX Property Pages should return FALSE
1135 void CSyncDlg::OnBnClickedButtonManage()
1137 CAppUtils::LaunchRemoteSetting();
1138 Refresh();
1141 void CSyncDlg::Refresh()
1143 theApp.DoWaitCursor(1);
1145 int lastSelected = m_ctrlURL.GetCurSel();
1146 CString url;
1147 this->m_ctrlURL.GetWindowText(url);
1149 this->m_ctrlURL.Reset();
1150 CString workingDir = g_Git.m_CurrentDir;
1151 workingDir.Replace(_T(':'), _T('_'));
1152 this->m_ctrlURL.LoadHistory(_T("Software\\TortoiseGit\\History\\SyncURL\\") + workingDir, _T("url"));
1154 STRING_VECTOR list;
1155 bool found = false;
1156 if (!g_Git.GetRemoteList(list))
1158 for (size_t i = 0; i < list.size(); ++i)
1160 m_ctrlURL.AddString(list[i]);
1161 if (list[i] == url)
1162 found = true;
1165 if (lastSelected >= 0 && !found)
1167 m_ctrlURL.SetCurSel(0);
1168 m_ctrlURL.GetWindowText(url);
1171 CString local;
1172 CString remote;
1173 this->m_ctrlLocalBranch.GetWindowText(local);
1174 this->m_ctrlRemoteBranch.GetWindowText(remote);
1176 this->LoadBranchInfo();
1178 this->m_ctrlLocalBranch.AddString(local);
1179 this->m_ctrlRemoteBranch.AddString(remote);
1180 this->m_ctrlURL.AddString(url);
1182 m_OutLogList.ShowText(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_REFRESHING)));
1183 this->FetchOutList(true);
1184 theApp.DoWaitCursor(-1);
1187 BOOL CSyncDlg::PreTranslateMessage(MSG* pMsg)
1189 if (pMsg->message == WM_KEYDOWN)
1191 switch (pMsg->wParam)
1193 case VK_F5:
1195 if (m_bBlock)
1196 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
1197 Refresh();
1199 break;
1201 /* Avoid TAB control destroy but dialog exist*/
1202 case VK_ESCAPE:
1203 case VK_CANCEL:
1205 TCHAR buff[128] = { 0 };
1206 ::GetClassName(pMsg->hwnd,buff,128);
1208 /* Use MSFTEDIT_CLASS http://msdn.microsoft.com/en-us/library/bb531344.aspx */
1209 if (_tcsnicmp(buff, MSFTEDIT_CLASS, 128) == 0 || //Unicode and MFC 2012 and later
1210 _tcsnicmp(buff, RICHEDIT_CLASS, 128) == 0 || //ANSI or MFC 2010
1211 _tcsnicmp(buff, _T("SysListView32"), 128) == 0)
1213 this->PostMessage(WM_KEYDOWN,VK_ESCAPE,0);
1214 return TRUE;
1219 return __super::PreTranslateMessage(pMsg);
1221 void CSyncDlg::FetchOutList(bool force)
1223 if(!m_bInited)
1224 return;
1225 m_OutChangeFileList.Clear();
1226 this->m_OutLogList.Clear();
1228 CString remote;
1229 this->m_ctrlURL.GetWindowText(remote);
1230 CString remotebranch;
1231 this->m_ctrlRemoteBranch.GetWindowText(remotebranch);
1232 remotebranch=remote+_T("/")+remotebranch;
1233 CGitHash remotebranchHash;
1234 g_Git.GetHash(remotebranchHash, remotebranch);
1236 if(IsURL())
1238 CString str;
1239 str.LoadString(IDS_PROC_SYNC_PUSH_UNKNOWN);
1240 m_OutLogList.ShowText(str);
1241 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1242 m_OutLocalBranch.Empty();
1243 m_OutRemoteBranch.Empty();
1245 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1246 return ;
1249 else if(remotebranchHash.IsEmpty())
1251 CString str;
1252 str.Format(IDS_PROC_SYNC_PUSH_UNKNOWNBRANCH, (LPCTSTR)remotebranch);
1253 m_OutLogList.ShowText(str);
1254 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1255 m_OutLocalBranch.Empty();
1256 m_OutRemoteBranch.Empty();
1258 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1259 return ;
1261 else
1263 CString localbranch;
1264 localbranch=this->m_ctrlLocalBranch.GetString();
1266 if(localbranch != m_OutLocalBranch || m_OutRemoteBranch != remotebranch || force)
1268 m_OutLogList.ClearText();
1270 CGitHash base, localBranchHash;
1271 bool isFastForward = g_Git.IsFastForward(remotebranch, localbranch, &base);
1273 if (g_Git.GetHash(localBranchHash, localbranch))
1275 MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + localbranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
1276 return;
1278 if (remotebranchHash == localBranchHash)
1280 CString str;
1281 str.Format(IDS_PROC_SYNC_COMMITSAHEAD, 0, (LPCTSTR)remotebranch);
1282 m_OutLogList.ShowText(str);
1283 this->m_ctrlStatus.SetWindowText(str);
1284 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1285 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1287 else if (isFastForward || m_bForce)
1289 CString range;
1290 range.Format(_T("%s..%s"), (LPCTSTR)g_Git.FixBranchName(remotebranch), (LPCTSTR)g_Git.FixBranchName(localbranch));
1291 //fast forward
1292 m_OutLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT | CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
1293 CString str;
1294 str.Format(IDS_PROC_SYNC_COMMITSAHEAD, m_OutLogList.GetItemCount(), (LPCTSTR)remotebranch);
1295 this->m_ctrlStatus.SetWindowText(str);
1297 if (isFastForward)
1298 AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, remotebranch);
1299 else
1301 AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, base.ToString());
1304 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,TRUE);
1305 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(TRUE);
1307 else
1309 CString str;
1310 str.Format(IDS_PROC_SYNC_NOFASTFORWARD, (LPCTSTR)localbranch, (LPCTSTR)remotebranch);
1311 m_OutLogList.ShowText(str);
1312 this->m_ctrlStatus.SetWindowText(str);
1313 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID() - 1, FALSE);
1314 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1317 this->m_OutLocalBranch=localbranch;
1318 this->m_OutRemoteBranch=remotebranch;
1322 bool CSyncDlg::IsURL()
1324 CString str;
1325 this->m_ctrlURL.GetWindowText(str);
1326 if(str.Find(_T('\\'))>=0 || str.Find(_T('/'))>=0)
1327 return true;
1328 else
1329 return false;
1332 void CSyncDlg::OnCbnEditchangeComboboxex()
1334 SetTimer(IDT_INPUT, 1000, nullptr);
1335 this->m_OutLogList.ShowText(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_WAINTINPUT)));
1337 //this->FetchOutList();
1340 UINT CSyncDlg::ProgressThread()
1342 m_startTick = GetTickCount64();
1343 m_bDone = false;
1344 STRING_VECTOR list;
1345 CProgressDlg::RunCmdList(this, m_GitCmdList, list, true, nullptr, &this->m_bAbort, &this->m_Databuf);
1346 InterlockedExchange(&m_bBlock, FALSE);
1347 return 0;
1350 LRESULT CSyncDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)
1352 if (m_bWantToExit)
1353 return 0;
1354 if(wParam == MSG_PROGRESSDLG_START)
1356 m_BufStart = 0;
1357 m_ctrlAnimate.Play(0, UINT_MAX, UINT_MAX);
1358 this->m_ctrlProgress.SetPos(0);
1359 if (m_pTaskbarList)
1361 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
1362 m_pTaskbarList->SetProgressValue(m_hWnd, 0, 100);
1366 if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)
1368 ULONGLONG tickSpent = GetTickCount64() - m_startTick;
1369 CString strEndTime = CLoglistUtils::FormatDateAndTime(CTime::GetCurrentTime(), DATE_SHORTDATE, true, false);
1371 m_BufStart = 0;
1372 m_Databuf.m_critSec.Lock();
1373 m_Databuf.clear();
1374 m_Databuf.m_critSec.Unlock();
1376 m_bDone = true;
1377 m_ctrlAnimate.Stop();
1378 m_ctrlProgress.SetPos(100);
1379 //this->DialogEnableWindow(IDOK,TRUE);
1381 DWORD exitCode = (DWORD)lParam;
1382 if (exitCode)
1384 if (m_pTaskbarList)
1386 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);
1387 m_pTaskbarList->SetProgressValue(m_hWnd, 100, 100);
1389 CString log;
1390 log.Format(IDS_PROC_PROGRESS_GITUNCLEANEXIT, exitCode);
1391 CString err;
1392 err.Format(_T("\r\n\r\n%s (%I64u ms @ %s)\r\n"), (LPCTSTR)log, tickSpent, (LPCTSTR)strEndTime);
1393 CProgressDlg::InsertColorText(this->m_ctrlCmdOut, err, RGB(255,0,0));
1394 if (CRegDWORD(_T("Software\\TortoiseGit\\NoSounds"), FALSE) == FALSE)
1395 PlaySound((LPCTSTR)SND_ALIAS_SYSTEMEXCLAMATION, nullptr, SND_ALIAS_ID | SND_ASYNC);
1397 else
1399 if (m_pTaskbarList)
1400 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
1401 CString temp;
1402 temp.LoadString(IDS_SUCCESS);
1403 CString log;
1404 log.Format(_T("\r\n%s (%I64u ms @ %s)\r\n"), (LPCTSTR)temp, tickSpent, (LPCTSTR)strEndTime);
1405 CProgressDlg::InsertColorText(this->m_ctrlCmdOut, log, RGB(0,0,255));
1407 m_GitCmdStatus = exitCode;
1409 //if(wParam == MSG_PROGRESSDLG_END)
1410 RunPostAction();
1413 if(lParam != 0)
1414 ParserCmdOutput((char)lParam);
1415 else
1417 m_Databuf.m_critSec.Lock();
1418 for (size_t i = m_BufStart; i < m_Databuf.size(); ++i)
1420 char c = m_Databuf[m_BufStart];
1421 ++m_BufStart;
1422 m_Databuf.m_critSec.Unlock();
1423 ParserCmdOutput(c);
1425 m_Databuf.m_critSec.Lock();
1428 if (m_BufStart > 1000)
1430 m_Databuf.erase(m_Databuf.cbegin(), m_Databuf.cbegin() + m_BufStart);
1431 m_BufStart = 0;
1433 m_Databuf.m_critSec.Unlock();
1436 return 0;
1439 static std::map<CString, CGitHash> * HashMapToRefMap(MAP_HASH_NAME &map)
1441 auto rmap = new std::map<CString, CGitHash>();
1442 for (auto mit = map.cbegin(); mit != map.cend(); ++mit)
1444 for (auto rit = mit->second.cbegin(); rit != mit->second.cend(); ++rit)
1446 rmap->insert(std::make_pair(*rit, mit->first));
1449 return rmap;
1452 void CSyncDlg::FillNewRefMap()
1454 m_refList.Clear();
1455 m_newHashMap.clear();
1457 if (!g_Git.m_IsUseLibGit2)
1458 return;
1460 CAutoRepository repo(g_Git.GetGitRepository());
1461 if (!repo)
1463 CMessageBox::Show(m_hWnd, CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
1464 return;
1467 if (CGit::GetMapHashToFriendName(repo, m_newHashMap))
1469 MessageBox(CGit::GetLibGit2LastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR);
1470 return;
1473 auto oldRefMap = HashMapToRefMap(m_oldHashMap);
1474 auto newRefMap = HashMapToRefMap(m_newHashMap);
1475 for (auto oit = oldRefMap->cbegin(); oit != oldRefMap->cend(); ++oit)
1477 bool found = false;
1478 for (auto nit = newRefMap->cbegin(); nit != newRefMap->cend(); ++nit)
1480 // changed ref
1481 if (oit->first == nit->first)
1483 found = true;
1484 m_refList.AddEntry(repo, oit->first, &oit->second, &nit->second);
1485 break;
1488 // deleted ref
1489 if (!found)
1490 m_refList.AddEntry(repo, oit->first, &oit->second, nullptr);
1492 for (auto nit = newRefMap->cbegin(); nit != newRefMap->cend(); ++nit)
1494 bool found = false;
1495 for (auto oit = oldRefMap->cbegin(); oit != oldRefMap->cend(); ++oit)
1497 if (oit->first == nit->first)
1499 found = true;
1500 break;
1503 // new ref
1504 if (!found)
1505 m_refList.AddEntry(repo, nit->first, nullptr, &nit->second);
1507 delete oldRefMap;
1508 delete newRefMap;
1509 m_refList.Show();
1512 void CSyncDlg::RunPostAction()
1514 if (m_bWantToExit)
1515 return;
1517 FillNewRefMap();
1519 if (this->m_CurrentCmd == GIT_COMMAND_PUSH)
1521 DWORD exitcode = 0xFFFFFFFF;
1522 CString error;
1523 if (CHooks::Instance().PostPush(g_Git.m_CurrentDir, exitcode, error))
1525 if (exitcode)
1527 CString temp;
1528 temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);
1529 CMessageBox::Show(GetSafeHwnd(), temp, L"TortoiseGit", MB_OK | MB_ICONERROR);
1530 return;
1534 EnableControlButton(true);
1535 SwitchToInput();
1536 this->FetchOutList(true);
1538 else if (this->m_CurrentCmd == GIT_COMMAND_PULL)
1539 PullComplete();
1540 else if (this->m_CurrentCmd == GIT_COMMAND_FETCH || this->m_CurrentCmd == GIT_COMMAND_FETCHANDREBASE)
1541 FetchComplete();
1542 else if (this->m_CurrentCmd == GIT_COMMAND_SUBMODULE)
1544 //this->m_ctrlCmdOut.SetSel(-1,-1);
1545 //this->m_ctrlCmdOut.ReplaceSel(_T("Done\r\n"));
1546 //this->m_ctrlCmdOut.SetSel(-1,-1);
1547 EnableControlButton(true);
1548 SwitchToInput();
1550 else if (this->m_CurrentCmd == GIT_COMMAND_STASH)
1551 StashComplete();
1552 else if (this->m_CurrentCmd == GIT_COMMAND_REMOTE)
1554 this->FetchOutList(true);
1555 EnableControlButton(true);
1556 SwitchToInput();
1557 ShowTab(IDC_REFLIST);
1560 void CSyncDlg::ParserCmdOutput(char ch)
1562 if (m_bAbort)
1563 return;
1564 CProgressDlg::ParserCmdOutput(m_ctrlCmdOut,m_ctrlProgress,m_hWnd,m_pTaskbarList,m_LogText,ch);
1566 void CSyncDlg::OnBnClickedButtonCommit()
1568 CString cmd = _T("/command:commit");
1569 cmd += _T(" /path:\"");
1570 cmd += g_Git.m_CurrentDir;
1571 cmd += _T("\"");
1573 CAppUtils::RunTortoiseGitProc(cmd);
1576 void CSyncDlg::OnOK()
1578 UpdateCombox();
1579 this->UpdateData();
1580 m_ctrlURL.SaveHistory();
1581 SaveHistory();
1582 m_regAutoLoadPutty = this->m_bAutoLoadPuttyKey;
1583 m_tooltips.Pop();
1584 __super::OnOK();
1587 void CSyncDlg::OnCancel()
1589 m_bAbort = true;
1590 m_GitProgressList.Cancel();
1591 if (m_bDone && !m_GitProgressList.IsRunning())
1593 CResizableStandAloneDialog::OnCancel();
1594 return;
1596 if (m_GitProgressList.IsRunning())
1597 WaitForSingleObject(m_GitProgressList.m_pThread->m_hThread, 10000);
1599 if (g_Git.m_CurrentGitPi.hProcess)
1601 DWORD dwConfirmKillProcess = CRegDWORD(_T("Software\\TortoiseGit\\ConfirmKillProcess"));
1602 if (dwConfirmKillProcess && CMessageBox::Show(m_hWnd, IDS_PROC_CONFIRMKILLPROCESS, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION) != IDYES)
1603 return;
1604 if (::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
1605 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess, 10000);
1606 else
1607 GetLastError();
1609 CProgressDlg::KillProcessTree(g_Git.m_CurrentGitPi.dwProcessId);
1612 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
1613 if (m_pThread)
1615 if (::WaitForSingleObject(m_pThread->m_hThread, 5000) == WAIT_TIMEOUT)
1616 g_Git.KillRelatedThreads(m_pThread);
1618 m_tooltips.Pop();
1619 CResizableStandAloneDialog::OnCancel();
1622 void CSyncDlg::OnBnClickedButtonSubmodule()
1624 this->UpdateData();
1625 UpdateCombox();
1626 m_ctrlCmdOut.SetWindowTextW(_T(""));
1627 m_LogText.Empty();
1629 this->m_regSubmoduleButton = (DWORD)this->m_ctrlSubmodule.GetCurrentEntry();
1631 this->SwitchToRun();
1633 this->m_bAbort=false;
1634 this->m_GitCmdList.clear();
1636 ShowTab(IDC_CMD_LOG);
1638 CString cmd;
1640 switch (m_ctrlSubmodule.GetCurrentEntry())
1642 case 0:
1643 cmd=_T("git.exe submodule update --init");
1644 break;
1645 case 1:
1646 cmd=_T("git.exe submodule init");
1647 break;
1648 case 2:
1649 cmd=_T("git.exe submodule sync");
1650 break;
1653 m_GitCmdList.push_back(cmd);
1655 m_CurrentCmd = GIT_COMMAND_SUBMODULE;
1657 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
1658 if (!m_pThread)
1660 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
1662 else
1664 m_pThread->m_bAutoDelete = TRUE;
1665 m_pThread->ResumeThread();
1669 void CSyncDlg::OnBnClickedButtonStash()
1671 UpdateData();
1672 UpdateCombox();
1673 m_ctrlCmdOut.SetWindowTextW(_T(""));
1674 m_LogText.Empty();
1676 SwitchToRun();
1678 m_bAbort = false;
1679 m_GitCmdList.clear();
1681 ShowTab(IDC_CMD_LOG);
1683 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST - 1, false);
1684 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST -1, false);
1685 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT -1, false);
1687 CString cmd;
1688 switch (m_ctrlStash.GetCurrentEntry())
1690 case 0:
1691 cmd = _T("git.exe stash save");
1692 break;
1693 case 1:
1694 cmd = _T("git.exe stash pop");
1695 break;
1696 case 2:
1697 cmd = _T("git.exe stash apply");
1698 break;
1701 m_GitCmdList.push_back(cmd);
1702 m_CurrentCmd = GIT_COMMAND_STASH;
1704 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
1705 if (!m_pThread)
1707 //ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
1709 else
1711 m_pThread->m_bAutoDelete = TRUE;
1712 m_pThread->ResumeThread();
1716 void CSyncDlg::OnTimer(UINT_PTR nIDEvent)
1718 if( nIDEvent == IDT_INPUT)
1720 KillTimer(IDT_INPUT);
1721 this->FetchOutList(true);
1726 void CSyncDlg::OnLvnInLogListColumnClick(NMHDR * /* pNMHDR */, LRESULT *pResult)
1728 *pResult = 0;
1731 LRESULT CSyncDlg::OnTaskbarBtnCreated(WPARAM wParam, LPARAM lParam)
1733 m_pTaskbarList.Release();
1734 m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
1735 m_GitProgressList.m_pTaskbarList = m_pTaskbarList;
1736 return __super::OnTaskbarButtonCreated(wParam, lParam);
1739 void CSyncDlg::OnBnClickedCheckForce()
1741 UpdateData();
1744 void CSyncDlg::OnBnClickedLog()
1746 CString cmd = _T("/command:log");
1747 cmd += _T(" /path:\"");
1748 cmd += g_Git.m_CurrentDir;
1749 cmd += _T("\"");
1751 CAppUtils::RunTortoiseGitProc(cmd);
1754 LRESULT CSyncDlg::OnProgCmdFinish(WPARAM /*wParam*/, LPARAM /*lParam*/)
1756 RefreshCursor();
1757 RunPostAction();
1758 return 0;
1761 void CSyncDlg::OnDestroy()
1763 m_bWantToExit = true;
1764 __super::OnDestroy();