Provide shortcuts to mark file as executable / symlink during Add
[TortoiseGit.git] / src / TortoiseProc / ProgressCommands / AddProgressCommand.cpp
blobd38187205c03d75a202a700966832ba51c0a0559
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2011-2016 - 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 bool AddProgressCommand::Run(CGitProgressList* list, CString& sWindowTitle, int& m_itemCountTotal, int& m_itemCount)
27 list->SetWindowTitle(IDS_PROGRS_TITLE_ADD, g_Git.CombinePath(m_targetPathList.GetCommonRoot().GetUIPathString()), sWindowTitle);
28 list->SetBackgroundImage(IDI_ADD_BKG);
29 if (m_bExecutable)
30 list->ReportCmd(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_ADD_EXE)));
31 else if (m_bSymlink)
32 list->ReportCmd(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_ADD_LINK)));
33 else
34 list->ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_ADD)));
36 m_itemCountTotal = m_targetPathList.GetCount();
38 if (g_Git.UsingLibGit2(CGit::GIT_CMD_ADD))
40 CAutoRepository repo(g_Git.GetGitRepository());
41 if (!repo)
43 list->ReportGitError();
44 return false;
47 CAutoIndex index;
48 if (git_repository_index(index.GetPointer(), repo))
50 list->ReportGitError();
51 return false;
53 if (git_index_read(index, true))
55 list->ReportGitError();
56 return false;
59 for (m_itemCount = 0; m_itemCount < m_itemCountTotal; ++m_itemCount)
61 CStringA filePathA = CUnicodeUtils::GetMulti(m_targetPathList[m_itemCount].GetGitPathString(), CP_UTF8).TrimRight(L'/');
62 if (git_index_add_bypath(index, filePathA))
64 list->ReportGitError();
65 return false;
68 if (!m_targetPathList[m_itemCount].IsDirectory() && (m_bExecutable || m_bSymlink))
70 auto entry = const_cast<git_index_entry*>(git_index_get_bypath(index, filePathA, 0));
71 if (m_bExecutable)
72 entry->mode = GIT_FILEMODE_BLOB_EXECUTABLE;
73 else if (m_bSymlink)
74 entry->mode = GIT_FILEMODE_LINK;
75 if (git_index_add(index, entry))
77 list->ReportGitError();
78 return false;
82 list->AddNotify(new CGitProgressList::WC_File_NotificationData(m_targetPathList[m_itemCount], CGitProgressList::WC_File_NotificationData::git_wc_notify_add));
84 if (list->IsCancelled() == TRUE)
86 list->ReportUserCanceled();
87 return false;
91 if (git_index_write(index))
93 list->ReportGitError();
94 return false;
97 else
99 CMassiveGitTask mgt(L"add -f");
100 if (!mgt.ExecuteWithNotify(&m_targetPathList, list->m_bCancelled, CGitProgressList::WC_File_NotificationData::git_wc_notify_add, list))
101 return false;
102 if (m_bExecutable)
104 if (!SetFileMode(GIT_FILEMODE_BLOB_EXECUTABLE))
105 return false;
107 else if (m_bSymlink)
109 if (!SetFileMode(GIT_FILEMODE_LINK))
110 return false;
114 CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);
116 m_PostCmdCallback = [this](DWORD status, PostCmdList& postCmdList)
118 if (status)
119 return;
121 if (m_bShowCommitButtonAfterAdd)
122 postCmdList.emplace_back(IDI_COMMIT, IDS_MENUCOMMIT, []
124 CString sCmd;
125 sCmd.Format(L"/command:commit /path:\"%s\"", (LPCTSTR)g_Git.m_CurrentDir);
126 CAppUtils::RunTortoiseGitProc(sCmd);
128 postCmdList.emplace_back(IDI_ADD, IDS_STATUSLIST_CONTEXT_ADD_EXE, [this] {
129 SetFileMode(GIT_FILEMODE_BLOB_EXECUTABLE);
131 postCmdList.emplace_back(IDI_ADD, IDS_STATUSLIST_CONTEXT_ADD_LINK, [this] {
132 SetFileMode(GIT_FILEMODE_LINK);
136 return true;
139 bool AddProgressCommand::SetFileMode(uint32_t mode)
141 CAutoRepository repo(g_Git.GetGitRepository());
142 if (!repo)
144 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not open repository."), L"TortoiseGit", MB_ICONERROR);
145 return false;
148 CAutoIndex index;
149 if (git_repository_index(index.GetPointer(), repo))
151 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not get index."), L"TortoiseGit", MB_ICONERROR);
152 return false;
154 if (git_index_read(index, true))
156 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not read index."), L"TortoiseGit", MB_ICONERROR);
157 return false;
160 for (int i = 0; i < m_targetPathList.GetCount(); ++i)
162 if (m_targetPathList[i].IsDirectory())
163 continue;
164 CStringA filePathA = CUnicodeUtils::GetMulti(m_targetPathList[i].GetGitPathString(), CP_UTF8).TrimRight(L'/');
165 auto entry = const_cast<git_index_entry*>(git_index_get_bypath(index, filePathA, 0));
166 entry->mode = mode;
167 if (git_index_add(index, entry))
169 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not update index."), L"TortoiseGit", MB_ICONERROR);
170 return false;
174 if (git_index_write(index))
176 MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not write index."), L"TortoiseGit", MB_ICONERROR);
177 return false;
180 return true;