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.
21 #include <ATLComTime.h>
25 #include "UnicodeUtils.h"
27 typedef CComCritSecLock
<CComCriticalSection
> CAutoLocker
;
39 this->m_ParentHash
.clear();
41 m_AuthorEmail
.Empty();
42 m_CommitterName
.Empty();
43 m_CommitterEmail
.Empty();
51 int GitRev::ParserParentFromCommit(GIT_COMMIT
*commit
)
53 this->m_ParentHash
.clear();
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
));
65 int GitRev::ParserFromCommit(GIT_COMMIT
*commit
)
69 if(commit
->m_Encode
!= 0 && commit
->m_EncodeSize
!= 0)
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
);
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
);
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
));
113 int GitRev::ParserFromCommit(const git_commit
* commit
)
117 int encode
= CP_UTF8
;
119 const char* encodingstr
= git_commit_message_encoding(commit
);
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');
138 m_Subject
= CUnicodeUtils::GetUnicode(msg
, encode
);
141 m_Subject
= CUnicodeUtils::GetUnicode(CStringA(msg
, (int)(body
- msg
)), encode
);
142 m_Body
= CUnicodeUtils::GetUnicode(body
+ 1, encode
);
148 int GitRev::GetCommitFromHash(git_repository
* repo
, const CGitHash
& hash
)
151 if (git_commit_lookup(commit
.GetPointer(), repo
, (const git_oid
*)hash
.m_hash
) < 0)
153 m_sErr
= CGit::GetLibGit2LastErr();
157 return ParserFromCommit(commit
);
160 int GitRev::GetCommit(git_repository
* repo
, const CString
& refname
)
162 if (refname
.GetLength() >= 8 && refname
.Find(_T("00000000")) == 0)
165 m_Subject
= _T("Working Copy");
170 if (CGit::GetHash(repo
, hash
, refname
))
172 m_sErr
= CGit::GetLibGit2LastErr();
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());
189 int GitRev::GetParentFromHash(CGitHash
&hash
)
191 CAutoLocker
lock(g_Git
.m_critGitDllSec
);
193 g_Git
.CheckAndInitDll();
198 if (git_get_commit_from_hash(&commit
, hash
.m_hash
))
200 m_sErr
= _T("git_get_commit_from_hash failed for ") + hash
.ToString();
206 m_sErr
= _T("Could not get parents of commit \"") + hash
.ToString() + _T("\".\nlibgit reports:\n") + CString(msg
);
210 this->ParserParentFromCommit(&commit
);
211 git_free_commit(&commit
);
213 this->m_CommitHash
=hash
;
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
)
232 if (git_get_commit_from_hash(&commit
, hash
.m_hash
))
234 m_sErr
= _T("git_get_commit_from_hash failed for ") + hash
.ToString();
240 m_sErr
= _T("Could not get commit \"") + hash
.ToString() + _T("\".\nlibgit reports:\n") + CString(msg
);
244 this->ParserFromCommit(&commit
);
245 git_free_commit(&commit
);
252 int GitRev::GetCommit(const CString
& refname
)
254 if (g_Git
.UsingLibGit2(CGit::GIT_CMD_GET_COMMIT
))
256 CAutoRepository
repo(g_Git
.GetGitRepository());
259 m_sErr
= g_Git
.GetLibGit2LastErr();
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");
278 rev
= CUnicodeUtils::GetUTF8(g_Git
.FixBranchName(refname
));
283 if (git_get_sha1(rev
.GetBuffer(), sha
))
285 m_sErr
= _T("Could not get SHA-1 of ref \"") + g_Git
.FixBranchName(refname
);
291 m_sErr
= _T("Could not get SHA-1 of ref \"") + g_Git
.FixBranchName(refname
) + _T("\".\nlibgit reports:\n") + CString(msg
);
295 CGitHash
hash((char*)sha
);
296 return GetCommitFromHash_withoutLock(hash
);