1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2007-2008 - TortoiseSVN
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
20 Description: start-up repository opening and reading
\r
22 Author: Marco Costalba (C) 2005-2007
\r
24 Copyright: See COPYING file that comes with this distribution
\r
29 #include "TortoiseProc.h"
\r
30 #include "GitLogListBase.h"
\r
32 //#include "VssStyle.h"
\r
33 #include "IconMenu.h"
\r
36 #include "InputDlg.h"
\r
37 #include "PropDlg.h"
\r
38 #include "SVNProgressDlg.h"
\r
39 #include "ProgressDlg.h"
\r
40 //#include "RepositoryBrowser.h"
\r
41 //#include "CopyDlg.h"
\r
42 //#include "StatGraphDlg.h"
\r
44 #include "MessageBox.h"
\r
45 #include "Registry.h"
\r
46 #include "AppUtils.h"
\r
47 #include "PathUtils.h"
\r
48 #include "StringUtils.h"
\r
49 #include "UnicodeUtils.h"
\r
50 #include "TempFile.h"
\r
51 //#include "GitInfo.h"
\r
52 //#include "GitDiff.h"
\r
53 #include "IconMenu.h"
\r
54 //#include "RevisionRangeDlg.h"
\r
55 //#include "BrowseFolder.h"
\r
56 //#include "BlameDlg.h"
\r
57 //#include "Blame.h"
\r
58 //#include "GitHelpers.h"
\r
59 #include "GitStatus.h"
\r
60 //#include "LogDlgHelper.h"
\r
61 //#include "CachedLogInfo.h"
\r
62 //#include "RepositoryInfo.h"
\r
63 //#include "EditPropertiesDlg.h"
\r
64 #include "FileDiffDlg.h"
\r
65 #include "GitHash.h"
\r
68 void CLogDataVector::ClearAll()
\r
78 m_RawlogData.clear();
\r
79 m_RawLogStart.clear();
\r
82 int CLogDataVector::ParserShortLog(CTGitPath *path ,CString &hash,int count ,int mask )
\r
87 if(g_Git.IsInitRepos())
\r
91 begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);
\r
93 //g_Git.GetShortLog(log,path,count);
\r
95 g_Git.GetLog(log,hash,path,count,mask);
\r
103 while( next>=0 && next<log.size())
\r
105 next=rev.ParserFromLog(log,next);
\r
107 rev.m_Subject=_T("Load .................................");
\r
108 this->push_back(rev.m_CommitHash);
\r
110 if(this->m_pLogCache->m_HashMap.IsExist(rev.m_CommitHash))
\r
112 if(!this->m_pLogCache->m_HashMap[rev.m_CommitHash].m_IsFull)
\r
113 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);
\r
115 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);
\r
117 m_HashMap[rev.m_CommitHash]=size()-1;
\r
119 //next=log.find(0,next);
\r
125 int CLogDataVector::FetchShortLog(CTGitPath *path ,CString &hash,int count ,int mask, int ShowWC )
\r
128 m_RawlogData.clear();
\r
129 m_RawLogStart.clear();
\r
133 if(g_Git.IsInitRepos())
\r
137 begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);
\r
139 //g_Git.GetShortLog(log,path,count);
\r
142 g_Git.GetLog(m_RawlogData, hash,path,count,mask);
\r
145 TRACE(_T("GetLog Time %ld\r\n"),t2-t1);
\r
147 if(m_RawlogData.size()==0)
\r
156 while( next>=0 && next<m_RawlogData.size())
\r
158 static const BYTE dataToFind[]={0,0};
\r
159 m_RawLogStart.push_back(next);
\r
160 //this->at(i).m_Subject=_T("parser...");
\r
161 next=m_RawlogData.findData(dataToFind,2,next+1);
\r
162 //next=log.find(0,next);
\r
165 resize(m_RawLogStart.size() + ShowWC);
\r
171 int CLogDataVector::FetchFullInfo(int i)
\r
173 return GetGitRevAt(i).SafeFetchFullInfo(&g_Git);
\r
175 //CLogDataVector Class
\r
176 int CLogDataVector::ParserFromLog(CTGitPath *path ,int count ,int infomask,CString *from,CString *to)
\r
181 g_Git.GetLog(log,emptyhash,path,count,infomask,from,to);
\r
184 begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);
\r
194 next=rev.ParserFromLog(log,next);
\r
196 if(this->m_pLogCache->m_HashMap.IsExist(rev.m_CommitHash))
\r
198 if(!this->m_pLogCache->m_HashMap[rev.m_CommitHash].m_IsFull)
\r
200 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);
\r
203 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);
\r
205 this->m_pLogCache->m_HashMap[rev.m_CommitHash].m_IsFull=true;
\r
207 this->push_back(rev.m_CommitHash);
\r
209 m_HashMap[rev.m_CommitHash]=size()-1;
\r
215 int CLogDataVector::ParserFromRefLog(CString ref)
\r
219 cmd.Format(_T("git.exe reflog show %s"),ref);
\r
220 if(g_Git.Run(cmd,&out,CP_UTF8))
\r
226 CString one=out.Tokenize(_T("\n"),pos);
\r
227 int ref=one.Find(_T(' '),0);
\r
233 rev.m_CommitHash=g_Git.GetHash(one.Left(ref));
\r
234 int action=one.Find(_T(' '),ref+1);
\r
238 rev.m_Ref=one.Mid(ref+1,action-ref-2);
\r
239 message=one.Find(_T(":"),action);
\r
242 rev.m_RefAction=one.Mid(action+1,message-action-1);
\r
243 rev.m_Subject=one.Right(one.GetLength()-message-1);
\r
247 if(this->m_pLogCache->m_HashMap.IsExist(rev.m_CommitHash))
\r
249 if(!this->m_pLogCache->m_HashMap[rev.m_CommitHash].m_IsFull)
\r
250 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);
\r
252 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);
\r
258 void CLogDataVector::setLane(CGitHash& sha)
\r
260 Lanes* l = &(this->m_Lns);
\r
261 int i = m_FirstFreeLane;
\r
263 // QVector<QByteArray> ba;
\r
264 // const ShaString& ss = toPersistentSha(sha, ba);
\r
265 // const ShaVect& shaVec(fh->revOrder);
\r
267 for (int cnt = size(); i < cnt; ++i) {
\r
269 GitRev* r = & this->GetGitRevAt(i);
\r
270 CGitHash curSha=r->m_CommitHash;
\r
272 if (r->m_Lanes.size() == 0)
\r
273 updateLanes(*r, *l, curSha);
\r
278 m_FirstFreeLane = ++i;
\r
281 Lanes* l = &(this->m_Lanes);
\r
282 int i = m_FirstFreeLane;
\r
284 QVector<QByteArray> ba;
\r
285 const ShaString& ss = toPersistentSha(sha, ba);
\r
286 const ShaVect& shaVec(fh->revOrder);
\r
288 for (uint cnt = shaVec.count(); i < cnt; ++i) {
\r
290 const ShaString& curSha = shaVec[i];
\r
291 Rev* r = m_HashMap[curSha]const_cast<Rev*>(revLookup(curSha, fh));
\r
292 if (r->lanes.count() == 0)
\r
293 updateLanes(*r, *l, curSha);
\r
298 fh->firstFreeLane = ++i;
\r
303 void CLogDataVector::updateLanes(GitRev& c, Lanes& lns, CGitHash &sha)
\r
305 // we could get third argument from c.sha(), but we are in fast path here
\r
306 // and c.sha() involves a deep copy, so we accept a little redundancy
\r
311 bool isDiscontinuity;
\r
312 bool isFork = lns.isFork(sha, isDiscontinuity);
\r
313 bool isMerge = (c.ParentsCount() > 1);
\r
314 bool isInitial = (c.ParentsCount() == 0);
\r
316 if (isDiscontinuity)
\r
317 lns.changeActiveLane(sha); // uses previous isBoundary state
\r
319 lns.setBoundary(c.IsBoundary() == TRUE); // update must be here
\r
320 TRACE(_T("%s %d"),c.m_CommitHash.ToString(),c.IsBoundary());
\r
325 lns.setMerge(c.m_ParentHash);
\r
327 // lns.setApplied();
\r
331 lns.getLanes(c.m_Lanes); // here lanes are snapshotted
\r
335 nextSha = c.m_ParentHash[0];
\r
337 lns.nextParent(nextSha);
\r
340 // lns.afterApplied();
\r
345 if (lns.isBranch())
\r
348 // QString tmp = "", tmp2;
\r
349 // for (uint i = 0; i < c.lanes.count(); i++) {
\r
350 // tmp2.setNum(c.lanes[i]);
\r
351 // tmp.append(tmp2 + "-");
\r
353 // qDebug("%s %s",tmp.latin1(), c.sha.latin1());
\r