OSDN Git Service

Fixed issue #234: First log(first commit in history) was missing...
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / LogDataVector.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2007-2008 - TortoiseSVN\r
4 \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
9 \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
14 \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
18 //\r
19 /*\r
20         Description: start-up repository opening and reading\r
21 \r
22         Author: Marco Costalba (C) 2005-2007\r
23 \r
24         Copyright: See COPYING file that comes with this distribution\r
25 \r
26 */\r
27 \r
28 #include "stdafx.h"\r
29 #include "TortoiseProc.h"\r
30 #include "GitLogListBase.h"\r
31 #include "GitRev.h"\r
32 //#include "VssStyle.h"\r
33 #include "IconMenu.h"\r
34 // CGitLogList\r
35 #include "cursor.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
43 #include "Logdlg.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 \r
66 void CLogDataVector::ClearAll()\r
67 {\r
68 \r
69         clear();\r
70         m_HashMap.clear();\r
71         m_Lns.clear();\r
72 \r
73         m_FirstFreeLane=0;\r
74         m_Lns.clear();\r
75 \r
76         m_RawlogData.clear();\r
77         m_RawLogStart.clear();\r
78 }\r
79 \r
80 int CLogDataVector::ParserShortLog(CTGitPath *path ,CString &hash,int count ,int mask )\r
81 {\r
82         BYTE_VECTOR log;\r
83         GitRev rev;\r
84 \r
85         if(g_Git.IsInitRepos())\r
86                 return 0;\r
87 \r
88         CString begin;\r
89         begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);\r
90 \r
91         //g_Git.GetShortLog(log,path,count);\r
92 \r
93         g_Git.GetLog(log,hash,path,count,mask);\r
94 \r
95         if(log.size()==0)\r
96                 return 0;\r
97         \r
98         int start=4;\r
99         int length;\r
100         int next =0;\r
101         while( next>=0 && next<log.size())\r
102         {\r
103                 next=rev.ParserFromLog(log,next);\r
104 \r
105                 rev.m_Subject=_T("Load .................................");\r
106                 this->push_back(rev);\r
107                 m_HashMap[rev.m_CommitHash]=size()-1;\r
108 \r
109                 //next=log.find(0,next);\r
110         }\r
111 \r
112         return 0;\r
113 \r
114 }\r
115 int CLogDataVector::FetchShortLog(CTGitPath *path ,CString &hash,int count ,int mask, int ShowWC )\r
116 {\r
117         //BYTE_VECTOR log;\r
118         m_RawlogData.clear();\r
119         m_RawLogStart.clear();\r
120 \r
121         GitRev rev;\r
122         \r
123         if(g_Git.IsInitRepos())\r
124                 return 0;\r
125 \r
126         CString begin;\r
127         begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);\r
128 \r
129         //g_Git.GetShortLog(log,path,count);\r
130         ULONGLONG  t1,t2;\r
131         t1=GetTickCount();\r
132         g_Git.GetLog(m_RawlogData, hash,path,count,mask);\r
133         t2=GetTickCount();\r
134 \r
135         TRACE(_T("GetLog Time %ld\r\n"),t2-t1);\r
136 \r
137         if(m_RawlogData.size()==0)\r
138                 return 0;\r
139         \r
140         int start=4;\r
141         int length;\r
142         int next =0;\r
143         t1=GetTickCount();\r
144         int a1=0,b1=0;\r
145 \r
146         while( next>=0 && next<m_RawlogData.size())\r
147         {\r
148                 static const BYTE dataToFind[]={0,0};\r
149                 m_RawLogStart.push_back(next);\r
150                 //this->at(i).m_Subject=_T("parser...");\r
151                 next=m_RawlogData.findData(dataToFind,2,next+1);\r
152                 //next=log.find(0,next);\r
153         }\r
154 \r
155         resize(m_RawLogStart.size() + ShowWC);\r
156 \r
157         t2=GetTickCount();\r
158 \r
159         return 0;\r
160 }\r
161 int CLogDataVector::FetchFullInfo(int i)\r
162 {\r
163         return at(i).SafeFetchFullInfo(&g_Git);\r
164 }\r
165 //CLogDataVector Class\r
166 int CLogDataVector::ParserFromLog(CTGitPath *path ,int count ,int infomask,CString *from,CString *to)\r
167 {\r
168         BYTE_VECTOR log;\r
169         GitRev rev;\r
170         CString emptyhash;\r
171         g_Git.GetLog(log,emptyhash,path,count,infomask,from,to);\r
172 \r
173         CString begin;\r
174         begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);\r
175         \r
176         if(log.size()==0)\r
177                 return 0;\r
178         \r
179         int start=4;\r
180         int length;\r
181         int next =0;\r
182         while( next>=0 )\r
183         {\r
184                 next=rev.ParserFromLog(log,next);\r
185                 this->push_back(rev);\r
186                 m_HashMap[rev.m_CommitHash]=size()-1;           \r
187         }\r
188 \r
189         return 0;\r
190 }\r
191 \r
192 int CLogDataVector::ParserFromRefLog(CString ref)\r
193 {\r
194         CString cmd,out;\r
195         GitRev rev;\r
196         cmd.Format(_T("git.exe reflog show %s"),ref);\r
197         if(g_Git.Run(cmd,&out,CP_UTF8))\r
198                 return -1;\r
199         \r
200         int pos=0;\r
201         while(pos>=0)\r
202         {\r
203                 CString one=out.Tokenize(_T("\n"),pos);\r
204                 int ref=one.Find(_T(' '),0);\r
205                 if(ref<0)\r
206                         continue;\r
207 \r
208                 rev.Clear();\r
209 \r
210                 rev.m_CommitHash=one.Left(ref);\r
211                 int action=one.Find(_T(' '),ref+1);\r
212                 int message;\r
213                 if(action>0)\r
214                 {\r
215                         rev.m_Ref=one.Mid(ref+1,action-ref-2);\r
216                         message=one.Find(_T(":"),action);\r
217                         if(message>0)\r
218                         {\r
219                                 rev.m_RefAction=one.Mid(action+1,message-action-1);\r
220                                 rev.m_Subject=one.Right(one.GetLength()-message-1);\r
221                         }\r
222                 }\r
223                 this->push_back(rev);\r
224         }\r
225         return 0;\r
226 }\r
227 \r
228 void CLogDataVector::setLane(CString& sha) \r
229 {\r
230         Lanes* l = &(this->m_Lns);\r
231         int i = m_FirstFreeLane;\r
232         \r
233 //      QVector<QByteArray> ba;\r
234 //      const ShaString& ss = toPersistentSha(sha, ba);\r
235 //      const ShaVect& shaVec(fh->revOrder);\r
236 \r
237         for (int cnt = size(); i < cnt; ++i) {\r
238 \r
239                 GitRev* r = &(*this)[i]; \r
240                 CString &curSha=r->m_CommitHash;\r
241 \r
242                 if (r->m_Lanes.size() == 0)\r
243                         updateLanes(*r, *l, curSha);\r
244 \r
245                 if (curSha == sha)\r
246                         break;\r
247         }\r
248         m_FirstFreeLane = ++i;\r
249 \r
250 #if 0\r
251         Lanes* l = &(this->m_Lanes);\r
252         int i = m_FirstFreeLane;\r
253         \r
254         QVector<QByteArray> ba;\r
255         const ShaString& ss = toPersistentSha(sha, ba);\r
256         const ShaVect& shaVec(fh->revOrder);\r
257 \r
258         for (uint cnt = shaVec.count(); i < cnt; ++i) {\r
259 \r
260                 const ShaString& curSha = shaVec[i];\r
261                 Rev* r = m_HashMap[curSha]const_cast<Rev*>(revLookup(curSha, fh));\r
262                 if (r->lanes.count() == 0)\r
263                         updateLanes(*r, *l, curSha);\r
264 \r
265                 if (curSha == ss)\r
266                         break;\r
267         }\r
268         fh->firstFreeLane = ++i;\r
269 #endif\r
270 }\r
271 \r
272 \r
273 void CLogDataVector::updateLanes(GitRev& c, Lanes& lns, CString &sha) \r
274 {\r
275 // we could get third argument from c.sha(), but we are in fast path here\r
276 // and c.sha() involves a deep copy, so we accept a little redundancy\r
277 \r
278         if (lns.isEmpty())\r
279                 lns.init(sha);\r
280 \r
281         bool isDiscontinuity;\r
282         bool isFork = lns.isFork(sha, isDiscontinuity);\r
283         bool isMerge = (c.ParentsCount() > 1);\r
284         bool isInitial = (c.ParentsCount() == 0);\r
285 \r
286         if (isDiscontinuity)\r
287                 lns.changeActiveLane(sha); // uses previous isBoundary state\r
288 \r
289         lns.setBoundary(c.IsBoundary() == TRUE); // update must be here\r
290         TRACE(_T("%s %d"),c.m_CommitHash,c.IsBoundary());\r
291 \r
292         if (isFork)\r
293                 lns.setFork(sha);\r
294         if (isMerge)\r
295                 lns.setMerge(c.m_ParentHash);\r
296         //if (c.isApplied)\r
297         //      lns.setApplied();\r
298         if (isInitial)\r
299                 lns.setInitial();\r
300 \r
301         lns.getLanes(c.m_Lanes); // here lanes are snapshotted\r
302 \r
303         CString nextSha = (isInitial) ? CString(_T("")) : QString(c.m_ParentHash[0]);\r
304 \r
305         lns.nextParent(nextSha);\r
306 \r
307         //if (c.isApplied)\r
308         //      lns.afterApplied();\r
309         if (isMerge)\r
310                 lns.afterMerge();\r
311         if (isFork)\r
312                 lns.afterFork();\r
313         if (lns.isBranch())\r
314                 lns.afterBranch();\r
315 \r
316 //      QString tmp = "", tmp2;\r
317 //      for (uint i = 0; i < c.lanes.count(); i++) {\r
318 //              tmp2.setNum(c.lanes[i]);\r
319 //              tmp.append(tmp2 + "-");\r
320 //      }\r
321 //      qDebug("%s %s",tmp.latin1(), c.sha.latin1());\r
322 }