Adjust checkbox and radio control widths to required size
[TortoiseGit.git] / src / TortoiseProc / Settings / SettingGitCredential.cpp
blob8e2695a56b53acc589d11f38fae09edf5917f529
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-2014 - 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.
19 // SettingGitCredential.cpp : implementation file
22 #include "stdafx.h"
23 #include "TortoiseProc.h"
24 #include "SettingGitCredential.h"
25 #include "Settings.h"
26 #include "GitAdminDir.h"
27 #include "MessageBox.h"
28 #include "AppUtils.h"
29 #include "Git.h"
30 #include "PathUtils.h"
32 namespace SimpleCredentialType
34 static int Advanced;
35 static int None;
36 static int LocalWincred;
37 static int LocalWinstore;
38 static int GlobalWincred;
39 static int GlobalWinstore;
40 static int SystemWincred;
42 static void Init()
44 Advanced = -1;
45 None = -1;
46 LocalWincred = -1;
47 LocalWinstore = -1;
48 GlobalWincred = -1;
49 GlobalWinstore = -1;
50 SystemWincred = -1;
54 namespace ConfigType
56 static int Local;
57 static int Global;
58 static int System;
60 static void Init()
62 Local = -1;
63 Global = -1;
64 System = -1;
68 // CSettingGitCredential dialog
70 IMPLEMENT_DYNAMIC(CSettingGitCredential, ISettingsPropPage)
72 CSettingGitCredential::CSettingGitCredential(CString cmdPath)
73 : ISettingsPropPage(CSettingGitCredential::IDD)
74 , m_strUrl(_T(""))
75 , m_strHelper(_T(""))
76 , m_strUsername(_T(""))
77 , m_bUseHttpPath(FALSE)
78 , m_cmdPath(cmdPath)
81 m_ChangedMask = 0;
84 CSettingGitCredential::~CSettingGitCredential()
88 void CSettingGitCredential::DoDataExchange(CDataExchange* pDX)
90 CPropertyPage::DoDataExchange(pDX);
91 DDX_Control(pDX, IDC_COMBO_SIMPLECREDENTIAL, m_ctrlSimpleCredential);
92 DDX_Control(pDX, IDC_LIST_REMOTE, m_ctrlUrlList);
93 DDX_Text(pDX, IDC_EDIT_URL, m_strUrl);
94 DDX_Text(pDX, IDC_COMBO_HELPER, m_strHelper);
95 DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUsername);
96 DDX_Check(pDX, IDC_CHECK_USEHTTPPATH, m_bUseHttpPath);
97 DDX_Control(pDX, IDC_COMBO_CONFIGTYPE, m_ctrlConfigType);
101 BEGIN_MESSAGE_MAP(CSettingGitCredential, CPropertyPage)
102 ON_CBN_SELCHANGE(IDC_COMBO_SIMPLECREDENTIAL, &CSettingGitCredential::OnCbnSelchangeComboSimplecredential)
103 ON_BN_CLICKED(IDC_BUTTON_ADD, &CSettingGitCredential::OnBnClickedButtonAdd)
104 ON_LBN_SELCHANGE(IDC_LIST_REMOTE, &CSettingGitCredential::OnLbnSelchangeListUrl)
105 ON_CBN_SELCHANGE(IDC_COMBO_CONFIGTYPE, &CSettingGitCredential::OnCbnSelchangeComboConfigType)
106 ON_EN_CHANGE(IDC_EDIT_URL, &CSettingGitCredential::OnEnChangeEditUrl)
107 ON_CBN_EDITCHANGE(IDC_COMBO_HELPER, &CSettingGitCredential::OnEnChangeEditHelper)
108 ON_CBN_SELCHANGE(IDC_COMBO_HELPER, &CSettingGitCredential::OnEnChangeEditHelper)
109 ON_EN_CHANGE(IDC_EDIT_USERNAME, &CSettingGitCredential::OnEnChangeEditUsername)
110 ON_BN_CLICKED(IDC_CHECK_USEHTTPPATH, &CSettingGitCredential::OnBnClickedCheckUsehttppath)
111 ON_BN_CLICKED(IDC_BUTTON_REMOVE, &CSettingGitCredential::OnBnClickedButtonRemove)
112 END_MESSAGE_MAP()
114 static bool RunUAC()
116 CString sCmd;
117 sCmd.Format(_T("/command:settings /page:gitcredential /path:\"%s\""), g_Git.m_CurrentDir);
118 return CAppUtils::RunTortoiseGitProc(sCmd, true);
121 static CString GetWinstorePath()
123 TCHAR winstorebuf[MAX_PATH] = {0};
124 ExpandEnvironmentStrings(_T("%AppData%\\GitCredStore\\git-credential-winstore.exe"), winstorebuf, MAX_PATH);
125 CString winstore;
126 winstore.Format(_T("!'%s'"), winstorebuf);
127 return winstore;
130 static bool WincredExists()
132 CString path = g_Git.ms_LastMsysGitDir;
133 if (g_Git.ms_LastMsysGitDir.Right(1) != _T("\\"))
134 path.AppendChar(_T('\\'));
135 path.Append(_T("..\\libexec\\git-core\\git-credential-wincred.exe"));
136 return !!PathFileExists(path);
139 static bool WinstoreExists()
141 return !!PathFileExists(GetWinstorePath());
144 static CStringA RegexEscape(CStringA str)
146 CStringA result;
147 for (int i = 0; i < str.GetLength(); ++i)
149 char c = str[i];
150 switch (c)
152 case '\\': case '*': case '+': case '?': case '|':
153 case '{': case '[': case '(': case ')': case '^':
154 case '$': case '.': case '#': case ' ':
155 result.AppendChar('\\');
156 result.AppendChar(c);
157 break;
158 case '\t': result.Append("\\t"); break;
159 case '\n': result.Append("\\n"); break;
160 case '\r': result.Append("\\r"); break;
161 case '\f': result.Append("\\f"); break;
162 default: result.AppendChar(c); break;
166 return result;
169 BOOL CSettingGitCredential::OnInitDialog()
171 ISettingsPropPage::OnInitDialog();
173 AdjustControlSize(IDC_CHECK_USEHTTPPATH);
175 CString proj;
176 bool hasLocal = g_GitAdminDir.HasAdminDir(m_cmdPath, &proj);
177 if (hasLocal)
179 CString title;
180 this->GetWindowText(title);
181 this->SetWindowText(title + _T(" - ") + proj);
184 m_ctrlUrlList.ResetContent();
186 ConfigType::Init();
187 AddConfigType(ConfigType::Local, CString(MAKEINTRESOURCE(IDS_SETTINGS_LOCAL)), hasLocal);
188 AddConfigType(ConfigType::Global, CString(MAKEINTRESOURCE(IDS_SETTINGS_GLOBAL)));
189 AddConfigType(ConfigType::System, CString(MAKEINTRESOURCE(IDS_SETTINGS_SYSTEM)));
190 m_ctrlConfigType.SetCurSel(0);
192 if (WincredExists())
193 ((CComboBox*) GetDlgItem(IDC_COMBO_HELPER))->AddString(_T("wincred"));
194 if (WinstoreExists())
195 ((CComboBox*) GetDlgItem(IDC_COMBO_HELPER))->AddString(GetWinstorePath());
197 SimpleCredentialType::Init();
198 AddSimpleCredential(SimpleCredentialType::Advanced, CString(MAKEINTRESOURCE(IDS_ADVANCED)));
199 AddSimpleCredential(SimpleCredentialType::None, CString(MAKEINTRESOURCE(IDS_NONE)));
200 AddSimpleCredential(SimpleCredentialType::LocalWincred, CString(MAKEINTRESOURCE(IDS_LOCAL_WINCRED)), hasLocal && WincredExists());
201 AddSimpleCredential(SimpleCredentialType::LocalWinstore, CString(MAKEINTRESOURCE(IDS_LOCAL_WINSTORE)), hasLocal && WinstoreExists());
202 AddSimpleCredential(SimpleCredentialType::GlobalWincred, CString(MAKEINTRESOURCE(IDS_GLOBAL_WINCRED)), WincredExists());
203 AddSimpleCredential(SimpleCredentialType::GlobalWinstore, CString(MAKEINTRESOURCE(IDS_GLOBAL_WINSTORE)), WinstoreExists());
204 AddSimpleCredential(SimpleCredentialType::SystemWincred, CString(MAKEINTRESOURCE(IDS_SYSTEM_WINCRED)), WincredExists());
206 LoadList();
208 EnableAdvancedOptions();
210 UpdateData(FALSE);
211 return TRUE;
213 // CSettingGitCredential message handlers
215 void CSettingGitCredential::OnCbnSelchangeComboSimplecredential()
217 EnableAdvancedOptions();
218 SetModified();
221 void CSettingGitCredential::OnBnClickedButtonAdd()
223 UpdateData();
225 if (m_strHelper.Trim().IsEmpty())
227 CMessageBox::Show(NULL, IDS_GITCREDENTIAL_HELPEREMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
228 return;
231 m_ChangedMask = CREDENTIAL_URL | CREDENTIAL_HELPER | CREDENTIAL_USERNAME | CREDENTIAL_USEHTTPPATH;
232 int sel = m_ctrlConfigType.GetCurSel();
233 CString prefix = sel == ConfigType::System ? _T("S") : sel == ConfigType::Global ? _T("G") : _T("L");
234 CString text;
235 if (!m_strUrl.IsEmpty())
236 text.Format(_T("%s:%s"), prefix, m_strUrl);
237 else
238 text = prefix;
239 if (IsUrlExist(text))
241 CString msg;
242 msg.Format(IDS_GITCREDENTIAL_OVERWRITEHELPER, m_strUrl);
243 if (CMessageBox::Show(NULL, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
244 m_ChangedMask &= ~CREDENTIAL_URL;
245 else
246 return;
248 else
250 if (m_strUsername.IsEmpty())
251 m_ChangedMask &= ~CREDENTIAL_USERNAME;
252 if (!m_bUseHttpPath)
253 m_ChangedMask &= ~CREDENTIAL_USEHTTPPATH;
256 OnApply();
259 void CSettingGitCredential::EnableAdvancedOptions()
261 BOOL enable = m_ctrlSimpleCredential.GetCurSel() == SimpleCredentialType::Advanced ? TRUE : FALSE;
262 GetDlgItem(IDC_LIST_REMOTE)->EnableWindow(enable);
263 GetDlgItem(IDC_EDIT_URL)->EnableWindow(enable);
264 GetDlgItem(IDC_COMBO_HELPER)->EnableWindow(enable);
265 GetDlgItem(IDC_EDIT_USERNAME)->EnableWindow(enable);
266 GetDlgItem(IDC_COMBO_CONFIGTYPE)->EnableWindow(enable);
267 GetDlgItem(IDC_CHECK_USEHTTPPATH)->EnableWindow(enable);
268 GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(enable);
269 GetDlgItem(IDC_BUTTON_REMOVE)->EnableWindow(enable);
272 BOOL CSettingGitCredential::IsUrlExist(CString &text)
274 CString str;
275 for(int i = 0; i < m_ctrlUrlList.GetCount();i++)
277 m_ctrlUrlList.GetText(i, str);
278 if (str == text)
280 return true;
283 return false;
286 void CSettingGitCredential::OnLbnSelchangeListUrl()
288 CWaitCursor wait;
290 if (m_ChangedMask)
292 if (CMessageBox::Show(NULL, IDS_GITCREDENTIAL_SAVEHELPER, IDS_APPNAME, 1, IDI_QUESTION, IDS_SAVEBUTTON, IDS_DISCARDBUTTON) == 1)
293 OnApply();
295 SetModified(FALSE);
297 CString cmd, output;
298 int index = m_ctrlUrlList.GetCurSel();
299 if (index < 0)
301 m_strHelper.Empty();
302 m_strUrl.Empty();
303 m_strHelper.Empty();
304 m_bUseHttpPath = FALSE;
305 UpdateData(FALSE);
306 return;
309 CString text;
310 m_ctrlUrlList.GetText(index, text);
311 int pos = text.Find(_T(':'));
312 CString prefix = pos >= 0 ? text.Left(pos) : text.Left(1);
313 m_ctrlConfigType.SetCurSel(prefix == _T("S") ? ConfigType::System : prefix == _T("X") ? ConfigType::Global : prefix == _T("G") ? ConfigType::Global : ConfigType::Local);
314 m_strUrl = pos >= 0 ? text.Mid(pos + 1) : _T("");
316 m_strHelper = Load(_T("helper"));
317 m_strUsername = Load(_T("username"));
318 m_bUseHttpPath = Load(_T("useHttpPath")) == _T("true") ? TRUE : FALSE;
320 m_ChangedMask = 0;
322 GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(TRUE);
323 GetDlgItem(IDC_BUTTON_REMOVE)->EnableWindow(TRUE);
324 this->UpdateData(FALSE);
327 void CSettingGitCredential::OnCbnSelchangeComboConfigType()
329 SetModified();
332 void CSettingGitCredential::OnEnChangeEditUrl()
334 m_ChangedMask |= CREDENTIAL_URL;
335 SetModified();
338 void CSettingGitCredential::OnEnChangeEditHelper()
340 m_ChangedMask |= CREDENTIAL_HELPER;
342 UpdateData();
343 if (!m_strHelper.IsEmpty())
344 SetModified();
345 else
346 SetModified(0);
349 void CSettingGitCredential::OnEnChangeEditUsername()
351 m_ChangedMask |= CREDENTIAL_USERNAME;
352 SetModified();
355 void CSettingGitCredential::OnBnClickedCheckUsehttppath()
357 m_ChangedMask |= CREDENTIAL_USEHTTPPATH;
358 SetModified();
361 static int GetCredentialDefaultUrlCallback(const git_config_entry *entry, void *payload)
363 CString display = entry->level == 1 ? _T("S") : entry->level == 2 ? _T("X") : entry->level == 3 ? _T("G") : _T("L");
364 ((STRING_VECTOR *)payload)->push_back(display);
365 return 0;
368 static int GetCredentialUrlCallback(const git_config_entry *entry, void *payload)
370 CString name = CUnicodeUtils::GetUnicode(entry->name);
371 int pos1 = name.Find(_T('.'));
372 int pos2 = name.ReverseFind(_T('.'));
373 CString url = name.Mid(pos1 + 1, pos2 - pos1 - 1);
374 CString display;
375 display.Format(_T("%s:%s"), entry->level == 1 ? _T("S") : entry->level == 2 ? _T("X") : entry->level == 3 ? _T("G") : _T("L"), url);
376 ((STRING_VECTOR *)payload)->push_back(display);
377 return 0;
380 static int GetCredentialEntryCallback(const git_config_entry *entry, void *payload)
382 CString name = CUnicodeUtils::GetUnicode(entry->name);
383 ((STRING_VECTOR *)payload)->push_back(name);
384 return 0;
387 static int GetCredentialAnyEntryCallback(const git_config_entry *entry, void *payload)
389 CString name = CUnicodeUtils::GetUnicode(entry->name);
390 CString value = CUnicodeUtils::GetUnicode(entry->value);
391 CString display = entry->level == 1 ? _T("S") : entry->level == 2 ? _T("X") : entry->level == 3 ? _T("G") : _T("L");
392 CString text;
393 text.Format(_T("%s\n%s\n%s"), display, name, value);
394 ((STRING_VECTOR *)payload)->push_back(text);
395 return 0;
398 void CSettingGitCredential::AddConfigType(int &index, CString text, bool add)
400 if (add)
401 index = m_ctrlConfigType.AddString(text);
404 void CSettingGitCredential::AddSimpleCredential(int &index, CString text, bool add)
406 if (add)
407 index = m_ctrlSimpleCredential.AddString(text);
410 void CSettingGitCredential::LoadList()
412 CAutoConfig config(true);
413 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL, FALSE);
414 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
415 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG, FALSE);
416 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM, FALSE);
418 STRING_VECTOR defaultList, urlList;
419 git_config_foreach_match(config, "credential\\.helper", GetCredentialDefaultUrlCallback, &defaultList);
420 git_config_foreach_match(config, "credential\\..*\\.helper", GetCredentialUrlCallback, &urlList);
421 STRING_VECTOR anyList;
422 git_config_foreach_match(config, "credential\\..*", GetCredentialAnyEntryCallback, &anyList);
424 for (size_t i = 0; i < defaultList.size(); ++i)
425 m_ctrlUrlList.AddString(defaultList[i]);
426 for (size_t i = 0; i < urlList.size(); ++i)
427 m_ctrlUrlList.AddString(urlList[i]);
429 if (anyList.empty())
431 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::None);
432 return;
434 if (anyList.size() > 1)
436 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::Advanced);
437 return;
440 int pos = 0;
441 CString prefix = anyList[0].Tokenize(_T("\n"), pos);
442 CString key = anyList[0].Tokenize(_T("\n"), pos);
443 CString value = anyList[0].Tokenize(_T("\n"), pos);
444 if (key != _T("credential.helper"))
446 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::Advanced);
447 return;
450 CString winstore = GetWinstorePath();
451 if (prefix == _T("L"))
453 if (value == _T("wincred"))
455 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::LocalWincred);
456 return;
458 else if (value == winstore)
460 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::LocalWinstore);
461 return;
465 if (prefix == _T("G") || prefix == _T("X"))
467 if (value == _T("wincred"))
469 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::GlobalWincred);
470 return;
472 else if (value == winstore)
474 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::GlobalWinstore);
475 return;
479 if (prefix == _T("S"))
481 if (value == _T("wincred"))
483 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::SystemWincred);
484 return;
488 m_ctrlSimpleCredential.SetCurSel(SimpleCredentialType::Advanced);
491 CString CSettingGitCredential::Load(CString key)
493 CString cmd;
495 if (m_strUrl.IsEmpty())
496 cmd.Format(_T("credential.%s"), key);
497 else
498 cmd.Format(_T("credential.%s.%s"), m_strUrl, key);
500 CAutoConfig config(true);
501 int sel = m_ctrlConfigType.GetCurSel();
502 if (sel == ConfigType::Local)
504 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL, FALSE);
506 else if (sel == ConfigType::Global)
508 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
509 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG, FALSE);
511 else if (sel == ConfigType::System)
513 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM, FALSE);
516 CStringA cmdA = CUnicodeUtils::GetUTF8(cmd);
517 CStringA valueA;
518 const git_config_entry *entry;
519 if (!git_config_get_entry(&entry, config, cmdA))
520 valueA = CStringA(entry->value);
522 return CUnicodeUtils::GetUnicode(valueA);
525 void CSettingGitCredential::Save(CString key, CString value)
527 CString cmd, out;
529 if (m_strUrl.IsEmpty())
530 cmd.Format(_T("credential.%s"), key);
531 else
532 cmd.Format(_T("credential.%s.%s"), m_strUrl, key);
534 int sel = m_ctrlConfigType.GetCurSel();
535 CONFIG_TYPE configLevel = sel == ConfigType::System ? CONFIG_SYSTEM : sel == ConfigType::Global ? CONFIG_GLOBAL : CONFIG_LOCAL;
537 bool old = g_Git.m_IsUseGitDLL;
538 // workaround gitdll bug
539 // TODO: switch to libgit2
540 g_Git.m_IsUseGitDLL = false;
541 if (g_Git.SetConfigValue(cmd, value, configLevel))
543 CString msg;
544 msg.Format(IDS_PROC_SAVECONFIGFAILED, cmd, value);
545 CMessageBox::Show(NULL, msg, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
547 if (value.IsEmpty())
549 if (g_Git.UnsetConfigValue(cmd, configLevel))
551 CString msg;
552 msg.Format(IDS_PROC_SAVECONFIGFAILED, cmd, value);
553 CMessageBox::Show(NULL, msg, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
556 g_Git.m_IsUseGitDLL = old;
559 static int DeleteOtherKeys(int type)
561 CString match;
562 if (type == SimpleCredentialType::LocalWincred)
563 match = _T("L\ncredential.helper\nwincred");
564 else if (type == SimpleCredentialType::LocalWinstore)
565 match = _T("L\ncredential.helper\n") + GetWinstorePath();
566 else if (type == SimpleCredentialType::GlobalWincred)
567 match = _T("G\ncredential.helper\nwincred");
568 else if (type == SimpleCredentialType::GlobalWinstore)
569 match = _T("G\ncredential.helper\n") + GetWinstorePath();
570 else if (type == SimpleCredentialType::SystemWincred)
571 match = _T("S\ncredential.helper\nwincred");
573 CAutoConfig config(true);
574 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL, FALSE);
575 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
576 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG, FALSE);
577 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM, FALSE);
579 STRING_VECTOR list;
580 git_config_foreach_match(config, "credential\\..*", GetCredentialAnyEntryCallback, &list);
581 for (size_t i = 0; i < list.size(); ++i)
583 int pos = 0;
584 CString prefix = list[i].Tokenize(_T("\n"), pos);
585 if (prefix == _T("S") && !CAppUtils::IsAdminLogin())
587 RunUAC();
588 return -1;
592 int result = 0;
593 // workaround gitdll bug
594 // TODO: switch to libgit2
595 bool old = g_Git.m_IsUseGitDLL;
596 g_Git.m_IsUseGitDLL = false;
597 for (size_t i = 0; i < list.size(); ++i)
599 if (list[i] != match)
601 int pos = 0;
602 CString prefix = list[i].Tokenize(_T("\n"), pos);
603 CString key = list[i].Tokenize(_T("\n"), pos);
604 CONFIG_TYPE configLevel = prefix == _T("S") ? CONFIG_SYSTEM : prefix == _T("G") || prefix == _T("X") ? CONFIG_GLOBAL : CONFIG_LOCAL;
605 if (g_Git.UnsetConfigValue(key, configLevel))
607 CString msg;
608 msg.Format(IDS_PROC_SAVECONFIGFAILED, key, _T(""));
609 CMessageBox::Show(NULL, msg, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
610 result = 1;
611 break;
615 g_Git.m_IsUseGitDLL = old;
617 return result;
620 bool SaveSimpleCredential(int type)
622 CONFIG_TYPE configLevel;
623 CString value;
624 if (type == SimpleCredentialType::LocalWincred)
626 configLevel = CONFIG_LOCAL;
627 value = _T("wincred");
629 else if (type == SimpleCredentialType::LocalWinstore)
631 configLevel = CONFIG_LOCAL;
632 value = GetWinstorePath();
634 else if (type == SimpleCredentialType::GlobalWincred)
636 configLevel = CONFIG_GLOBAL;
637 value = _T("wincred");
639 else if (type == SimpleCredentialType::GlobalWinstore)
641 configLevel = CONFIG_GLOBAL;
642 value = GetWinstorePath();
644 else if (type == SimpleCredentialType::SystemWincred)
646 configLevel = CONFIG_SYSTEM;
647 value = _T("wincred");
649 else
651 return true;
654 // workaround gitdll bug
655 // TODO: switch to libgit2
656 bool old = g_Git.m_IsUseGitDLL;
657 g_Git.m_IsUseGitDLL = false;
658 if (g_Git.SetConfigValue(_T("credential.helper"), value, configLevel))
660 CString msg;
661 msg.Format(IDS_PROC_SAVECONFIGFAILED, _T("credential.helper"), value);
662 CMessageBox::Show(NULL, msg, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
663 return false;
665 g_Git.m_IsUseGitDLL = old;
666 return true;
669 BOOL CSettingGitCredential::OnApply()
671 CWaitCursor wait;
672 UpdateData();
674 int type = m_ctrlSimpleCredential.GetCurSel();
675 if (type == SimpleCredentialType::SystemWincred && !CAppUtils::IsAdminLogin())
677 RunUAC();
678 EndDialog(0);
679 return FALSE;
681 if (type != SimpleCredentialType::Advanced)
683 if (!SaveSimpleCredential(type))
684 return FALSE;
686 int ret = DeleteOtherKeys(type);
687 if (ret < 0)
688 EndDialog(0);
689 if (ret)
690 return FALSE;
691 SetModified(FALSE);
692 return ISettingsPropPage::OnApply();
695 int sel = m_ctrlConfigType.GetCurSel();
696 if (sel == ConfigType::System && !CAppUtils::IsAdminLogin())
698 RunUAC();
699 EndDialog(0);
700 return FALSE;
703 if (m_ChangedMask & CREDENTIAL_URL)
705 //Add Helper
706 if (m_strHelper.IsEmpty())
708 CMessageBox::Show(NULL, IDS_GITCREDENTIAL_HELPEREMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
709 return FALSE;
711 m_strUrl.Replace(L'\\', L'/');
712 m_strHelper.Replace(L'\\', L'/');
714 Save(_T("helper"), m_strHelper);
715 m_ChangedMask &= ~CREDENTIAL_HELPER;
717 int sel = m_ctrlConfigType.GetCurSel();
718 CString prefix = sel == ConfigType::System ? _T("S") : sel == ConfigType::Global ? _T("G") : _T("L");
719 CString text;
720 if (!m_strUrl.IsEmpty())
721 text.Format(_T("%s:%s"), prefix, m_strUrl);
722 else
723 text = prefix;
724 int urlIndex = m_ctrlUrlList.AddString(text);
725 m_ctrlUrlList.SetCurSel(urlIndex);
726 GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(TRUE);
729 if (m_ChangedMask & CREDENTIAL_HELPER)
731 m_strHelper.Replace(L'\\', L'/');
732 Save(_T("helper"), m_strHelper);
735 if (m_ChangedMask & CREDENTIAL_USERNAME)
736 Save(_T("username"), m_strUsername);
738 if (m_ChangedMask & CREDENTIAL_USEHTTPPATH)
739 Save(_T("useHttpPath"), m_bUseHttpPath ? _T("true") : _T(""));
741 SetModified(FALSE);
743 m_ChangedMask = 0;
744 return ISettingsPropPage::OnApply();
747 void CSettingGitCredential::OnBnClickedButtonRemove()
749 int index = m_ctrlUrlList.GetCurSel();
750 if (index >= 0)
752 CString str;
753 m_ctrlUrlList.GetText(index, str);
754 CString msg;
755 msg.Format(IDS_GITCREDENTIAL_DELETEHELPER, str);
756 if (CMessageBox::Show(NULL, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
758 CAutoConfig config(true);
759 int pos = str.Find(_T(':'));
760 CString prefix = pos >= 0 ? str.Left(pos) : str;
761 CString url = pos >= 0 ? str.Mid(pos + 1) : _T("");
762 CONFIG_TYPE configLevel = CONFIG_LOCAL;
763 switch (prefix[0])
765 case _T('L'):
767 configLevel = CONFIG_LOCAL;
768 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL, FALSE);
769 break;
771 case _T('G'):
772 case _T('X'):
774 configLevel = CONFIG_GLOBAL;
775 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
776 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG, FALSE);
777 break;
779 case _T('S'):
781 if (!CAppUtils::IsAdminLogin())
783 RunUAC();
784 EndDialog(0);
785 return;
787 configLevel = CONFIG_SYSTEM;
788 git_config_add_file_ondisk(config, CGit::GetGitPathStringA(g_Git.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM, FALSE);
789 break;
793 STRING_VECTOR list;
794 CStringA urlA = CUnicodeUtils::GetUTF8(url);
795 CStringA pattern = urlA.IsEmpty() ? "^credential\\.[^.]+$" : ("credential\\." + RegexEscape(urlA) + "\\..*");
796 git_config_foreach_match(config, pattern, GetCredentialEntryCallback, &list);
797 for (size_t i = 0; i < list.size(); ++i)
798 g_Git.UnsetConfigValue(list[i], configLevel);
799 m_ctrlUrlList.DeleteString(index);
800 OnLbnSelchangeListUrl();