Use correct length for buffer
[TortoiseGit.git] / src / TortoiseProc / PullFetchDlg.cpp
blob9131215b9442decd7db8ac4c3a1c0981bc5b7be1
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 // PullFetchDlg.cpp : implementation file
23 #include "stdafx.h"
24 #include "TortoiseProc.h"
25 #include "PullFetchDlg.h"
26 #include "Git.h"
27 #include "AppUtils.h"
28 #include "BrowseRefsDlg.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_IsPull=TRUE;
38 m_bRebaseActivatedInConfigForPull = false;
39 m_bAutoLoad = CAppUtils::IsSSHPutty();
40 m_bAutoLoadEnable=CAppUtils::IsSSHPutty();;
41 m_regRebase = false;
42 m_bNoFF = false;
43 m_bRebase = FALSE;
44 m_bRebasePreserveMerges = false;
45 m_bSquash = false;
46 m_bNoCommit = false;
47 m_nDepth = 1;
48 m_bDepth = FALSE;
49 m_bFFonly = false;
50 m_bFetchTags = 2;
51 m_bAllRemotes = FALSE;
52 m_bPrune = BST_INDETERMINATE;
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)
89 END_MESSAGE_MAP()
91 BOOL CPullFetchDlg::OnInitDialog()
93 CHorizontalResizableStandAloneDialog::OnInitDialog();
94 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
96 AddAnchor(IDC_REMOTE_COMBO, TOP_LEFT, TOP_RIGHT);
97 AddAnchor(IDC_OTHER, TOP_LEFT,TOP_RIGHT);
99 AddAnchor(IDC_REMOTE_BRANCH, TOP_LEFT,TOP_RIGHT);
100 AddAnchor(IDC_BUTTON_BROWSE_REF,TOP_RIGHT);
102 AddAnchor(IDOK,BOTTOM_RIGHT);
103 AddAnchor(IDCANCEL,BOTTOM_RIGHT);
104 AddAnchor(IDC_GROUPT_REMOTE,TOP_LEFT,TOP_RIGHT);
105 AddAnchor(IDC_GROUP_OPTION,TOP_LEFT,TOP_RIGHT);
106 AddAnchor(IDC_PUTTYKEY_AUTOLOAD,BOTTOM_LEFT);
107 AddAnchor(IDC_CHECK_PRUNE,BOTTOM_LEFT);
108 AddAnchor(IDC_CHECK_REBASE,BOTTOM_LEFT);
109 AddAnchor(IDC_REMOTE_MANAGE,BOTTOM_LEFT);
110 AddAnchor(IDHELP, BOTTOM_RIGHT);
112 AdjustControlSize(IDC_REMOTE_RD);
113 AdjustControlSize(IDC_OTHER_RD);
114 AdjustControlSize(IDC_CHECK_SQUASH);
115 AdjustControlSize(IDC_CHECK_NOCOMMIT);
116 AdjustControlSize(IDC_CHECK_DEPTH);
117 AdjustControlSize(IDC_CHECK_NOFF);
118 AdjustControlSize(IDC_CHECK_FFONLY);
119 AdjustControlSize(IDC_CHECK_FETCHTAGS);
120 AdjustControlSize(IDC_PUTTYKEY_AUTOLOAD);
121 AdjustControlSize(IDC_CHECK_REBASE);
122 AdjustControlSize(IDC_CHECK_PRUNE);
124 CString WorkingDir=g_Git.m_CurrentDir;
125 WorkingDir.Replace(_T(':'),_T('_'));
127 m_RemoteReg = CRegString(CString(_T("Software\\TortoiseGit\\History\\PullRemote\\")+WorkingDir));
128 CString regkey;
129 regkey.Format(_T("Software\\TortoiseGit\\TortoiseProc\\PullFetch\\%s_%d\\rebase"), (LPCTSTR)WorkingDir, m_IsPull);
130 m_regRebase=CRegDWORD(regkey,false);
131 regkey.Format(_T("Software\\TortoiseGit\\TortoiseProc\\PullFetch\\%s_%d\\ffonly"), (LPCTSTR)WorkingDir, m_IsPull);
132 m_regFFonly = CRegDWORD(regkey, false);
133 regkey.Format(_T("Software\\TortoiseGit\\TortoiseProc\\PullFetch\\%s_%d\\autoload"), (LPCTSTR)WorkingDir, m_IsPull);
135 m_regAutoLoadPutty = CRegDWORD(regkey,this->m_bAutoLoad);
136 m_bAutoLoad = m_regAutoLoadPutty;
138 if(!CAppUtils::IsSSHPutty())
139 m_bAutoLoad = false;
141 m_bRebase = m_regRebase;
143 CAutoRepository repo(g_Git.GetGitRepository());
144 if (!repo)
145 MessageBox(CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
147 // Check config branch.<name>.rebase and pull.reabse
150 if (!m_IsPull)
151 break;
152 if (!repo)
153 break;
155 if (git_repository_head_detached(repo) == 1)
156 break;
158 CAutoConfig config(true);
159 if (git_repository_config(config.GetPointer(), repo))
160 break;
162 BOOL rebase = FALSE;
163 // branch.<name>.rebase overrides pull.rebase
164 if (config.GetBOOL(_T("branch.") + g_Git.GetCurrentBranch() + _T(".rebase"), rebase) == GIT_ENOTFOUND)
166 if (config.GetBOOL(_T("pull.rebase"), rebase) == GIT_ENOTFOUND)
167 break;
168 else if (CRegDWORD(L"Software\\TortoiseGit\\PullRebaseBehaviorLike1816", FALSE) == FALSE)
170 CString value;
171 config.GetString(_T("pull.rebase"), value);
172 if (value == _T("preserve"))
174 rebase = TRUE;
175 m_bRebasePreserveMerges = true;
179 else if (CRegDWORD(L"Software\\TortoiseGit\\PullRebaseBehaviorLike1816", FALSE) == FALSE)
181 CString value;
182 config.GetString(_T("branch.") + g_Git.GetCurrentBranch() + _T(".rebase"), value);
183 if (value == _T("preserve"))
185 rebase = TRUE;
186 m_bRebasePreserveMerges = true;
189 if (!rebase)
190 break;
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.
194 m_bRebase = TRUE;
195 m_bRebaseActivatedInConfigForPull = (CRegDWORD(L"Software\\TortoiseGit\\PullRebaseBehaviorLike1816", FALSE) == FALSE);
196 } while (0);
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 if(!m_IsPull)
210 m_RemoteBranch.EnableWindow(FALSE);
211 GetDlgItem(IDC_BUTTON_BROWSE_REF)->EnableWindow(FALSE);
214 if(m_IsPull)
216 m_bFFonly = m_regFFonly;
217 UpdateData(FALSE);
218 OnBnClickedCheckFfonly();
220 else
222 this->GetDlgItem(IDC_GROUP_OPTION)->EnableWindow(FALSE);
223 this->GetDlgItem(IDC_CHECK_SQUASH)->EnableWindow(FALSE);
224 this->GetDlgItem(IDC_CHECK_NOFF)->EnableWindow(FALSE);
225 this->GetDlgItem(IDC_CHECK_FFONLY)->EnableWindow(FALSE);
226 this->GetDlgItem(IDC_CHECK_NOCOMMIT)->EnableWindow(FALSE);
229 if (GitAdminDir::IsBareRepo(g_Git.m_CurrentDir))
230 this->GetDlgItem(IDC_CHECK_REBASE)->EnableWindow(FALSE);
232 if (repo && git_repository_is_shallow(repo))
234 m_bDepth = TRUE;
235 UpdateData(FALSE);
237 else
239 GetDlgItem(IDC_CHECK_DEPTH)->ShowWindow(SW_HIDE);
240 GetDlgItem(IDC_EDIT_DEPTH)->ShowWindow(SW_HIDE);
242 OnBnClickedCheckDepth();
244 m_Other.SetCaseSensitive(TRUE);
245 m_Other.SetURLHistory(TRUE);
246 m_Other.LoadHistory(_T("Software\\TortoiseGit\\History\\PullURLS"), _T("url"));
248 m_RemoteBranch.LoadHistory(_T("Software\\TortoiseGit\\History\\PullRemoteBranch"), _T("br"));
249 m_RemoteBranch.SetCurSel(0);
251 CString sWindowTitle;
252 if(m_IsPull)
253 sWindowTitle.LoadString(IDS_PROGRS_TITLE_PULL);
254 else
255 sWindowTitle.LoadString(IDS_PROGRS_TITLE_FETCH);
257 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
259 Refresh();
261 EnableSaveRestore(_T("PullFetchDlg"));
262 this->m_RemoteManage.SetURL(CString());
263 return TRUE;
266 void CPullFetchDlg::Refresh()
268 //Select pull-remote from current branch
269 CString currentBranch;
270 if (g_Git.GetCurrentBranchFromFile(g_Git.m_CurrentDir, currentBranch))
271 currentBranch.Empty();
273 CString pullRemote, pullBranch;
274 g_Git.GetRemoteTrackedBranch(currentBranch, pullRemote, pullBranch);
275 m_configPullRemote = pullRemote;
276 m_configPullBranch = pullBranch;
278 if (pullBranch.IsEmpty())
279 m_RemoteBranch.AddString(currentBranch);
280 else
281 m_RemoteBranch.AddString(pullBranch);
283 if(pullRemote.IsEmpty())
284 pullRemote = m_RemoteReg;
286 if (!m_PreSelectRemote.IsEmpty())
287 pullRemote = m_PreSelectRemote;
289 STRING_VECTOR list;
290 m_Remote.Reset();
291 int sel=0;
292 if(!g_Git.GetRemoteList(list))
294 if (!m_IsPull && list.size() > 1)
295 m_Remote.AddString(CString(MAKEINTRESOURCE(IDS_PROC_PUSHFETCH_ALLREMOTES)));
297 for (unsigned int i = 0; i < list.size(); ++i)
299 m_Remote.AddString(list[i]);
300 if (!m_bAllRemotes && list[i] == pullRemote)
301 sel = i + (!m_IsPull && list.size() > 1 ? 1 : 0);
304 m_Remote.SetCurSel(sel);
305 OnCbnSelchangeRemote();
307 // CPullFetchDlg message handlers
309 void CPullFetchDlg::OnCbnSelchangeRemote()
311 CString remote = m_Remote.GetString();
312 if (remote.IsEmpty() || remote == CString(MAKEINTRESOURCE(IDS_PROC_PUSHFETCH_ALLREMOTES)))
314 GetDlgItem(IDC_STATIC_TAGOPT)->SetWindowText(_T(""));
315 GetDlgItem(IDC_STATIC_PRUNE)->SetWindowText(_T(""));
316 return;
319 CString key;
320 key.Format(_T("remote.%s.tagopt"), (LPCTSTR)remote);
321 CString tagopt = g_Git.GetConfigValue(key);
322 if (tagopt == "--no-tags")
323 tagopt.LoadString(IDS_NONE);
324 else if (tagopt == "--tags")
325 tagopt.LoadString(IDS_ALL);
326 else
327 tagopt.LoadString(IDS_FETCH_REACHABLE);
328 CString value;
329 value.Format(_T("%s: %s"), (LPCTSTR)CString(MAKEINTRESOURCE(IDS_DEFAULT)), (LPCTSTR)tagopt);
330 GetDlgItem(IDC_STATIC_TAGOPT)->SetWindowText(value);
332 key.Format(_T("remote.%s.prune"), (LPCTSTR)remote);
333 CString prune = g_Git.GetConfigValue(key);
334 if (prune.IsEmpty())
335 prune = g_Git.GetConfigValue(_T("fetch.prune"));
336 if (!prune.IsEmpty())
338 value.Format(_T("%s: %s"), (LPCTSTR)CString(MAKEINTRESOURCE(IDS_DEFAULT)), (LPCTSTR)prune);
339 GetDlgItem(IDC_STATIC_PRUNE)->SetWindowText(value);
341 else
342 GetDlgItem(IDC_STATIC_PRUNE)->SetWindowText(_T(""));
345 void CPullFetchDlg::OnBnClickedRd()
347 if( GetCheckedRadioButton(IDC_REMOTE_RD,IDC_OTHER_RD) == IDC_REMOTE_RD)
349 m_Remote.EnableWindow(TRUE);
350 m_Other.EnableWindow(FALSE);
351 DialogEnableWindow(IDC_CHECK_REBASE, TRUE);
352 m_bRebase = m_bRebaseActivatedInConfigForPull;
353 UpdateData(FALSE);
354 if(!m_IsPull)
355 m_RemoteBranch.EnableWindow(FALSE);
357 if( GetCheckedRadioButton(IDC_REMOTE_RD,IDC_OTHER_RD) == IDC_OTHER_RD)
359 CString clippath = CAppUtils::GetClipboardLink(m_IsPull ? _T("git pull") : _T("git fetch"), 1);
360 if (clippath.IsEmpty())
361 m_Other.SetCurSel(0);
362 else
364 int argSeparator = clippath.Find(' ');
365 if (argSeparator > 1 && clippath.GetLength() > argSeparator + 2)
367 m_Other.SetWindowText(clippath.Left(argSeparator));
368 m_RemoteBranch.SetWindowText(clippath.Mid(argSeparator + 1));
370 else
371 m_Other.SetWindowText(clippath);
373 m_Remote.EnableWindow(FALSE);
374 m_Other.EnableWindow(TRUE);;
375 DialogEnableWindow(IDC_CHECK_REBASE, FALSE);
376 m_bRebase = FALSE;
377 UpdateData(FALSE);
378 if(!m_IsPull)
379 m_RemoteBranch.EnableWindow(TRUE);
383 void CPullFetchDlg::OnBnClickedOk()
385 this->UpdateData();
386 if( GetCheckedRadioButton(IDC_REMOTE_RD,IDC_OTHER_RD) == IDC_REMOTE_RD)
388 m_RemoteURL=m_Remote.GetString();
389 m_bAllRemotes = (m_Remote.GetCurSel() == 0 && m_Remote.GetCount() > 1 && !m_IsPull);
390 if( !m_IsPull ||
391 (m_configPullRemote == m_RemoteURL && m_configPullBranch == m_RemoteBranch.GetString() ))
392 //When fetching or when pulling from the configured tracking branch, dont explicitly set the remote branch name,
393 //because otherwise git will not update the remote tracking branches.
394 m_RemoteBranchName.Empty();
395 else
396 m_RemoteBranchName=m_RemoteBranch.GetString();
398 if( GetCheckedRadioButton(IDC_REMOTE_RD,IDC_OTHER_RD) == IDC_OTHER_RD)
400 m_Other.GetWindowTextW(m_RemoteURL);
401 m_RemoteBranchName=m_RemoteBranch.GetString();
403 // only store URL in history if it's value was used
404 m_Other.SaveHistory();
407 if (m_bRebase && m_RemoteBranch.GetString().IsEmpty() && m_IsPull)
409 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_PULL_EMPTYBRANCH, IDS_APPNAME, MB_ICONEXCLAMATION);
410 return;
413 m_RemoteReg = m_Remote.GetString();
415 m_RemoteBranch.SaveHistory();
416 this->m_regRebase=this->m_bRebase;
417 m_regFFonly = m_bFFonly;
419 m_regAutoLoadPutty = m_bAutoLoad;
421 this->OnOK();
424 void CPullFetchDlg::OnStnClickedRemoteManage()
426 CAppUtils::LaunchRemoteSetting();
427 Refresh();
430 void CPullFetchDlg::OnBnClickedButtonBrowseRef()
432 CString initialRef;
433 initialRef.Format(L"refs/remotes/%s/%s", (LPCTSTR)m_Remote.GetString(), (LPCTSTR)m_RemoteBranch.GetString());
434 CString selectedRef = CBrowseRefsDlg::PickRef(false, initialRef, gPickRef_Remote);
435 if(selectedRef.Left(13) != "refs/remotes/")
436 return;
438 selectedRef = selectedRef.Mid(13);
439 int ixSlash = selectedRef.Find('/');
441 CString remoteName = selectedRef.Left(ixSlash);
442 CString remoteBranch = selectedRef.Mid(ixSlash + 1);
444 int ixFound = m_Remote.FindStringExact(0, remoteName);
445 if(ixFound >= 0)
446 m_Remote.SetCurSel(ixFound);
447 m_RemoteBranch.AddString(remoteBranch, 0);
449 CheckRadioButton(IDC_REMOTE_RD,IDC_OTHER_RD,IDC_REMOTE_RD);
452 void CPullFetchDlg::OnBnClickedCheckDepth()
454 UpdateData(TRUE);
455 GetDlgItem(IDC_EDIT_DEPTH)->EnableWindow(m_bDepth);
458 void CPullFetchDlg::OnBnClickedCheckFfonly()
460 UpdateData();
461 if (m_bNoFF)
463 m_bFFonly = FALSE;
464 GetDlgItem(IDC_CHECK_FFONLY)->EnableWindow(FALSE);
466 else
467 GetDlgItem(IDC_CHECK_FFONLY)->EnableWindow(TRUE);
468 if (m_bFFonly)
470 m_bNoFF = FALSE;
471 GetDlgItem(IDC_CHECK_NOFF)->EnableWindow(FALSE);
473 else
474 GetDlgItem(IDC_CHECK_NOFF)->EnableWindow(TRUE);
475 UpdateData(FALSE);