Extend static functions in CAppUtils with a window handle parameter
[TortoiseGit.git] / src / Git / GitRev.cpp
blobabc491caf021278fefd238af2819b1611a9a64c4
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-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.
20 #include "stdafx.h"
21 #include <ATLComTime.h>
22 #include "GitRev.h"
23 #include "Git.h"
24 #include "gitdll.h"
25 #include "UnicodeUtils.h"
27 typedef CComCritSecLock<CComCriticalSection> CAutoLocker;
29 GitRev::GitRev(void)
33 GitRev::~GitRev(void)
37 void GitRev::Clear()
39 this->m_ParentHash.clear();
40 m_AuthorName.Empty();
41 m_AuthorEmail.Empty();
42 m_CommitterName.Empty();
43 m_CommitterEmail.Empty();
44 m_Body.Empty();
45 m_Subject.Empty();
46 m_CommitHash.Empty();
47 m_sErr.Empty();
50 int GitRev::ParserParentFromCommit(GIT_COMMIT *commit)
52 this->m_ParentHash.clear();
53 GIT_COMMIT_LIST list;
54 GIT_HASH parent;
56 git_get_commit_first_parent(commit,&list);
57 while(git_get_commit_next_parent(&list,parent)==0)
58 m_ParentHash.emplace_back(parent);
59 return 0;
62 int GitRev::ParserFromCommit(GIT_COMMIT *commit)
64 int encode =CP_UTF8;
66 if(commit->m_Encode != 0 && commit->m_EncodeSize != 0)
68 CString str;
69 CGit::StringAppend(&str, (BYTE*)commit->m_Encode, CP_UTF8, commit->m_EncodeSize);
70 encode = CUnicodeUtils::GetCPCode(str);
73 this->m_CommitHash = commit->m_hash;
75 this->m_AuthorDate = commit->m_Author.Date;
77 this->m_AuthorEmail.Empty();
78 CGit::StringAppend(&m_AuthorEmail, (BYTE*)commit->m_Author.Email, encode, commit->m_Author.EmailSize);
80 this->m_AuthorName.Empty();
81 CGit::StringAppend(&m_AuthorName, (BYTE*)commit->m_Author.Name, encode, commit->m_Author.NameSize);
83 this->m_Body.Empty();
84 CGit::StringAppend(&m_Body, (BYTE*)commit->m_Body, encode, commit->m_BodySize);
86 this->m_CommitterDate = commit->m_Committer.Date;
88 this->m_CommitterEmail.Empty();
89 CGit::StringAppend(&m_CommitterEmail, (BYTE*)commit->m_Committer.Email, encode, commit->m_Committer.EmailSize);
91 this->m_CommitterName.Empty();
92 CGit::StringAppend(&m_CommitterName, (BYTE*)commit->m_Committer.Name, encode, commit->m_Committer.NameSize);
94 this->m_Subject.Empty();
95 CGit::StringAppend(&m_Subject, (BYTE*)commit->m_Subject,encode,commit->m_SubjectSize);
97 return 0;
100 int GitRev::ParserParentFromCommit(const git_commit* commit)
102 m_ParentHash.clear();
103 unsigned int parentCount = git_commit_parentcount(commit);
104 for (unsigned int i = 0; i < parentCount; ++i)
105 m_ParentHash.emplace_back(git_commit_parent_id(commit, i)->id);
107 return 0;
110 int GitRev::ParserFromCommit(const git_commit* commit)
112 Clear();
114 int encode = CP_UTF8;
116 const char* encodingstr = git_commit_message_encoding(commit);
117 if (encodingstr)
118 encode = CUnicodeUtils::GetCPCode(CUnicodeUtils::GetUnicode(encodingstr));
120 m_CommitHash = git_commit_id(commit)->id;
122 const git_signature* author = git_commit_author(commit);
123 m_AuthorDate = author->when.time;
124 m_AuthorEmail = CUnicodeUtils::GetUnicode(author->email, encode);
125 m_AuthorName = CUnicodeUtils::GetUnicode(author->name, encode);
127 const git_signature* committer = git_commit_committer(commit);
128 m_CommitterDate = committer->when.time;
129 m_CommitterEmail = CUnicodeUtils::GetUnicode(committer->email, encode);
130 m_CommitterName = CUnicodeUtils::GetUnicode(committer->name, encode);
132 const char* msg = git_commit_message_raw(commit);
133 const char* body = strchr(msg, '\n');
134 if (!body)
135 m_Subject = CUnicodeUtils::GetUnicode(msg, encode);
136 else
138 m_Subject = CUnicodeUtils::GetUnicode(CStringA(msg, (int)(body - msg)), encode);
139 m_Body = CUnicodeUtils::GetUnicode(body + 1, encode);
142 return 0;
145 int GitRev::GetCommitFromHash(git_repository* repo, const CGitHash& hash)
147 CAutoCommit commit;
148 if (git_commit_lookup(commit.GetPointer(), repo, (const git_oid*)hash.m_hash) < 0)
150 m_sErr = CGit::GetLibGit2LastErr();
151 return -1;
154 return ParserFromCommit(commit);
157 int GitRev::GetCommit(git_repository* repo, const CString& refname)
159 if (refname.GetLength() >= 8 && wcsncmp(refname, GitRev::GetWorkingCopy(), refname.GetLength()) == 0)
161 Clear();
162 m_Subject = L"Working Tree";
163 return 0;
166 CGitHash hash;
167 if (CGit::GetHash(repo, hash, refname))
169 m_sErr = CGit::GetLibGit2LastErr();
170 return -1;
173 return GetCommitFromHash(repo, hash);
176 void GitRev::DbgPrint()
178 ATLTRACE(L"Commit %s\r\n", (LPCTSTR)this->m_CommitHash.ToString());
179 for (unsigned int i = 0; i < this->m_ParentHash.size(); ++i)
181 ATLTRACE(L"Parent %i %s", i, (LPCTSTR)m_ParentHash[i].ToString());
183 ATLTRACE(L"\n");
186 int GitRev::GetParentFromHash(const CGitHash& hash)
188 CAutoLocker lock(g_Git.m_critGitDllSec);
190 GIT_COMMIT commit;
193 g_Git.CheckAndInitDll();
195 if (git_get_commit_from_hash(&commit, hash.m_hash))
197 m_sErr = L"git_get_commit_from_hash failed for " + hash.ToString();
198 return -1;
201 catch (char* msg)
203 m_sErr = L"Could not get parents of commit \"" + hash.ToString() + L"\".\nlibgit reports:\n" + CString(msg);
204 return -1;
207 this->ParserParentFromCommit(&commit);
208 git_free_commit(&commit);
210 this->m_CommitHash=hash;
212 return 0;
215 int GitRev::GetCommitFromHash(const CGitHash& hash)
217 CAutoLocker lock(g_Git.m_critGitDllSec);
219 g_Git.CheckAndInitDll();
221 return GetCommitFromHash_withoutLock(hash);
224 int GitRev::GetCommitFromHash_withoutLock(const CGitHash& hash)
226 GIT_COMMIT commit;
229 if (git_get_commit_from_hash(&commit, hash.m_hash))
231 m_sErr = L"git_get_commit_from_hash failed for " + hash.ToString();
232 return -1;
235 catch (char * msg)
237 m_sErr = L"Could not get commit \"" + hash.ToString() + L"\".\nlibgit reports:\n" + CString(msg);
238 return -1;
241 this->ParserFromCommit(&commit);
242 git_free_commit(&commit);
244 m_sErr.Empty();
246 return 0;
249 int GitRev::GetCommit(const CString& refname)
251 if (g_Git.UsingLibGit2(CGit::GIT_CMD_GET_COMMIT))
253 CAutoRepository repo(g_Git.GetGitRepository());
254 if (!repo)
256 m_sErr = g_Git.GetLibGit2LastErr();
257 return -1;
259 return GetCommit(repo, refname);
262 CAutoLocker lock(g_Git.m_critGitDllSec);
266 g_Git.CheckAndInitDll();
268 catch (char* msg)
270 m_sErr = L"Could not initiate libgit.\nlibgit reports:\n" + CString(msg);
271 return -1;
274 if(refname.GetLength() >= 8)
275 if (refname.GetLength() >= 8 && wcsncmp(refname, GitRev::GetWorkingCopy(), refname.GetLength()) == 0)
277 this->m_CommitHash.Empty();
278 this->m_Subject = L"Working Tree";
279 m_sErr.Empty();
280 return 0;
282 CStringA rev;
283 rev= CUnicodeUtils::GetUTF8(g_Git.FixBranchName(refname));
284 GIT_HASH sha;
288 if (git_get_sha1(rev.GetBuffer(), sha))
290 m_sErr = L"Could not get SHA-1 of ref \"" + g_Git.FixBranchName(refname);
291 return -1;
294 catch (char * msg)
296 m_sErr = L"Could not get SHA-1 of ref \"" + g_Git.FixBranchName(refname) + L"\".\nlibgit reports:\n" + CString(msg);
297 return -1;
300 CGitHash hash(sha);
301 return GetCommitFromHash_withoutLock(hash);