PushDlg: Prevent users from pushing if no remote archive is selected
[TortoiseGit.git] / src / TortoiseProc / PushDlg.cpp
blobef155b20246524b18e2ec996dc8cd0d64510844f
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2012 - 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 // PushDlg.cpp : implementation file
23 #include "stdafx.h"
24 #include "TortoiseProc.h"
25 #include "PushDlg.h"
27 #include "Git.h"
28 #include "registry.h"
29 #include "AppUtils.h"
30 #include "LogDlg.h"
31 #include "BrowseRefsDlg.h"
32 #include "RefLogDlg.h"
33 #include "MessageBox.h"
35 // CPushDlg dialog
37 IMPLEMENT_DYNAMIC(CPushDlg, CHorizontalResizableStandAloneDialog)
39 CPushDlg::CPushDlg(CWnd* pParent /*=NULL*/)
40 : CHorizontalResizableStandAloneDialog(CPushDlg::IDD, pParent)
41 , m_bPushAllBranches(FALSE)
42 , m_bForce(FALSE)
43 , m_bPack(FALSE)
44 , m_bTags(FALSE)
45 , m_bAutoLoad(FALSE)
46 , m_bPushAllRemotes(FALSE)
48 m_bAutoLoad = CAppUtils::IsSSHPutty();
51 CPushDlg::~CPushDlg()
55 void CPushDlg::DoDataExchange(CDataExchange* pDX)
57 CHorizontalResizableStandAloneDialog::DoDataExchange(pDX);
58 DDX_Control(pDX, IDC_BRANCH_REMOTE, this->m_BranchRemote);
59 DDX_Control(pDX, IDC_BRANCH_SOURCE, this->m_BranchSource);
60 DDX_Control(pDX, IDC_REMOTE, this->m_Remote);
61 DDX_Control(pDX, IDC_URL, this->m_RemoteURL);
62 DDX_Control(pDX, IDC_BUTTON_BROWSE_SOURCE_BRANCH, m_BrowseLocalRef);
63 DDX_Check(pDX,IDC_FORCE,this->m_bForce);
64 DDX_Check(pDX,IDC_PUSHALL,this->m_bPushAllBranches);
65 DDX_Check(pDX,IDC_PACK,this->m_bPack);
66 DDX_Check(pDX,IDC_TAGS,this->m_bTags);
67 DDX_Check(pDX,IDC_PUTTYKEY_AUTOLOAD,this->m_bAutoLoad);
70 BEGIN_MESSAGE_MAP(CPushDlg, CHorizontalResizableStandAloneDialog)
71 ON_BN_CLICKED(IDC_RD_REMOTE, &CPushDlg::OnBnClickedRd)
72 ON_BN_CLICKED(IDC_RD_URL, &CPushDlg::OnBnClickedRd)
73 ON_CBN_SELCHANGE(IDC_BRANCH_SOURCE, &CPushDlg::OnCbnSelchangeBranchSource)
74 ON_BN_CLICKED(IDOK, &CPushDlg::OnBnClickedOk)
75 ON_BN_CLICKED(IDC_REMOTE_MANAGE, &CPushDlg::OnBnClickedRemoteManage)
76 ON_BN_CLICKED(IDC_BUTTON_BROWSE_SOURCE_BRANCH, &CPushDlg::OnBnClickedButtonBrowseSourceBranch)
77 ON_BN_CLICKED(IDC_BUTTON_BROWSE_DEST_BRANCH, &CPushDlg::OnBnClickedButtonBrowseDestBranch)
78 ON_BN_CLICKED(IDC_PUSHALL, &CPushDlg::OnBnClickedPushall)
79 END_MESSAGE_MAP()
81 BOOL CPushDlg::OnInitDialog()
83 CHorizontalResizableStandAloneDialog::OnInitDialog();
84 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
86 AddAnchor(IDOK,BOTTOM_RIGHT);
87 AddAnchor(IDCANCEL,BOTTOM_RIGHT);
88 AddAnchor(IDC_BRANCH_GROUP, TOP_LEFT,TOP_RIGHT);
89 AddAnchor(IDC_STATIC_REMOTE, TOP_LEFT);
90 AddAnchor(IDC_STATIC_SOURCE, TOP_LEFT);
92 AddAnchor(IDC_PUSHALL, TOP_LEFT);
93 AddAnchor(IDC_BRANCH_REMOTE, TOP_LEFT, TOP_RIGHT);
94 AddAnchor(IDC_BUTTON_BROWSE_DEST_BRANCH, TOP_RIGHT);
95 AddAnchor(IDC_BRANCH_SOURCE, TOP_LEFT, TOP_RIGHT);
96 AddAnchor(IDC_BUTTON_BROWSE_SOURCE_BRANCH, TOP_RIGHT);
98 AddAnchor(IDC_URL_GROUP, TOP_LEFT,TOP_RIGHT);
99 AddAnchor(IDC_RD_REMOTE, TOP_LEFT);
100 AddAnchor(IDC_RD_URL, TOP_LEFT);
102 AddAnchor(IDC_REMOTE, TOP_LEFT, TOP_RIGHT);
104 AddAnchor(IDC_URL, TOP_LEFT,TOP_RIGHT);
106 AddAnchor(IDC_OPTION_GROUP, TOP_LEFT,TOP_RIGHT);
108 AddAnchor(IDC_FORCE, TOP_LEFT);
109 AddAnchor(IDC_PACK, TOP_LEFT);
110 AddAnchor(IDC_TAGS, TOP_LEFT);
111 AddAnchor(IDC_PUTTYKEY_AUTOLOAD,TOP_LEFT);
113 AddAnchor(IDC_REMOTE_MANAGE,TOP_RIGHT);
114 AddAnchor(IDHELP, BOTTOM_RIGHT);
116 AddOthersToAnchor();
118 AdjustControlSize(IDC_RD_REMOTE);
119 AdjustControlSize(IDC_RD_URL);
120 AdjustControlSize(IDC_PUSHALL);
121 AdjustControlSize(IDC_FORCE);
122 AdjustControlSize(IDC_PACK);
123 AdjustControlSize(IDC_TAGS);
124 AdjustControlSize(IDC_PUTTYKEY_AUTOLOAD);
126 CString sWindowTitle;
127 GetWindowText(sWindowTitle);
128 CAppUtils::SetWindowTitle(m_hWnd, g_Git.m_CurrentDir, sWindowTitle);
130 this->GetDlgItem(IDC_PUTTYKEY_AUTOLOAD)->EnableWindow(CAppUtils::IsSSHPutty());
132 EnableSaveRestore(_T("PushDlg"));
134 m_RemoteURL.SetURLHistory(TRUE);
136 CString WorkingDir=g_Git.m_CurrentDir;
137 WorkingDir.Replace(_T(':'),_T('_'));
138 m_RemoteURL.LoadHistory(CString(_T("Software\\TortoiseGit\\History\\PushURLS\\"))+WorkingDir, _T("url"));
139 CString clippath=CAppUtils::GetClipboardLink();
140 if(clippath.IsEmpty())
141 m_RemoteURL.SetCurSel(0);
142 else
143 m_RemoteURL.SetWindowText(clippath);
145 m_RemoteURL.EnableWindow(FALSE);
146 CheckRadioButton(IDC_RD_REMOTE,IDC_RD_URL,IDC_RD_REMOTE);
149 this->m_regAutoLoad = CRegDWORD(CString(_T("Software\\TortoiseGit\\History\\PushDlgAutoLoad\\"))+WorkingDir,
150 m_bAutoLoad);
151 m_bAutoLoad = this->m_regAutoLoad;
152 if(!CAppUtils::IsSSHPutty())
153 m_bAutoLoad = false;
155 m_BrowseLocalRef.m_bRightArrow = TRUE;
156 m_BrowseLocalRef.m_bDefaultClick = FALSE;
157 m_BrowseLocalRef.m_bMarkDefault = FALSE;
158 m_BrowseLocalRef.AddEntry(CString(MAKEINTRESOURCE(IDS_REFBROWSE)));
159 m_BrowseLocalRef.AddEntry(CString(MAKEINTRESOURCE(IDS_LOG)));
160 m_BrowseLocalRef.AddEntry(CString(MAKEINTRESOURCE(IDS_REFLOG)));
162 Refresh();
165 //m_BranchRemote.SetWindowTextW(m_BranchSource.GetString());
167 this->UpdateData(false);
168 return TRUE;
171 void CPushDlg::Refresh()
173 CString WorkingDir=g_Git.m_CurrentDir;
174 WorkingDir.Replace(_T(':'),_T('_'));
176 CRegString remote(CString(_T("Software\\TortoiseGit\\History\\PushRemote\\")+WorkingDir));
177 m_RemoteReg = remote;
178 int sel = -1;
180 STRING_VECTOR list;
181 m_Remote.Reset();
183 list.push_back(CString(MAKEINTRESOURCE(IDS_PROC_PUSHFETCH_ALLREMOTES)));
184 if(!g_Git.GetRemoteList(list))
186 if (list.size() <= 2)
187 list.erase(list.begin());
189 for(unsigned int i=0;i<list.size();i++)
191 m_Remote.AddString(list[i]);
192 if(list[i] == remote)
193 sel = i;
196 // if the last selected remote was "- All -" and "- All -" is still in the list -> select it
197 if (list.size() > 1 && remote == CString(MAKEINTRESOURCE(IDS_PROC_PUSHFETCH_ALLREMOTES)))
198 sel = 0;
199 m_Remote.SetCurSel(sel);
201 int current=0;
202 list.clear();
203 m_BranchSource.Reset();
204 m_BranchSource.AddString(_T(" ")); // empty string does not work, for removal of remote branches/tags
205 m_BranchSource.SetMaxHistoryItems(0x7FFFFFFF);
206 if(!g_Git.GetBranchList(list,&current))
208 for(unsigned int i=0;i<list.size();i++)
209 m_BranchSource.AddString(list[i]);
210 current++; // shift for " "
212 if (wcsncmp(m_BranchSourceName, _T("refs/"), 5) == 0)
213 m_BranchSourceName = m_BranchSourceName.Mid(5);
214 if (wcsncmp(m_BranchSourceName, _T("heads/"), 6) == 0)
216 m_BranchSourceName = m_BranchSourceName.Mid(6);
217 m_BranchSource.SetCurSel(m_BranchSource.FindStringExact(-1, m_BranchSourceName));
219 else if (wcsncmp(m_BranchSourceName, _T("remotes/"), 8) == 0)
220 m_BranchSource.SetCurSel(m_BranchSource.FindStringExact(-1, m_BranchSourceName));
221 else
222 m_BranchSource.SetCurSel(current);
224 GetRemoteBranch(m_BranchSource.GetString());
226 this->GetDlgItem(IDOK)->EnableWindow(m_BranchSource.GetCount() != 0);
229 void CPushDlg::GetRemoteBranch(CString currentBranch)
231 CString WorkingDir=g_Git.m_CurrentDir;
232 WorkingDir.Replace(_T(':'), _T('_'));
234 if (currentBranch.IsEmpty())
235 return;
237 CString configName;
239 configName.Format(L"branch.%s.pushremote", currentBranch);
240 CString pushRemote = g_Git.GetConfigValue(configName);
241 if( pushRemote.IsEmpty() )
243 configName.Format(L"branch.%s.remote", currentBranch);
244 pushRemote = g_Git.GetConfigValue(configName);
247 CRegString remote(CString(_T("Software\\TortoiseGit\\History\\PushRemote\\")+WorkingDir));
249 if (!pushRemote.IsEmpty())
251 remote = pushRemote;
252 // if a pushRemote exists, select it
253 for (int i = 0; i < m_Remote.GetCount(); i++)
255 CString str;
256 int n = m_Remote.GetLBTextLen(i);
257 m_Remote.GetLBText(i, str.GetBuffer(n));
258 str.ReleaseBuffer();
259 if (str == pushRemote)
261 m_Remote.SetCurSel(i);
262 break;
266 // select no remote if no push-remote is specified AND push to all remotes is not selected
267 else if (!(m_Remote.GetCount() > 1 && m_Remote.GetCurSel() == 0))
269 m_Remote.SetCurSel(-1);
272 //Select pull-branch from current branch
273 configName.Format(L"branch.%s.pushbranch", currentBranch);
274 CString pushBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));
275 if( pushBranch.IsEmpty() )
277 configName.Format(L"branch.%s.merge", currentBranch);
278 pushBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));
281 m_BranchRemote.LoadHistory(CString(_T("Software\\TortoiseGit\\History\\RemoteBranch\\"))+WorkingDir, _T("branch"));
282 if( !pushBranch.IsEmpty() )
283 m_BranchRemote.AddString(pushBranch);
286 // CPushDlg message handlers
288 void CPushDlg::OnBnClickedRd()
290 if( GetCheckedRadioButton(IDC_RD_REMOTE,IDC_RD_URL) == IDC_RD_REMOTE)
292 m_Remote.EnableWindow(TRUE);
293 GetDlgItem(IDC_REMOTE_MANAGE)->EnableWindow(TRUE);
294 m_RemoteURL.EnableWindow(FALSE);
296 if( GetCheckedRadioButton(IDC_RD_REMOTE,IDC_RD_URL) == IDC_RD_URL)
298 m_Remote.EnableWindow(FALSE);
299 GetDlgItem(IDC_REMOTE_MANAGE)->EnableWindow(FALSE);
300 m_RemoteURL.EnableWindow(TRUE);
305 void CPushDlg::OnCbnSelchangeBranchSource()
307 GetRemoteBranch(m_BranchSource.GetString());
310 void CPushDlg::OnBnClickedOk()
312 CHorizontalResizableStandAloneDialog::UpdateData(TRUE);
314 if( GetCheckedRadioButton(IDC_RD_REMOTE,IDC_RD_URL) == IDC_RD_REMOTE)
316 m_URL=m_Remote.GetString();
317 if (m_URL.IsEmpty())
319 CMessageBox::Show(NULL, IDS_PROC_GITCONFIG_REMOTEEMPTY, IDS_APPNAME, MB_OK);
320 return;
322 m_bPushAllRemotes = (m_Remote.GetCurSel() == 0 && m_Remote.GetCount() > 1);
324 if( GetCheckedRadioButton(IDC_RD_REMOTE,IDC_RD_URL) == IDC_RD_URL)
326 m_URL=m_RemoteURL.GetString();
329 if (!m_bPushAllBranches)
331 this->m_BranchRemoteName=m_BranchRemote.GetString().Trim();
332 this->m_BranchSourceName=m_BranchSource.GetString().Trim();
334 if (m_BranchSourceName.IsEmpty() && m_BranchRemoteName.IsEmpty())
336 if (CMessageBox::Show(NULL, IDS_B_T_BOTHEMPTY, IDS_APPNAME, MB_ICONQUESTION | MB_YESNO) == IDNO)
337 return;
339 if (m_BranchSourceName.IsEmpty() && !m_BranchRemoteName.IsEmpty())
341 if (CMessageBox::Show(NULL, IDS_B_T_LOCALEMPTY, IDS_APPNAME, MB_ICONEXCLAMATION | MB_YESNO) == IDNO)
342 return;
344 else if (!m_BranchRemoteName.IsEmpty() && !g_Git.IsBranchNameValid(this->m_BranchRemoteName))
346 CMessageBox::Show(NULL, IDS_B_T_INVALID, IDS_APPNAME, MB_OK);
347 return;
349 else
351 // do not store branch names on removal
352 this->m_RemoteURL.SaveHistory();
353 this->m_BranchRemote.SaveHistory();
354 m_RemoteReg = m_Remote.GetString();
356 if (!m_BranchSourceName.IsEmpty() && !g_Git.IsBranchTagNameUnique(m_BranchSourceName))
358 CMessageBox::Show(NULL, IDS_B_T_NOT_UNIQUE, IDS_APPNAME, MB_OK | MB_ICONEXCLAMATION);
359 return;
363 this->m_regAutoLoad = m_bAutoLoad ;
365 CHorizontalResizableStandAloneDialog::OnOK();
368 void CPushDlg::OnBnClickedRemoteManage()
370 CAppUtils::LaunchRemoteSetting();
371 Refresh();
374 void CPushDlg::OnBnClickedButtonBrowseSourceBranch()
376 switch (m_BrowseLocalRef.GetCurrentEntry())
378 case 0: /* Browse Refence*/
380 if(CBrowseRefsDlg::PickRefForCombo(&m_BranchSource, gPickRef_Head))
381 OnCbnSelchangeBranchSource();
383 break;
385 case 1: /* Log */
387 CLogDlg dlg;
388 dlg.SetSelect(true);
389 if(dlg.DoModal() == IDOK)
391 if (dlg.GetSelectedHash().IsEmpty())
392 return;
394 m_BranchSource.SetWindowText(dlg.GetSelectedHash());
395 OnCbnSelchangeBranchSource();
398 break;
400 case 2: /*RefLog*/
402 CRefLogDlg dlg;
403 if(dlg.DoModal() == IDOK)
405 m_BranchSource.SetWindowText(dlg.m_SelectedHash);
406 OnCbnSelchangeBranchSource();
409 break;
413 void CPushDlg::OnBnClickedButtonBrowseDestBranch()
415 CString remoteBranchName;
416 CString remoteName;
417 m_BranchRemote.GetWindowText(remoteBranchName);
418 remoteName = m_Remote.GetString();
419 remoteBranchName = remoteName + '/' + remoteBranchName;
420 remoteBranchName = CBrowseRefsDlg::PickRef(false, remoteBranchName, gPickRef_Remote);
421 if(remoteBranchName.IsEmpty())
422 return; //Canceled
423 remoteBranchName = remoteBranchName.Mid(13);//Strip 'refs/remotes/'
424 int slashPlace = remoteBranchName.Find('/');
425 remoteName = remoteBranchName.Left(slashPlace);
426 remoteBranchName = remoteBranchName.Mid(slashPlace + 1); //Strip remote name (for example 'origin/')
428 //Select remote
429 int remoteSel = m_Remote.FindStringExact(0,remoteName);
430 if(remoteSel >= 0)
431 m_Remote.SetCurSel(remoteSel);
433 //Select branch
434 m_BranchRemote.AddString(remoteBranchName);
437 BOOL CPushDlg::PreTranslateMessage(MSG* pMsg)
439 if (pMsg->message == WM_KEYDOWN)
441 switch (pMsg->wParam)
443 case VK_F5:
445 Refresh();
447 break;
451 return CHorizontalResizableStandAloneDialog::PreTranslateMessage(pMsg);
454 void CPushDlg::OnBnClickedPushall()
456 this->UpdateData();
457 this->GetDlgItem(IDC_BRANCH_REMOTE)->EnableWindow(!m_bPushAllBranches);
458 this->GetDlgItem(IDC_BRANCH_SOURCE)->EnableWindow(!m_bPushAllBranches);
459 this->GetDlgItem(IDC_BUTTON_BROWSE_SOURCE_BRANCH)->EnableWindow(!m_bPushAllBranches);
460 this->GetDlgItem(IDC_BUTTON_BROWSE_DEST_BRANCH)->EnableWindow(!m_bPushAllBranches);
461 this->GetDlgItem(IDC_TAGS)->EnableWindow(!m_bPushAllBranches);
462 if (m_bTags && m_bPushAllBranches)
464 m_bTags = FALSE;
465 UpdateData(FALSE);