Randomize Sync Dialog startup position
[TortoiseGit.git] / src / TortoiseProc / SyncDlg.cpp
blob4e7edf54dc390f21d01e84317d6d25bb7ccdeba5
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2013 - 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 "SoundUtils.h"
35 // CSyncDlg dialog
37 IMPLEMENT_DYNAMIC(CSyncDlg, CResizableStandAloneDialog)
39 CSyncDlg::CSyncDlg(CWnd* pParent /*=NULL*/)
40 : CResizableStandAloneDialog(CSyncDlg::IDD, pParent)
42 m_CurrentCmd = 0;
43 m_pTooltip=&this->m_tooltips;
44 m_bInited=false;
45 m_CmdOutCurrentPos=0;
46 m_bAutoLoadPuttyKey = CAppUtils::IsSSHPutty();
47 m_bForce=false;
48 m_Gitverion = 0;
49 m_bBlock = false;
50 m_BufStart = 0;
51 m_pThread = NULL;
52 m_bAbort = false;
53 m_bDone = false;
54 m_bWantToExit = false;
55 m_GitCmdStatus = -1;
56 m_startTick = GetTickCount();
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;
83 BEGIN_MESSAGE_MAP(CSyncDlg, CResizableStandAloneDialog)
84 ON_BN_CLICKED(IDC_BUTTON_PULL, &CSyncDlg::OnBnClickedButtonPull)
85 ON_BN_CLICKED(IDC_BUTTON_PUSH, &CSyncDlg::OnBnClickedButtonPush)
86 ON_BN_CLICKED(IDC_BUTTON_APPLY, &CSyncDlg::OnBnClickedButtonApply)
87 ON_BN_CLICKED(IDC_BUTTON_EMAIL, &CSyncDlg::OnBnClickedButtonEmail)
88 ON_BN_CLICKED(IDC_BUTTON_MANAGE, &CSyncDlg::OnBnClickedButtonManage)
89 BRANCH_COMBOX_EVENT
90 ON_CBN_EDITCHANGE(IDC_COMBOBOXEX_URL, &CSyncDlg::OnCbnEditchangeComboboxex)
91 ON_CBN_EDITCHANGE(IDC_COMBOBOXEX_REMOTE_BRANCH, &CSyncDlg::OnCbnEditchangeComboboxex)
92 ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)
93 ON_MESSAGE(WM_PROG_CMD_FINISH, OnProgCmdFinish)
94 ON_NOTIFY(LVN_COLUMNCLICK, IDC_IN_LOGLIST, OnLvnInLogListColumnClick)
95 ON_BN_CLICKED(IDC_BUTTON_COMMIT, &CSyncDlg::OnBnClickedButtonCommit)
96 ON_BN_CLICKED(IDC_BUTTON_SUBMODULE, &CSyncDlg::OnBnClickedButtonSubmodule)
97 ON_BN_CLICKED(IDC_BUTTON_STASH, &CSyncDlg::OnBnClickedButtonStash)
98 ON_WM_TIMER()
99 ON_REGISTERED_MESSAGE(WM_TASKBARBTNCREATED, OnTaskbarBtnCreated)
100 ON_BN_CLICKED(IDC_CHECK_FORCE, &CSyncDlg::OnBnClickedCheckForce)
101 ON_BN_CLICKED(IDC_LOG, &CSyncDlg::OnBnClickedLog)
102 ON_WM_DESTROY()
103 END_MESSAGE_MAP()
106 void CSyncDlg::EnableControlButton(bool bEnabled)
108 GetDlgItem(IDC_BUTTON_PULL)->EnableWindow(bEnabled);
109 GetDlgItem(IDC_BUTTON_PUSH)->EnableWindow(bEnabled);
110 GetDlgItem(IDC_BUTTON_APPLY)->EnableWindow(bEnabled);
111 GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(bEnabled);
112 GetDlgItem(IDOK)->EnableWindow(bEnabled);
113 GetDlgItem(IDC_BUTTON_SUBMODULE)->EnableWindow(bEnabled);
114 GetDlgItem(IDC_BUTTON_STASH)->EnableWindow(bEnabled);
116 // CSyncDlg message handlers
118 void CSyncDlg::OnBnClickedButtonPull()
120 int CurrentEntry;
121 CurrentEntry = (int)this->m_ctrlPull.GetCurrentEntry();
122 this->m_regPullButton = CurrentEntry;
124 this->m_bAbort=false;
125 this->m_GitCmdList.clear();
126 m_ctrlCmdOut.SetWindowTextW(_T(""));
127 m_LogText = "";
129 this->UpdateData();
130 UpdateCombox();
132 if (g_Git.GetHash(m_oldHash, _T("HEAD")))
134 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR);
135 return;
138 if( CurrentEntry == 0)
140 CGitHash localBranchHash;
141 if (g_Git.GetHash(localBranchHash, m_strLocalBranch))
143 MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + m_strLocalBranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
144 return;
146 if (localBranchHash != m_oldHash)
148 CMessageBox::Show(NULL, IDS_PROC_SYNC_PULLWRONGBRANCH, IDS_APPNAME, MB_OK | MB_ICONERROR);
149 return;
153 if(this->m_strURL.IsEmpty())
155 CMessageBox::Show(NULL, IDS_PROC_GITCONFIG_URLEMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
156 return;
159 if (m_bAutoLoadPuttyKey && CurrentEntry != 3) // CurrentEntry (Remote Update) handles this on its own)
161 CAppUtils::LaunchPAgent(NULL,&this->m_strURL);
164 this->SwitchToRun();
166 CString force;
167 if(this->m_bForce)
168 force = _T(" --force ");
170 CString cmd;
172 ShowTab(IDC_CMD_LOG);
174 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,false);
175 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
176 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT-1,false);
178 ///Pull
179 if(CurrentEntry == 0) //Pull
181 CString remotebranch;
182 remotebranch = m_strRemoteBranch;
184 if(!IsURL())
186 CString configName;
187 configName.Format(L"branch.%s.merge", this->m_strLocalBranch);
188 CString pullBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));
190 configName.Format(L"branch.%s.remote", m_strLocalBranch);
191 CString pullRemote = g_Git.GetConfigValue(configName);
193 if(pullBranch == remotebranch && pullRemote == this->m_strURL)
194 remotebranch.Empty();
197 if(m_Gitverion >= 0x01070203) //above 1.7.0.2
198 force += _T("--progress ");
200 cmd.Format(_T("git.exe pull -v %s \"%s\" %s"),
201 force,
202 m_strURL,
203 remotebranch);
205 m_CurrentCmd = GIT_COMMAND_PULL;
206 m_GitCmdList.push_back(cmd);
208 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
209 if (m_pThread==NULL)
211 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
213 else
215 m_pThread->m_bAutoDelete = TRUE;
216 m_pThread->ResumeThread();
221 ///Fetch
222 if(CurrentEntry == 1 || CurrentEntry ==2 ) //Fetch
224 CString remotebranch;
225 if(this->IsURL() || m_strRemoteBranch.IsEmpty())
227 remotebranch=this->m_strRemoteBranch;
230 else
232 remotebranch.Format(_T("remotes/%s/%s"),
233 m_strURL,m_strRemoteBranch);
234 CGitHash remoteBranchHash;
235 g_Git.GetHash(remoteBranchHash, remotebranch);
236 if (remoteBranchHash.IsEmpty())
237 remotebranch=m_strRemoteBranch;
238 else
239 remotebranch=m_strRemoteBranch+_T(":")+remotebranch;
242 if(CurrentEntry == 1)
243 m_CurrentCmd = GIT_COMMAND_FETCH;
244 else
245 m_CurrentCmd = GIT_COMMAND_FETCHANDREBASE;
247 if (g_Git.UsingLibGit2(CGit::GIT_CMD_FETCH))
249 CString refspec;
250 // current libgit2 only supports well formated refspec
251 refspec.Format(_T("refs/heads/%s:refs/remotes/%s/%s"), m_strRemoteBranch, m_strURL, m_strRemoteBranch);
252 m_GitProgressList.SetUrl(m_strURL);
253 m_GitProgressList.SetRefSpec(refspec);
254 m_GitProgressList.SetCommand(CGitProgressList::GitProgress_Fetch);
255 m_GitProgressList.Init();
256 ShowTab(IDC_CMD_GIT_PROG);
258 else
260 if(m_Gitverion >= 0x01070203) //above 1.7.0.2
261 force += _T("--progress ");
263 cmd.Format(_T("git.exe fetch -v %s \"%s\" %s"),
264 force,
265 m_strURL,
266 remotebranch);
268 m_GitCmdList.push_back(cmd);
270 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
271 if (m_pThread==NULL)
273 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
275 else
277 m_pThread->m_bAutoDelete = TRUE;
278 m_pThread->ResumeThread();
283 ///Remote Update
284 if(CurrentEntry == 3)
286 if (m_bAutoLoadPuttyKey)
288 STRING_VECTOR list;
289 if (!g_Git.GetRemoteList(list))
291 for (size_t i = 0; i < list.size(); ++i)
292 CAppUtils::LaunchPAgent(NULL, &list[i]);
296 m_CurrentCmd = GIT_COMMAND_REMOTE;
297 cmd=_T("git.exe remote update");
298 m_GitCmdList.push_back(cmd);
300 InterlockedExchange(&m_bBlock, TRUE);
302 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
303 if (m_pThread==NULL)
305 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
306 InterlockedExchange(&m_bBlock, FALSE);
308 else
310 m_pThread->m_bAutoDelete = TRUE;
311 m_pThread->ResumeThread();
315 ///Cleanup stale remote banches
316 if(CurrentEntry == 4)
318 m_CurrentCmd = GIT_COMMAND_REMOTE;
319 cmd.Format(_T("git.exe remote prune \"%s\""), m_strURL);
320 m_GitCmdList.push_back(cmd);
322 InterlockedExchange(&m_bBlock, TRUE);
324 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
325 if (m_pThread==NULL)
327 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
328 InterlockedExchange(&m_bBlock, FALSE);
330 else
332 m_pThread->m_bAutoDelete = TRUE;
333 m_pThread->ResumeThread();
338 void CSyncDlg::PullComplete()
340 EnableControlButton(true);
341 SwitchToInput();
342 this->FetchOutList(true);
344 CGitHash newhash;
345 if (g_Git.GetHash(newhash, _T("HEAD")))
346 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash after pulling.")), _T("TortoiseGit"), MB_ICONERROR);
348 if( this ->m_GitCmdStatus )
350 CTGitPathList list;
351 if(g_Git.ListConflictFile(list))
353 this->m_ctrlCmdOut.SetSel(-1,-1);
354 this->m_ctrlCmdOut.ReplaceSel(_T("Get conflict files fail\n"));
356 this->ShowTab(IDC_CMD_LOG);
357 return;
360 if(list.GetCount()>0)
362 this->m_ConflictFileList.Clear();
363 CTGitPathList list;
364 CTGitPath path;
365 list.AddPath(path);
367 this->m_ConflictFileList.GetStatus(&list,true);
368 this->m_ConflictFileList.Show(CTGitPath::LOGACTIONS_UNMERGED,
369 CTGitPath::LOGACTIONS_UNMERGED);
371 this->ShowTab(IDC_IN_CONFLICT);
373 else
374 this->ShowTab(IDC_CMD_LOG);
377 else
379 if(newhash == this->m_oldHash)
381 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
382 this->m_InLogList.ShowText(CString(MAKEINTRESOURCE(IDS_UPTODATE)));
383 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true);
385 else
387 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,true);
388 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true);
390 this->AddDiffFileList(&m_InChangeFileList, &m_arInChangeList, newhash.ToString(), m_oldHash.ToString());
392 CString range;
393 range.Format(_T("%s..%s"), m_oldHash.ToString(), newhash.ToString());
394 m_InLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
396 this->ShowTab(IDC_IN_LOGLIST);
400 void CSyncDlg::FetchComplete()
402 EnableControlButton(true);
403 SwitchToInput();
404 this->FetchOutList(true);
406 if (g_Git.UsingLibGit2(CGit::GIT_CMD_FETCH))
407 ShowTab(IDC_CMD_GIT_PROG);
408 else
409 ShowTab(IDC_CMD_LOG);
410 if( (!this->m_GitCmdStatus) && this->m_CurrentCmd == GIT_COMMAND_FETCHANDREBASE)
412 CRebaseDlg dlg;
413 dlg.m_PostButtonTexts.Add(CString(MAKEINTRESOURCE(IDS_MENULOG)));
414 dlg.m_PostButtonTexts.Add(_T("Email &Patch..."));
415 INT_PTR response = dlg.DoModal();
416 if(response == IDOK)
418 return ;
421 if (response == IDC_REBASE_POST_BUTTON)
423 CString cmd = _T("/command:log");
424 cmd += _T(" /path:\"") + g_Git.m_CurrentDir + _T("\"");
425 CAppUtils::RunTortoiseGitProc(cmd);
427 if(response == IDC_REBASE_POST_BUTTON + 1)
429 CString cmd, out, err;
430 cmd.Format(_T("git.exe format-patch -o \"%s\" %s..%s"),
431 g_Git.m_CurrentDir,
432 g_Git.FixBranchName(dlg.m_Upstream),
433 g_Git.FixBranchName(dlg.m_Branch));
434 if (g_Git.Run(cmd, &out, &err, CP_UTF8))
436 CMessageBox::Show(NULL, out + L"\n" + err, _T("TortoiseGit"), MB_OK|MB_ICONERROR);
437 return ;
440 CAppUtils::SendPatchMail(cmd,out);
445 void CSyncDlg::StashComplete()
447 EnableControlButton(true);
448 INT_PTR entry = m_ctrlStash.GetCurrentEntry();
449 if (entry != 1 && entry != 2)
450 return;
452 SwitchToInput();
453 if (m_GitCmdStatus)
455 CTGitPathList list;
456 if (g_Git.ListConflictFile(list))
458 m_ctrlCmdOut.SetSel(-1, -1);
459 m_ctrlCmdOut.ReplaceSel(_T("Get conflict files fail\n"));
461 ShowTab(IDC_CMD_LOG);
462 return;
465 if (list.GetCount() > 0)
467 m_ConflictFileList.Clear();
468 CTGitPathList list;
469 CTGitPath path;
470 list.AddPath(path);
472 m_ConflictFileList.GetStatus(&list,true);
473 m_ConflictFileList.Show(CTGitPath::LOGACTIONS_UNMERGED, CTGitPath::LOGACTIONS_UNMERGED);
475 ShowTab(IDC_IN_CONFLICT);
477 else
478 ShowTab(IDC_CMD_LOG);
482 void CSyncDlg::OnBnClickedButtonPush()
484 this->UpdateData();
485 UpdateCombox();
486 m_ctrlCmdOut.SetWindowTextW(_T(""));
487 m_LogText = "";
489 if(this->m_strURL.IsEmpty())
491 CMessageBox::Show(NULL, IDS_PROC_GITCONFIG_URLEMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
492 return;
495 this->m_regPushButton=(DWORD)this->m_ctrlPush.GetCurrentEntry();
496 this->SwitchToRun();
497 this->m_bAbort=false;
498 this->m_GitCmdList.clear();
500 ShowTab(IDC_CMD_LOG);
502 CString cmd;
503 CString arg;
505 CString error;
506 DWORD exitcode;
507 CTGitPathList list;
508 list.AddPath(CTGitPath(g_Git.m_CurrentDir));
510 if (CHooks::Instance().PrePush(list,exitcode, error))
512 if (exitcode)
514 CString temp;
515 temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);
516 //ReportError(temp);
517 CMessageBox::Show(NULL,temp,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
518 return ;
522 CString refName = g_Git.FixBranchName(m_strLocalBranch);
523 switch (m_ctrlPush.GetCurrentEntry())
525 case 1:
526 arg += _T(" --tags ");
527 break;
528 case 2:
529 refName = _T("refs/notes/commits"); //default ref for notes
530 break;
533 if(this->m_bForce)
534 arg += _T(" --force ");
536 if(m_Gitverion >= 0x01070203) //above 1.7.0.2
537 arg += _T("--progress ");
539 cmd.Format(_T("git.exe push -v %s \"%s\" %s"),
540 arg,
541 m_strURL,
542 refName);
544 if (!m_strRemoteBranch.IsEmpty() && m_ctrlPush.GetCurrentEntry() != 2)
546 cmd += _T(":") + m_strRemoteBranch;
549 m_GitCmdList.push_back(cmd);
551 m_CurrentCmd = GIT_COMMAND_PUSH;
553 if(this->m_bAutoLoadPuttyKey)
555 CAppUtils::LaunchPAgent(NULL,&this->m_strURL);
558 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
559 if (m_pThread==NULL)
561 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
563 else
565 m_pThread->m_bAutoDelete = TRUE;
566 m_pThread->ResumeThread();
570 void CSyncDlg::OnBnClickedButtonApply()
572 CGitHash oldhash;
573 if (g_Git.GetHash(oldhash, _T("HEAD")))
575 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR);
576 return;
579 CImportPatchDlg dlg;
580 CString cmd,output;
582 if(dlg.DoModal() == IDOK)
584 int err=0;
585 for (int i = 0; i < dlg.m_PathList.GetCount(); ++i)
587 cmd.Format(_T("git.exe am \"%s\""),dlg.m_PathList[i].GetGitPathString());
589 if (g_Git.Run(cmd, &output, CP_UTF8))
591 CMessageBox::Show(NULL,output,_T("TortoiseGit"),MB_OK);
593 err=1;
594 break;
596 this->m_ctrlCmdOut.SetSel(-1,-1);
597 this->m_ctrlCmdOut.ReplaceSel(cmd+_T("\n"));
598 this->m_ctrlCmdOut.SetSel(-1,-1);
599 this->m_ctrlCmdOut.ReplaceSel(output);
602 CGitHash newhash;
603 if (g_Git.GetHash(newhash, _T("HEAD")))
605 MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash after applying patches.")), _T("TortoiseGit"), MB_ICONERROR);
606 return;
609 this->m_InLogList.Clear();
610 this->m_InChangeFileList.Clear();
612 if(newhash == oldhash)
614 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
615 this->m_InLogList.ShowText(_T("No commits get from patch"));
616 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true);
619 else
621 this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,true);
622 this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true);
624 CString range;
625 range.Format(_T("%s..%s"), m_oldHash.ToString(), newhash.ToString());
626 this->AddDiffFileList(&m_InChangeFileList, &m_arInChangeList, newhash.ToString(), oldhash.ToString());
627 m_InLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
629 this->FetchOutList(true);
632 this->m_ctrlTabCtrl.ShowTab(IDC_CMD_LOG-1,true);
634 if(err)
636 this->ShowTab(IDC_CMD_LOG);
638 else
640 this->ShowTab(IDC_IN_LOGLIST);
645 void CSyncDlg::OnBnClickedButtonEmail()
647 CString cmd, out, err;
649 this->m_strLocalBranch = this->m_ctrlLocalBranch.GetString();
650 this->m_ctrlRemoteBranch.GetWindowText(this->m_strRemoteBranch);
651 this->m_ctrlURL.GetWindowText(this->m_strURL);
652 m_strURL=m_strURL.Trim();
653 m_strRemoteBranch=m_strRemoteBranch.Trim();
655 cmd.Format(_T("git.exe format-patch -o \"%s\" %s..%s"),
656 g_Git.m_CurrentDir,
657 m_strURL+_T('/')+m_strRemoteBranch,g_Git.FixBranchName(m_strLocalBranch));
659 if (g_Git.Run(cmd, &out, &err, CP_UTF8))
661 CMessageBox::Show(NULL, out + L"\n" + err, _T("TortoiseGit"), MB_OK|MB_ICONERROR);
662 return ;
665 CAppUtils::SendPatchMail(cmd,out);
668 void CSyncDlg::ShowProgressCtrl(bool bShow)
670 int b=bShow?SW_NORMAL:SW_HIDE;
671 this->m_ctrlAnimate.ShowWindow(b);
672 this->m_ctrlProgress.ShowWindow(b);
673 this->m_ctrlProgLabel.ShowWindow(b);
674 this->m_ctrlAnimate.Open(IDR_DOWNLOAD);
675 if(b == SW_NORMAL)
676 this->m_ctrlAnimate.Play(0, UINT_MAX, UINT_MAX);
677 else
678 this->m_ctrlAnimate.Stop();
680 void CSyncDlg::ShowInputCtrl(bool bShow)
682 int b=bShow?SW_NORMAL:SW_HIDE;
683 this->m_ctrlURL.ShowWindow(b);
684 this->m_ctrlLocalBranch.ShowWindow(b);
685 this->m_ctrlRemoteBranch.ShowWindow(b);
686 this->GetDlgItem(IDC_BUTTON_LOCAL_BRANCH)->ShowWindow(b);
687 this->GetDlgItem(IDC_BUTTON_REMOTE_BRANCH)->ShowWindow(b);
688 this->GetDlgItem(IDC_STATIC_LOCAL_BRANCH)->ShowWindow(b);
689 this->GetDlgItem(IDC_STATIC_REMOTE_BRANCH)->ShowWindow(b);
690 this->GetDlgItem(IDC_BUTTON_MANAGE)->ShowWindow(b);
691 this->GetDlgItem(IDC_CHECK_PUTTY_KEY)->ShowWindow(b);
692 this->GetDlgItem(IDC_CHECK_FORCE)->ShowWindow(b);
693 this->GetDlgItem(IDC_STATIC_REMOTE_URL)->ShowWindow(b);
695 BOOL CSyncDlg::OnInitDialog()
697 CResizableStandAloneDialog::OnInitDialog();
698 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
700 // Let the TaskbarButtonCreated message through the UIPI filter. If we don't
701 // do this, Explorer would be unable to send that message to our window if we
702 // were running elevated. It's OK to make the call all the time, since if we're
703 // not elevated, this is a no-op.
704 CHANGEFILTERSTRUCT cfs = { sizeof(CHANGEFILTERSTRUCT) };
705 typedef BOOL STDAPICALLTYPE ChangeWindowMessageFilterExDFN(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct);
706 CAutoLibrary hUser = AtlLoadSystemLibraryUsingFullPath(_T("user32.dll"));
707 if (hUser)
709 ChangeWindowMessageFilterExDFN *pfnChangeWindowMessageFilterEx = (ChangeWindowMessageFilterExDFN*)GetProcAddress(hUser, "ChangeWindowMessageFilterEx");
710 if (pfnChangeWindowMessageFilterEx)
712 pfnChangeWindowMessageFilterEx(m_hWnd, WM_TASKBARBTNCREATED, MSGFLT_ALLOW, &cfs);
715 m_pTaskbarList.Release();
716 if (FAILED(m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList)))
717 m_pTaskbarList = nullptr;
719 this->GetDlgItem(IDC_CHECK_PUTTY_KEY)->EnableWindow(CAppUtils::IsSSHPutty());
722 this->m_ctrlAnimate.ShowWindow(SW_NORMAL);
723 this->m_ctrlAnimate.Open(IDR_DOWNLOAD);
724 this->m_ctrlAnimate.Play(0,-1,-1);
727 // ------------------ Create Tabctrl -----------
728 CWnd *pwnd=this->GetDlgItem(IDC_BUTTON_TABCTRL);
729 CRect rectDummy;
730 pwnd->GetWindowRect(&rectDummy);
731 this->ScreenToClient(rectDummy);
733 if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_SYNC_TAB))
735 TRACE0("Failed to create output tab window\n");
736 return FALSE; // fail to create
738 m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);
740 // -------------Create Command Log Ctrl ---------
741 DWORD dwStyle;
742 dwStyle= ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL |WS_VSCROLL ;
744 if( !m_ctrlCmdOut.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_CMD_LOG))
746 TRACE0("Failed to create Log commits window\n");
747 return FALSE; // fail to create
750 // set the font to use in the log message view, configured in the settings dialog
751 CFont m_logFont;
752 CAppUtils::CreateFontForLogs(m_logFont);
753 //GetDlgItem(IDC_CMD_LOG)->SetFont(&m_logFont);
754 m_ctrlCmdOut.SetFont(&m_logFont);
755 m_ctrlTabCtrl.InsertTab(&m_ctrlCmdOut, CString(MAKEINTRESOURCE(IDS_LOG)), -1);
757 //m_ctrlCmdOut.ReplaceSel(_T("Hello"));
759 //---------- Create in coming list ctrl -----------
760 dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;;
762 if( !m_InLogList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_IN_LOGLIST))
764 TRACE0("Failed to create output commits window\n");
765 return FALSE; // fail to create
768 m_ctrlTabCtrl.InsertTab(&m_InLogList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_INCOMMITS)), -1);
770 m_InLogList.m_ColumnRegKey=_T("SyncIn");
771 m_InLogList.InsertGitColumn();
773 //----------- Create In Change file list -----------
774 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;
776 if( !m_InChangeFileList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_IN_CHANGELIST))
778 TRACE0("Failed to create output change files window\n");
779 return FALSE; // fail to create
781 m_ctrlTabCtrl.InsertTab(&m_InChangeFileList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_INCHANGELIST)), -1);
783 m_InChangeFileList.Init(GITSLC_COLEXT | GITSLC_COLSTATUS |GITSLC_COLADD|GITSLC_COLDEL , _T("InSyncDlg"),
784 (CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWO)|
785 CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF2)), false, true, GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD| GITSLC_COLDEL);
788 //---------- Create Conflict List Ctrl -----------------
789 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;
791 if( !m_ConflictFileList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_IN_CONFLICT))
793 TRACE0("Failed to create output change files window\n");
794 return FALSE; // fail to create
796 m_ctrlTabCtrl.InsertTab(&m_ConflictFileList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_CONFLICTS)), -1);
798 m_ConflictFileList.Init(GITSLC_COLEXT | GITSLC_COLSTATUS |GITSLC_COLADD|GITSLC_COLDEL , _T("ConflictSyncDlg"),
799 (CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWO)|
800 CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF2)|
801 GITSLC_POPCONFLICT|GITSLC_POPRESOLVE),false);
804 //---------- Create Commit Out List Ctrl---------------
806 dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;;
808 if( !m_OutLogList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_OUT_LOGLIST))
810 TRACE0("Failed to create output commits window\n");
811 return FALSE; // fail to create
815 m_ctrlTabCtrl.InsertTab(&m_OutLogList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_OUTCOMMITS)), -1);
817 m_OutLogList.m_ColumnRegKey = _T("SyncOut");
818 m_OutLogList.InsertGitColumn();
820 //------------- Create Change File List Control ----------------
822 dwStyle = LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;
824 if( !m_OutChangeFileList.Create(dwStyle,rectDummy,&m_ctrlTabCtrl,IDC_OUT_CHANGELIST))
826 TRACE0("Failed to create output change files window\n");
827 return FALSE; // fail to create
829 m_ctrlTabCtrl.InsertTab(&m_OutChangeFileList, CString(MAKEINTRESOURCE(IDS_PROC_SYNC_OUTCHANGELIST)), -1);
831 m_OutChangeFileList.Init(GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD | GITSLC_COLDEL, _T("OutSyncDlg"),
832 (CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWO)|
833 CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF2)), false, true, GITSLC_COLEXT | GITSLC_COLSTATUS | GITSLC_COLADD| GITSLC_COLDEL);
835 if (!m_GitProgressList.Create(dwStyle | LVS_OWNERDATA, rectDummy, &m_ctrlTabCtrl, IDC_CMD_GIT_PROG))
837 TRACE0("Failed to create Git Progress List Window\n");
838 return FALSE; // fail to create
840 m_ctrlTabCtrl.InsertTab(&m_GitProgressList, CString(MAKEINTRESOURCE(IDS_LOG)), -1);
841 m_GitProgressList.m_pAnimate = &m_ctrlAnimate;
842 m_GitProgressList.m_pPostWnd = this;
843 m_GitProgressList.m_pProgressLabelCtrl = &m_ctrlProgLabel;
844 m_GitProgressList.m_pProgControl = &m_ctrlProgress;
845 m_GitProgressList.m_pTaskbarList = m_pTaskbarList;
847 this->m_tooltips.Create(this);
849 AddAnchor(IDC_SYNC_TAB,TOP_LEFT,BOTTOM_RIGHT);
851 AddAnchor(IDC_GROUP_INFO,TOP_LEFT,TOP_RIGHT);
852 AddAnchor(IDC_COMBOBOXEX_URL,TOP_LEFT,TOP_RIGHT);
853 AddAnchor(IDC_BUTTON_MANAGE,TOP_RIGHT);
854 AddAnchor(IDC_BUTTON_PULL,BOTTOM_LEFT);
855 AddAnchor(IDC_BUTTON_PUSH,BOTTOM_LEFT);
856 AddAnchor(IDC_BUTTON_SUBMODULE,BOTTOM_LEFT);
857 AddAnchor(IDC_BUTTON_STASH,BOTTOM_LEFT);
858 AddAnchor(IDC_BUTTON_APPLY,BOTTOM_RIGHT);
859 AddAnchor(IDC_BUTTON_EMAIL,BOTTOM_RIGHT);
860 AddAnchor(IDC_PROGRESS_SYNC,TOP_LEFT,TOP_RIGHT);
861 AddAnchor(IDOK,BOTTOM_RIGHT);
862 AddAnchor(IDHELP,BOTTOM_RIGHT);
863 AddAnchor(IDC_STATIC_STATUS, BOTTOM_LEFT, BOTTOM_RIGHT);
864 AddAnchor(IDC_ANIMATE_SYNC,TOP_LEFT);
865 AddAnchor(IDC_BUTTON_COMMIT,BOTTOM_LEFT);
866 AddAnchor(IDC_LOG, BOTTOM_LEFT);
868 // do not use BRANCH_COMBOX_ADD_ANCHOR here, we want to have different stylings
869 AddAnchor(IDC_COMBOBOXEX_LOCAL_BRANCH, TOP_LEFT,TOP_CENTER);
870 AddAnchor(IDC_COMBOBOXEX_REMOTE_BRANCH, TOP_CENTER, TOP_RIGHT);
871 AddAnchor(IDC_BUTTON_LOCAL_BRANCH, TOP_CENTER);
872 AddAnchor(IDC_BUTTON_REMOTE_BRANCH, TOP_RIGHT);
873 AddAnchor(IDC_STATIC_REMOTE_BRANCH, TOP_CENTER);
874 AddAnchor(IDC_PROG_LABEL, TOP_LEFT);
876 AdjustControlSize(IDC_CHECK_PUTTY_KEY);
877 AdjustControlSize(IDC_CHECK_FORCE);
879 CString WorkingDir=g_Git.m_CurrentDir;
880 WorkingDir.Replace(_T(':'),_T('_'));
881 m_RegKeyRemoteBranch = CString(_T("Software\\TortoiseGit\\History\\SyncBranch\\"))+WorkingDir;
884 this->AddOthersToAnchor();
886 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSH)));
887 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSHTAGS)));
888 this->m_ctrlPush.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PUSHNOTES)));
890 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_PULL)));
891 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCH)));
892 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_FETCHREBASE)));
893 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_REMOTEUPDATE)));
894 this->m_ctrlPull.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_CLEANUPSTALEBRANCHES)));
896 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULEUPDATE)));
897 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULEINIT)));
898 this->m_ctrlSubmodule.AddEntry(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_SUBKODULESYNC)));
900 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHSAVE)));
901 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHPOP)));
902 this->m_ctrlStash.AddEntry(CString(MAKEINTRESOURCE(IDS_MENUSTASHAPPLY)));
904 WorkingDir.Replace(_T(':'),_T('_'));
906 CString regkey ;
907 regkey.Format(_T("Software\\TortoiseGit\\TortoiseProc\\Sync\\%s"),WorkingDir);
909 this->m_regPullButton = CRegDWORD(regkey+_T("\\Pull"),0);
910 this->m_regPushButton = CRegDWORD(regkey+_T("\\Push"),0);
911 this->m_regSubmoduleButton = CRegDWORD(regkey+_T("\\Submodule"));
912 this->m_regAutoLoadPutty = CRegDWORD(regkey + _T("\\AutoLoadPutty"), CAppUtils::IsSSHPutty());
914 this->UpdateData();
915 this->m_bAutoLoadPuttyKey = m_regAutoLoadPutty;
916 if(!CAppUtils::IsSSHPutty())
917 m_bAutoLoadPuttyKey = false;
918 this->UpdateData(FALSE);
920 this->m_ctrlPull.SetCurrentEntry(this->m_regPullButton);
921 this->m_ctrlPush.SetCurrentEntry(this->m_regPushButton);
922 this->m_ctrlSubmodule.SetCurrentEntry(this->m_regSubmoduleButton);
924 CString sWindowTitle;
925 GetWindowText(sWindowTitle);
926 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
928 EnableSaveRestore(_T("SyncDlg"));
930 this->m_ctrlURL.LoadHistory(CString(_T("Software\\TortoiseGit\\History\\SyncURL\\"))+WorkingDir, _T("url"));
932 STRING_VECTOR list;
934 if(!g_Git.GetRemoteList(list))
936 for (unsigned int i = 0; i < list.size(); ++i)
938 m_ctrlURL.AddString(list[i]);
941 m_ctrlURL.SetCurSel(0);
942 m_ctrlRemoteBranch.SetCurSel(0);
943 m_ctrlURL.SetURLHistory(true);
945 this->LoadBranchInfo();
947 this->m_bInited=true;
948 FetchOutList();
950 m_ctrlTabCtrl.ShowTab(IDC_CMD_LOG-1,false);
951 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,false);
952 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
953 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT-1,false);
954 m_ctrlTabCtrl.ShowTab(IDC_CMD_GIT_PROG-1, false);
956 m_ctrlRemoteBranch.m_bWantReturn = TRUE;
957 m_ctrlURL.m_bWantReturn = TRUE;
959 this->m_Gitverion = CAppUtils::GetMsysgitVersion();
961 if (m_seq > 0 && (DWORD)CRegDWORD(_T("Software\\TortoiseGit\\SyncDialogRandomPos")))
963 m_seq %= 5;
964 RECT rect;
965 GetWindowRect(&rect);
966 rect.top -= m_seq * 30;
967 rect.bottom -= m_seq * 30;
968 if (rect.top < 0)
970 rect.top += 150;
971 rect.bottom += 150;
973 MoveWindow(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
976 return TRUE; // return TRUE unless you set the focus to a control
977 // EXCEPTION: OCX Property Pages should return FALSE
980 void CSyncDlg::OnBnClickedButtonManage()
982 CAppUtils::LaunchRemoteSetting();
983 Refresh();
986 void CSyncDlg::Refresh()
988 theApp.DoWaitCursor(1);
990 int lastSelected = m_ctrlURL.GetCurSel();
991 CString url;
992 this->m_ctrlURL.GetWindowText(url);
994 this->m_ctrlURL.Reset();
995 CString workingDir = g_Git.m_CurrentDir;
996 workingDir.Replace(_T(':'), _T('_'));
997 this->m_ctrlURL.LoadHistory(_T("Software\\TortoiseGit\\History\\SyncURL\\") + workingDir, _T("url"));
999 STRING_VECTOR list;
1000 bool found = false;
1001 if (!g_Git.GetRemoteList(list))
1003 for (int i = 0; i < list.size(); ++i)
1005 m_ctrlURL.AddString(list[i]);
1006 if (list[i] == url)
1007 found = true;
1010 if (lastSelected >= 0 && !found)
1012 m_ctrlURL.SetCurSel(0);
1013 m_ctrlURL.GetWindowText(url);
1016 CString local;
1017 CString remote;
1018 this->m_ctrlLocalBranch.GetWindowText(local);
1019 this->m_ctrlRemoteBranch.GetWindowText(remote);
1021 this->LoadBranchInfo();
1023 this->m_ctrlLocalBranch.AddString(local);
1024 this->m_ctrlRemoteBranch.AddString(remote);
1025 this->m_ctrlURL.AddString(url);
1027 m_OutLogList.ShowText(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_REFRESHING)));
1028 this->FetchOutList(true);
1029 theApp.DoWaitCursor(-1);
1032 BOOL CSyncDlg::PreTranslateMessage(MSG* pMsg)
1034 if (pMsg->message == WM_KEYDOWN)
1036 switch (pMsg->wParam)
1039 case VK_F5:
1041 if (m_bBlock)
1042 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
1043 Refresh();
1045 break;
1047 /* Avoid TAB control destroy but dialog exist*/
1048 case VK_ESCAPE:
1049 case VK_CANCEL:
1051 TCHAR buff[128];
1052 ::GetClassName(pMsg->hwnd,buff,128);
1054 /* Use MSFTEDIT_CLASS http://msdn.microsoft.com/en-us/library/bb531344.aspx */
1055 if (_tcsnicmp(buff, MSFTEDIT_CLASS, 128) == 0 || //Unicode and MFC 2012 and later
1056 _tcsnicmp(buff, RICHEDIT_CLASS, 128) == 0 || //ANSI or MFC 2010
1057 _tcsnicmp(buff, _T("SysListView32"), 128) == 0)
1059 this->PostMessage(WM_KEYDOWN,VK_ESCAPE,0);
1060 return TRUE;
1065 m_tooltips.RelayEvent(pMsg);
1066 return __super::PreTranslateMessage(pMsg);
1068 void CSyncDlg::FetchOutList(bool force)
1070 if(!m_bInited)
1071 return;
1072 m_OutChangeFileList.Clear();
1073 this->m_OutLogList.Clear();
1075 CString remote;
1076 this->m_ctrlURL.GetWindowText(remote);
1077 CString remotebranch;
1078 this->m_ctrlRemoteBranch.GetWindowText(remotebranch);
1079 remotebranch=remote+_T("/")+remotebranch;
1080 CGitHash remotebranchHash;
1081 g_Git.GetHash(remotebranchHash, remotebranch);
1083 if(IsURL())
1085 CString str;
1086 str.LoadString(IDS_PROC_SYNC_PUSH_UNKNOWN);
1087 m_OutLogList.ShowText(str);
1088 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1089 m_OutLocalBranch.Empty();
1090 m_OutRemoteBranch.Empty();
1092 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1093 return ;
1096 else if(remotebranchHash.IsEmpty())
1098 CString str;
1099 str.Format(IDS_PROC_SYNC_PUSH_UNKNOWNBRANCH, remotebranch);
1100 m_OutLogList.ShowText(str);
1101 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1102 m_OutLocalBranch.Empty();
1103 m_OutRemoteBranch.Empty();
1105 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1106 return ;
1108 else
1110 CString localbranch;
1111 localbranch=this->m_ctrlLocalBranch.GetString();
1113 if(localbranch != m_OutLocalBranch || m_OutRemoteBranch != remotebranch || force)
1115 m_OutLogList.ClearText();
1117 CGitHash base, localBranchHash;
1118 bool isFastForward = g_Git.IsFastForward(remotebranch, localbranch, &base);
1120 if (g_Git.GetHash(localBranchHash, localbranch))
1122 MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + localbranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
1123 return;
1125 if (remotebranchHash == localBranchHash)
1127 CString str;
1128 str.Format(IDS_PROC_SYNC_COMMITSAHEAD, 0, remotebranch);
1129 m_OutLogList.ShowText(str);
1130 this->m_ctrlStatus.SetWindowText(str);
1131 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
1132 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1134 else if (isFastForward || m_bForce)
1136 CString range;
1137 range.Format(_T("%s..%s"), g_Git.FixBranchName(remotebranch), g_Git.FixBranchName(localbranch));
1138 //fast forward
1139 m_OutLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT | CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
1140 CString str;
1141 str.Format(IDS_PROC_SYNC_COMMITSAHEAD, m_OutLogList.GetItemCount(), remotebranch);
1142 this->m_ctrlStatus.SetWindowText(str);
1144 if (isFastForward)
1145 AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, remotebranch);
1146 else
1148 AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, base.ToString());
1151 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,TRUE);
1152 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(TRUE);
1154 else
1156 CString str;
1157 str.Format(IDS_PROC_SYNC_NOFASTFORWARD, localbranch, remotebranch);
1158 m_OutLogList.ShowText(str);
1159 this->m_ctrlStatus.SetWindowText(str);
1160 this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID() - 1, FALSE);
1161 this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
1164 this->m_OutLocalBranch=localbranch;
1165 this->m_OutRemoteBranch=remotebranch;
1170 bool CSyncDlg::IsURL()
1172 CString str;
1173 this->m_ctrlURL.GetWindowText(str);
1174 if(str.Find(_T('\\'))>=0 || str.Find(_T('/'))>=0)
1175 return true;
1176 else
1177 return false;
1179 void CSyncDlg::OnCbnEditchangeComboboxex()
1181 SetTimer(IDT_INPUT, 1000, NULL);
1182 this->m_OutLogList.ShowText(CString(MAKEINTRESOURCE(IDS_PROC_SYNC_WAINTINPUT)));
1184 //this->FetchOutList();
1187 UINT CSyncDlg::ProgressThread()
1189 m_startTick = GetTickCount();
1190 m_bDone = false;
1191 CProgressDlg::RunCmdList(this, m_GitCmdList, true, NULL, &this->m_bAbort, &this->m_Databuf);
1192 InterlockedExchange(&m_bBlock, FALSE);
1193 return 0;
1197 LRESULT CSyncDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)
1199 if(wParam == MSG_PROGRESSDLG_START)
1201 m_BufStart = 0;
1202 m_ctrlAnimate.Play(0, UINT_MAX, UINT_MAX);
1203 this->m_ctrlProgress.SetPos(0);
1204 if (m_pTaskbarList)
1206 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
1207 m_pTaskbarList->SetProgressValue(m_hWnd, 0, 100);
1211 if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)
1213 DWORD tickSpent = GetTickCount() - m_startTick;
1214 CString strEndTime = CLoglistUtils::FormatDateAndTime(CTime::GetCurrentTime(), DATE_SHORTDATE, true, false);
1216 m_BufStart = 0;
1217 m_Databuf.m_critSec.Lock();
1218 m_Databuf.clear();
1219 m_Databuf.m_critSec.Unlock();
1221 m_bDone = true;
1222 m_ctrlAnimate.Stop();
1223 m_ctrlProgress.SetPos(100);
1224 //this->DialogEnableWindow(IDOK,TRUE);
1226 DWORD exitCode = (DWORD)lParam;
1227 if (exitCode)
1229 if (m_pTaskbarList)
1231 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);
1232 m_pTaskbarList->SetProgressValue(m_hWnd, 100, 100);
1234 CString log;
1235 log.Format(IDS_PROC_PROGRESS_GITUNCLEANEXIT, exitCode);
1236 CString err;
1237 err.Format(_T("\r\n\r\n%s (%d ms @ %s)\r\n"), log, tickSpent, strEndTime);
1238 CProgressDlg::InsertColorText(this->m_ctrlCmdOut, err, RGB(255,0,0));
1239 CSoundUtils::PlayTGitError();
1241 else
1243 if (m_pTaskbarList)
1244 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
1245 CString temp;
1246 temp.LoadString(IDS_SUCCESS);
1247 CString log;
1248 log.Format(_T("\r\n%s (%d ms @ %s)\r\n"), temp, tickSpent, strEndTime);
1249 CProgressDlg::InsertColorText(this->m_ctrlCmdOut, log, RGB(0,0,255));
1251 m_GitCmdStatus = exitCode;
1253 //if(wParam == MSG_PROGRESSDLG_END)
1254 RunPostAction();
1257 if(lParam != 0)
1258 ParserCmdOutput((char)lParam);
1259 else
1261 m_Databuf.m_critSec.Lock();
1262 for (int i = m_BufStart; i < m_Databuf.size(); ++i)
1264 char c = m_Databuf[m_BufStart];
1265 ++m_BufStart;
1266 m_Databuf.m_critSec.Unlock();
1267 ParserCmdOutput(c);
1269 m_Databuf.m_critSec.Lock();
1272 if (m_BufStart > 1000)
1274 m_Databuf.erase(m_Databuf.begin(), m_Databuf.begin() + m_BufStart);
1275 m_BufStart = 0;
1277 m_Databuf.m_critSec.Unlock();
1280 return 0;
1283 void CSyncDlg::RunPostAction()
1285 if (m_bWantToExit)
1286 return;
1287 if (this->m_CurrentCmd == GIT_COMMAND_PUSH)
1289 if (!m_GitCmdStatus)
1291 CTGitPathList list;
1292 list.AddPath(CTGitPath(g_Git.m_CurrentDir));
1293 DWORD exitcode;
1294 CString error;
1295 if (CHooks::Instance().PostPush(list,exitcode, error))
1297 if (exitcode)
1299 CString temp;
1300 temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);
1301 //ReportError(temp);
1302 CMessageBox::Show(NULL,temp,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
1303 return;
1308 EnableControlButton(true);
1309 SwitchToInput();
1310 this->FetchOutList(true);
1312 else if (this->m_CurrentCmd == GIT_COMMAND_PULL)
1314 PullComplete();
1316 else if (this->m_CurrentCmd == GIT_COMMAND_FETCH || this->m_CurrentCmd == GIT_COMMAND_FETCHANDREBASE)
1318 FetchComplete();
1320 else if (this->m_CurrentCmd == GIT_COMMAND_SUBMODULE)
1322 //this->m_ctrlCmdOut.SetSel(-1,-1);
1323 //this->m_ctrlCmdOut.ReplaceSel(_T("Done\r\n"));
1324 //this->m_ctrlCmdOut.SetSel(-1,-1);
1325 EnableControlButton(true);
1326 SwitchToInput();
1328 else if (this->m_CurrentCmd == GIT_COMMAND_STASH)
1330 StashComplete();
1332 else if (this->m_CurrentCmd == GIT_COMMAND_REMOTE)
1334 this->FetchOutList(true);
1335 EnableControlButton(true);
1336 SwitchToInput();
1339 void CSyncDlg::ParserCmdOutput(char ch)
1341 CProgressDlg::ParserCmdOutput(m_ctrlCmdOut,m_ctrlProgress,m_hWnd,m_pTaskbarList,m_LogText,ch);
1343 void CSyncDlg::OnBnClickedButtonCommit()
1345 CString cmd = _T("/command:commit");
1346 cmd += _T(" /path:\"");
1347 cmd += g_Git.m_CurrentDir;
1348 cmd += _T("\"");
1350 CAppUtils::RunTortoiseGitProc(cmd);
1353 void CSyncDlg::OnOK()
1355 UpdateCombox();
1356 this->UpdateData();
1357 m_ctrlURL.SaveHistory();
1358 SaveHistory();
1359 m_regAutoLoadPutty = this->m_bAutoLoadPuttyKey;
1360 m_tooltips.Pop();
1361 __super::OnOK();
1364 void CSyncDlg::OnCancel()
1366 m_bAbort = true;
1367 if (m_bDone)
1369 CResizableStandAloneDialog::OnCancel();
1370 return;
1373 if (g_Git.m_CurrentGitPi.hProcess)
1375 DWORD dwConfirmKillProcess = CRegDWORD(_T("Software\\TortoiseGit\\ConfirmKillProcess"));
1376 if (dwConfirmKillProcess && CMessageBox::Show(m_hWnd, IDS_PROC_CONFIRMKILLPROCESS, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION) != IDYES)
1377 return;
1378 if (::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
1380 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess, 10000);
1382 else
1384 GetLastError();
1387 CProgressDlg::KillProcessTree(g_Git.m_CurrentGitPi.dwProcessId);
1390 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
1391 m_tooltips.Pop();
1392 CResizableStandAloneDialog::OnCancel();
1395 void CSyncDlg::OnBnClickedButtonSubmodule()
1397 this->UpdateData();
1398 UpdateCombox();
1399 m_ctrlCmdOut.SetWindowTextW(_T(""));
1400 m_LogText = "";
1402 this->m_regSubmoduleButton = (DWORD)this->m_ctrlSubmodule.GetCurrentEntry();
1404 this->SwitchToRun();
1406 this->m_bAbort=false;
1407 this->m_GitCmdList.clear();
1409 ShowTab(IDC_CMD_LOG);
1411 CString cmd;
1413 switch (m_ctrlSubmodule.GetCurrentEntry())
1415 case 0:
1416 cmd=_T("git.exe submodule update --init");
1417 break;
1418 case 1:
1419 cmd=_T("git.exe submodule init");
1420 break;
1421 case 2:
1422 cmd=_T("git.exe submodule sync");
1423 break;
1426 m_GitCmdList.push_back(cmd);
1428 m_CurrentCmd = GIT_COMMAND_SUBMODULE;
1430 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
1431 if (m_pThread==NULL)
1433 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
1435 else
1437 m_pThread->m_bAutoDelete = TRUE;
1438 m_pThread->ResumeThread();
1442 void CSyncDlg::OnBnClickedButtonStash()
1444 UpdateData();
1445 UpdateCombox();
1446 m_ctrlCmdOut.SetWindowTextW(_T(""));
1447 m_LogText = "";
1449 SwitchToRun();
1451 m_bAbort = false;
1452 m_GitCmdList.clear();
1454 ShowTab(IDC_CMD_LOG);
1456 m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST - 1, false);
1457 m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST -1, false);
1458 m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT -1, false);
1460 CString cmd;
1461 switch (m_ctrlStash.GetCurrentEntry())
1463 case 0:
1464 cmd = _T("git.exe stash save");
1465 break;
1466 case 1:
1467 cmd = _T("git.exe stash pop");
1468 break;
1469 case 2:
1470 cmd = _T("git.exe stash apply");
1471 break;
1474 m_GitCmdList.push_back(cmd);
1475 m_CurrentCmd = GIT_COMMAND_STASH;
1477 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
1478 if (!m_pThread)
1480 //ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
1482 else
1484 m_pThread->m_bAutoDelete = TRUE;
1485 m_pThread->ResumeThread();
1489 void CSyncDlg::OnTimer(UINT_PTR nIDEvent)
1491 if( nIDEvent == IDT_INPUT)
1493 KillTimer(IDT_INPUT);
1494 this->FetchOutList(true);
1499 void CSyncDlg::OnLvnInLogListColumnClick(NMHDR * /* pNMHDR */, LRESULT *pResult)
1501 *pResult = 0;
1504 LRESULT CSyncDlg::OnTaskbarBtnCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
1506 m_pTaskbarList.Release();
1507 m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
1508 m_GitProgressList.m_pTaskbarList = m_pTaskbarList;
1509 SetUUIDOverlayIcon(m_hWnd);
1510 return 0;
1513 void CSyncDlg::OnBnClickedCheckForce()
1515 UpdateData();
1518 void CSyncDlg::OnBnClickedLog()
1520 CString cmd = _T("/command:log");
1521 cmd += _T(" /path:\"");
1522 cmd += g_Git.m_CurrentDir;
1523 cmd += _T("\"");
1525 CAppUtils::RunTortoiseGitProc(cmd);
1528 LRESULT CSyncDlg::OnProgCmdFinish(WPARAM /*wParam*/, LPARAM /*lParam*/)
1530 RunPostAction();
1531 return 0;
1534 void CSyncDlg::OnDestroy()
1536 m_bWantToExit = true;
1537 __super::OnDestroy();