Fixed issue #4133: libgit2 returned: failed to parse revision specifier (ref ending...
[TortoiseGit.git] / src / TortoiseProc / Settings / SettingGitConfig.cpp
bloba391ed081a05c416d873e3652df66d1c5fd366ea
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2017, 2019-2021, 2023 - 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 // SettingGitConfig.cpp : implementation file
22 #include "stdafx.h"
23 #include "TortoiseProc.h"
24 #include "SettingGitConfig.h"
25 #include "Settings.h"
26 #include "GitAdminDir.h"
27 #include "AppUtils.h"
28 // CSettingGitConfig dialog
30 IMPLEMENT_DYNAMIC(CSettingGitConfig, ISettingsPropPage)
32 CSettingGitConfig::CSettingGitConfig()
33 : ISettingsPropPage(CSettingGitConfig::IDD)
34 , m_bNeedSave(false)
35 , m_bQuotePath(TRUE)
36 , m_bPrune(FALSE)
37 , m_bInheritUserName(FALSE)
38 , m_bInheritEmail(FALSE)
39 , m_bInheritSigningKey(FALSE)
43 CSettingGitConfig::~CSettingGitConfig()
47 void CSettingGitConfig::DoDataExchange(CDataExchange* pDX)
49 CPropertyPage::DoDataExchange(pDX);
50 DDX_Text(pDX, IDC_GIT_USERNAME, m_UserName);
51 DDX_Text(pDX, IDC_GIT_USEREMAIL, m_UserEmail);
52 DDX_Text(pDX, IDC_GIT_USERESINGNINGKEY, m_UserSigningKey);
53 DDX_Check(pDX, IDC_CHECK_QUOTEPATH, m_bQuotePath);
54 DDX_Check(pDX, IDC_CHECK_PRUNE, m_bPrune);
55 DDX_Check(pDX, IDC_CHECK_INHERIT_NAME, m_bInheritUserName);
56 DDX_Check(pDX, IDC_CHECK_INHERIT_EMAIL, m_bInheritEmail);
57 DDX_Check(pDX, IDC_CHECK_INHERIT_KEYID, m_bInheritSigningKey);
58 DDX_Control(pDX, IDC_COMBO_AUTOCRLF, m_cAutoCrLf);
59 DDX_Control(pDX, IDC_COMBO_SAFECRLF, m_cSafeCrLf);
60 GITSETTINGS_DDX
63 BEGIN_MESSAGE_MAP(CSettingGitConfig, CPropertyPage)
64 ON_EN_CHANGE(IDC_GIT_USERNAME, &CSettingGitConfig::OnChange)
65 ON_EN_CHANGE(IDC_GIT_USEREMAIL, &CSettingGitConfig::OnChange)
66 ON_EN_CHANGE(IDC_GIT_USERESINGNINGKEY, &CSettingGitConfig::OnChange)
67 ON_CBN_SELCHANGE(IDC_COMBO_AUTOCRLF, &CSettingGitConfig::OnChange)
68 ON_BN_CLICKED(IDC_CHECK_QUOTEPATH, &CSettingGitConfig::OnChange)
69 ON_BN_CLICKED(IDC_CHECK_PRUNE, &CSettingGitConfig::OnChange)
70 ON_CBN_SELCHANGE(IDC_COMBO_SAFECRLF, &CSettingGitConfig::OnChange)
71 ON_BN_CLICKED(IDC_CHECK_INHERIT_NAME, &CSettingGitConfig::OnChange)
72 ON_BN_CLICKED(IDC_CHECK_INHERIT_EMAIL, &CSettingGitConfig::OnChange)
73 ON_BN_CLICKED(IDC_CHECK_INHERIT_KEYID, &CSettingGitConfig::OnChange)
74 ON_BN_CLICKED(IDC_EDITGLOBALGITCONFIG, &CSettingGitConfig::OnBnClickedEditglobalgitconfig)
75 ON_BN_CLICKED(IDC_EDITGLOBALXDGGITCONFIG, &CSettingGitConfig::OnBnClickedEditglobalxdggitconfig)
76 ON_BN_CLICKED(IDC_EDITLOCALGITCONFIG, &CSettingGitConfig::OnBnClickedEditlocalgitconfig)
77 ON_BN_CLICKED(IDC_EDITTGITCONFIG, &CSettingGitConfig::OnBnClickedEdittgitconfig)
78 ON_BN_CLICKED(IDC_VIEWEFFECTIVEGITCONFIG, &CSettingGitConfig::OnBnClickedVieweffectivegitconfig)
79 ON_BN_CLICKED(IDC_EDITSYSTEMGITCONFIG, &CSettingGitConfig::OnBnClickedEditsystemgitconfig)
80 ON_BN_CLICKED(IDC_VIEWSYSTEMGITCONFIG, &CSettingGitConfig::OnBnClickedViewsystemgitconfig)
81 GITSETTINGS_RADIO_EVENT
82 END_MESSAGE_MAP()
84 BOOL CSettingGitConfig::OnInitDialog()
86 ISettingsPropPage::OnInitDialog();
88 m_cAutoCrLf.AddString(L"");
89 m_cAutoCrLf.AddString(L"false");
90 m_cAutoCrLf.AddString(L"true");
91 m_cAutoCrLf.AddString(L"input");
93 m_cSafeCrLf.AddString(L"");
94 m_cSafeCrLf.AddString(L"false");
95 m_cSafeCrLf.AddString(L"true");
96 m_cSafeCrLf.AddString(L"warn");
98 AdjustControlSize(IDC_CHECK_QUOTEPATH);
99 AdjustControlSize(IDC_CHECK_INHERIT_NAME);
100 AdjustControlSize(IDC_CHECK_INHERIT_EMAIL);
101 AdjustControlSize(IDC_CHECK_INHERIT_KEYID);
102 GITSETTINGS_ADJUSTCONTROLSIZE
104 m_tooltips.AddTool(IDC_CHECK_INHERIT_NAME, IDS_SETTINGS_GITCONFIG_INHERIT_TT);
105 m_tooltips.AddTool(IDC_CHECK_INHERIT_EMAIL, IDS_SETTINGS_GITCONFIG_INHERIT_TT);
106 m_tooltips.AddTool(IDC_CHECK_INHERIT_KEYID, IDS_SETTINGS_GITCONFIG_INHERIT_TT);
108 InitGitSettings(this, false, &m_tooltips);
110 if (!m_bGlobal || m_bIsBareRepo)
111 this->GetDlgItem(IDC_EDITLOCALGITCONFIG)->EnableWindow(TRUE);
112 else
113 this->GetDlgItem(IDC_EDITLOCALGITCONFIG)->EnableWindow(FALSE);
115 if (m_bGlobal)
116 this->GetDlgItem(IDC_EDITTGITCONFIG)->EnableWindow(FALSE);
118 if (m_bIsBareRepo)
120 this->GetDlgItem(IDC_EDITLOCALGITCONFIG)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_GITCONFIG_EDITLOCALGONCFIG)));
121 this->GetDlgItem(IDC_EDITTGITCONFIG)->SetWindowText(CString(MAKEINTRESOURCE(IDS_PROC_GITCONFIG_VIEWTGITCONFIG)));
124 if (!CAppUtils::IsAdminLogin())
126 static_cast<CButton*>(this->GetDlgItem(IDC_EDITSYSTEMGITCONFIG))->SetShield(TRUE);
127 GetDlgItem(IDC_VIEWSYSTEMGITCONFIG)->EnableWindow(TRUE);
128 this->GetDlgItem(IDC_VIEWSYSTEMGITCONFIG)->ShowWindow(SW_SHOW);
131 if (PathIsDirectory(g_Git.GetGitGlobalXDGConfigPath()))
133 GetDlgItem(IDC_EDITGLOBALXDGGITCONFIG)->EnableWindow(TRUE);
134 this->GetDlgItem(IDC_EDITGLOBALXDGGITCONFIG)->ShowWindow(SW_SHOW);
137 this->UpdateData(FALSE);
139 if (m_UserName.IsEmpty() && m_UserEmail.IsEmpty())
141 // preselect "global" and remove check in "inherit" checkboxes if no username and email are set on first open
142 m_iConfigSource = CFG_SRC_GLOBAL;
143 CheckRadioButton(IDC_RADIO_SETTINGS_EFFECTIVE, IDC_RADIO_SETTINGS_SYSTEM, IDC_RADIO_SETTINGS_EFFECTIVE + m_iConfigSource);
144 m_cSaveTo.SelectString(0, CString(MAKEINTRESOURCE(IDS_CONFIG_GLOBAL)));
145 LoadData();
146 m_bInheritUserName = FALSE;
147 m_bInheritEmail = FALSE;
148 EnDisableControls();
150 return TRUE;
152 // CSettingGitConfig message handlers
154 void CSettingGitConfig::LoadDataImpl(CAutoConfig& config)
156 m_bInheritSigningKey = (config.GetString(L"user.signingkey", m_UserSigningKey) == GIT_ENOTFOUND);
158 // special handling for UserName and UserEmail, because these can also be defined as environment variables for effective settings
159 if (m_iConfigSource == CFG_SRC_EFFECTIVE)
161 m_UserName = g_Git.GetUserName();
162 m_UserEmail = g_Git.GetUserEmail();
163 m_bInheritUserName = FALSE;
164 m_bInheritEmail = FALSE;
165 m_bInheritSigningKey = FALSE;
167 else
169 m_bInheritUserName = (config.GetString(L"user.name", m_UserName) == GIT_ENOTFOUND);
170 m_bInheritEmail = (config.GetString(L"user.email", m_UserEmail) == GIT_ENOTFOUND);
173 BOOL bAutoCrLf = FALSE;
174 if (git_config_get_bool(&bAutoCrLf, config, "core.autocrlf") == GIT_ENOTFOUND)
175 m_cAutoCrLf.SetCurSel(0);
176 else if (bAutoCrLf)
177 m_cAutoCrLf.SetCurSel(2);
178 else
180 CString sAutoCrLf;
181 config.GetString(L"core.autocrlf", sAutoCrLf);
182 sAutoCrLf = sAutoCrLf.MakeLower().Trim();
183 if (sAutoCrLf == L"input")
184 m_cAutoCrLf.SetCurSel(3);
185 else
186 m_cAutoCrLf.SetCurSel(1);
189 if (git_config_get_bool(&m_bQuotePath, config, "core.quotepath") == GIT_ENOTFOUND)
191 if (m_iConfigSource == CFG_SRC_EFFECTIVE)
192 m_bQuotePath = BST_CHECKED;
193 else
194 m_bQuotePath = BST_INDETERMINATE;
197 if (git_config_get_bool(&m_bPrune, config, "fetch.prune") == GIT_ENOTFOUND)
199 if (m_iConfigSource == CFG_SRC_EFFECTIVE)
200 m_bPrune = BST_UNCHECKED;
201 else
202 m_bPrune = BST_INDETERMINATE;
205 BOOL bSafeCrLf = FALSE;
206 if (git_config_get_bool(&bSafeCrLf, config, "core.safecrlf") == GIT_ENOTFOUND)
207 m_cSafeCrLf.SetCurSel(0);
208 else if (bSafeCrLf)
209 m_cSafeCrLf.SetCurSel(2);
210 else
212 CString sSafeCrLf;
213 config.GetString(L"core.safecrlf", sSafeCrLf);
214 sSafeCrLf = sSafeCrLf.MakeLower().Trim();
215 if (sSafeCrLf == L"warn")
216 m_cSafeCrLf.SetCurSel(3);
217 else
218 m_cSafeCrLf.SetCurSel(1);
221 m_bNeedSave = false;
222 SetModified(FALSE);
223 UpdateData(FALSE);
226 void CSettingGitConfig::EnDisableControls()
228 GetDlgItem(IDC_GIT_USERNAME)->SendMessage(EM_SETREADONLY, m_iConfigSource == CFG_SRC_EFFECTIVE, 0);
229 GetDlgItem(IDC_GIT_USEREMAIL)->SendMessage(EM_SETREADONLY, m_iConfigSource == CFG_SRC_EFFECTIVE, 0);
230 GetDlgItem(IDC_GIT_USERESINGNINGKEY)->SendMessage(EM_SETREADONLY, m_iConfigSource == CFG_SRC_EFFECTIVE, 0);
231 GetDlgItem(IDC_COMBO_AUTOCRLF)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
232 GetDlgItem(IDC_CHECK_QUOTEPATH)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
233 GetDlgItem(IDC_CHECK_PRUNE)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
234 GetDlgItem(IDC_COMBO_SAFECRLF)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
235 GetDlgItem(IDC_COMBO_SETTINGS_SAFETO)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
236 GetDlgItem(IDC_CHECK_INHERIT_NAME)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
237 GetDlgItem(IDC_CHECK_INHERIT_EMAIL)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
238 GetDlgItem(IDC_CHECK_INHERIT_KEYID)->EnableWindow(m_iConfigSource != CFG_SRC_EFFECTIVE);
240 GetDlgItem(IDC_GIT_USERNAME)->EnableWindow(!m_bInheritUserName);
241 GetDlgItem(IDC_GIT_USEREMAIL)->EnableWindow(!m_bInheritEmail);
242 GetDlgItem(IDC_GIT_USERESINGNINGKEY)->EnableWindow(!m_bInheritSigningKey);
243 UpdateData(FALSE);
246 void CSettingGitConfig::OnChange()
248 UpdateData();
249 EnDisableControls();
250 m_bNeedSave = true;
251 SetModified();
254 BOOL CSettingGitConfig::SafeDataImpl(CAutoConfig& config)
256 if (!Save(config, L"user.name", m_UserName, m_bInheritUserName == TRUE))
257 return FALSE;
259 if (!Save(config, L"user.email", m_UserEmail, m_bInheritEmail == TRUE))
260 return FALSE;
262 if (!Save(config, L"user.signingkey", this->m_UserSigningKey, m_bInheritSigningKey == TRUE))
263 return FALSE;
265 if (!Save(config, L"core.quotepath", m_bQuotePath ? L"true" : L"false", m_bQuotePath == BST_INDETERMINATE))
266 return FALSE;
268 if (!Save(config, L"fetch.prune", m_bPrune ? L"true" : L"false", m_bPrune == BST_INDETERMINATE))
269 return FALSE;
272 CString autocrlf;
273 m_cAutoCrLf.GetWindowText(autocrlf);
274 if (!Save(config, L"core.autocrlf", autocrlf, autocrlf.IsEmpty()))
275 return FALSE;
279 CString safecrlf;
280 this->m_cSafeCrLf.GetWindowText(safecrlf);
281 if (!Save(config, L"core.safecrlf", safecrlf, safecrlf.IsEmpty()))
282 return FALSE;
285 return TRUE;
288 BOOL CSettingGitConfig::OnApply()
290 if (!m_bNeedSave)
291 return TRUE;
292 UpdateData();
293 if (!SafeData())
294 return FALSE;
295 m_bNeedSave = false;
296 SetModified(FALSE);
297 return ISettingsPropPage::OnApply();
300 void CSettingGitConfig::OnBnClickedEditglobalgitconfig()
302 // use alternative editor because of LineEndings
303 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitGlobalConfig());
306 void CSettingGitConfig::OnBnClickedEditglobalxdggitconfig()
308 // use alternative editor because of LineEndings
309 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitGlobalXDGConfig());
312 void CSettingGitConfig::OnBnClickedEditlocalgitconfig()
314 // use alternative editor because of LineEndings
315 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitLocalConfig());
318 void CSettingGitConfig::OnBnClickedEdittgitconfig()
320 // use alternative editor because of LineEndings
321 if (GitAdminDir::IsBareRepo(g_Git.m_CurrentDir))
323 CString tmpFile = GetTempFile();
324 if (tmpFile.IsEmpty())
326 MessageBox(L"Could not create temp file.", L"TortoiseGit", MB_OK | MB_ICONERROR);
327 return;
329 CTGitPath path(L".tgitconfig");
330 if (g_Git.GetOneFile(L"HEAD", path, tmpFile) == 0)
332 ::SetFileAttributes(tmpFile, FILE_ATTRIBUTE_READONLY);
333 CAppUtils::LaunchAlternativeEditor(tmpFile);
336 else
338 CAppUtils::LaunchAlternativeEditor(g_Git.m_CurrentDir + L"\\.tgitconfig");
342 void CSettingGitConfig::OnBnClickedVieweffectivegitconfig()
344 CString err;
345 CString tempfile = ::GetTempFile();
346 if (tempfile.IsEmpty())
348 MessageBox(L"Could not create temp file.", L"TortoiseGit", MB_OK | MB_ICONERROR);
349 return;
352 CString cmd = L"git config --show-origin -l";
353 if (g_Git.RunLogFile(cmd, tempfile, &err))
355 CMessageBox::Show(GetSafeHwnd(), L"Could not get effective git config:\n" + err, L"TortoiseGit", MB_OK);
356 return;
358 ::SetFileAttributes(tempfile, FILE_ATTRIBUTE_READONLY);
359 CAppUtils::LaunchAlternativeEditor(tempfile);
362 void CSettingGitConfig::OnBnClickedEditsystemgitconfig()
364 CString filename = g_Git.GetGitSystemConfig();
365 if (filename.IsEmpty())
367 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_GITCONFIG_NOMSYSGIT, IDS_APPNAME, MB_ICONERROR);
368 return;
370 // use alternative editor because of LineEndings
371 CAppUtils::LaunchAlternativeEditor(filename, true);
374 void CSettingGitConfig::OnBnClickedViewsystemgitconfig()
376 CString filename = g_Git.GetGitSystemConfig();
377 if (filename.IsEmpty())
379 CMessageBox::Show(GetSafeHwnd(), IDS_PROC_GITCONFIG_NOMSYSGIT, IDS_APPNAME, MB_ICONERROR);
380 return;
382 // use alternative editor because of LineEndings
383 CAppUtils::LaunchAlternativeEditor(filename);