1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-2015 - 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
23 #include "TortoiseProc.h"
24 #include "SettingGitCredential.h"
26 #include "GitAdminDir.h"
27 #include "MessageBox.h"
30 #include "PathUtils.h"
32 namespace SimpleCredentialType
36 static int LocalWincred
;
37 static int LocalWinstore
;
39 static int GlobalWincred
;
40 static int GlobalWinstore
;
42 static int SystemWincred
;
74 // CSettingGitCredential dialog
76 IMPLEMENT_DYNAMIC(CSettingGitCredential
, ISettingsPropPage
)
78 CSettingGitCredential::CSettingGitCredential()
79 : ISettingsPropPage(CSettingGitCredential::IDD
)
80 , m_bUseHttpPath(FALSE
)
86 CSettingGitCredential::~CSettingGitCredential()
90 void CSettingGitCredential::DoDataExchange(CDataExchange
* pDX
)
92 CPropertyPage::DoDataExchange(pDX
);
93 DDX_Control(pDX
, IDC_COMBO_SIMPLECREDENTIAL
, m_ctrlSimpleCredential
);
94 DDX_Control(pDX
, IDC_LIST_REMOTE
, m_ctrlUrlList
);
95 DDX_Text(pDX
, IDC_EDIT_URL
, m_strUrl
);
96 DDX_Text(pDX
, IDC_COMBO_HELPER
, m_strHelper
);
97 DDX_Text(pDX
, IDC_EDIT_USERNAME
, m_strUsername
);
98 DDX_Check(pDX
, IDC_CHECK_USEHTTPPATH
, m_bUseHttpPath
);
99 DDX_Control(pDX
, IDC_COMBO_CONFIGTYPE
, m_ctrlConfigType
);
103 BEGIN_MESSAGE_MAP(CSettingGitCredential
, CPropertyPage
)
104 ON_CBN_SELCHANGE(IDC_COMBO_SIMPLECREDENTIAL
, &CSettingGitCredential::OnCbnSelchangeComboSimplecredential
)
105 ON_BN_CLICKED(IDC_BUTTON_ADD
, &CSettingGitCredential::OnBnClickedButtonAdd
)
106 ON_LBN_SELCHANGE(IDC_LIST_REMOTE
, &CSettingGitCredential::OnLbnSelchangeListUrl
)
107 ON_CBN_SELCHANGE(IDC_COMBO_CONFIGTYPE
, &CSettingGitCredential::OnCbnSelchangeComboConfigType
)
108 ON_EN_CHANGE(IDC_EDIT_URL
, &CSettingGitCredential::OnEnChangeEditUrl
)
109 ON_CBN_EDITCHANGE(IDC_COMBO_HELPER
, &CSettingGitCredential::OnEnChangeEditHelper
)
110 ON_CBN_SELCHANGE(IDC_COMBO_HELPER
, &CSettingGitCredential::OnEnChangeEditHelper
)
111 ON_EN_CHANGE(IDC_EDIT_USERNAME
, &CSettingGitCredential::OnEnChangeEditUsername
)
112 ON_BN_CLICKED(IDC_CHECK_USEHTTPPATH
, &CSettingGitCredential::OnBnClickedCheckUsehttppath
)
113 ON_BN_CLICKED(IDC_BUTTON_REMOVE
, &CSettingGitCredential::OnBnClickedButtonRemove
)
119 sCmd
.Format(_T("/command:settings /page:gitcredential /path:\"%s\""), (LPCTSTR
)g_Git
.m_CurrentDir
);
120 return CAppUtils::RunTortoiseGitProc(sCmd
, true);
123 static CString
GetWinstorePath()
125 TCHAR winstorebuf
[MAX_PATH
] = {0};
126 ExpandEnvironmentStrings(_T("%AppData%\\GitCredStore\\git-credential-winstore.exe"), winstorebuf
, MAX_PATH
);
128 winstore
.Format(_T("!'%s'"), winstorebuf
);
132 static bool WincredExists()
134 CString path
= CGit::ms_MsysGitRootDir
;
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 bool GCMExists()
146 CString path
= CGit::ms_MsysGitRootDir
;
147 path
.Append(_T("libexec\\git-core\\git-credential-manager.exe"));
148 return !!PathFileExists(path
);
151 static CStringA
RegexEscape(CStringA str
)
154 for (int i
= 0; i
< str
.GetLength(); ++i
)
159 case '\\': case '*': case '+': case '?': case '|':
160 case '{': case '[': case '(': case ')': case '^':
161 case '$': case '.': case '#': case ' ':
162 result
.AppendChar('\\');
163 result
.AppendChar(c
);
165 case '\t': result
.Append("\\t"); break;
166 case '\n': result
.Append("\\n"); break;
167 case '\r': result
.Append("\\r"); break;
168 case '\f': result
.Append("\\f"); break;
169 default: result
.AppendChar(c
); break;
176 BOOL
CSettingGitCredential::OnInitDialog()
178 ISettingsPropPage::OnInitDialog();
180 AdjustControlSize(IDC_CHECK_USEHTTPPATH
);
182 bool hasLocal
= GitAdminDir::HasAdminDir(g_Git
.m_CurrentDir
);
184 m_ctrlUrlList
.ResetContent();
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);
193 ((CComboBox
*) GetDlgItem(IDC_COMBO_HELPER
))->AddString(_T("wincred"));
194 if (WinstoreExists())
195 ((CComboBox
*) GetDlgItem(IDC_COMBO_HELPER
))->AddString(GetWinstorePath());
197 ((CComboBox
*)GetDlgItem(IDC_COMBO_HELPER
))->AddString(_T("manager"));
199 SimpleCredentialType::Init();
200 AddSimpleCredential(SimpleCredentialType::Advanced
, CString(MAKEINTRESOURCE(IDS_ADVANCED
)));
201 AddSimpleCredential(SimpleCredentialType::None
, CString(MAKEINTRESOURCE(IDS_NONE
)));
202 AddSimpleCredential(SimpleCredentialType::LocalWincred
, CString(MAKEINTRESOURCE(IDS_LOCAL_WINCRED
)), hasLocal
&& WincredExists());
203 AddSimpleCredential(SimpleCredentialType::LocalWinstore
, CString(MAKEINTRESOURCE(IDS_LOCAL_WINSTORE
)), hasLocal
&& WinstoreExists());
204 AddSimpleCredential(SimpleCredentialType::LocalGCM
, CString(MAKEINTRESOURCE(IDS_LOCAL_GCM
)), hasLocal
&& GCMExists());
205 AddSimpleCredential(SimpleCredentialType::GlobalWincred
, CString(MAKEINTRESOURCE(IDS_GLOBAL_WINCRED
)), WincredExists());
206 AddSimpleCredential(SimpleCredentialType::GlobalWinstore
, CString(MAKEINTRESOURCE(IDS_GLOBAL_WINSTORE
)), WinstoreExists());
207 AddSimpleCredential(SimpleCredentialType::GlobalGCM
, CString(MAKEINTRESOURCE(IDS_GLOBAL_GCM
)), GCMExists());
208 AddSimpleCredential(SimpleCredentialType::SystemWincred
, CString(MAKEINTRESOURCE(IDS_SYSTEM_WINCRED
)), WincredExists());
209 AddSimpleCredential(SimpleCredentialType::SystemGCM
, CString(MAKEINTRESOURCE(IDS_SYSTEM_GCM
)), GCMExists());
213 EnableAdvancedOptions();
218 // CSettingGitCredential message handlers
220 void CSettingGitCredential::OnCbnSelchangeComboSimplecredential()
222 EnableAdvancedOptions();
226 void CSettingGitCredential::OnBnClickedButtonAdd()
230 if (m_strHelper
.Trim().IsEmpty())
232 CMessageBox::Show(NULL
, IDS_GITCREDENTIAL_HELPEREMPTY
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
236 m_ChangedMask
= CREDENTIAL_URL
| CREDENTIAL_HELPER
| CREDENTIAL_USERNAME
| CREDENTIAL_USEHTTPPATH
;
237 int sel
= m_ctrlConfigType
.GetCurSel();
238 CString prefix
= sel
== ConfigType::System
? _T("S") : sel
== ConfigType::Global
? _T("G") : _T("L");
240 if (!m_strUrl
.IsEmpty())
241 text
.Format(_T("%s:%s"), (LPCTSTR
)prefix
, (LPCTSTR
)m_strUrl
);
244 if (IsUrlExist(text
))
247 msg
.Format(IDS_GITCREDENTIAL_OVERWRITEHELPER
, (LPCTSTR
)m_strUrl
);
248 if (CMessageBox::Show(NULL
, msg
, _T("TortoiseGit"), MB_YESNO
| MB_ICONQUESTION
| MB_DEFBUTTON2
) == IDYES
)
249 m_ChangedMask
&= ~CREDENTIAL_URL
;
255 if (m_strUsername
.IsEmpty())
256 m_ChangedMask
&= ~CREDENTIAL_USERNAME
;
258 m_ChangedMask
&= ~CREDENTIAL_USEHTTPPATH
;
264 void CSettingGitCredential::EnableAdvancedOptions()
266 BOOL enable
= m_ctrlSimpleCredential
.GetCurSel() == SimpleCredentialType::Advanced
? TRUE
: FALSE
;
267 GetDlgItem(IDC_LIST_REMOTE
)->EnableWindow(enable
);
268 GetDlgItem(IDC_EDIT_URL
)->EnableWindow(enable
);
269 GetDlgItem(IDC_COMBO_HELPER
)->EnableWindow(enable
);
270 GetDlgItem(IDC_EDIT_USERNAME
)->EnableWindow(enable
);
271 GetDlgItem(IDC_COMBO_CONFIGTYPE
)->EnableWindow(enable
);
272 GetDlgItem(IDC_CHECK_USEHTTPPATH
)->EnableWindow(enable
);
273 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(enable
);
274 GetDlgItem(IDC_BUTTON_REMOVE
)->EnableWindow(enable
);
277 BOOL
CSettingGitCredential::IsUrlExist(CString
&text
)
280 for(int i
= 0; i
< m_ctrlUrlList
.GetCount();i
++)
282 m_ctrlUrlList
.GetText(i
, str
);
291 void CSettingGitCredential::OnLbnSelchangeListUrl()
297 if (CMessageBox::Show(NULL
, IDS_GITCREDENTIAL_SAVEHELPER
, IDS_APPNAME
, 1, IDI_QUESTION
, IDS_SAVEBUTTON
, IDS_DISCARDBUTTON
) == 1)
303 int index
= m_ctrlUrlList
.GetCurSel();
309 m_bUseHttpPath
= FALSE
;
315 m_ctrlUrlList
.GetText(index
, text
);
316 int pos
= text
.Find(_T(':'));
317 CString prefix
= pos
>= 0 ? text
.Left(pos
) : text
.Left(1);
318 m_ctrlConfigType
.SetCurSel(prefix
== _T("S") ? ConfigType::System
: prefix
== _T("X") ? ConfigType::Global
: prefix
== _T("G") ? ConfigType::Global
: ConfigType::Local
);
319 m_strUrl
= pos
>= 0 ? text
.Mid(pos
+ 1) : _T("");
321 m_strHelper
= Load(_T("helper"));
322 m_strUsername
= Load(_T("username"));
323 m_bUseHttpPath
= Load(_T("useHttpPath")) == _T("true") ? TRUE
: FALSE
;
327 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(TRUE
);
328 GetDlgItem(IDC_BUTTON_REMOVE
)->EnableWindow(TRUE
);
329 this->UpdateData(FALSE
);
332 void CSettingGitCredential::OnCbnSelchangeComboConfigType()
337 void CSettingGitCredential::OnEnChangeEditUrl()
339 m_ChangedMask
|= CREDENTIAL_URL
;
343 void CSettingGitCredential::OnEnChangeEditHelper()
345 m_ChangedMask
|= CREDENTIAL_HELPER
;
348 if (!m_strHelper
.IsEmpty())
354 void CSettingGitCredential::OnEnChangeEditUsername()
356 m_ChangedMask
|= CREDENTIAL_USERNAME
;
360 void CSettingGitCredential::OnBnClickedCheckUsehttppath()
362 m_ChangedMask
|= CREDENTIAL_USEHTTPPATH
;
366 static int GetCredentialDefaultUrlCallback(const git_config_entry
*entry
, void *payload
)
368 CString display
= entry
->level
== 1 ? _T("S") : entry
->level
== 2 ? _T("X") : entry
->level
== 3 ? _T("G") : _T("L");
369 ((STRING_VECTOR
*)payload
)->push_back(display
);
373 static int GetCredentialUrlCallback(const git_config_entry
*entry
, void *payload
)
375 CString name
= CUnicodeUtils::GetUnicode(entry
->name
);
376 int pos1
= name
.Find(_T('.'));
377 int pos2
= name
.ReverseFind(_T('.'));
378 CString url
= name
.Mid(pos1
+ 1, pos2
- pos1
- 1);
380 display
.Format(_T("%s:%s"), entry
->level
== 1 ? _T("S") : entry
->level
== 2 ? _T("X") : entry
->level
== 3 ? _T("G") : _T("L"), url
);
381 ((STRING_VECTOR
*)payload
)->push_back(display
);
385 static int GetCredentialEntryCallback(const git_config_entry
*entry
, void *payload
)
387 CString name
= CUnicodeUtils::GetUnicode(entry
->name
);
388 ((STRING_VECTOR
*)payload
)->push_back(name
);
392 static int GetCredentialAnyEntryCallback(const git_config_entry
*entry
, void *payload
)
394 CString name
= CUnicodeUtils::GetUnicode(entry
->name
);
395 CString value
= CUnicodeUtils::GetUnicode(entry
->value
);
396 CString display
= entry
->level
== 1 ? _T("S") : entry
->level
== 2 ? _T("X") : entry
->level
== 3 ? _T("G") : _T("L");
398 text
.Format(_T("%s\n%s\n%s"), (LPCTSTR
)display
, (LPCTSTR
)name
, (LPCTSTR
)value
);
399 ((STRING_VECTOR
*)payload
)->push_back(text
);
403 void CSettingGitCredential::AddConfigType(int &index
, CString text
, bool add
)
406 index
= m_ctrlConfigType
.AddString(text
);
409 void CSettingGitCredential::AddSimpleCredential(int &index
, CString text
, bool add
)
412 index
= m_ctrlSimpleCredential
.AddString(text
);
415 void CSettingGitCredential::LoadList()
417 CAutoConfig
config(true);
418 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, FALSE
);
419 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, FALSE
);
420 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, FALSE
);
421 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, FALSE
);
423 STRING_VECTOR defaultList
, urlList
;
424 git_config_foreach_match(config
, "credential\\.helper", GetCredentialDefaultUrlCallback
, &defaultList
);
425 git_config_foreach_match(config
, "credential\\..*\\.helper", GetCredentialUrlCallback
, &urlList
);
426 STRING_VECTOR anyList
;
427 git_config_foreach_match(config
, "credential\\..*", GetCredentialAnyEntryCallback
, &anyList
);
429 for (size_t i
= 0; i
< defaultList
.size(); ++i
)
430 m_ctrlUrlList
.AddString(defaultList
[i
]);
431 for (size_t i
= 0; i
< urlList
.size(); ++i
)
432 m_ctrlUrlList
.AddString(urlList
[i
]);
436 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::None
);
439 if (anyList
.size() > 1)
441 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::Advanced
);
446 CString prefix
= anyList
[0].Tokenize(_T("\n"), pos
);
447 CString key
= anyList
[0].Tokenize(_T("\n"), pos
);
448 CString value
= anyList
[0].Tokenize(_T("\n"), pos
);
449 if (key
!= _T("credential.helper"))
451 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::Advanced
);
455 CString winstore
= GetWinstorePath();
456 if (prefix
== _T("L"))
458 if (value
== _T("wincred"))
460 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalWincred
);
463 else if (value
== winstore
)
465 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalWinstore
);
468 else if (value
== _T("manager"))
470 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalGCM
);
475 if (prefix
== _T("G") || prefix
== _T("X"))
477 if (value
== _T("wincred"))
479 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalWincred
);
482 else if (value
== winstore
)
484 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalWinstore
);
487 else if (value
== _T("manager"))
489 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalGCM
);
494 if (prefix
== _T("S"))
496 if (value
== _T("wincred"))
498 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::SystemWincred
);
501 else if (value
== _T("manager"))
503 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::SystemGCM
);
508 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::Advanced
);
511 CString
CSettingGitCredential::Load(CString key
)
515 if (m_strUrl
.IsEmpty())
516 cmd
.Format(_T("credential.%s"), (LPCTSTR
)key
);
518 cmd
.Format(_T("credential.%s.%s"), (LPCTSTR
)m_strUrl
, (LPCTSTR
)key
);
520 CAutoConfig
config(true);
521 int sel
= m_ctrlConfigType
.GetCurSel();
522 if (sel
== ConfigType::Local
)
524 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, FALSE
);
526 else if (sel
== ConfigType::Global
)
528 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, FALSE
);
529 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, FALSE
);
531 else if (sel
== ConfigType::System
)
533 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, FALSE
);
536 CStringA cmdA
= CUnicodeUtils::GetUTF8(cmd
);
538 git_config_entry
* entry
;
539 if (!git_config_get_entry(&entry
, config
, cmdA
))
540 valueA
= CStringA(entry
->value
);
541 git_config_entry_free(entry
);
543 return CUnicodeUtils::GetUnicode(valueA
);
546 void CSettingGitCredential::Save(CString key
, CString value
)
550 if (m_strUrl
.IsEmpty())
551 cmd
.Format(_T("credential.%s"), (LPCTSTR
)key
);
553 cmd
.Format(_T("credential.%s.%s"), (LPCTSTR
)m_strUrl
, (LPCTSTR
)key
);
555 int sel
= m_ctrlConfigType
.GetCurSel();
556 CONFIG_TYPE configLevel
= sel
== ConfigType::System
? CONFIG_SYSTEM
: sel
== ConfigType::Global
? CONFIG_GLOBAL
: CONFIG_LOCAL
;
558 bool old
= g_Git
.m_IsUseGitDLL
;
559 // workaround gitdll bug
560 // TODO: switch to libgit2
561 g_Git
.m_IsUseGitDLL
= false;
562 if (g_Git
.SetConfigValue(cmd
, value
, configLevel
))
565 msg
.Format(IDS_PROC_SAVECONFIGFAILED
, (LPCTSTR
)cmd
, (LPCTSTR
)value
);
566 CMessageBox::Show(NULL
, msg
, _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
570 if (g_Git
.UnsetConfigValue(cmd
, configLevel
))
573 msg
.Format(IDS_PROC_SAVECONFIGFAILED
, (LPCTSTR
)cmd
, (LPCTSTR
)value
);
574 CMessageBox::Show(NULL
, msg
, _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
577 g_Git
.m_IsUseGitDLL
= old
;
580 static int DeleteOtherKeys(int type
)
583 if (type
== SimpleCredentialType::LocalWincred
)
584 match
= _T("L\ncredential.helper\nwincred");
585 else if (type
== SimpleCredentialType::LocalWinstore
)
586 match
= _T("L\ncredential.helper\n") + GetWinstorePath();
587 else if (type
== SimpleCredentialType::LocalGCM
)
588 match
= _T("L\ncredential.helper\nmanager");
589 else if (type
== SimpleCredentialType::GlobalWincred
)
590 match
= _T("G\ncredential.helper\nwincred");
591 else if (type
== SimpleCredentialType::GlobalWinstore
)
592 match
= _T("G\ncredential.helper\n") + GetWinstorePath();
593 else if (type
== SimpleCredentialType::GlobalGCM
)
594 match
= _T("G\ncredential.helper\nmanager");
595 else if (type
== SimpleCredentialType::SystemWincred
)
596 match
= _T("S\ncredential.helper\nwincred");
597 else if (type
== SimpleCredentialType::SystemGCM
)
598 match
= _T("S\ncredential.helper\nmanager");
600 CAutoConfig
config(true);
601 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, FALSE
);
602 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, FALSE
);
603 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, FALSE
);
604 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, FALSE
);
607 git_config_foreach_match(config
, "credential\\..*", GetCredentialAnyEntryCallback
, &list
);
608 for (size_t i
= 0; i
< list
.size(); ++i
)
611 CString prefix
= list
[i
].Tokenize(_T("\n"), pos
);
612 if (prefix
== _T("S") && !CAppUtils::IsAdminLogin())
620 // workaround gitdll bug
621 // TODO: switch to libgit2
622 bool old
= g_Git
.m_IsUseGitDLL
;
623 g_Git
.m_IsUseGitDLL
= false;
624 for (size_t i
= 0; i
< list
.size(); ++i
)
626 if (list
[i
] != match
)
629 CString prefix
= list
[i
].Tokenize(_T("\n"), pos
);
630 CString key
= list
[i
].Tokenize(_T("\n"), pos
);
631 CONFIG_TYPE configLevel
= prefix
== _T("S") ? CONFIG_SYSTEM
: prefix
== _T("G") || prefix
== _T("X") ? CONFIG_GLOBAL
: CONFIG_LOCAL
;
632 if (g_Git
.UnsetConfigValue(key
, configLevel
))
635 msg
.Format(IDS_PROC_SAVECONFIGFAILED
, (LPCTSTR
)key
, _T(""));
636 CMessageBox::Show(NULL
, msg
, _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
642 g_Git
.m_IsUseGitDLL
= old
;
647 bool SaveSimpleCredential(int type
)
649 CONFIG_TYPE configLevel
;
651 if (type
== SimpleCredentialType::LocalWincred
)
653 configLevel
= CONFIG_LOCAL
;
654 value
= _T("wincred");
656 else if (type
== SimpleCredentialType::LocalWinstore
)
658 configLevel
= CONFIG_LOCAL
;
659 value
= GetWinstorePath();
661 else if (type
== SimpleCredentialType::LocalGCM
)
663 configLevel
= CONFIG_LOCAL
;
664 value
= _T("manager");
666 else if (type
== SimpleCredentialType::GlobalWincred
)
668 configLevel
= CONFIG_GLOBAL
;
669 value
= _T("wincred");
671 else if (type
== SimpleCredentialType::GlobalWinstore
)
673 configLevel
= CONFIG_GLOBAL
;
674 value
= GetWinstorePath();
676 else if (type
== SimpleCredentialType::GlobalGCM
)
678 configLevel
= CONFIG_GLOBAL
;
679 value
= _T("manager");
681 else if (type
== SimpleCredentialType::SystemWincred
)
683 configLevel
= CONFIG_SYSTEM
;
684 value
= _T("wincred");
686 else if (type
== SimpleCredentialType::SystemGCM
)
688 configLevel
= CONFIG_SYSTEM
;
689 value
= _T("manager");
696 // workaround gitdll bug
697 // TODO: switch to libgit2
698 bool old
= g_Git
.m_IsUseGitDLL
;
699 g_Git
.m_IsUseGitDLL
= false;
700 if (g_Git
.SetConfigValue(_T("credential.helper"), value
, configLevel
))
703 msg
.Format(IDS_PROC_SAVECONFIGFAILED
, _T("credential.helper"), (LPCTSTR
)value
);
704 CMessageBox::Show(NULL
, msg
, _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
707 g_Git
.m_IsUseGitDLL
= old
;
711 BOOL
CSettingGitCredential::OnApply()
716 int type
= m_ctrlSimpleCredential
.GetCurSel();
717 if (type
== SimpleCredentialType::SystemWincred
&& !CAppUtils::IsAdminLogin())
723 if (type
== SimpleCredentialType::SystemGCM
&& !CAppUtils::IsAdminLogin())
729 if (type
!= SimpleCredentialType::Advanced
)
731 if (!SaveSimpleCredential(type
))
734 int ret
= DeleteOtherKeys(type
);
740 return ISettingsPropPage::OnApply();
743 int sel
= m_ctrlConfigType
.GetCurSel();
744 if (sel
== ConfigType::System
&& !CAppUtils::IsAdminLogin())
751 if (m_ChangedMask
& CREDENTIAL_URL
)
754 if (m_strHelper
.IsEmpty())
756 CMessageBox::Show(NULL
, IDS_GITCREDENTIAL_HELPEREMPTY
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
759 m_strUrl
.Replace(L
'\\', L
'/');
760 m_strHelper
.Replace(L
'\\', L
'/');
762 Save(_T("helper"), m_strHelper
);
763 m_ChangedMask
&= ~CREDENTIAL_HELPER
;
765 sel
= m_ctrlConfigType
.GetCurSel();
766 CString prefix
= sel
== ConfigType::System
? _T("S") : sel
== ConfigType::Global
? _T("G") : _T("L");
768 if (!m_strUrl
.IsEmpty())
769 text
.Format(_T("%s:%s"), (LPCTSTR
)prefix
, (LPCTSTR
)m_strUrl
);
772 int urlIndex
= m_ctrlUrlList
.AddString(text
);
773 m_ctrlUrlList
.SetCurSel(urlIndex
);
774 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(TRUE
);
777 if (m_ChangedMask
& CREDENTIAL_HELPER
)
779 m_strHelper
.Replace(L
'\\', L
'/');
780 Save(_T("helper"), m_strHelper
);
783 if (m_ChangedMask
& CREDENTIAL_USERNAME
)
784 Save(_T("username"), m_strUsername
);
786 if (m_ChangedMask
& CREDENTIAL_USEHTTPPATH
)
787 Save(_T("useHttpPath"), m_bUseHttpPath
? _T("true") : _T(""));
792 return ISettingsPropPage::OnApply();
795 void CSettingGitCredential::OnBnClickedButtonRemove()
797 int index
= m_ctrlUrlList
.GetCurSel();
801 m_ctrlUrlList
.GetText(index
, str
);
803 msg
.Format(IDS_WARN_REMOVE
, (LPCTSTR
)str
);
804 if (CMessageBox::Show(NULL
, msg
, _T("TortoiseGit"), MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
806 CAutoConfig
config(true);
807 int pos
= str
.Find(_T(':'));
808 CString prefix
= pos
>= 0 ? str
.Left(pos
) : str
;
809 CString url
= pos
>= 0 ? str
.Mid(pos
+ 1) : _T("");
810 CONFIG_TYPE configLevel
= CONFIG_LOCAL
;
815 configLevel
= CONFIG_LOCAL
;
816 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, FALSE
);
822 configLevel
= CONFIG_GLOBAL
;
823 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, FALSE
);
824 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, FALSE
);
829 if (!CAppUtils::IsAdminLogin())
835 configLevel
= CONFIG_SYSTEM
;
836 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, FALSE
);
842 CStringA urlA
= CUnicodeUtils::GetUTF8(url
);
843 CStringA pattern
= urlA
.IsEmpty() ? "^credential\\.[^.]+$" : ("credential\\." + RegexEscape(urlA
) + "\\..*");
844 git_config_foreach_match(config
, pattern
, GetCredentialEntryCallback
, &list
);
845 for (size_t i
= 0; i
< list
.size(); ++i
)
846 g_Git
.UnsetConfigValue(list
[i
], configLevel
);
847 m_ctrlUrlList
.DeleteString(index
);
848 OnLbnSelchangeListUrl();