Merge branch 'scintilla-551'
[TortoiseGit.git] / src / TortoiseProc / ProgressCommands / AddProgressCommand.cpp
blob84c14126bbbfb76ace57348faee07c9a21f7a021
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2011-2016, 2018-2020, 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 #include "stdafx.h"
20 #include "AddProgressCommand.h"
21 #include "ShellUpdater.h"
22 #include "MassiveGitTask.h"
23 #include "AppUtils.h"
25 using Git_WC_Notify_Action = CGitProgressList::WC_File_NotificationData::Git_WC_Notify_Action;
27 bool AddProgressCommand::Run(CGitProgressList* list, CString& sWindowTitle, int& m_itemCountTotal, int& m_itemCount)
29 ATLASSERT(!(m_bExecutable && m_bSymlink));
30 list->SetWindowTitle(IDS_PROGRS_TITLE_ADD, g_Git.CombinePath(m_targetPathList.GetCommonRoot().GetUIPathString()), sWindowTitle);
31 list->SetBackgroundImage(IDI_ADD_BKG);
32 if (m_bExecutable)
33 list->ReportCmd(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_ADD_EXE)));
34 else if (m_bSymlink)
35 list->ReportCmd(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_ADD_LINK)));
36 else
37 list->ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_ADD)));
39 m_itemCountTotal = m_targetPathList.GetCount();
41 if (g_Git.UsingLibGit2(CGit::GIT_CMD_ADD))
43 CAutoRepository repo(g_Git.GetGitRepository());
44 if (!repo)
46 list->ReportGitError();
47 return false;
50 CAutoIndex index;
51 if (git_repository_index(index.GetPointer(), repo))
53 list->ReportGitError();
54 return false;
56 if (git_index_read(index, true))
58 list->ReportGitError();
59 return false;
62 for (m_itemCount = 0; m_itemCount < m_itemCountTotal; ++m_itemCount)
64 CStringA filePathA = CUnicodeUtils::GetUTF8(m_targetPathList[m_itemCount].GetGitPathString()).TrimRight(L'/');
65 if (git_index_add_bypath(index, filePathA))
67 list->ReportGitError();
68 return false;
71 if (!m_targetPathList[m_itemCount].IsDirectory() && (m_bExecutable || m_bSymlink))
73 auto entry = const_cast<git_index_entry*>(git_index_get_bypath(index, filePathA, 0));
74 if (m_bExecutable)
75 entry->mode = GIT_FILEMODE_BLOB_EXECUTABLE;
76 else if (m_bSymlink)
77 entry->mode = GIT_FILEMODE_LINK;
78 if (git_index_add(index, entry))
80 list->ReportGitError();
81 return false;
85 list->AddNotify(new CGitProgressList::WC_File_NotificationData(m_targetPathList[m_itemCount], Git_WC_Notify_Action::Add));
87 if (list->IsCancelled() == TRUE)
89 list->ReportUserCanceled();
90 return false;
94 if (git_index_write(index))
96 list->ReportGitError();
97 return false;
100 else
102 CMassiveGitTask mgt(L"add -f");
103 if (!mgt.ExecuteWithNotify(&m_targetPathList, list->m_bCancelled, Git_WC_Notify_Action::Add, list))
104 return false;
105 if (m_bExecutable)
107 if (!SetFileMode(GIT_FILEMODE_BLOB_EXECUTABLE))
108 return false;
110 else if (m_bSymlink)
112 if (!SetFileMode(GIT_FILEMODE_LINK))
113 return false;
117 CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);
119 m_PostCmdCallback = [this](DWORD status, PostCmdList& postCmdList)
121 if (status)
122 return;
124 if (m_bShowCommitButtonAfterAdd)
125 postCmdList.emplace_back(IDI_COMMIT, IDS_MENUCOMMIT, []
127 CString sCmd;
128 sCmd.Format(L"/command:commit /path:\"%s\"", static_cast<LPCWSTR>(g_Git.m_CurrentDir));
129 CAppUtils::RunTortoiseGitProc(sCmd);
131 if (!(m_bExecutable || m_bSymlink))
133 postCmdList.emplace_back(IDI_ADD, IDS_STATUSLIST_CONTEXT_ADD_EXE, [this] {
134 SetFileMode(GIT_FILEMODE_BLOB_EXECUTABLE);
136 postCmdList.emplace_back(IDI_ADD, IDS_STATUSLIST_CONTEXT_ADD_LINK, [this] {
137 SetFileMode(GIT_FILEMODE_LINK);
142 return true;
145 bool AddProgressCommand::SetFileMode(uint32_t mode)
147 CAutoRepository repo(g_Git.GetGitRepository());
148 if (!repo)
150 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not open repository."), L"TortoiseGit", MB_ICONERROR);
151 return false;
154 CAutoIndex index;
155 if (git_repository_index(index.GetPointer(), repo))
157 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not get index."), L"TortoiseGit", MB_ICONERROR);
158 return false;
160 if (git_index_read(index, true))
162 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not read index."), L"TortoiseGit", MB_ICONERROR);
163 return false;
166 for (int i = 0; i < m_targetPathList.GetCount(); ++i)
168 if (m_targetPathList[i].IsDirectory())
169 continue;
170 CStringA filePathA = CUnicodeUtils::GetUTF8(m_targetPathList[i].GetGitPathString()).TrimRight(L'/');
171 auto entry = const_cast<git_index_entry*>(git_index_get_bypath(index, filePathA, 0));
172 if (!entry)
174 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not update file mode."), L"TortoiseGit", MB_ICONERROR);
175 return false;
177 entry->mode = mode;
178 if (git_index_add(index, entry))
180 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not update index."), L"TortoiseGit", MB_ICONERROR);
181 return false;
185 if (git_index_write(index))
187 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not write index."), L"TortoiseGit", MB_ICONERROR);
188 return false;
191 return true;