1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-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.
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
34 static int Advanced
= -1;
36 static int LocalWincred
= -1;
37 static int LocalWinstore
= -1;
38 static int LocalGCM
= -1;
39 static int LocalGCMCore
= -1;
40 static int GlobalWincred
= -1;
41 static int GlobalWinstore
= -1;
42 static int GlobalGCM
= -1;
43 static int GlobalGCMCore
= -1;
44 static int SystemWincred
= -1;
45 static int SystemGCM
= -1;
46 static int SystemGCMCore
= -1;
51 static int Local
= -1;
52 static int Global
= -1;
53 static int System
= -1;
56 // CSettingGitCredential dialog
58 IMPLEMENT_DYNAMIC(CSettingGitCredential
, ISettingsPropPage
)
60 CSettingGitCredential::CSettingGitCredential()
61 : ISettingsPropPage(CSettingGitCredential::IDD
)
62 , m_bUseHttpPath(FALSE
)
63 , m_iSimpleStoredValue(-2)
68 CSettingGitCredential::~CSettingGitCredential()
72 void CSettingGitCredential::DoDataExchange(CDataExchange
* pDX
)
74 CPropertyPage::DoDataExchange(pDX
);
75 DDX_Control(pDX
, IDC_COMBO_SIMPLECREDENTIAL
, m_ctrlSimpleCredential
);
76 DDX_Control(pDX
, IDC_LIST_REMOTE
, m_ctrlUrlList
);
77 DDX_Text(pDX
, IDC_EDIT_URL
, m_strUrl
);
78 DDX_Text(pDX
, IDC_COMBO_HELPER
, m_strHelper
);
79 DDX_Text(pDX
, IDC_EDIT_USERNAME
, m_strUsername
);
80 DDX_Check(pDX
, IDC_CHECK_USEHTTPPATH
, m_bUseHttpPath
);
81 DDX_Control(pDX
, IDC_COMBO_CONFIGTYPE
, m_ctrlConfigType
);
85 BEGIN_MESSAGE_MAP(CSettingGitCredential
, CPropertyPage
)
86 ON_CBN_SELCHANGE(IDC_COMBO_SIMPLECREDENTIAL
, &CSettingGitCredential::OnCbnSelchangeComboSimplecredential
)
87 ON_BN_CLICKED(IDC_BUTTON_ADD
, &CSettingGitCredential::OnBnClickedButtonAdd
)
88 ON_LBN_SELCHANGE(IDC_LIST_REMOTE
, &CSettingGitCredential::OnLbnSelchangeListUrl
)
89 ON_CBN_SELCHANGE(IDC_COMBO_CONFIGTYPE
, &CSettingGitCredential::OnCbnSelchangeComboConfigType
)
90 ON_EN_CHANGE(IDC_EDIT_URL
, &CSettingGitCredential::OnEnChangeEditUrl
)
91 ON_CBN_EDITCHANGE(IDC_COMBO_HELPER
, &CSettingGitCredential::OnEnChangeEditHelper
)
92 ON_CBN_SELCHANGE(IDC_COMBO_HELPER
, &CSettingGitCredential::OnEnChangeEditHelper
)
93 ON_EN_CHANGE(IDC_EDIT_USERNAME
, &CSettingGitCredential::OnEnChangeEditUsername
)
94 ON_BN_CLICKED(IDC_CHECK_USEHTTPPATH
, &CSettingGitCredential::OnBnClickedCheckUsehttppath
)
95 ON_BN_CLICKED(IDC_BUTTON_REMOVE
, &CSettingGitCredential::OnBnClickedButtonRemove
)
96 ON_BN_CLICKED(IDC_OPENSETTINGSELEVATED
, &CSettingGitCredential::OnBnClickedOpensettingselevated
)
99 static CStringA
RegexEscape(CStringA str
)
102 for (int i
= 0; i
< str
.GetLength(); ++i
)
107 case '\\': case '*': case '+': case '?': case '|':
108 case '{': case '[': case '(': case ')': case '^':
109 case '$': case '.': case '#': case ' ':
110 result
.AppendChar('\\');
111 result
.AppendChar(c
);
113 case '\t': result
.Append("\\t"); break;
114 case '\n': result
.Append("\\n"); break;
115 case '\r': result
.Append("\\r"); break;
116 case '\f': result
.Append("\\f"); break;
117 default: result
.AppendChar(c
); break;
124 BOOL
CSettingGitCredential::OnInitDialog()
126 ISettingsPropPage::OnInitDialog();
128 AdjustControlSize(IDC_CHECK_USEHTTPPATH
);
130 bool hasLocal
= GitAdminDir::HasAdminDir(g_Git
.m_CurrentDir
);
132 m_ctrlUrlList
.ResetContent();
134 AddConfigType(ConfigType::Local
, CString(MAKEINTRESOURCE(IDS_SETTINGS_LOCAL
)), hasLocal
);
135 AddConfigType(ConfigType::Global
, CString(MAKEINTRESOURCE(IDS_SETTINGS_GLOBAL
)));
136 AddConfigType(ConfigType::System
, CString(MAKEINTRESOURCE(IDS_SETTINGS_SYSTEM
)));
137 m_ctrlConfigType
.SetCurSel(0);
140 static_cast<CComboBox
*>(GetDlgItem(IDC_COMBO_HELPER
))->AddString(L
"wincred");
141 if (WinstoreExists())
142 static_cast<CComboBox
*>(GetDlgItem(IDC_COMBO_HELPER
))->AddString(GetWinstorePath());
144 static_cast<CComboBox
*>(GetDlgItem(IDC_COMBO_HELPER
))->AddString(L
"manager");
146 static_cast<CComboBox
*>(GetDlgItem(IDC_COMBO_HELPER
))->AddString(L
"manager-core");
149 m_iSimpleStoredValue
= m_ctrlSimpleCredential
.GetCurSel();
151 if (!CAppUtils::IsAdminLogin())
153 reinterpret_cast<CButton
*>(GetDlgItem(IDC_OPENSETTINGSELEVATED
))->SetShield(TRUE
);
154 GetDlgItem(IDC_OPENSETTINGSELEVATED
)->ShowWindow(SW_SHOW
);
155 GetDlgItem(IDC_STATICELEVATIONNEEDED
)->ShowWindow(SW_SHOW
);
158 EnableAdvancedOptions();
163 // CSettingGitCredential message handlers
165 void CSettingGitCredential::OnCbnSelchangeComboSimplecredential()
167 EnableAdvancedOptions();
169 m_ChangedMask
|= CREDENTIAL_SIMPLE
;
172 void CSettingGitCredential::OnBnClickedButtonAdd()
176 if (m_strHelper
.Trim().IsEmpty())
178 CMessageBox::Show(GetSafeHwnd(), IDS_GITCREDENTIAL_HELPEREMPTY
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
182 m_ChangedMask
= CREDENTIAL_URL
| CREDENTIAL_HELPER
| CREDENTIAL_USERNAME
| CREDENTIAL_USEHTTPPATH
;
183 int sel
= m_ctrlConfigType
.GetCurSel();
184 CString prefix
= sel
== ConfigType::System
? L
"S" : sel
== ConfigType::Global
? L
"G" : L
"L";
186 if (!m_strUrl
.IsEmpty())
187 text
.Format(L
"%s:%s", static_cast<LPCTSTR
>(prefix
), static_cast<LPCTSTR
>(m_strUrl
));
190 if (IsUrlExist(text
))
193 msg
.Format(IDS_GITCREDENTIAL_OVERWRITEHELPER
, static_cast<LPCTSTR
>(m_strUrl
));
194 if (CMessageBox::Show(GetSafeHwnd(), msg
, L
"TortoiseGit", MB_YESNO
| MB_ICONQUESTION
| MB_DEFBUTTON2
) == IDYES
)
195 m_ChangedMask
&= ~CREDENTIAL_URL
;
201 if (m_strUsername
.IsEmpty())
202 m_ChangedMask
&= ~CREDENTIAL_USERNAME
;
204 m_ChangedMask
&= ~CREDENTIAL_USEHTTPPATH
;
210 void CSettingGitCredential::EnableAdvancedOptions()
212 BOOL enable
= m_ctrlSimpleCredential
.GetCurSel() == SimpleCredentialType::Advanced
? TRUE
: FALSE
;
213 GetDlgItem(IDC_LIST_REMOTE
)->EnableWindow(enable
);
214 GetDlgItem(IDC_EDIT_URL
)->EnableWindow(enable
);
215 GetDlgItem(IDC_COMBO_HELPER
)->EnableWindow(enable
);
216 GetDlgItem(IDC_EDIT_USERNAME
)->EnableWindow(enable
);
217 GetDlgItem(IDC_COMBO_CONFIGTYPE
)->EnableWindow(enable
);
218 GetDlgItem(IDC_CHECK_USEHTTPPATH
)->EnableWindow(enable
);
220 bool canModifySystem
= CAppUtils::IsAdminLogin() || (m_ctrlConfigType
.GetCurSel() != ConfigType::System
);
221 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(enable
&& canModifySystem
);
222 GetDlgItem(IDC_BUTTON_REMOVE
)->EnableWindow(enable
&& canModifySystem
);
225 BOOL
CSettingGitCredential::IsUrlExist(const CString
& text
)
228 for(int i
= 0; i
< m_ctrlUrlList
.GetCount();i
++)
230 m_ctrlUrlList
.GetText(i
, str
);
237 void CSettingGitCredential::OnLbnSelchangeListUrl()
241 if (m_ChangedMask
& CREDENTIAL_ADVANCED_MASK
)
243 if (CMessageBox::Show(GetSafeHwnd(), IDS_GITCREDENTIAL_SAVEHELPER
, IDS_APPNAME
, 1, IDI_QUESTION
, IDS_SAVEBUTTON
, IDS_DISCARDBUTTON
) == 1)
246 m_ChangedMask
&= ~CREDENTIAL_ADVANCED_MASK
;
251 int index
= m_ctrlUrlList
.GetCurSel();
257 m_bUseHttpPath
= FALSE
;
263 m_ctrlUrlList
.GetText(index
, text
);
264 int pos
= text
.Find(L
':');
265 CString prefix
= pos
>= 0 ? text
.Left(pos
) : text
.Left(1);
266 m_ctrlConfigType
.SetCurSel((prefix
== L
"S" || prefix
== L
"P") ? ConfigType::System
: prefix
== L
"X" ? ConfigType::Global
: prefix
== L
"G" ? ConfigType::Global
: ConfigType::Local
);
267 m_strUrl
= pos
>= 0 ? text
.Mid(pos
+ 1) : L
"";
269 m_strHelper
= Load(L
"helper");
270 m_strUsername
= Load(L
"username");
271 m_bUseHttpPath
= Load(L
"useHttpPath") == L
"true" ? TRUE
: FALSE
;
273 bool canModifySystem
= CAppUtils::IsAdminLogin() || (m_ctrlConfigType
.GetCurSel() != ConfigType::System
);
274 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(canModifySystem
? TRUE
: FALSE
);
275 GetDlgItem(IDC_BUTTON_REMOVE
)->EnableWindow(canModifySystem
? TRUE
: FALSE
);
276 this->UpdateData(FALSE
);
279 void CSettingGitCredential::OnCbnSelchangeComboConfigType()
281 if (!CAppUtils::IsAdminLogin())
283 int sel
= m_ctrlConfigType
.GetCurSel();
284 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(sel
!= ConfigType::System
);
285 GetDlgItem(IDC_BUTTON_REMOVE
)->EnableWindow(sel
!= ConfigType::System
);
286 if (sel
== ConfigType::System
)
292 void CSettingGitCredential::OnEnChangeEditUrl()
294 m_ChangedMask
|= CREDENTIAL_URL
;
298 void CSettingGitCredential::OnEnChangeEditHelper()
300 m_ChangedMask
|= CREDENTIAL_HELPER
;
303 if (!m_strHelper
.IsEmpty())
305 else if (!m_ChangedMask
)
309 void CSettingGitCredential::OnEnChangeEditUsername()
311 m_ChangedMask
|= CREDENTIAL_USERNAME
;
315 void CSettingGitCredential::OnBnClickedCheckUsehttppath()
317 m_ChangedMask
|= CREDENTIAL_USEHTTPPATH
;
321 void CSettingGitCredential::AddConfigType(int &index
, CString text
, bool add
)
324 index
= m_ctrlConfigType
.AddString(text
);
327 void CSettingGitCredential::AddSimpleCredential(int &index
, CString text
, bool add
)
330 index
= m_ctrlSimpleCredential
.AddString(text
);
333 void CSettingGitCredential::FillSimpleList(bool anySystem
, bool systemWincred
, bool systemGCM
, bool systemGCMCore
)
335 ATLASSERT(SimpleCredentialType::Advanced
== -1);
337 bool hasLocal
= GitAdminDir::HasAdminDir(g_Git
.m_CurrentDir
);
338 bool isAdmin
= CAppUtils::IsAdminLogin();
340 AddSimpleCredential(SimpleCredentialType::Advanced
, CString(MAKEINTRESOURCE(IDS_ADVANCED
)));
341 if (isAdmin
|| !anySystem
)
342 AddSimpleCredential(SimpleCredentialType::None
, CString(MAKEINTRESOURCE(IDS_NONE
)));
343 if (isAdmin
|| !(systemWincred
|| systemGCM
|| systemGCMCore
|| anySystem
))
345 AddSimpleCredential(SimpleCredentialType::LocalWincred
, CString(MAKEINTRESOURCE(IDS_LOCAL_WINCRED
)), hasLocal
&& WincredExists());
346 AddSimpleCredential(SimpleCredentialType::LocalWinstore
, CString(MAKEINTRESOURCE(IDS_LOCAL_WINSTORE
)), hasLocal
&& WinstoreExists());
347 AddSimpleCredential(SimpleCredentialType::LocalGCM
, CString(MAKEINTRESOURCE(IDS_LOCAL_GCM
)), hasLocal
&& GCMExists());
348 AddSimpleCredential(SimpleCredentialType::LocalGCMCore
, CString(MAKEINTRESOURCE(IDS_LOCAL_GCMCORE
)), hasLocal
&& GCMCoreExists());
349 AddSimpleCredential(SimpleCredentialType::GlobalWincred
, CString(MAKEINTRESOURCE(IDS_GLOBAL_WINCRED
)), WincredExists());
350 AddSimpleCredential(SimpleCredentialType::GlobalWinstore
, CString(MAKEINTRESOURCE(IDS_GLOBAL_WINSTORE
)), WinstoreExists());
351 AddSimpleCredential(SimpleCredentialType::GlobalGCM
, CString(MAKEINTRESOURCE(IDS_GLOBAL_GCM
)), GCMExists());
352 AddSimpleCredential(SimpleCredentialType::GlobalGCMCore
, CString(MAKEINTRESOURCE(IDS_GLOBAL_GCMCORE
)), GCMCoreExists());
354 if (isAdmin
|| systemWincred
)
355 AddSimpleCredential(SimpleCredentialType::SystemWincred
, CString(MAKEINTRESOURCE(IDS_SYSTEM_WINCRED
)), WincredExists());
356 if (isAdmin
|| systemGCM
)
357 AddSimpleCredential(SimpleCredentialType::SystemGCM
, CString(MAKEINTRESOURCE(IDS_SYSTEM_GCM
)), GCMExists());
358 if (isAdmin
|| systemGCMCore
)
359 AddSimpleCredential(SimpleCredentialType::SystemGCMCore
, CString(MAKEINTRESOURCE(IDS_SYSTEM_GCMCORE
)), GCMCoreExists());
362 void CSettingGitCredential::LoadList()
364 CAutoConfig
config(true);
365 CAutoRepository
repo(g_Git
.GetGitRepository());
366 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, repo
, FALSE
);
367 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, repo
, FALSE
);
368 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, repo
, FALSE
);
369 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, repo
, FALSE
);
370 if (!g_Git
.ms_bCygwinGit
&& !g_Git
.ms_bMsys2Git
&& !g_Git
.GetGitProgramDataConfig().IsEmpty())
371 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitProgramDataConfig()), GIT_CONFIG_LEVEL_PROGRAMDATA
, repo
, FALSE
);
373 STRING_VECTOR defaultList
, urlList
;
374 git_config_foreach_match(config
, "credential\\.helper", GetCredentialDefaultUrlCallback
, &defaultList
);
375 git_config_foreach_match(config
, "credential\\..*\\.helper", GetCredentialUrlCallback
, &urlList
);
376 STRING_VECTOR anyList
;
377 git_config_foreach_match(config
, "credential\\..*", GetCredentialAnyEntryCallback
, &anyList
);
379 for (size_t i
= 0; i
< defaultList
.size(); ++i
)
380 m_ctrlUrlList
.AddString(defaultList
[i
]);
381 for (size_t i
= 0; i
< urlList
.size(); ++i
)
382 m_ctrlUrlList
.AddString(urlList
[i
]);
386 FillSimpleList(false, false, false, false);
387 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::None
);
390 if (anyList
.size() > 1)
392 bool hasSystemType
= false;
393 for (size_t i
= 0; i
< anyList
.size(); ++i
)
396 CString prefix
= anyList
[i
].Tokenize(L
"\n", pos
);
397 if (prefix
== L
"S" || prefix
== L
"P")
399 hasSystemType
= true;
403 FillSimpleList(hasSystemType
, false, false, false);
404 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::Advanced
);
409 CString prefix
= anyList
[0].Tokenize(L
"\n", pos
);
410 CString key
= anyList
[0].Tokenize(L
"\n", pos
);
411 CString value
= anyList
[0].Tokenize(L
"\n", pos
);
412 if (key
!= L
"credential.helper")
414 FillSimpleList(true, false, false, false);
415 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::Advanced
);
419 CString winstore
= GetWinstorePath();
422 if (value
== L
"wincred")
424 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalWincred
);
427 else if (value
== winstore
)
429 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalWinstore
);
432 else if (value
== L
"manager")
434 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalGCM
);
437 else if (value
== L
"manager-core")
439 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::LocalGCMCore
);
444 if (prefix
== L
"G" || prefix
== L
"X")
446 if (value
== L
"wincred")
448 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalWincred
);
451 else if (value
== winstore
)
453 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalWinstore
);
456 else if (value
== L
"manager")
458 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalGCM
);
461 else if (value
== L
"manager-core")
463 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::GlobalGCMCore
);
468 if (prefix
== L
"S" || prefix
== L
"P")
470 if (value
== L
"wincred")
472 FillSimpleList(true, true, false, false);
473 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::SystemWincred
);
476 else if (value
== L
"manager")
478 FillSimpleList(true, false, true, false);
479 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::SystemGCM
);
482 else if (value
== L
"manager-core")
484 FillSimpleList(true, false, false, true);
485 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::SystemGCMCore
);
490 FillSimpleList((prefix
== L
"S" || prefix
== L
"P"), false, false, false);
491 m_ctrlSimpleCredential
.SetCurSel(SimpleCredentialType::Advanced
);
494 CString
CSettingGitCredential::Load(CString key
)
498 if (m_strUrl
.IsEmpty())
499 cmd
.Format(L
"credential.%s", static_cast<LPCTSTR
>(key
));
501 cmd
.Format(L
"credential.%s.%s", static_cast<LPCTSTR
>(m_strUrl
), static_cast<LPCTSTR
>(key
));
503 CAutoConfig
config(true);
504 CAutoRepository
repo(g_Git
.GetGitRepository());
505 int sel
= m_ctrlConfigType
.GetCurSel();
506 if (sel
== ConfigType::Local
)
507 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, repo
, FALSE
);
508 else if (sel
== ConfigType::Global
)
510 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, repo
, FALSE
);
511 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, repo
, FALSE
);
513 else if (sel
== ConfigType::System
)
514 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, repo
, FALSE
);
516 CStringA cmdA
= CUnicodeUtils::GetUTF8(cmd
);
518 git_config_entry
* entry
;
519 if (!git_config_get_entry(&entry
, config
, cmdA
))
520 valueA
= CStringA(entry
->value
);
521 git_config_entry_free(entry
);
523 return CUnicodeUtils::GetUnicode(valueA
);
526 void CSettingGitCredential::Save(CString key
, CString value
)
530 if (m_strUrl
.IsEmpty())
531 cmd
.Format(L
"credential.%s", static_cast<LPCTSTR
>(key
));
533 cmd
.Format(L
"credential.%s.%s", static_cast<LPCTSTR
>(m_strUrl
), static_cast<LPCTSTR
>(key
));
535 int sel
= m_ctrlConfigType
.GetCurSel();
536 CONFIG_TYPE configLevel
= sel
== ConfigType::System
? CONFIG_SYSTEM
: sel
== ConfigType::Global
? CONFIG_GLOBAL
: CONFIG_LOCAL
;
538 bool old
= g_Git
.m_IsUseGitDLL
;
539 // workaround gitdll bug
540 // TODO: switch to libgit2
541 g_Git
.m_IsUseGitDLL
= false;
542 if (g_Git
.SetConfigValue(cmd
, value
, configLevel
))
545 msg
.FormatMessage(IDS_PROC_SAVECONFIGFAILED
, static_cast<LPCTSTR
>(cmd
), static_cast<LPCTSTR
>(value
));
546 CMessageBox::Show(GetSafeHwnd(), msg
, L
"TortoiseGit", MB_OK
| MB_ICONERROR
);
550 if (g_Git
.UnsetConfigValue(cmd
, configLevel
))
553 msg
.FormatMessage(IDS_PROC_SAVECONFIGFAILED
, static_cast<LPCTSTR
>(cmd
), static_cast<LPCTSTR
>(value
));
554 CMessageBox::Show(GetSafeHwnd(), msg
, L
"TortoiseGit", MB_OK
| MB_ICONERROR
);
557 g_Git
.m_IsUseGitDLL
= old
;
560 int CSettingGitCredential::DeleteOtherKeys(int type
)
563 if (type
== SimpleCredentialType::LocalWincred
)
564 match
= L
"L\ncredential.helper\nwincred";
565 else if (type
== SimpleCredentialType::LocalWinstore
)
566 match
= L
"L\ncredential.helper\n" + GetWinstorePath();
567 else if (type
== SimpleCredentialType::LocalGCM
)
568 match
= L
"L\ncredential.helper\nmanager";
569 else if (type
== SimpleCredentialType::LocalGCMCore
)
570 match
= L
"L\ncredential.helper\nmanager-core";
571 else if (type
== SimpleCredentialType::GlobalWincred
)
572 match
= L
"G\ncredential.helper\nwincred";
573 else if (type
== SimpleCredentialType::GlobalWinstore
)
574 match
= L
"G\ncredential.helper\n" + GetWinstorePath();
575 else if (type
== SimpleCredentialType::GlobalGCM
)
576 match
= L
"G\ncredential.helper\nmanager";
577 else if (type
== SimpleCredentialType::GlobalGCMCore
)
578 match
= L
"G\ncredential.helper\nmanager-core";
579 else if (type
== SimpleCredentialType::SystemWincred
)
580 match
= L
"S\ncredential.helper\nwincred";
581 else if (type
== SimpleCredentialType::SystemGCM
)
582 match
= L
"S\ncredential.helper\nmanager";
583 else if (type
== SimpleCredentialType::SystemGCMCore
)
584 match
= L
"S\ncredential.helper\nmanager-core";
586 CAutoConfig
config(true);
587 CAutoRepository repo
= g_Git
.GetGitRepository();
588 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, repo
, FALSE
);
589 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, repo
, FALSE
);
590 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, repo
, FALSE
);
591 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, repo
, FALSE
);
594 git_config_foreach_match(config
, "credential\\..*", GetCredentialAnyEntryCallback
, &list
);
595 for (size_t i
= 0; i
< list
.size(); ++i
)
598 CString prefix
= list
[i
].Tokenize(L
"\n", pos
);
599 if ((prefix
== L
"S" || prefix
== L
"P") && list
[i
] != match
&& !CAppUtils::IsAdminLogin())
601 if (MessageBox(L
"Cannot modify a system config without proper rights.\nDiscard changes?", L
"TortoiseGit", MB_ICONERROR
| MB_YESNO
) == IDYES
)
607 // workaround gitdll bug
608 // TODO: switch to libgit2
609 bool old
= g_Git
.m_IsUseGitDLL
;
610 g_Git
.m_IsUseGitDLL
= false;
611 SCOPE_EXIT
{ g_Git
.m_IsUseGitDLL
= old
; };
612 for (size_t i
= 0; i
< list
.size(); ++i
)
614 if (list
[i
] == match
)
618 CString prefix
= list
[i
].Tokenize(L
"\n", pos
);
619 CString key
= list
[i
].Tokenize(L
"\n", pos
);
620 CONFIG_TYPE configLevel
= (prefix
== L
"S" || prefix
== L
"P") ? CONFIG_SYSTEM
: prefix
== L
"G" || prefix
== L
"X" ? CONFIG_GLOBAL
: CONFIG_LOCAL
;
621 if (g_Git
.UnsetConfigValue(key
, configLevel
))
624 msg
.FormatMessage(IDS_PROC_SAVECONFIGFAILED
, static_cast<LPCTSTR
>(key
), L
"");
625 CMessageBox::Show(GetSafeHwnd(), msg
, L
"TortoiseGit", MB_OK
| MB_ICONERROR
);
633 bool CSettingGitCredential::SaveSimpleCredential(int type
)
635 CONFIG_TYPE configLevel
;
637 if (type
== SimpleCredentialType::LocalWincred
)
639 configLevel
= CONFIG_LOCAL
;
642 else if (type
== SimpleCredentialType::LocalWinstore
)
644 configLevel
= CONFIG_LOCAL
;
645 value
= GetWinstorePath();
647 else if (type
== SimpleCredentialType::LocalGCM
)
649 configLevel
= CONFIG_LOCAL
;
652 else if (type
== SimpleCredentialType::LocalGCMCore
)
654 configLevel
= CONFIG_LOCAL
;
655 value
= L
"manager-core";
657 else if (type
== SimpleCredentialType::GlobalWincred
)
659 configLevel
= CONFIG_GLOBAL
;
662 else if (type
== SimpleCredentialType::GlobalWinstore
)
664 configLevel
= CONFIG_GLOBAL
;
665 value
= GetWinstorePath();
667 else if (type
== SimpleCredentialType::GlobalGCM
)
669 configLevel
= CONFIG_GLOBAL
;
672 else if (type
== SimpleCredentialType::GlobalGCMCore
)
674 configLevel
= CONFIG_GLOBAL
;
675 value
= L
"manager-core";
677 else if (type
== SimpleCredentialType::SystemWincred
)
679 configLevel
= CONFIG_SYSTEM
;
682 else if (type
== SimpleCredentialType::SystemGCM
)
684 configLevel
= CONFIG_SYSTEM
;
687 else if (type
== SimpleCredentialType::SystemGCMCore
)
689 configLevel
= CONFIG_SYSTEM
;
690 value
= L
"manager-core";
695 // workaround gitdll bug
696 // TODO: switch to libgit2
697 bool old
= g_Git
.m_IsUseGitDLL
;
698 g_Git
.m_IsUseGitDLL
= false;
699 if (g_Git
.SetConfigValue(L
"credential.helper", value
, configLevel
))
702 msg
.FormatMessage(IDS_PROC_SAVECONFIGFAILED
, L
"credential.helper", static_cast<LPCTSTR
>(value
));
703 CMessageBox::Show(GetSafeHwnd(), msg
, L
"TortoiseGit", MB_OK
| MB_ICONERROR
);
706 g_Git
.m_IsUseGitDLL
= old
;
710 BOOL
CSettingGitCredential::OnApply()
713 return ISettingsPropPage::OnApply();
716 return ISettingsPropPage::OnApply();
721 bool CSettingGitCredential::SaveSettings()
726 int type
= m_ctrlSimpleCredential
.GetCurSel();
727 if ((type
== SimpleCredentialType::SystemWincred
|| type
== SimpleCredentialType::SystemGCM
|| type
== SimpleCredentialType::SystemGCMCore
) && !CAppUtils::IsAdminLogin())
729 if (m_iSimpleStoredValue
== type
)
731 if (DeleteOtherKeys(type
) > 0)
737 if (MessageBox(L
"Cannot modify a system config without proper rights.\nDiscard changes?", L
"TortoiseGit", MB_ICONERROR
| MB_YESNO
) == IDYES
)
741 if (type
!= SimpleCredentialType::Advanced
)
743 if (!SaveSimpleCredential(type
))
746 if (DeleteOtherKeys(type
) > 0)
752 int sel
= m_ctrlConfigType
.GetCurSel();
753 if (sel
== ConfigType::System
&& !CAppUtils::IsAdminLogin())
755 if (MessageBox(L
"Cannot modify a system config without proper rights.\nDiscard changes?", L
"TortoiseGit", MB_ICONERROR
| MB_YESNO
) == IDYES
)
760 if (m_ChangedMask
& CREDENTIAL_URL
)
763 if (m_strHelper
.IsEmpty())
765 CMessageBox::Show(GetSafeHwnd(), IDS_GITCREDENTIAL_HELPEREMPTY
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
768 m_strUrl
.Replace(L
'\\', L
'/');
769 m_strHelper
.Replace(L
'\\', L
'/');
771 Save(L
"helper", m_strHelper
);
772 m_ChangedMask
&= ~CREDENTIAL_HELPER
;
774 sel
= m_ctrlConfigType
.GetCurSel();
775 CString prefix
= sel
== ConfigType::System
? L
"S" : sel
== ConfigType::Global
? L
"G" : L
"L";
777 if (!m_strUrl
.IsEmpty())
778 text
.Format(L
"%s:%s", static_cast<LPCTSTR
>(prefix
), static_cast<LPCTSTR
>(m_strUrl
));
781 int urlIndex
= m_ctrlUrlList
.AddString(text
);
782 m_ctrlUrlList
.SetCurSel(urlIndex
);
783 GetDlgItem(IDC_BUTTON_ADD
)->EnableWindow(TRUE
);
786 if (m_ChangedMask
& CREDENTIAL_HELPER
)
788 m_strHelper
.Replace(L
'\\', L
'/');
789 Save(L
"helper", m_strHelper
);
792 if (m_ChangedMask
& CREDENTIAL_USERNAME
)
793 Save(L
"username", m_strUsername
);
795 if (m_ChangedMask
& CREDENTIAL_USEHTTPPATH
)
796 Save(L
"useHttpPath", m_bUseHttpPath
? L
"true" : L
"");
798 m_ChangedMask
&= ~CREDENTIAL_ADVANCED_MASK
;
805 void CSettingGitCredential::OnBnClickedButtonRemove()
807 int index
= m_ctrlUrlList
.GetCurSel();
811 m_ctrlUrlList
.GetText(index
, str
);
813 msg
.Format(IDS_WARN_REMOVE
, static_cast<LPCTSTR
>(str
));
814 if (CMessageBox::Show(GetSafeHwnd(), msg
, L
"TortoiseGit", MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
816 CAutoConfig
config(true);
817 CAutoRepository
repo(g_Git
.GetGitRepository());
818 int pos
= str
.Find(L
':');
819 CString prefix
= pos
>= 0 ? str
.Left(pos
) : str
;
820 CString url
= pos
>= 0 ? str
.Mid(pos
+ 1) : L
"";
821 CONFIG_TYPE configLevel
= CONFIG_LOCAL
;
826 configLevel
= CONFIG_LOCAL
;
827 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitLocalConfig()), GIT_CONFIG_LEVEL_LOCAL
, repo
, FALSE
);
833 configLevel
= CONFIG_GLOBAL
;
834 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalConfig()), GIT_CONFIG_LEVEL_GLOBAL
, repo
, FALSE
);
835 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitGlobalXDGConfig()), GIT_CONFIG_LEVEL_XDG
, repo
, FALSE
);
841 if (!CAppUtils::IsAdminLogin())
843 MessageBox(L
"Cannot modify a system config without proper rights.", L
"TortoiseGit", MB_ICONERROR
);
846 configLevel
= CONFIG_SYSTEM
;
847 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitSystemConfig()), GIT_CONFIG_LEVEL_SYSTEM
, repo
, FALSE
);
848 if (!g_Git
.ms_bCygwinGit
&& !g_Git
.ms_bMsys2Git
&& !g_Git
.GetGitProgramDataConfig().IsEmpty())
849 git_config_add_file_ondisk(config
, CGit::GetGitPathStringA(g_Git
.GetGitProgramDataConfig()), GIT_CONFIG_LEVEL_PROGRAMDATA
, repo
, FALSE
);
855 CStringA urlA
= CUnicodeUtils::GetUTF8(url
);
856 CStringA pattern
= urlA
.IsEmpty() ? "^credential\\.[^.]+$" : ("credential\\." + RegexEscape(urlA
) + "\\..*");
857 git_config_foreach_match(config
, pattern
, GetCredentialEntryCallback
, &list
);
858 for (size_t i
= 0; i
< list
.size(); ++i
)
859 g_Git
.UnsetConfigValue(list
[i
], configLevel
);
860 m_ctrlUrlList
.DeleteString(index
);
861 OnLbnSelchangeListUrl();
866 void CSettingGitCredential::OnBnClickedOpensettingselevated()
869 sCmd
.Format(L
"/command:settings /page:gitcredential /path:\"%s\"", static_cast<LPCTSTR
>(g_Git
.m_CurrentDir
));
870 CAppUtils::RunTortoiseGitProc(sCmd
, true);