drop unused code for editing properties
[TortoiseGit.git] / src / Git / GitRev.cpp
blobb9ee0d62140473eaa73150bf9ce27ecd30715441
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2011 - 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 class CException; //Just in case afx.h is not included (cannot be included in every project which uses this file)
29 // provide an ASSERT macro for when compiled without MFC
30 #if !defined ASSERT
31 // Don't use _asm here, it isn't supported by x64 version of compiler. In fact, MFC's ASSERT() is the same with _ASSERTE().
32 #define ASSERT(x) _ASSERTE(x)
33 #endif
35 typedef CComCritSecLock<CComCriticalSection> CAutoLocker;
37 GitRev::GitRev(void)
39 m_Action=0;
40 m_IsFull = 0;
41 m_IsUpdateing = 0;
42 m_IsCommitParsed = 0;
43 m_IsDiffFiles = 0;
44 m_CallDiffAsync = NULL;
45 m_IsSimpleListReady =0;
47 memset(&this->m_GitCommit,0,sizeof(GIT_COMMIT));
49 // fetch local machine timezone info
50 if ( GetTimeZoneInformation( &m_TimeZone ) == TIME_ZONE_ID_INVALID )
52 ASSERT(false);
56 GitRev::~GitRev(void)
60 #if 0
61 GitRev::GitRev(GitRev & rev)
64 GitRev& GitRev::operator=(GitRev &rev)
66 return *this;
68 #endif
69 void GitRev::Clear()
71 this->m_Action=0;
72 this->m_Files.Clear();
73 this->m_Action=0;
74 this->m_ParentHash.clear();
75 m_CommitterName.Empty();
76 m_CommitterEmail.Empty();
77 m_Body.Empty();
78 m_Subject.Empty();
79 m_CommitHash.Empty();
80 m_Ref.Empty();
81 m_RefAction.Empty();
82 m_Mark=0;
85 int GitRev::CopyFrom(GitRev &rev,bool OmitParentAndMark)
87 m_AuthorName =rev.m_AuthorName;
88 m_AuthorEmail =rev.m_AuthorEmail;
89 m_AuthorDate =rev.m_AuthorDate;
90 m_CommitterName =rev.m_CommitterName;
91 m_CommitterEmail=rev.m_CommitterEmail;
92 m_CommitterDate =rev.m_CommitterDate;
93 m_Subject =rev.m_Subject;
94 m_Body =rev.m_Body;
95 m_CommitHash =rev.m_CommitHash;
96 m_Files =rev.m_Files;
97 m_Action =rev.m_Action;
98 m_IsFull =rev.m_IsFull;
100 if(!OmitParentAndMark)
102 m_ParentHash =rev.m_ParentHash;
103 m_Mark =rev.m_Mark;
105 return 0;
108 CTime GitRev::ConverFromString(CString input)
110 // pick up date from string
113 COleDateTime tm(_wtoi(input.Mid(0,4)),
114 _wtoi(input.Mid(5,2)),
115 _wtoi(input.Mid(8,2)),
116 _wtoi(input.Mid(11,2)),
117 _wtoi(input.Mid(14,2)),
118 _wtoi(input.Mid(17,2)));
119 if( tm.GetStatus() != COleDateTime::valid )
120 return CTime();//Error parsing time-string
122 // pick up utc offset
123 CString sign = input.Mid(20,1); // + or -
124 int hoursOffset = _wtoi(input.Mid(21,2));
125 int minsOffset = _wtoi(input.Mid(23,2));
126 // convert to a fraction of a day
127 double offset = (hoursOffset*60 + minsOffset) / 1440.0; // 1440 mins = 1 day
128 if ( sign == "-" )
130 offset = -offset;
132 // we have to subtract this from the time given to get UTC
133 tm -= offset;
134 // get utc time as a SYSTEMTIME
135 SYSTEMTIME sysTime;
136 tm.GetAsSystemTime( sysTime );
137 // and convert to users local time
138 SYSTEMTIME local;
139 if ( SystemTimeToTzSpecificLocalTime( &m_TimeZone, &sysTime, &local ) )
141 sysTime = local;
143 else
145 ASSERT(false); // this should not happen but leave time in utc if it does
147 // convert to CTime and return
148 return CTime( sysTime, -1 );
150 catch(CException* e)
152 //Probably the date was something like 1970-01-01 00:00:00. _mktime64() doesnt like this.
153 //Dont let the application crash on this exception
155 #ifdef _AFX //CException classes are only defined when afx.h is included.
156 //When afx.h is not included, the exception is leaked.
157 //This will probably never happen because when CException is not defined, it cannot be thrown.
158 e->Delete();
159 #endif //ifdef _AFX
161 return CTime(); //Return an invalid time
164 int GitRev::SafeGetSimpleList(CGit *git)
166 if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
168 m_SimpleFileList.clear();
169 git->CheckAndInitDll();
170 GIT_COMMIT commit;
171 GIT_COMMIT_LIST list;
172 GIT_HASH parent;
173 memset(&commit,0,sizeof(GIT_COMMIT));
175 CAutoLocker lock(g_Git.m_critGitDllSec);
177 if(git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))
178 return -1;
180 int i=0;
181 bool isRoot = this->m_ParentHash.size()==0;
182 git_get_commit_first_parent(&commit,&list);
183 while(git_get_commit_next_parent(&list,parent) == 0 || isRoot)
185 GIT_FILE file=0;
186 int count=0;
187 if(isRoot)
188 git_root_diff(git->GetGitSimpleListDiff(), commit.m_hash, &file, &count,0);
189 else
190 git_diff(git->GetGitSimpleListDiff(),parent,commit.m_hash,&file,&count,0);
192 isRoot = false;
194 CTGitPath path;
195 CString strnewname;
196 CString stroldname;
198 for(int j=0;j<count;j++)
200 path.Reset();
201 char *newname;
202 char *oldname;
204 strnewname.Empty();
205 stroldname.Empty();
207 int mode,IsBin,inc,dec;
208 git_get_diff_file(git->GetGitSimpleListDiff(),file,j,&newname,&oldname,
209 &mode,&IsBin,&inc,&dec);
211 git->StringAppend(&strnewname,(BYTE*)newname,CP_ACP);
213 m_SimpleFileList.push_back(strnewname);
216 git_diff_flush(git->GetGitSimpleListDiff());
217 i++;
220 InterlockedExchange(&m_IsUpdateing,FALSE);
221 InterlockedExchange(&m_IsSimpleListReady, TRUE);
222 git_free_commit(&commit);
225 return 0;
227 int GitRev::SafeFetchFullInfo(CGit *git)
229 if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
231 this->m_Files.Clear();
232 git->CheckAndInitDll();
233 GIT_COMMIT commit;
234 GIT_COMMIT_LIST list;
235 GIT_HASH parent;
236 memset(&commit,0,sizeof(GIT_COMMIT));
238 CAutoLocker lock(g_Git.m_critGitDllSec);
240 if(git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))
241 return -1;
243 int i=0;
245 git_get_commit_first_parent(&commit,&list);
246 bool isRoot = (list==NULL);
248 while(git_get_commit_next_parent(&list,parent) == 0 || isRoot)
250 GIT_FILE file=0;
251 int count=0;
253 if(isRoot)
254 git_root_diff(git->GetGitDiff(), this->m_CommitHash.m_hash, &file, &count,1);
255 else
256 git_diff(git->GetGitDiff(),parent,commit.m_hash,&file,&count,1);
258 isRoot = false;
260 CTGitPath path;
261 CString strnewname;
262 CString stroldname;
264 for(int j=0;j<count;j++)
266 path.Reset();
267 char *newname;
268 char *oldname;
270 strnewname.Empty();
271 stroldname.Empty();
273 int mode,IsBin,inc,dec;
274 git_get_diff_file(git->GetGitDiff(),file,j,&newname,&oldname,
275 &mode,&IsBin,&inc,&dec);
277 git->StringAppend(&strnewname,(BYTE*)newname,CP_ACP);
278 git->StringAppend(&stroldname,(BYTE*)oldname,CP_ACP);
280 path.SetFromGit(strnewname,&stroldname);
281 path.ParserAction((BYTE)mode);
282 path.m_ParentNo = i;
284 this->m_Action|=path.m_Action;
286 if(IsBin)
288 path.m_StatAdd=_T("-");
289 path.m_StatDel=_T("-");
291 else
293 path.m_StatAdd.Format(_T("%d"),inc);
294 path.m_StatDel.Format(_T("%d"),dec);
296 m_Files.AddPath(path);
298 git_diff_flush(git->GetGitDiff());
299 i++;
303 InterlockedExchange(&m_IsUpdateing,FALSE);
304 InterlockedExchange(&m_IsFull,TRUE);
305 git_free_commit(&commit);
308 return 0;
311 int GitRev::ParserParentFromCommit(GIT_COMMIT *commit)
313 this->m_ParentHash.clear();
314 GIT_COMMIT_LIST list;
315 GIT_HASH parent;
317 git_get_commit_first_parent(commit,&list);
318 while(git_get_commit_next_parent(&list,parent)==0)
320 m_ParentHash.push_back(CGitHash((char *)parent));
322 return 0;
325 int GitRev::ParserFromCommit(GIT_COMMIT *commit)
327 int encode =CP_UTF8;
329 if(commit->m_Encode != 0 && commit->m_EncodeSize != 0)
331 CString str;
332 g_Git.StringAppend(&str, (BYTE*)commit->m_Encode, CP_UTF8, commit->m_EncodeSize);
333 encode = CUnicodeUtils::GetCPCode(str);
336 this->m_AuthorDate = commit->m_Author.Date;
338 this->m_AuthorEmail.Empty();
339 g_Git.StringAppend(&m_AuthorEmail,(BYTE*)commit->m_Author.Email,encode,commit->m_Author.EmailSize);
341 this->m_AuthorName.Empty();
342 g_Git.StringAppend(&m_AuthorName,(BYTE*)commit->m_Author.Name,encode,commit->m_Author.NameSize);
344 this->m_Body.Empty();
345 g_Git.StringAppend(&m_Body,(BYTE*)commit->m_Body,encode,commit->m_BodySize);
347 this->m_CommitterDate = commit->m_Committer.Date;
349 this->m_CommitterEmail.Empty();
350 g_Git.StringAppend(&m_CommitterEmail, (BYTE*)commit->m_Committer.Email,encode, commit->m_Committer.EmailSize);
352 this->m_CommitterName.Empty();
353 g_Git.StringAppend(&m_CommitterName, (BYTE*)commit->m_Committer.Name,encode, commit->m_Committer.NameSize);
355 this->m_Subject.Empty();
356 g_Git.StringAppend(&m_Subject, (BYTE*)commit->m_Subject,encode,commit->m_SubjectSize);
358 return 0;
360 #ifndef TRACE
361 #define TRACE(x) 1?0:(x)
362 #endif
363 void GitRev::DbgPrint()
365 TRACE(_T("Commit %s\r\n"), this->m_CommitHash.ToString());
366 for(unsigned int i=0;i<this->m_ParentHash.size();i++)
368 TRACE(_T("Parent %i %s"),i, m_ParentHash[i].ToString());
370 TRACE(_T("\n"));
373 int GitRev::GetParentFromHash(CGitHash &hash)
375 g_Git.CheckAndInitDll();
377 CAutoLocker lock(g_Git.m_critGitDllSec);
379 GIT_COMMIT commit;
380 if(git_get_commit_from_hash( &commit, hash.m_hash))
381 return -1;
383 this->ParserParentFromCommit(&commit);
384 git_free_commit(&commit);
386 this->m_CommitHash=hash;
388 return 0;
390 int GitRev::GetCommitFromHash(CGitHash &hash)
392 g_Git.CheckAndInitDll();
394 GIT_COMMIT commit;
395 if(git_get_commit_from_hash( &commit, hash.m_hash))
396 return -1;
398 this->ParserFromCommit(&commit);
399 git_free_commit(&commit);
401 this->m_CommitHash=hash;
403 return 0;
407 int GitRev::GetCommit(CString refname)
409 g_Git.CheckAndInitDll();
411 if(refname.GetLength() >= 8)
412 if(refname.Find(_T("00000000")) == 0)
414 this->m_CommitHash.Empty();
415 this->m_Subject=_T("Working Copy");
416 return 0;
418 CStringA rev;
419 rev= CUnicodeUtils::GetUTF8(g_Git.FixBranchName(refname));
420 GIT_HASH sha;
422 if(git_get_sha1(rev.GetBuffer(),sha))
423 return -1;
425 CGitHash hash((char*)sha);
426 GetCommitFromHash(hash);
427 return 0;
430 int GitRev::AddMergeFiles()
432 std::map<CString, int> map;
433 std::map<CString, int>::iterator it;
435 for(int i=0;i<m_Files.GetCount();i++)
437 if(map.find(m_Files[i].GetGitPathString()) == map.end())
439 map[m_Files[i].GetGitPathString()]=0;
441 else
443 map[m_Files[i].GetGitPathString()]++;
447 for(it=map.begin();it!=map.end();it++)
449 if(it->second)
451 CTGitPath path;
452 path.SetFromGit(it->first);
453 path.m_ParentNo = MERGE_MASK;
454 path.m_StatAdd=_T("-");
455 path.m_StatDel=_T("-");
456 path.m_Action = CTGitPath::LOGACTIONS_MERGED;
457 m_Files.AddPath(path);
460 return 0;