Re-integrate the GPG signed commit into the unit tests
[TortoiseGit.git] / src / TortoiseProc / SubmoduleUpdateDlg.cpp
blobaf6f06781a6c53e859e43c2efda042ed7d8fb388
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2017 - 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 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "SubmoduleUpdateDlg.h"
23 #include "AppUtils.h"
24 #include "UnicodeUtils.h"
26 IMPLEMENT_DYNAMIC(CSubmoduleUpdateDlg, CResizableStandAloneDialog)
28 bool CSubmoduleUpdateDlg::s_bSortLogical = true;
30 CSubmoduleUpdateDlg::CSubmoduleUpdateDlg(CWnd* pParent /*=nullptr*/)
31 : CResizableStandAloneDialog(CSubmoduleUpdateDlg::IDD, pParent)
32 , m_bInit(TRUE)
33 , m_bRecursive(FALSE)
34 , m_bForce(FALSE)
35 , m_bNoFetch(FALSE)
36 , m_bMerge(FALSE)
37 , m_bRebase(FALSE)
38 , m_bRemote(FALSE)
39 , m_bWholeProject(FALSE)
41 s_bSortLogical = !CRegDWORD(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_CURRENT_USER);
42 if (s_bSortLogical)
43 s_bSortLogical = !CRegDWORD(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_LOCAL_MACHINE);
46 CSubmoduleUpdateDlg::~CSubmoduleUpdateDlg()
50 void CSubmoduleUpdateDlg::DoDataExchange(CDataExchange* pDX)
52 CResizableStandAloneDialog::DoDataExchange(pDX);
53 DDX_Control(pDX, IDC_LIST_PATH, m_PathListBox);
54 DDX_Control(pDX, IDC_SELECTALL, m_SelectAll);
55 DDX_Check(pDX, IDC_WHOLE_PROJECT, m_bWholeProject);
56 DDX_Check(pDX, IDC_CHECK_SUBMODULE_INIT, m_bInit);
57 DDX_Check(pDX, IDC_CHECK_SUBMODULE_RECURSIVE, m_bRecursive);
58 DDX_Check(pDX, IDC_FORCE, m_bForce);
59 DDX_Check(pDX, IDC_CHECK_SUBMODULE_NOFETCH, m_bNoFetch);
60 DDX_Check(pDX, IDC_CHECK_SUBMODULE_MERGE, m_bMerge);
61 DDX_Check(pDX, IDC_CHECK_SUBMODULE_REBASE, m_bRebase);
62 DDX_Check(pDX, IDC_CHECK_SUBMODULE_REMOTE, m_bRemote);
65 BEGIN_MESSAGE_MAP(CSubmoduleUpdateDlg, CResizableStandAloneDialog)
66 ON_BN_CLICKED(IDC_SELECTALL, OnBnClickedSelectall)
67 ON_BN_CLICKED(IDC_WHOLE_PROJECT, OnBnClickedShowWholeProject)
68 ON_BN_CLICKED(IDOK, &CSubmoduleUpdateDlg::OnBnClickedOk)
69 ON_LBN_SELCHANGE(IDC_LIST_PATH, &CSubmoduleUpdateDlg::OnLbnSelchangeListPath)
70 END_MESSAGE_MAP()
72 static int SubmoduleCallback(git_submodule *sm, const char * /*name*/, void *payload)
74 STRING_VECTOR *list = *(STRING_VECTOR **)payload;
75 STRING_VECTOR *prefixList = *((STRING_VECTOR **)payload + 1);
76 CString path = CUnicodeUtils::GetUnicode(git_submodule_path(sm));
77 if (prefixList->empty())
78 list->push_back(path);
79 else
81 for (size_t i = 0; i < prefixList->size(); ++i)
83 CString prefix = prefixList->at(i) + L'/';
84 if (CStringUtils::StartsWith(path, prefix))
85 list->push_back(path);
88 return 0;
91 int LogicalComparePredicate(const CString &left, const CString &right)
93 if (CSubmoduleUpdateDlg::s_bSortLogical)
94 return StrCmpLogicalW(left, right) < 0;
95 return StrCmpI(left, right) < 0;
98 static void GetSubmodulePathList(STRING_VECTOR &list, STRING_VECTOR &prefixList)
100 CAutoRepository repo(g_Git.GetGitRepository());
101 if (!repo)
103 MessageBox(nullptr, CGit::GetLibGit2LastErr(L"Could not open repository."), L"TortoiseGit", MB_ICONERROR);
104 return;
107 STRING_VECTOR *listParams[] = { &list, &prefixList };
108 if (git_submodule_foreach(repo, SubmoduleCallback, &listParams))
110 MessageBox(nullptr, CGit::GetLibGit2LastErr(L"Could not get submodule list."), L"TortoiseGit", MB_ICONERROR);
111 return;
114 std::sort(list.begin(), list.end(), LogicalComparePredicate);
117 BOOL CSubmoduleUpdateDlg::OnInitDialog()
119 CResizableStandAloneDialog::OnInitDialog();
120 CAppUtils::MarkWindowAsUnpinnable(m_hWnd);
122 AdjustControlSize(IDC_CHECK_SUBMODULE_INIT);
123 AdjustControlSize(IDC_CHECK_SUBMODULE_RECURSIVE);
124 AdjustControlSize(IDC_CHECK_SUBMODULE_NOFETCH);
125 AdjustControlSize(IDC_CHECK_SUBMODULE_MERGE);
126 AdjustControlSize(IDC_CHECK_SUBMODULE_REBASE);
128 AddAnchor(IDOK, BOTTOM_RIGHT);
129 AddAnchor(IDCANCEL, BOTTOM_RIGHT);
130 AddAnchor(IDHELP, BOTTOM_RIGHT);
131 AddAnchor((UINT)IDC_STATIC, TOP_LEFT);
132 AddAnchor(IDC_LIST_PATH, TOP_LEFT, BOTTOM_RIGHT);
133 AddAnchor(IDC_SELECTALL, BOTTOM_LEFT);
134 AddAnchor(IDC_WHOLE_PROJECT, BOTTOM_LEFT);
135 AddAnchor(IDC_GROUP_INFO, BOTTOM_LEFT, BOTTOM_RIGHT);
136 AddAnchor(IDC_CHECK_SUBMODULE_INIT, BOTTOM_LEFT);
137 AddAnchor(IDC_CHECK_SUBMODULE_RECURSIVE, BOTTOM_LEFT);
138 AddAnchor(IDC_FORCE, BOTTOM_LEFT);
139 AddAnchor(IDC_CHECK_SUBMODULE_REMOTE, BOTTOM_LEFT);
140 AddAnchor(IDC_CHECK_SUBMODULE_NOFETCH, BOTTOM_RIGHT);
141 AddAnchor(IDC_CHECK_SUBMODULE_MERGE, BOTTOM_RIGHT);
142 AddAnchor(IDC_CHECK_SUBMODULE_REBASE, BOTTOM_RIGHT);
144 CString str(g_Git.m_CurrentDir);
145 str.Replace(L':', L'_');
146 m_regShowWholeProject = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\ShowWholeProject\\" + str, FALSE);
147 m_bWholeProject = m_regShowWholeProject;
149 m_regInit = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\init", TRUE);
150 m_bInit = m_regInit;
151 m_regRecursive = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\recursive", FALSE);
152 m_bRecursive = m_regRecursive;
153 m_regForce = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\force", FALSE);
154 m_bForce = m_regForce;
155 m_regRemote = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\remote", FALSE);
156 m_bRemote = m_regRemote;
157 m_regNoFetch = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\nofetch", FALSE);
158 m_bNoFetch = m_regNoFetch;
159 m_regMerge = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\merge", FALSE);
160 m_bMerge = m_regMerge;
161 m_regRebase = CRegDWORD(L"Software\\TortoiseGit\\TortoiseProc\\SubmoduleUpdate\\" + str + L"\\rebase", FALSE);
162 m_bRebase = m_regRebase;
164 DialogEnableWindow(IDC_WHOLE_PROJECT, !(m_PathFilterList.empty() || (m_PathFilterList.size() == 1 && m_PathFilterList[0].IsEmpty())));
166 SetDlgTitle();
168 EnableSaveRestore(L"SubmoduleUpdateDlg");
170 Refresh();
171 UpdateData(FALSE);
173 return TRUE;
176 void CSubmoduleUpdateDlg::SetDlgTitle()
178 if (m_sTitle.IsEmpty())
179 GetWindowText(m_sTitle);
180 CString dir = g_Git.m_CurrentDir;
181 if (!m_bWholeProject)
183 if (!m_PathFilterList.empty())
184 dir += (CStringUtils::EndsWith(g_Git.m_CurrentDir, L'\\') ? L"" : L"\\") + CTGitPath(m_PathFilterList[0]).GetWinPathString();
185 if (m_PathFilterList.size() > 1)
186 dir += L", ...";
188 CAppUtils::SetWindowTitle(m_hWnd, dir, m_sTitle);
191 void CSubmoduleUpdateDlg::OnBnClickedOk()
193 CResizableStandAloneDialog::UpdateData(TRUE);
194 m_PathList.clear();
196 CString selected;
197 for (int i = 0; i < m_PathListBox.GetCount(); ++i)
199 if (m_PathListBox.GetSel(i))
201 if (!selected.IsEmpty())
202 selected.AppendChar(L'|');
203 CString text;
204 m_PathListBox.GetText(i, text);
205 m_PathList.push_back(text);
206 selected.Append(text);
209 m_regPath = selected;
211 m_regInit = m_bInit;
212 m_regRecursive = m_bRecursive;
213 m_regForce = m_bForce;
214 m_regRemote = m_bRemote;
215 m_regNoFetch = m_bNoFetch;
216 m_regMerge = m_bMerge;
217 m_regRebase = m_bRebase;
219 CResizableStandAloneDialog::OnOK();
222 void CSubmoduleUpdateDlg::OnLbnSelchangeListPath()
224 GetDlgItem(IDOK)->EnableWindow(m_PathListBox.GetSelCount() > 0 ? TRUE : FALSE);
225 if (m_PathListBox.GetSelCount() == 0)
226 m_SelectAll.SetCheck(BST_UNCHECKED);
227 else if ((int)m_PathListBox.GetSelCount() < m_PathListBox.GetCount())
228 m_SelectAll.SetCheck(BST_INDETERMINATE);
229 else
230 m_SelectAll.SetCheck(BST_CHECKED);
233 void CSubmoduleUpdateDlg::OnBnClickedSelectall()
235 UINT state = (m_SelectAll.GetState() & 0x0003);
236 if (state == BST_INDETERMINATE)
238 // It is not at all useful to manually place the checkbox into the indeterminate state...
239 // We will force this on to the unchecked state
240 state = BST_UNCHECKED;
241 m_SelectAll.SetCheck(state);
243 if (state == BST_UNCHECKED)
245 for (int i = 0; i < m_PathListBox.GetCount(); ++i)
246 m_PathListBox.SetSel(i, FALSE);
248 else
250 for (int i = 0; i < m_PathListBox.GetCount(); ++i)
251 m_PathListBox.SetSel(i, TRUE);
253 OnLbnSelchangeListPath();
256 void CSubmoduleUpdateDlg::OnBnClickedShowWholeProject()
258 UpdateData();
259 m_regShowWholeProject = m_bWholeProject;
260 SetDlgTitle();
261 Refresh();
264 void CSubmoduleUpdateDlg::Refresh()
266 while (m_PathListBox.GetCount() > 0)
267 m_PathListBox.DeleteString(m_PathListBox.GetCount() - 1);
269 CString WorkingDir = g_Git.m_CurrentDir;
270 WorkingDir.Replace(L':', L'_');
272 m_regPath = CRegString(L"Software\\TortoiseGit\\History\\SubmoduleUpdatePath\\" + WorkingDir);
273 CString path = m_regPath;
274 STRING_VECTOR emptylist;
275 STRING_VECTOR list;
276 GetSubmodulePathList(list, m_bWholeProject ? emptylist : m_PathFilterList);
277 STRING_VECTOR selected;
278 if (m_PathList.empty())
280 int pos = 0;
281 while (pos >= 0)
283 CString part = path.Tokenize(L"|", pos);
284 if (!part.IsEmpty())
285 selected.push_back(part);
288 else
290 for (size_t i = 0; i < m_PathList.size(); ++i)
291 selected.push_back(m_PathList[i]);
294 for (size_t i = 0; i < list.size(); ++i)
296 m_PathListBox.AddString(list[i]);
297 if (selected.size() == 0)
298 m_PathListBox.SetSel((int)i);
299 else
301 for (size_t j = 0; j < selected.size(); ++j)
303 if (selected[j] == list[i])
304 m_PathListBox.SetSel((int)i);
309 OnLbnSelchangeListPath();