Use correct length for buffer
[TortoiseGit.git] / src / TortoiseProc / SyncDlg.cpp
blob2c7f8dffd4ebb5346ffa6499e663db0223aa82e7
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(WM_TASKBARBTNCREATED, 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 = reinterpret_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, WM_TASKBARBTNCREATED, 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 | LVS_EX_FULLROWSELECT;
992 if (g_Git.m_IsUseLibGit2)
994 m_refList.Create(dwStyle, rectDummy, &m_ctrlTabCtrl, IDC_REFLIST);
995 m_refList.SetExtendedStyle(exStyle);
996 m_refList.Init();
997 m_ctrlTabCtrl.InsertTab(&m_refList, CString(MAKEINTRESOURCE(IDS_REFLIST)), -1);
1000 AddAnchor(IDC_SYNC_TAB,TOP_LEFT,BOTTOM_RIGHT);
1002 AddAnchor(IDC_GROUP_INFO,TOP_LEFT,TOP_RIGHT);
1003 AddAnchor(IDC_COMBOBOXEX_URL,TOP_LEFT,TOP_RIGHT);
1004 AddAnchor(IDC_BUTTON_MANAGE,TOP_RIGHT);
1005 AddAnchor(IDC_BUTTON_PULL,BOTTOM_LEFT);
1006 AddAnchor(IDC_BUTTON_PUSH,BOTTOM_LEFT);
1007 AddAnchor(IDC_BUTTON_SUBMODULE,BOTTOM_LEFT);
1008 AddAnchor(IDC_BUTTON_STASH,BOTTOM_LEFT);
1009 AddAnchor(IDC_BUTTON_APPLY,BOTTOM_RIGHT);
1010 AddAnchor(IDC_BUTTON_EMAIL,BOTTOM_RIGHT);
1011 AddAnchor(IDC_PROGRESS_SYNC,TOP_LEFT,TOP_RIGHT);
1012 AddAnchor(IDOK,BOTTOM_RIGHT);
1013 AddAnchor(IDHELP,BOTTOM_RIGHT);
1014 AddAnchor(IDC_STATIC_STATUS, BOTTOM_LEFT, BOTTOM_RIGHT);
1015 AddAnchor(IDC_ANIMATE_SYNC,TOP_LEFT);
1016 AddAnchor(IDC_BUTTON_COMMIT,BOTTOM_LEFT);
1017 AddAnchor(IDC_LOG, BOTTOM_LEFT);
1019 // do not use BRANCH_COMBOX_ADD_ANCHOR here, we want to have different stylings
1020 AddAnchor(IDC_COMBOBOXEX_LOCAL_BRANCH, TOP_LEFT,TOP_CENTER);
1021 AddAnchor(IDC_COMBOBOXEX_REMOTE_BRANCH, TOP_CENTER, TOP_RIGHT);
1022 AddAnchor(IDC_BUTTON_LOCAL_BRANCH, TOP_CENTER);
1023 AddAnchor(IDC_BUTTON_REMOTE_BRANCH, TOP_RIGHT);
1024 AddAnchor(IDC_STATIC_REMOTE_BRANCH, TOP_CENTER);
1025 AddAnchor(IDC_PROG_LABEL, TOP_LEFT);
1027 AdjustControlSize(IDC_CHECK_PUTTY_KEY);
1028 AdjustControlSize(IDC_CHECK_FORCE);
1030 CString WorkingDir=g_Git.m_CurrentDir;
1031 WorkingDir.Replace(_T(':'),_T('_'));
1032 m_RegKeyRemoteBranch = CString(_T("Software\\TortoiseGit\\History\\SyncBranch\\"))+WorkingDir;
1035 this->AddOthersToAnchor();
1037 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSH)));
1038 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSHTAGS)));
1039 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSHNOTES)));
1041 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PULL)));
1042 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCH)));
1043 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCHREBASE)));
1044 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCHALL)));
1045 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_REMOTEUPDATE)));
1046 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_CLEANUPSTALEBRANCHES)));
1048 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULEUPDATE)));
1049 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULEINIT)));
1050 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULESYNC)));
1052 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHSAVE)));
1053 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHPOP)));
1054 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHAPPLY)));
1056 WorkingDir.Replace(_T(':'),_T('_'));
1058 CString regkey ;
1059 regkey.Format(_T("Software\\TortoiseGit\\TortoiseProc\\Sync\\%s"), (LPCTSTR)WorkingDir);
1061 this->m_regPullButton = CRegDWORD(regkey+_T("\\Pull"),0);
1062 this->m_regPushButton = CRegDWORD(regkey+_T("\\Push"),0);
1063 this->m_regSubmoduleButton = CRegDWORD(regkey+_T("\\Submodule"));
1064 this->m_regAutoLoadPutty = CRegDWORD(regkey + _T("\\AutoLoadPutty"), CAppUtils::IsSSHPutty());
1066 this->UpdateData();
1067 this->m_bAutoLoadPuttyKey = m_regAutoLoadPutty;
1068 if(!CAppUtils::IsSSHPutty())
1069 m_bAutoLoadPuttyKey = false;
1070 this->UpdateData(FALSE);
1072 this->m_ctrlPull.SetCurrentEntry(this->m_regPullButton);
1073 this->m_ctrlPush.SetCurrentEntry(this->m_regPushButton);
1074 this->m_ctrlSubmodule.SetCurrentEntry(this->m_regSubmoduleButton);
1076 CString sWindowTitle;
1077 GetWindowText(sWindowTitle);
1078 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
1080 EnableSaveRestore(_T("SyncDlg"));
1082 m_ctrlURL.SetCaseSensitive(TRUE);
1083 m_ctrlURL.SetURLHistory(true);
1084 m_ctrlURL.SetMaxHistoryItems(0x7FFFFFFF);
1085 this->m_ctrlURL.LoadHistory(CString(_T("Software\\TortoiseGit\\History\\SyncURL\\"))+WorkingDir, _T("url"));
1087 STRING_VECTOR list;
1089 if(!g_Git.GetRemoteList(list))
1091 for (unsigned int i = 0; i < list.size(); ++i)
1093 m_ctrlURL.AddString(list[i]);
1096 m_ctrlURL.SetCurSel(0);
1097 m_ctrlRemoteBranch.SetCurSel(0);
1099 this->LoadBranchInfo();
1101 this->m_bInited=true;
1102 FetchOutList();
1104 m_ctrlTabCtrl.ShowTab(IDC_CMD_LOG-1,false);
1105 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,false);
1106 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
1107 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT-1,false);
1108 m_ctrlTabCtrl.ShowTab(IDC_CMD_GIT_PROG-1, false);
1109 m_ctrlTabCtrl.ShowTab(IDC_REFLIST-1, false);
1111 m_ctrlRemoteBranch.m_bWantReturn = TRUE;
1112 m_ctrlURL.m_bWantReturn = TRUE;
1114 if (m_seq > 0 && (DWORD)CRegDWORD(_T("Software\\TortoiseGit\\SyncDialogRandomPos")))
1116 m_seq %= 5;
1117 RECT rect;
1118 GetWindowRect(&rect);
1119 rect.top -= m_seq * 30;
1120 rect.bottom -= m_seq * 30;
1121 if (rect.top < 0)
1123 rect.top += 150;
1124 rect.bottom += 150;
1126 MoveWindow(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
1129 return TRUE; // return TRUE unless you set the focus to a control
1130 // EXCEPTION: OCX Property Pages should return FALSE
1133 void CSyncDlg::OnBnClickedButtonManage()
1135 CAppUtils::LaunchRemoteSetting();
1136 Refresh();
1139 void CSyncDlg::Refresh()
1141 theApp.DoWaitCursor(1);
1143 int lastSelected = m_ctrlURL.GetCurSel();
1144 CString url;
1145 this->m_ctrlURL.GetWindowText(url);
1147 this->m_ctrlURL.Reset();
1148 CString workingDir = g_Git.m_CurrentDir;
1149 workingDir.Replace(_T(':'), _T('_'));
1150 this->m_ctrlURL.LoadHistory(_T("Software\\TortoiseGit\\History\\SyncURL\\") + workingDir, _T("url"));
1152 STRING_VECTOR list;
1153 bool found = false;
1154 if (!g_Git.GetRemoteList(list))
1156 for (size_t i = 0; i < list.size(); ++i)
1158 m_ctrlURL.AddString(list[i]);
1159 if (list[i] == url)
1160 found = true;
1163 if (lastSelected >= 0 && !found)
1165 m_ctrlURL.SetCurSel(0);
1166 m_ctrlURL.GetWindowText(url);
1169 CString local;
1170 CString remote;
1171 this->m_ctrlLocalBranch.GetWindowText(local);
1172 this->m_ctrlRemoteBranch.GetWindowText(remote);
1174 this->LoadBranchInfo();
1176 this->m_ctrlLocalBranch.AddString(local);
1177 this->m_ctrlRemoteBranch.AddString(remote);
1178 this->m_ctrlURL.AddString(url);
1180 m_OutLogList.ShowText(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_REFRESHING)));
1181 this->FetchOutList(true);
1182 theApp.DoWaitCursor(-1);
1185 BOOL CSyncDlg::PreTranslateMessage(MSG* pMsg)
1187 if (pMsg->message == WM_KEYDOWN)
1189 switch (pMsg->wParam)
1191 case VK_F5:
1193 if (m_bBlock)
1194 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
1195 Refresh();
1197 break;
1199 /* Avoid TAB control destroy but dialog exist*/
1200 case VK_ESCAPE:
1201 case VK_CANCEL:
1203 TCHAR buff[128] = { 0 };
1204 ::GetClassName(pMsg->hwnd,buff,128);
1206 /* Use MSFTEDIT_CLASS http://msdn.microsoft.com/en-us/library/bb531344.aspx */
1207 if (_tcsnicmp(buff, MSFTEDIT_CLASS, 128) == 0 || //Unicode and MFC 2012 and later
1208 _tcsnicmp(buff, RICHEDIT_CLASS, 128) == 0 || //ANSI or MFC 2010
1209 _tcsnicmp(buff, _T("SysListView32"), 128) == 0)
1211 this->PostMessage(WM_KEYDOWN,VK_ESCAPE,0);
1212 return TRUE;
1217 return __super::PreTranslateMessage(pMsg);
1219 void CSyncDlg::FetchOutList(bool force)
1221 if(!m_bInited)
1222 return;
1223 m_OutChangeFileList.Clear();
1224 this->m_OutLogList.Clear();
1226 CString remote;
1227 this->m_ctrlURL.GetWindowText(remote);
1228 CString remotebranch;
1229 this->m_ctrlRemoteBranch.GetWindowText(remotebranch);
1230 remotebranch=remote+_T("/")+remotebranch;
1231 CGitHash remotebranchHash;
1232 g_Git.GetHash(remotebranchHash, remotebranch);
1234 if(IsURL())
1236 CString str;
1237 str.LoadString(IDS_PROC_SYNC_PUSH_UNKNOWN);
1238 m_OutLogList.ShowText(str);
1239 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1240 m_OutLocalBranch.Empty();
1241 m_OutRemoteBranch.Empty();
1243 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1244 return ;
1247 else if(remotebranchHash.IsEmpty())
1249 CString str;
1250 str.Format(IDS_PROC_SYNC_PUSH_UNKNOWNBRANCH, (LPCTSTR)remotebranch);
1251 m_OutLogList.ShowText(str);
1252 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1253 m_OutLocalBranch.Empty();
1254 m_OutRemoteBranch.Empty();
1256 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1257 return ;
1259 else
1261 CString localbranch;
1262 localbranch=this->m_ctrlLocalBranch.GetString();
1264 if(localbranch != m_OutLocalBranch || m_OutRemoteBranch != remotebranch || force)
1266 m_OutLogList.ClearText();
1268 CGitHash base, localBranchHash;
1269 bool isFastForward = g_Git.IsFastForward(remotebranch, localbranch, &base);
1271 if (g_Git.GetHash(localBranchHash, localbranch))
1273 MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + localbranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
1274 return;
1276 if (remotebranchHash == localBranchHash)
1278 CString str;
1279 str.Format(IDS_PROC_SYNC_COMMITSAHEAD, 0, (LPCTSTR)remotebranch);
1280 m_OutLogList.ShowText(str);
1281 this->m_ctrlStatus.SetWindowText(str);
1282 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1283 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1285 else if (isFastForward || m_bForce)
1287 CString range;
1288 range.Format(_T("%s..%s"), (LPCTSTR)g_Git.FixBranchName(remotebranch), (LPCTSTR)g_Git.FixBranchName(localbranch));
1289 //fast forward
1290 m_OutLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT | CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
1291 CString str;
1292 str.Format(IDS_PROC_SYNC_COMMITSAHEAD, m_OutLogList.GetItemCount(), (LPCTSTR)remotebranch);
1293 this->m_ctrlStatus.SetWindowText(str);
1295 if (isFastForward)
1296 AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, remotebranch);
1297 else
1299 AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, base.ToString());
1302 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,TRUE);
1303 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(TRUE);
1305 else
1307 CString str;
1308 str.Format(IDS_PROC_SYNC_NOFASTFORWARD, (LPCTSTR)localbranch, (LPCTSTR)remotebranch);
1309 m_OutLogList.ShowText(str);
1310 this->m_ctrlStatus.SetWindowText(str);
1311 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID() - 1, FALSE);
1312 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1315 this->m_OutLocalBranch=localbranch;
1316 this->m_OutRemoteBranch=remotebranch;
1320 bool CSyncDlg::IsURL()
1322 CString str;
1323 this->m_ctrlURL.GetWindowText(str);
1324 if(str.Find(_T('\\'))>=0 || str.Find(_T('/'))>=0)
1325 return true;
1326 else
1327 return false;
1330 void CSyncDlg::OnCbnEditchangeComboboxex()
1332 SetTimer(IDT_INPUT, 1000, nullptr);
1333 this->m_OutLogList.ShowText(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_WAINTINPUT)));
1335 //this->FetchOutList();
1338 UINT CSyncDlg::ProgressThread()
1340 m_startTick = GetTickCount64();
1341 m_bDone = false;
1342 STRING_VECTOR list;
1343 CProgressDlg::RunCmdList(this, m_GitCmdList, list, true, nullptr, &this->m_bAbort, &this->m_Databuf);
1344 InterlockedExchange(&m_bBlock, FALSE);
1345 return 0;
1348 LRESULT CSyncDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)
1350 if (m_bWantToExit)
1351 return 0;
1352 if(wParam == MSG_PROGRESSDLG_START)
1354 m_BufStart = 0;
1355 m_ctrlAnimate.Play(0, UINT_MAX, UINT_MAX);
1356 this->m_ctrlProgress.SetPos(0);
1357 if (m_pTaskbarList)
1359 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
1360 m_pTaskbarList->SetProgressValue(m_hWnd, 0, 100);
1364 if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)
1366 ULONGLONG tickSpent = GetTickCount64() - m_startTick;
1367 CString strEndTime = CLoglistUtils::FormatDateAndTime(CTime::GetCurrentTime(), DATE_SHORTDATE, true, false);
1369 m_BufStart = 0;
1370 m_Databuf.m_critSec.Lock();
1371 m_Databuf.clear();
1372 m_Databuf.m_critSec.Unlock();
1374 m_bDone = true;
1375 m_ctrlAnimate.Stop();
1376 m_ctrlProgress.SetPos(100);
1377 //this->DialogEnableWindow(IDOK,TRUE);
1379 DWORD exitCode = (DWORD)lParam;
1380 if (exitCode)
1382 if (m_pTaskbarList)
1384 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);
1385 m_pTaskbarList->SetProgressValue(m_hWnd, 100, 100);
1387 CString log;
1388 log.Format(IDS_PROC_PROGRESS_GITUNCLEANEXIT, exitCode);
1389 CString err;
1390 err.Format(_T("\r\n\r\n%s (%I64u ms @ %s)\r\n"), (LPCTSTR)log, tickSpent, (LPCTSTR)strEndTime);
1391 CProgressDlg::InsertColorText(this->m_ctrlCmdOut, err, RGB(255,0,0));
1392 if (CRegDWORD(_T("Software\\TortoiseGit\\NoSounds"), FALSE) == FALSE)
1393 PlaySound((LPCTSTR)SND_ALIAS_SYSTEMEXCLAMATION, nullptr, SND_ALIAS_ID | SND_ASYNC);
1395 else
1397 if (m_pTaskbarList)
1398 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
1399 CString temp;
1400 temp.LoadString(IDS_SUCCESS);
1401 CString log;
1402 log.Format(_T("\r\n%s (%I64u ms @ %s)\r\n"), (LPCTSTR)temp, tickSpent, (LPCTSTR)strEndTime);
1403 CProgressDlg::InsertColorText(this->m_ctrlCmdOut, log, RGB(0,0,255));
1405 m_GitCmdStatus = exitCode;
1407 //if(wParam == MSG_PROGRESSDLG_END)
1408 RunPostAction();
1411 if(lParam != 0)
1412 ParserCmdOutput((char)lParam);
1413 else
1415 m_Databuf.m_critSec.Lock();
1416 for (size_t i = m_BufStart; i < m_Databuf.size(); ++i)
1418 char c = m_Databuf[m_BufStart];
1419 ++m_BufStart;
1420 m_Databuf.m_critSec.Unlock();
1421 ParserCmdOutput(c);
1423 m_Databuf.m_critSec.Lock();
1426 if (m_BufStart > 1000)
1428 m_Databuf.erase(m_Databuf.cbegin(), m_Databuf.cbegin() + m_BufStart);
1429 m_BufStart = 0;
1431 m_Databuf.m_critSec.Unlock();
1434 return 0;
1437 static std::map<CString, CGitHash> * HashMapToRefMap(MAP_HASH_NAME &map)
1439 auto rmap = new std::map<CString, CGitHash>();
1440 for (auto mit = map.cbegin(); mit != map.cend(); ++mit)
1442 for (auto rit = mit->second.cbegin(); rit != mit->second.cend(); ++rit)
1444 rmap->insert(std::make_pair(*rit, mit->first));
1447 return rmap;
1450 void CSyncDlg::FillNewRefMap()
1452 m_refList.Clear();
1453 m_newHashMap.clear();
1455 if (!g_Git.m_IsUseLibGit2)
1456 return;
1458 CAutoRepository repo(g_Git.GetGitRepository());
1459 if (!repo)
1461 CMessageBox::Show(m_hWnd, CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
1462 return;
1465 if (CGit::GetMapHashToFriendName(repo, m_newHashMap))
1467 MessageBox(CGit::GetLibGit2LastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR);
1468 return;
1471 auto oldRefMap = HashMapToRefMap(m_oldHashMap);
1472 auto newRefMap = HashMapToRefMap(m_newHashMap);
1473 for (auto oit = oldRefMap->cbegin(); oit != oldRefMap->cend(); ++oit)
1475 bool found = false;
1476 for (auto nit = newRefMap->cbegin(); nit != newRefMap->cend(); ++nit)
1478 // changed ref
1479 if (oit->first == nit->first)
1481 found = true;
1482 m_refList.AddEntry(repo, oit->first, &oit->second, &nit->second);
1483 break;
1486 // deleted ref
1487 if (!found)
1488 m_refList.AddEntry(repo, oit->first, &oit->second, nullptr);
1490 for (auto nit = newRefMap->cbegin(); nit != newRefMap->cend(); ++nit)
1492 bool found = false;
1493 for (auto oit = oldRefMap->cbegin(); oit != oldRefMap->cend(); ++oit)
1495 if (oit->first == nit->first)
1497 found = true;
1498 break;
1501 // new ref
1502 if (!found)
1503 m_refList.AddEntry(repo, nit->first, nullptr, &nit->second);
1505 delete oldRefMap;
1506 delete newRefMap;
1507 m_refList.Show();
1510 void CSyncDlg::RunPostAction()
1512 if (m_bWantToExit)
1513 return;
1515 FillNewRefMap();
1517 if (this->m_CurrentCmd == GIT_COMMAND_PUSH)
1519 DWORD exitcode = 0xFFFFFFFF;
1520 CString error;
1521 if (CHooks::Instance().PostPush(g_Git.m_CurrentDir, exitcode, error))
1523 if (exitcode)
1525 CString temp;
1526 temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);
1527 CMessageBox::Show(GetSafeHwnd(), temp, L"TortoiseGit", MB_OK | MB_ICONERROR);
1528 return;
1532 EnableControlButton(true);
1533 SwitchToInput();
1534 this->FetchOutList(true);
1536 else if (this->m_CurrentCmd == GIT_COMMAND_PULL)
1537 PullComplete();
1538 else if (this->m_CurrentCmd == GIT_COMMAND_FETCH || this->m_CurrentCmd == GIT_COMMAND_FETCHANDREBASE)
1539 FetchComplete();
1540 else if (this->m_CurrentCmd == GIT_COMMAND_SUBMODULE)
1542 //this->m_ctrlCmdOut.SetSel(-1,-1);
1543 //this->m_ctrlCmdOut.ReplaceSel(_T("Done\r\n"));
1544 //this->m_ctrlCmdOut.SetSel(-1,-1);
1545 EnableControlButton(true);
1546 SwitchToInput();
1548 else if (this->m_CurrentCmd == GIT_COMMAND_STASH)
1549 StashComplete();
1550 else if (this->m_CurrentCmd == GIT_COMMAND_REMOTE)
1552 this->FetchOutList(true);
1553 EnableControlButton(true);
1554 SwitchToInput();
1555 ShowTab(IDC_REFLIST);
1558 void CSyncDlg::ParserCmdOutput(char ch)
1560 if (m_bAbort)
1561 return;
1562 CProgressDlg::ParserCmdOutput(m_ctrlCmdOut,m_ctrlProgress,m_hWnd,m_pTaskbarList,m_LogText,ch);
1564 void CSyncDlg::OnBnClickedButtonCommit()
1566 CString cmd = _T("/command:commit");
1567 cmd += _T(" /path:\"");
1568 cmd += g_Git.m_CurrentDir;
1569 cmd += _T("\"");
1571 CAppUtils::RunTortoiseGitProc(cmd);
1574 void CSyncDlg::OnOK()
1576 UpdateCombox();
1577 this->UpdateData();
1578 m_ctrlURL.SaveHistory();
1579 SaveHistory();
1580 m_regAutoLoadPutty = this->m_bAutoLoadPuttyKey;
1581 m_tooltips.Pop();
1582 __super::OnOK();
1585 void CSyncDlg::OnCancel()
1587 m_bAbort = true;
1588 m_GitProgressList.Cancel();
1589 if (m_bDone && !m_GitProgressList.IsRunning())
1591 CResizableStandAloneDialog::OnCancel();
1592 return;
1594 if (m_GitProgressList.IsRunning())
1595 WaitForSingleObject(m_GitProgressList.m_pThread->m_hThread, 10000);
1597 if (g_Git.m_CurrentGitPi.hProcess)
1599 DWORD dwConfirmKillProcess = CRegDWORD(_T("Software\\TortoiseGit\\ConfirmKillProcess"));
1600 if (dwConfirmKillProcess && CMessageBox::Show(m_hWnd, IDS_PROC_CONFIRMKILLPROCESS, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION) != IDYES)
1601 return;
1602 if (::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
1603 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess, 10000);
1604 else
1605 GetLastError();
1607 CProgressDlg::KillProcessTree(g_Git.m_CurrentGitPi.dwProcessId);
1610 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
1611 if (m_pThread)
1613 if (::WaitForSingleObject(m_pThread->m_hThread, 5000) == WAIT_TIMEOUT)
1614 g_Git.KillRelatedThreads(m_pThread);
1616 m_tooltips.Pop();
1617 CResizableStandAloneDialog::OnCancel();
1620 void CSyncDlg::OnBnClickedButtonSubmodule()
1622 this->UpdateData();
1623 UpdateCombox();
1624 m_ctrlCmdOut.SetWindowTextW(_T(""));
1625 m_LogText.Empty();
1627 this->m_regSubmoduleButton = (DWORD)this->m_ctrlSubmodule.GetCurrentEntry();
1629 this->SwitchToRun();
1631 this->m_bAbort=false;
1632 this->m_GitCmdList.clear();
1634 ShowTab(IDC_CMD_LOG);
1636 CString cmd;
1638 switch (m_ctrlSubmodule.GetCurrentEntry())
1640 case 0:
1641 cmd=_T("git.exe submodule update --init");
1642 break;
1643 case 1:
1644 cmd=_T("git.exe submodule init");
1645 break;
1646 case 2:
1647 cmd=_T("git.exe submodule sync");
1648 break;
1651 m_GitCmdList.push_back(cmd);
1653 m_CurrentCmd = GIT_COMMAND_SUBMODULE;
1655 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
1656 if (!m_pThread)
1658 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
1660 else
1662 m_pThread->m_bAutoDelete = TRUE;
1663 m_pThread->ResumeThread();
1667 void CSyncDlg::OnBnClickedButtonStash()
1669 UpdateData();
1670 UpdateCombox();
1671 m_ctrlCmdOut.SetWindowTextW(_T(""));
1672 m_LogText.Empty();
1674 SwitchToRun();
1676 m_bAbort = false;
1677 m_GitCmdList.clear();
1679 ShowTab(IDC_CMD_LOG);
1681 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST - 1, false);
1682 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST -1, false);
1683 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT -1, false);
1685 CString cmd;
1686 switch (m_ctrlStash.GetCurrentEntry())
1688 case 0:
1689 cmd = _T("git.exe stash save");
1690 break;
1691 case 1:
1692 cmd = _T("git.exe stash pop");
1693 break;
1694 case 2:
1695 cmd = _T("git.exe stash apply");
1696 break;
1699 m_GitCmdList.push_back(cmd);
1700 m_CurrentCmd = GIT_COMMAND_STASH;
1702 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
1703 if (!m_pThread)
1705 //ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
1707 else
1709 m_pThread->m_bAutoDelete = TRUE;
1710 m_pThread->ResumeThread();
1714 void CSyncDlg::OnTimer(UINT_PTR nIDEvent)
1716 if( nIDEvent == IDT_INPUT)
1718 KillTimer(IDT_INPUT);
1719 this->FetchOutList(true);
1724 void CSyncDlg::OnLvnInLogListColumnClick(NMHDR * /* pNMHDR */, LRESULT *pResult)
1726 *pResult = 0;
1729 LRESULT CSyncDlg::OnTaskbarBtnCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
1731 m_pTaskbarList.Release();
1732 m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
1733 m_GitProgressList.m_pTaskbarList = m_pTaskbarList;
1734 SetUUIDOverlayIcon(m_hWnd);
1735 return 0;
1738 void CSyncDlg::OnBnClickedCheckForce()
1740 UpdateData();
1743 void CSyncDlg::OnBnClickedLog()
1745 CString cmd = _T("/command:log");
1746 cmd += _T(" /path:\"");
1747 cmd += g_Git.m_CurrentDir;
1748 cmd += _T("\"");
1750 CAppUtils::RunTortoiseGitProc(cmd);
1753 LRESULT CSyncDlg::OnProgCmdFinish(WPARAM /*wParam*/, LPARAM /*lParam*/)
1755 RefreshCursor();
1756 RunPostAction();
1757 return 0;
1760 void CSyncDlg::OnDestroy()
1762 m_bWantToExit = true;
1763 __super::OnDestroy();