1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2020 - 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 // PullFetchDlg.cpp : implementation file
24 #include "TortoiseProc.h"
25 #include "PullFetchDlg.h"
28 #include "SelectRemoteRefDlg.h"
29 #include "MessageBox.h"
30 // CPullFetchDlg dialog
32 IMPLEMENT_DYNAMIC(CPullFetchDlg
, CHorizontalResizableStandAloneDialog
)
34 CPullFetchDlg::CPullFetchDlg(CWnd
* pParent
/*=nullptr*/)
35 : CHorizontalResizableStandAloneDialog(CPullFetchDlg::IDD
, pParent
)
37 , m_bRebaseActivatedInConfigForPull(false)
38 , m_bNoFF(BST_UNCHECKED
)
39 , m_bRebase(BST_UNCHECKED
)
40 , m_bRebasePreserveMerges(false)
41 , m_bSquash(BST_UNCHECKED
)
42 , m_bNoCommit(BST_UNCHECKED
)
44 , m_bDepth(BST_UNCHECKED
)
45 , m_bFFonly(BST_UNCHECKED
)
46 , m_bFetchTags(BST_INDETERMINATE
)
47 , m_bAllRemotes(BST_UNCHECKED
)
48 , m_bPrune(BST_INDETERMINATE
)
49 , m_bAutoLoad(CAppUtils::IsSSHPutty())
50 , m_bAutoLoadEnable(CAppUtils::IsSSHPutty())
51 , m_bNamedRemoteFetchAll(!!CRegDWORD(L
"Software\\TortoiseGit\\NamedRemoteFetchAll", TRUE
))
55 CPullFetchDlg::~CPullFetchDlg()
59 void CPullFetchDlg::DoDataExchange(CDataExchange
* pDX
)
61 CDialog::DoDataExchange(pDX
);
62 DDX_Control(pDX
, IDC_REMOTE_COMBO
, this->m_Remote
);
63 DDX_Control(pDX
, IDC_OTHER
, this->m_Other
);
64 DDX_Control(pDX
, IDC_REMOTE_BRANCH
, this->m_RemoteBranch
);
65 DDX_Control(pDX
,IDC_REMOTE_MANAGE
, this->m_RemoteManage
);
66 DDX_Check(pDX
,IDC_CHECK_NOFF
, this->m_bNoFF
);
67 DDX_Check(pDX
,IDC_CHECK_SQUASH
, this->m_bSquash
);
68 DDX_Check(pDX
,IDC_CHECK_NOCOMMIT
, this->m_bNoCommit
);
69 DDX_Check(pDX
,IDC_PUTTYKEY_AUTOLOAD
,m_bAutoLoad
);
70 DDX_Check(pDX
,IDC_CHECK_REBASE
,m_bRebase
);
71 DDX_Check(pDX
,IDC_CHECK_PRUNE
,m_bPrune
);
72 DDX_Check(pDX
, IDC_CHECK_DEPTH
, m_bDepth
);
73 DDX_Text(pDX
, IDC_EDIT_DEPTH
, m_nDepth
);
74 DDX_Check(pDX
, IDC_CHECK_FFONLY
, m_bFFonly
);
75 DDX_Check(pDX
, IDC_CHECK_FETCHTAGS
, m_bFetchTags
);
79 BEGIN_MESSAGE_MAP(CPullFetchDlg
, CHorizontalResizableStandAloneDialog
)
80 ON_CBN_SELCHANGE(IDC_REMOTE_COMBO
, &CPullFetchDlg::OnCbnSelchangeRemote
)
81 ON_BN_CLICKED(IDC_REMOTE_RD
, &CPullFetchDlg::OnBnClickedRd
)
82 ON_BN_CLICKED(IDC_OTHER_RD
, &CPullFetchDlg::OnBnClickedRd
)
83 ON_BN_CLICKED(IDOK
, &CPullFetchDlg::OnBnClickedOk
)
84 ON_STN_CLICKED(IDC_REMOTE_MANAGE
, &CPullFetchDlg::OnStnClickedRemoteManage
)
85 ON_BN_CLICKED(IDC_BUTTON_BROWSE_REF
, &CPullFetchDlg::OnBnClickedButtonBrowseRef
)
86 ON_BN_CLICKED(IDC_CHECK_DEPTH
, OnBnClickedCheckDepth
)
87 ON_BN_CLICKED(IDC_CHECK_FFONLY
, OnBnClickedCheckFfonly
)
88 ON_BN_CLICKED(IDC_CHECK_NOFF
, OnBnClickedCheckFfonly
)
91 BOOL
CPullFetchDlg::OnInitDialog()
93 CHorizontalResizableStandAloneDialog::OnInitDialog();
94 CAppUtils::MarkWindowAsUnpinnable(m_hWnd
);
96 AdjustControlSize(IDC_REMOTE_RD
);
97 AdjustControlSize(IDC_OTHER_RD
);
98 AdjustControlSize(IDC_CHECK_SQUASH
);
99 AdjustControlSize(IDC_CHECK_NOCOMMIT
);
100 AdjustControlSize(IDC_CHECK_DEPTH
);
101 AdjustControlSize(IDC_CHECK_NOFF
);
102 AdjustControlSize(IDC_CHECK_FFONLY
);
103 AdjustControlSize(IDC_CHECK_FETCHTAGS
);
104 AdjustControlSize(IDC_PUTTYKEY_AUTOLOAD
);
105 AdjustControlSize(IDC_CHECK_REBASE
);
106 AdjustControlSize(IDC_CHECK_PRUNE
);
108 AddAnchor(IDC_REMOTE_COMBO
, TOP_LEFT
, TOP_RIGHT
);
109 AddAnchor(IDC_OTHER
, TOP_LEFT
,TOP_RIGHT
);
111 AddAnchor(IDC_REMOTE_BRANCH
, TOP_LEFT
,TOP_RIGHT
);
112 AddAnchor(IDC_BUTTON_BROWSE_REF
,TOP_RIGHT
);
114 AddAnchor(IDOK
,BOTTOM_RIGHT
);
115 AddAnchor(IDCANCEL
,BOTTOM_RIGHT
);
116 AddAnchor(IDC_GROUPT_REMOTE
,TOP_LEFT
,TOP_RIGHT
);
117 AddAnchor(IDC_GROUP_OPTION
,TOP_LEFT
,TOP_RIGHT
);
118 AddAnchor(IDC_PUTTYKEY_AUTOLOAD
,BOTTOM_LEFT
);
119 AddAnchor(IDC_CHECK_PRUNE
,BOTTOM_LEFT
);
120 AddAnchor(IDC_CHECK_REBASE
,BOTTOM_LEFT
);
121 AddAnchor(IDC_REMOTE_MANAGE
,BOTTOM_LEFT
);
122 AddAnchor(IDHELP
, BOTTOM_RIGHT
);
124 CString WorkingDir
=g_Git
.m_CurrentDir
;
125 WorkingDir
.Replace(L
':', L
'_');
127 m_RemoteReg
= CRegString(L
"Software\\TortoiseGit\\History\\PullRemote\\" + WorkingDir
);
129 regkey
.Format(L
"Software\\TortoiseGit\\TortoiseProc\\PullFetch\\%s_%d\\rebase", static_cast<LPCTSTR
>(WorkingDir
), m_IsPull
);
130 m_regRebase
=CRegDWORD(regkey
,false);
131 regkey
.Format(L
"Software\\TortoiseGit\\TortoiseProc\\PullFetch\\%s_%d\\ffonly", static_cast<LPCTSTR
>(WorkingDir
), m_IsPull
);
132 m_regFFonly
= CRegDWORD(regkey
, false);
133 regkey
.Format(L
"Software\\TortoiseGit\\TortoiseProc\\PullFetch\\%s_%d\\autoload", static_cast<LPCTSTR
>(WorkingDir
), m_IsPull
);
135 m_regAutoLoadPutty
= CRegDWORD(regkey
,this->m_bAutoLoad
);
136 m_bAutoLoad
= m_regAutoLoadPutty
;
138 if(!CAppUtils::IsSSHPutty())
141 m_bRebase
= m_regRebase
;
143 CAutoRepository
repo(g_Git
.GetGitRepository());
145 MessageBox(CGit::GetLibGit2LastErr(L
"Could not open repository."), L
"TortoiseGit", MB_OK
| MB_ICONERROR
);
147 // Check config branch.<name>.rebase and pull.reabse
155 if (git_repository_head_detached(repo
) == 1)
158 CAutoConfig
config(true);
159 if (git_repository_config(config
.GetPointer(), repo
))
163 // branch.<name>.rebase overrides pull.rebase
164 if (config
.GetBOOL(L
"branch." + g_Git
.GetCurrentBranch() + L
".rebase", rebase
) == GIT_ENOTFOUND
)
166 if (config
.GetBOOL(L
"pull.rebase", rebase
) == GIT_ENOTFOUND
)
171 config
.GetString(L
"pull.rebase", value
);
172 if (value
== L
"preserve")
175 m_bRebasePreserveMerges
= true;
182 config
.GetString(L
"branch." + g_Git
.GetCurrentBranch() + L
".rebase", value
);
183 if (value
== L
"preserve")
186 m_bRebasePreserveMerges
= true;
192 // Since rebase = true in config, means that "git.exe pull" will ALWAYS rebase without "--rebase".
193 // So, lock it, then let Fetch Rebase do the rest things.
195 m_bRebaseActivatedInConfigForPull
= true;
198 this->UpdateData(FALSE
);
200 this->AddOthersToAnchor();
202 this->GetDlgItem(IDC_PUTTYKEY_AUTOLOAD
)->EnableWindow(m_bAutoLoadEnable
);
204 CheckRadioButton(IDC_REMOTE_RD
,IDC_OTHER_RD
,IDC_REMOTE_RD
);
205 m_Remote
.EnableWindow(TRUE
);
206 m_Remote
.SetMaxHistoryItems(0x7FFFFFFF);
207 m_Other
.EnableWindow(FALSE
);
208 m_RemoteBranch
.SetCaseSensitive(TRUE
);
209 if (!m_IsPull
&& m_bNamedRemoteFetchAll
)
211 m_RemoteBranch
.EnableWindow(FALSE
);
212 GetDlgItem(IDC_BUTTON_BROWSE_REF
)->EnableWindow(FALSE
);
217 m_bFFonly
= m_regFFonly
;
219 OnBnClickedCheckFfonly();
223 this->GetDlgItem(IDC_GROUP_OPTION
)->EnableWindow(FALSE
);
224 this->GetDlgItem(IDC_CHECK_SQUASH
)->EnableWindow(FALSE
);
225 this->GetDlgItem(IDC_CHECK_NOFF
)->EnableWindow(FALSE
);
226 this->GetDlgItem(IDC_CHECK_FFONLY
)->EnableWindow(FALSE
);
227 this->GetDlgItem(IDC_CHECK_NOCOMMIT
)->EnableWindow(FALSE
);
230 if (GitAdminDir::IsBareRepo(g_Git
.m_CurrentDir
))
231 this->GetDlgItem(IDC_CHECK_REBASE
)->EnableWindow(FALSE
);
233 if (repo
&& git_repository_is_shallow(repo
))
240 GetDlgItem(IDC_CHECK_DEPTH
)->ShowWindow(SW_HIDE
);
241 GetDlgItem(IDC_EDIT_DEPTH
)->ShowWindow(SW_HIDE
);
243 OnBnClickedCheckDepth();
245 m_Other
.SetCaseSensitive(TRUE
);
246 m_Other
.SetURLHistory(TRUE
);
247 m_Other
.LoadHistory(L
"Software\\TortoiseGit\\History\\PullURLS", L
"url");
249 m_RemoteBranch
.LoadHistory(L
"Software\\TortoiseGit\\History\\PullRemoteBranch", L
"br");
250 m_RemoteBranch
.SetCurSel(0);
252 CString sWindowTitle
;
254 sWindowTitle
.LoadString(IDS_PROGRS_TITLE_PULL
);
256 sWindowTitle
.LoadString(IDS_PROGRS_TITLE_FETCH
);
258 CAppUtils::SetWindowTitle(m_hWnd
, g_Git
.m_CurrentDir
, sWindowTitle
);
262 EnableSaveRestore(L
"PullFetchDlg");
263 this->m_RemoteManage
.SetURL(CString());
264 SetTheme(CTheme::Instance().IsDarkTheme());
268 void CPullFetchDlg::Refresh()
270 //Select pull-remote from current branch
271 CString currentBranch
;
272 if (g_Git
.GetCurrentBranchFromFile(g_Git
.m_CurrentDir
, currentBranch
))
273 currentBranch
.Empty();
275 CString pullRemote
, pullBranch
;
276 g_Git
.GetRemoteTrackedBranch(currentBranch
, pullRemote
, pullBranch
);
277 m_configPullRemote
= pullRemote
;
278 m_configPullBranch
= pullBranch
;
280 if (pullBranch
.IsEmpty())
281 m_RemoteBranch
.AddString(currentBranch
);
283 m_RemoteBranch
.AddString(pullBranch
);
285 if(pullRemote
.IsEmpty())
286 pullRemote
= m_RemoteReg
;
288 if (!m_PreSelectRemote
.IsEmpty())
289 pullRemote
= m_PreSelectRemote
;
294 if(!g_Git
.GetRemoteList(list
))
296 if (!m_IsPull
&& list
.size() > 1)
297 m_Remote
.AddString(CString(MAKEINTRESOURCE(IDS_PROC_PUSHFETCH_ALLREMOTES
)));
299 for (unsigned int i
= 0; i
< list
.size(); ++i
)
301 m_Remote
.AddString(list
[i
]);
302 if (!m_bAllRemotes
&& list
[i
] == pullRemote
)
303 sel
= i
+ (!m_IsPull
&& list
.size() > 1 ? 1 : 0);
306 m_Remote
.SetCurSel(sel
);
307 OnCbnSelchangeRemote();
309 // CPullFetchDlg message handlers
311 void CPullFetchDlg::OnCbnSelchangeRemote()
313 CString remote
= m_Remote
.GetString();
314 if (remote
.IsEmpty() || remote
== CString(MAKEINTRESOURCE(IDS_PROC_PUSHFETCH_ALLREMOTES
)))
316 GetDlgItem(IDC_STATIC_TAGOPT
)->SetWindowText(L
"");
317 GetDlgItem(IDC_STATIC_PRUNE
)->SetWindowText(L
"");
322 key
.Format(L
"remote.%s.tagopt", static_cast<LPCTSTR
>(remote
));
323 CString tagopt
= g_Git
.GetConfigValue(key
);
324 if (tagopt
== "--no-tags")
325 tagopt
.LoadString(IDS_NONE
);
326 else if (tagopt
== "--tags")
327 tagopt
.LoadString(IDS_ALL
);
329 tagopt
.LoadString(IDS_FETCH_REACHABLE
);
331 value
.Format(L
"%s: %s", static_cast<LPCTSTR
>(CString(MAKEINTRESOURCE(IDS_DEFAULT
))), static_cast<LPCTSTR
>(tagopt
));
332 GetDlgItem(IDC_STATIC_TAGOPT
)->SetWindowText(value
);
334 key
.Format(L
"remote.%s.prune", static_cast<LPCTSTR
>(remote
));
335 CString prune
= g_Git
.GetConfigValue(key
);
337 prune
= g_Git
.GetConfigValue(L
"fetch.prune");
338 if (!prune
.IsEmpty())
340 value
.Format(L
"%s: %s", static_cast<LPCTSTR
>(CString(MAKEINTRESOURCE(IDS_DEFAULT
))), static_cast<LPCTSTR
>(prune
));
341 GetDlgItem(IDC_STATIC_PRUNE
)->SetWindowText(value
);
344 GetDlgItem(IDC_STATIC_PRUNE
)->SetWindowText(L
"");
347 void CPullFetchDlg::OnBnClickedRd()
349 if( GetCheckedRadioButton(IDC_REMOTE_RD
,IDC_OTHER_RD
) == IDC_REMOTE_RD
)
351 m_Remote
.EnableWindow(TRUE
);
352 m_Other
.EnableWindow(FALSE
);
353 DialogEnableWindow(IDC_CHECK_REBASE
, TRUE
);
354 m_bRebase
= m_bRebaseActivatedInConfigForPull
;
356 if (!m_IsPull
&& m_bNamedRemoteFetchAll
)
358 m_RemoteBranch
.EnableWindow(FALSE
);
359 GetDlgItem(IDC_BUTTON_BROWSE_REF
)->EnableWindow(FALSE
);
362 if( GetCheckedRadioButton(IDC_REMOTE_RD
,IDC_OTHER_RD
) == IDC_OTHER_RD
)
364 CString clippath
= CAppUtils::GetClipboardLink(m_IsPull
? L
"git pull" : L
"git fetch", 1);
365 if (clippath
.IsEmpty())
366 clippath
= CAppUtils::GetClipboardLink(!m_IsPull
? L
"git pull" : L
"git fetch", 1);
367 if (clippath
.IsEmpty())
368 m_Other
.SetCurSel(0);
371 int argSeparator
= clippath
.Find(' ');
372 if (argSeparator
> 1 && clippath
.GetLength() > argSeparator
+ 2)
374 CString url
= clippath
.Left(argSeparator
);
375 if (url
.GetLength() > 2 && url
[0] == L
'"' && url
[url
.GetLength() - 1] == L
'"')
376 url
= url
.Mid(1, url
.GetLength() - 2);
377 m_Other
.SetWindowText(url
);
378 CString branch
= clippath
.Mid(argSeparator
+ 1);
379 if (branch
.GetLength() > 2 && branch
[0] == L
'"' && branch
[branch
.GetLength() - 1] == L
'"')
380 branch
= branch
.Mid(1, branch
.GetLength() - 2);
381 m_RemoteBranch
.SetWindowText(branch
);
384 m_Other
.SetWindowText(clippath
);
386 m_Remote
.EnableWindow(FALSE
);
387 m_Other
.EnableWindow(TRUE
);;
388 DialogEnableWindow(IDC_CHECK_REBASE
, FALSE
);
393 m_RemoteBranch
.EnableWindow(TRUE
);
394 GetDlgItem(IDC_BUTTON_BROWSE_REF
)->EnableWindow(TRUE
);
399 void CPullFetchDlg::OnBnClickedOk()
402 if( GetCheckedRadioButton(IDC_REMOTE_RD
,IDC_OTHER_RD
) == IDC_REMOTE_RD
)
404 m_RemoteURL
=m_Remote
.GetString();
405 m_bAllRemotes
= (m_Remote
.GetCurSel() == 0 && m_Remote
.GetCount() > 1 && !m_IsPull
);
406 if (m_bNamedRemoteFetchAll
&& (!m_IsPull
||
407 (m_configPullRemote
== m_RemoteURL
&& m_configPullBranch
== m_RemoteBranch
.GetString())))
408 //When fetching or when pulling from the configured tracking branch, dont explicitly set the remote branch name,
409 //because otherwise git will not update the remote tracking branches.
410 m_RemoteBranchName
.Empty();
412 m_RemoteBranchName
=m_RemoteBranch
.GetString();
414 if( GetCheckedRadioButton(IDC_REMOTE_RD
,IDC_OTHER_RD
) == IDC_OTHER_RD
)
416 m_RemoteURL
= m_Other
.GetString();
417 m_RemoteBranchName
=m_RemoteBranch
.GetString();
419 // only store URL in history if it's value was used
420 m_Other
.SaveHistory();
423 if (m_bRebase
&& m_RemoteBranch
.GetString().IsEmpty() && m_IsPull
)
425 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_PULL_EMPTYBRANCH
, IDS_APPNAME
, MB_ICONEXCLAMATION
);
429 m_RemoteReg
= m_Remote
.GetString();
431 m_RemoteBranch
.SaveHistory();
432 this->m_regRebase
=this->m_bRebase
;
433 m_regFFonly
= m_bFFonly
;
435 m_regAutoLoadPutty
= m_bAutoLoad
;
440 void CPullFetchDlg::OnStnClickedRemoteManage()
442 CAppUtils::LaunchRemoteSetting();
446 void CPullFetchDlg::OnBnClickedButtonBrowseRef()
448 CSelectRemoteRefDlg dlg
;
449 if (GetCheckedRadioButton(IDC_REMOTE_RD
, IDC_OTHER_RD
) == IDC_REMOTE_RD
)
450 dlg
.m_sRemote
= m_Remote
.GetString();
451 else if (GetCheckedRadioButton(IDC_REMOTE_RD
, IDC_OTHER_RD
) == IDC_OTHER_RD
)
452 dlg
.m_sRemote
= m_Other
.GetString();
458 if (!dlg
.DoModal() == IDOK
&& !dlg
.m_sRemoteBranch
.IsEmpty())
460 m_RemoteBranch
.AddString(dlg
.m_sRemoteBranch
, 0);
463 void CPullFetchDlg::OnBnClickedCheckDepth()
466 GetDlgItem(IDC_EDIT_DEPTH
)->EnableWindow(m_bDepth
);
469 void CPullFetchDlg::OnBnClickedCheckFfonly()
475 GetDlgItem(IDC_CHECK_FFONLY
)->EnableWindow(FALSE
);
478 GetDlgItem(IDC_CHECK_FFONLY
)->EnableWindow(TRUE
);
482 GetDlgItem(IDC_CHECK_NOFF
)->EnableWindow(FALSE
);
485 GetDlgItem(IDC_CHECK_NOFF
)->EnableWindow(TRUE
);