Fixed issue #234: First log(first commit in history) was missing...
[TortoiseGit.git] / src / TortoiseProc / LogDataVector.cpp
blob35057e4c3736f1ce9f7c77b5e26424813450811e
1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2007-2008 - TortoiseSVN
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 Description: start-up repository opening and reading
22 Author: Marco Costalba (C) 2005-2007
24 Copyright: See COPYING file that comes with this distribution
28 #include "stdafx.h"
29 #include "TortoiseProc.h"
30 #include "GitLogListBase.h"
31 #include "GitRev.h"
32 //#include "VssStyle.h"
33 #include "IconMenu.h"
34 // CGitLogList
35 #include "cursor.h"
36 #include "InputDlg.h"
37 #include "PropDlg.h"
38 #include "SVNProgressDlg.h"
39 #include "ProgressDlg.h"
40 //#include "RepositoryBrowser.h"
41 //#include "CopyDlg.h"
42 //#include "StatGraphDlg.h"
43 #include "Logdlg.h"
44 #include "MessageBox.h"
45 #include "Registry.h"
46 #include "AppUtils.h"
47 #include "PathUtils.h"
48 #include "StringUtils.h"
49 #include "UnicodeUtils.h"
50 #include "TempFile.h"
51 //#include "GitInfo.h"
52 //#include "GitDiff.h"
53 #include "IconMenu.h"
54 //#include "RevisionRangeDlg.h"
55 //#include "BrowseFolder.h"
56 //#include "BlameDlg.h"
57 //#include "Blame.h"
58 //#include "GitHelpers.h"
59 #include "GitStatus.h"
60 //#include "LogDlgHelper.h"
61 //#include "CachedLogInfo.h"
62 //#include "RepositoryInfo.h"
63 //#include "EditPropertiesDlg.h"
64 #include "FileDiffDlg.h"
66 void CLogDataVector::ClearAll()
69 clear();
70 m_HashMap.clear();
71 m_Lns.clear();
73 m_FirstFreeLane=0;
74 m_Lns.clear();
76 m_RawlogData.clear();
77 m_RawLogStart.clear();
80 int CLogDataVector::ParserShortLog(CTGitPath *path ,CString &hash,int count ,int mask )
82 BYTE_VECTOR log;
83 GitRev rev;
85 if(g_Git.IsInitRepos())
86 return 0;
88 CString begin;
89 begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);
91 //g_Git.GetShortLog(log,path,count);
93 g_Git.GetLog(log,hash,path,count,mask);
95 if(log.size()==0)
96 return 0;
98 int start=4;
99 int length;
100 int next =0;
101 while( next>=0 && next<log.size())
103 next=rev.ParserFromLog(log,next);
105 rev.m_Subject=_T("Load .................................");
106 this->push_back(rev);
107 m_HashMap[rev.m_CommitHash]=size()-1;
109 //next=log.find(0,next);
112 return 0;
115 int CLogDataVector::FetchShortLog(CTGitPath *path ,CString &hash,int count ,int mask, int ShowWC )
117 //BYTE_VECTOR log;
118 m_RawlogData.clear();
119 m_RawLogStart.clear();
121 GitRev rev;
123 if(g_Git.IsInitRepos())
124 return 0;
126 CString begin;
127 begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);
129 //g_Git.GetShortLog(log,path,count);
130 ULONGLONG t1,t2;
131 t1=GetTickCount();
132 g_Git.GetLog(m_RawlogData, hash,path,count,mask);
133 t2=GetTickCount();
135 TRACE(_T("GetLog Time %ld\r\n"),t2-t1);
137 if(m_RawlogData.size()==0)
138 return 0;
140 int start=4;
141 int length;
142 int next =0;
143 t1=GetTickCount();
144 int a1=0,b1=0;
146 while( next>=0 && next<m_RawlogData.size())
148 static const BYTE dataToFind[]={0,0};
149 m_RawLogStart.push_back(next);
150 //this->at(i).m_Subject=_T("parser...");
151 next=m_RawlogData.findData(dataToFind,2,next+1);
152 //next=log.find(0,next);
155 resize(m_RawLogStart.size() + ShowWC);
157 t2=GetTickCount();
159 return 0;
161 int CLogDataVector::FetchFullInfo(int i)
163 return at(i).SafeFetchFullInfo(&g_Git);
165 //CLogDataVector Class
166 int CLogDataVector::ParserFromLog(CTGitPath *path ,int count ,int infomask,CString *from,CString *to)
168 BYTE_VECTOR log;
169 GitRev rev;
170 CString emptyhash;
171 g_Git.GetLog(log,emptyhash,path,count,infomask,from,to);
173 CString begin;
174 begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);
176 if(log.size()==0)
177 return 0;
179 int start=4;
180 int length;
181 int next =0;
182 while( next>=0 )
184 next=rev.ParserFromLog(log,next);
185 this->push_back(rev);
186 m_HashMap[rev.m_CommitHash]=size()-1;
189 return 0;
192 int CLogDataVector::ParserFromRefLog(CString ref)
194 CString cmd,out;
195 GitRev rev;
196 cmd.Format(_T("git.exe reflog show %s"),ref);
197 if(g_Git.Run(cmd,&out,CP_UTF8))
198 return -1;
200 int pos=0;
201 while(pos>=0)
203 CString one=out.Tokenize(_T("\n"),pos);
204 int ref=one.Find(_T(' '),0);
205 if(ref<0)
206 continue;
208 rev.Clear();
210 rev.m_CommitHash=one.Left(ref);
211 int action=one.Find(_T(' '),ref+1);
212 int message;
213 if(action>0)
215 rev.m_Ref=one.Mid(ref+1,action-ref-2);
216 message=one.Find(_T(":"),action);
217 if(message>0)
219 rev.m_RefAction=one.Mid(action+1,message-action-1);
220 rev.m_Subject=one.Right(one.GetLength()-message-1);
223 this->push_back(rev);
225 return 0;
228 void CLogDataVector::setLane(CString& sha)
230 Lanes* l = &(this->m_Lns);
231 int i = m_FirstFreeLane;
233 // QVector<QByteArray> ba;
234 // const ShaString& ss = toPersistentSha(sha, ba);
235 // const ShaVect& shaVec(fh->revOrder);
237 for (int cnt = size(); i < cnt; ++i) {
239 GitRev* r = &(*this)[i];
240 CString &curSha=r->m_CommitHash;
242 if (r->m_Lanes.size() == 0)
243 updateLanes(*r, *l, curSha);
245 if (curSha == sha)
246 break;
248 m_FirstFreeLane = ++i;
250 #if 0
251 Lanes* l = &(this->m_Lanes);
252 int i = m_FirstFreeLane;
254 QVector<QByteArray> ba;
255 const ShaString& ss = toPersistentSha(sha, ba);
256 const ShaVect& shaVec(fh->revOrder);
258 for (uint cnt = shaVec.count(); i < cnt; ++i) {
260 const ShaString& curSha = shaVec[i];
261 Rev* r = m_HashMap[curSha]const_cast<Rev*>(revLookup(curSha, fh));
262 if (r->lanes.count() == 0)
263 updateLanes(*r, *l, curSha);
265 if (curSha == ss)
266 break;
268 fh->firstFreeLane = ++i;
269 #endif
273 void CLogDataVector::updateLanes(GitRev& c, Lanes& lns, CString &sha)
275 // we could get third argument from c.sha(), but we are in fast path here
276 // and c.sha() involves a deep copy, so we accept a little redundancy
278 if (lns.isEmpty())
279 lns.init(sha);
281 bool isDiscontinuity;
282 bool isFork = lns.isFork(sha, isDiscontinuity);
283 bool isMerge = (c.ParentsCount() > 1);
284 bool isInitial = (c.ParentsCount() == 0);
286 if (isDiscontinuity)
287 lns.changeActiveLane(sha); // uses previous isBoundary state
289 lns.setBoundary(c.IsBoundary() == TRUE); // update must be here
290 TRACE(_T("%s %d"),c.m_CommitHash,c.IsBoundary());
292 if (isFork)
293 lns.setFork(sha);
294 if (isMerge)
295 lns.setMerge(c.m_ParentHash);
296 //if (c.isApplied)
297 // lns.setApplied();
298 if (isInitial)
299 lns.setInitial();
301 lns.getLanes(c.m_Lanes); // here lanes are snapshotted
303 CString nextSha = (isInitial) ? CString(_T("")) : QString(c.m_ParentHash[0]);
305 lns.nextParent(nextSha);
307 //if (c.isApplied)
308 // lns.afterApplied();
309 if (isMerge)
310 lns.afterMerge();
311 if (isFork)
312 lns.afterFork();
313 if (lns.isBranch())
314 lns.afterBranch();
316 // QString tmp = "", tmp2;
317 // for (uint i = 0; i < c.lanes.count(); i++) {
318 // tmp2.setNum(c.lanes[i]);
319 // tmp.append(tmp2 + "-");
320 // }
321 // qDebug("%s %s",tmp.latin1(), c.sha.latin1());