Fixed issue #2495: "Show Reflog" dialog shows empty action for "push" entries
[TortoiseGit.git] / src / Git / GitRev.cpp
bloba03584ba3a21cb27c592cd3336fd410026728db8
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2015 - 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();
51 int GitRev::ParserParentFromCommit(GIT_COMMIT *commit)
53 this->m_ParentHash.clear();
54 GIT_COMMIT_LIST list;
55 GIT_HASH parent;
57 git_get_commit_first_parent(commit,&list);
58 while(git_get_commit_next_parent(&list,parent)==0)
60 m_ParentHash.push_back(CGitHash((char *)parent));
62 return 0;
65 int GitRev::ParserFromCommit(GIT_COMMIT *commit)
67 int encode =CP_UTF8;
69 if(commit->m_Encode != 0 && commit->m_EncodeSize != 0)
71 CString str;
72 CGit::StringAppend(&str, (BYTE*)commit->m_Encode, CP_UTF8, commit->m_EncodeSize);
73 encode = CUnicodeUtils::GetCPCode(str);
76 this->m_CommitHash = commit->m_hash;
78 this->m_AuthorDate = commit->m_Author.Date;
80 this->m_AuthorEmail.Empty();
81 CGit::StringAppend(&m_AuthorEmail, (BYTE*)commit->m_Author.Email, encode, commit->m_Author.EmailSize);
83 this->m_AuthorName.Empty();
84 CGit::StringAppend(&m_AuthorName, (BYTE*)commit->m_Author.Name, encode, commit->m_Author.NameSize);
86 this->m_Body.Empty();
87 CGit::StringAppend(&m_Body, (BYTE*)commit->m_Body, encode, commit->m_BodySize);
89 this->m_CommitterDate = commit->m_Committer.Date;
91 this->m_CommitterEmail.Empty();
92 CGit::StringAppend(&m_CommitterEmail, (BYTE*)commit->m_Committer.Email, encode, commit->m_Committer.EmailSize);
94 this->m_CommitterName.Empty();
95 CGit::StringAppend(&m_CommitterName, (BYTE*)commit->m_Committer.Name, encode, commit->m_Committer.NameSize);
97 this->m_Subject.Empty();
98 CGit::StringAppend(&m_Subject, (BYTE*)commit->m_Subject,encode,commit->m_SubjectSize);
100 return 0;
103 int GitRev::ParserParentFromCommit(const git_commit* commit)
105 m_ParentHash.clear();
106 unsigned int parentCount = git_commit_parentcount(commit);
107 for (unsigned int i = 0; i < parentCount; ++i)
108 m_ParentHash.push_back(CGitHash((char*)git_commit_parent_id(commit, i)->id));
110 return 0;
113 int GitRev::ParserFromCommit(const git_commit* commit)
115 Clear();
117 int encode = CP_UTF8;
119 const char* encodingstr = git_commit_message_encoding(commit);
120 if (encodingstr)
121 encode = CUnicodeUtils::GetCPCode(CUnicodeUtils::GetUnicode(encodingstr));
123 m_CommitHash = git_commit_id(commit)->id;
125 const git_signature* author = git_commit_author(commit);
126 m_AuthorDate = author->when.time;
127 m_AuthorEmail = CUnicodeUtils::GetUnicode(author->email, encode);
128 m_AuthorName = CUnicodeUtils::GetUnicode(author->name, encode);
130 const git_signature* committer = git_commit_committer(commit);
131 m_CommitterDate = committer->when.time;
132 m_CommitterEmail = CUnicodeUtils::GetUnicode(committer->email, encode);
133 m_CommitterName = CUnicodeUtils::GetUnicode(committer->name, encode);
135 const char* msg = git_commit_message_raw(commit);
136 const char* body = strchr(msg, '\n');
137 if (!body)
138 m_Subject = CUnicodeUtils::GetUnicode(msg, encode);
139 else
141 m_Subject = CUnicodeUtils::GetUnicode(CStringA(msg, (int)(body - msg)), encode);
142 m_Body = CUnicodeUtils::GetUnicode(body + 1, encode);
145 return 0;
148 int GitRev::GetCommitFromHash(git_repository* repo, const CGitHash& hash)
150 CAutoCommit commit;
151 if (git_commit_lookup(commit.GetPointer(), repo, (const git_oid*)hash.m_hash) < 0)
153 m_sErr = CGit::GetLibGit2LastErr();
154 return -1;
157 return ParserFromCommit(commit);
160 int GitRev::GetCommit(git_repository* repo, const CString& refname)
162 if (refname.GetLength() >= 8 && refname.Find(_T("00000000")) == 0)
164 Clear();
165 m_Subject = _T("Working Copy");
166 return 0;
169 CGitHash hash;
170 if (CGit::GetHash(repo, hash, refname))
172 m_sErr = CGit::GetLibGit2LastErr();
173 return -1;
176 return GetCommitFromHash(repo, hash);
179 void GitRev::DbgPrint()
181 ATLTRACE(_T("Commit %s\r\n"), this->m_CommitHash.ToString());
182 for (unsigned int i = 0; i < this->m_ParentHash.size(); ++i)
184 ATLTRACE(_T("Parent %i %s"), i, m_ParentHash[i].ToString());
186 ATLTRACE(_T("\n"));
189 int GitRev::GetParentFromHash(CGitHash &hash)
191 CAutoLocker lock(g_Git.m_critGitDllSec);
193 g_Git.CheckAndInitDll();
195 GIT_COMMIT commit;
198 if (git_get_commit_from_hash(&commit, hash.m_hash))
200 m_sErr = _T("git_get_commit_from_hash failed for ") + hash.ToString();
201 return -1;
204 catch (char* msg)
206 m_sErr = _T("Could not get parents of commit \"") + hash.ToString() + _T("\".\nlibgit reports:\n") + CString(msg);
207 return -1;
210 this->ParserParentFromCommit(&commit);
211 git_free_commit(&commit);
213 this->m_CommitHash=hash;
215 return 0;
218 int GitRev::GetCommitFromHash(CGitHash &hash)
220 CAutoLocker lock(g_Git.m_critGitDllSec);
222 g_Git.CheckAndInitDll();
224 return GetCommitFromHash_withoutLock(hash);
227 int GitRev::GetCommitFromHash_withoutLock(CGitHash &hash)
229 GIT_COMMIT commit;
232 if (git_get_commit_from_hash(&commit, hash.m_hash))
234 m_sErr = _T("git_get_commit_from_hash failed for ") + hash.ToString();
235 return -1;
238 catch (char * msg)
240 m_sErr = _T("Could not get commit \"") + hash.ToString() + _T("\".\nlibgit reports:\n") + CString(msg);
241 return -1;
244 this->ParserFromCommit(&commit);
245 git_free_commit(&commit);
247 m_sErr.Empty();
249 return 0;
252 int GitRev::GetCommit(const CString& refname)
254 if (g_Git.UsingLibGit2(CGit::GIT_CMD_GET_COMMIT))
256 CAutoRepository repo(g_Git.GetGitRepository());
257 if (!repo)
259 m_sErr = g_Git.GetLibGit2LastErr();
260 return -1;
262 return GetCommit(repo, refname);
265 CAutoLocker lock(g_Git.m_critGitDllSec);
267 g_Git.CheckAndInitDll();
269 if(refname.GetLength() >= 8)
270 if(refname.Find(_T("00000000")) == 0)
272 this->m_CommitHash.Empty();
273 this->m_Subject=_T("Working Copy");
274 m_sErr.Empty();
275 return 0;
277 CStringA rev;
278 rev= CUnicodeUtils::GetUTF8(g_Git.FixBranchName(refname));
279 GIT_HASH sha;
283 if (git_get_sha1(rev.GetBuffer(), sha))
285 m_sErr = _T("Could not get SHA-1 of ref \"") + g_Git.FixBranchName(refname);
286 return -1;
289 catch (char * msg)
291 m_sErr = _T("Could not get SHA-1 of ref \"") + g_Git.FixBranchName(refname) + _T("\".\nlibgit reports:\n") + CString(msg);
292 return -1;
295 CGitHash hash((char*)sha);
296 return GetCommitFromHash_withoutLock(hash);