OSDN Git Service

0c6d3d418019956c3d7372141f6e23888f11fd7e
[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 #include "GitHash.h"\r
66 CGitHashMap a;\r
67 \r
68 void CLogDataVector::ClearAll()\r
69 {\r
70 \r
71         clear();\r
72         m_HashMap.clear();\r
73         m_Lns.clear();\r
74 \r
75         m_FirstFreeLane=0;\r
76         m_Lns.clear();\r
77 \r
78         m_RawlogData.clear();\r
79         m_RawLogStart.clear();\r
80 }\r
81 \r
82 int CLogDataVector::ParserShortLog(CTGitPath *path ,CString &hash,int count ,int mask )\r
83 {\r
84         BYTE_VECTOR log;\r
85         GitRev rev;\r
86 \r
87         if(g_Git.IsInitRepos())\r
88                 return 0;\r
89 \r
90         CString begin;\r
91         begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);\r
92 \r
93         //g_Git.GetShortLog(log,path,count);\r
94 \r
95         g_Git.GetLog(log,hash,path,count,mask);\r
96 \r
97         if(log.size()==0)\r
98                 return 0;\r
99         \r
100         int start=4;\r
101         int length;\r
102         int next =0;\r
103         while( next>=0 && next<log.size())\r
104         {\r
105                 next=rev.ParserFromLog(log,next);\r
106 \r
107                 rev.m_Subject=_T("Load .................................");\r
108                 this->push_back(rev.m_CommitHash);\r
109 \r
110                 if(this->m_pLogCache->m_HashMap.IsExist(rev.m_CommitHash))\r
111                 {\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
114                 }else\r
115                         this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);\r
116 \r
117                 m_HashMap[rev.m_CommitHash]=size()-1;\r
118 \r
119                 //next=log.find(0,next);\r
120         }\r
121 \r
122         return 0;\r
123 \r
124 }\r
125 int CLogDataVector::FetchShortLog(CTGitPath *path ,CString &hash,int count ,int mask, int ShowWC )\r
126 {\r
127         //BYTE_VECTOR log;\r
128         m_RawlogData.clear();\r
129         m_RawLogStart.clear();\r
130 \r
131         GitRev rev;\r
132         \r
133         if(g_Git.IsInitRepos())\r
134                 return 0;\r
135 \r
136         CString begin;\r
137         begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);\r
138 \r
139         //g_Git.GetShortLog(log,path,count);\r
140         ULONGLONG  t1,t2;\r
141         t1=GetTickCount();\r
142         g_Git.GetLog(m_RawlogData, hash,path,count,mask);\r
143         t2=GetTickCount();\r
144 \r
145         TRACE(_T("GetLog Time %ld\r\n"),t2-t1);\r
146 \r
147         if(m_RawlogData.size()==0)\r
148                 return 0;\r
149         \r
150         int start=4;\r
151         int length;\r
152         int next =0;\r
153         t1=GetTickCount();\r
154         int a1=0,b1=0;\r
155 \r
156         while( next>=0 && next<m_RawlogData.size())\r
157         {\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
163         }\r
164 \r
165         resize(m_RawLogStart.size() + ShowWC);\r
166 \r
167         t2=GetTickCount();\r
168 \r
169         return 0;\r
170 }\r
171 int CLogDataVector::FetchFullInfo(int i)\r
172 {\r
173         return GetGitRevAt(i).SafeFetchFullInfo(&g_Git);\r
174 }\r
175 //CLogDataVector Class\r
176 int CLogDataVector::ParserFromLog(CTGitPath *path ,int count ,int infomask,CString *from,CString *to)\r
177 {\r
178         BYTE_VECTOR log;\r
179         GitRev rev;\r
180         CString emptyhash;\r
181         g_Git.GetLog(log,emptyhash,path,count,infomask,from,to);\r
182 \r
183         CString begin;\r
184         begin.Format(_T("#<%c>"),LOG_REV_ITEM_BEGIN);\r
185         \r
186         if(log.size()==0)\r
187                 return 0;\r
188         \r
189         int start=4;\r
190         int length;\r
191         int next =0;\r
192         while( next>=0 )\r
193         {\r
194                 next=rev.ParserFromLog(log,next);\r
195 \r
196                 if(this->m_pLogCache->m_HashMap.IsExist(rev.m_CommitHash))\r
197                 {\r
198                         if(!this->m_pLogCache->m_HashMap[rev.m_CommitHash].m_IsFull)\r
199                                 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);\r
200                 }else\r
201                         this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);\r
202 \r
203                 m_HashMap[rev.m_CommitHash]=size()-1;           \r
204         }\r
205 \r
206         return 0;\r
207 }\r
208 \r
209 int CLogDataVector::ParserFromRefLog(CString ref)\r
210 {\r
211         CString cmd,out;\r
212         GitRev rev;\r
213         cmd.Format(_T("git.exe reflog show %s"),ref);\r
214         if(g_Git.Run(cmd,&out,CP_UTF8))\r
215                 return -1;\r
216         \r
217         int pos=0;\r
218         while(pos>=0)\r
219         {\r
220                 CString one=out.Tokenize(_T("\n"),pos);\r
221                 int ref=one.Find(_T(' '),0);\r
222                 if(ref<0)\r
223                         continue;\r
224 \r
225                 rev.Clear();\r
226 \r
227                 rev.m_CommitHash=g_Git.GetHash(one.Left(ref));\r
228                 int action=one.Find(_T(' '),ref+1);\r
229                 int message;\r
230                 if(action>0)\r
231                 {\r
232                         rev.m_Ref=one.Mid(ref+1,action-ref-2);\r
233                         message=one.Find(_T(":"),action);\r
234                         if(message>0)\r
235                         {\r
236                                 rev.m_RefAction=one.Mid(action+1,message-action-1);\r
237                                 rev.m_Subject=one.Right(one.GetLength()-message-1);\r
238                         }\r
239                 }\r
240 \r
241                 if(this->m_pLogCache->m_HashMap.IsExist(rev.m_CommitHash))\r
242                 {\r
243                         if(!this->m_pLogCache->m_HashMap[rev.m_CommitHash].m_IsFull)\r
244                                 this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);\r
245                 }else\r
246                         this->m_pLogCache->m_HashMap[rev.m_CommitHash].CopyFrom(rev);\r
247 \r
248         }\r
249         return 0;\r
250 }\r
251 \r
252 void CLogDataVector::setLane(CGitHash& sha) \r
253 {\r
254         Lanes* l = &(this->m_Lns);\r
255         int i = m_FirstFreeLane;\r
256         \r
257 //      QVector<QByteArray> ba;\r
258 //      const ShaString& ss = toPersistentSha(sha, ba);\r
259 //      const ShaVect& shaVec(fh->revOrder);\r
260 \r
261         for (int cnt = size(); i < cnt; ++i) {\r
262 \r
263                 GitRev* r = & this->GetGitRevAt(i); \r
264                 CGitHash curSha=r->m_CommitHash;\r
265 \r
266                 if (r->m_Lanes.size() == 0)\r
267                         updateLanes(*r, *l, curSha);\r
268 \r
269                 if (curSha == sha)\r
270                         break;\r
271         }\r
272         m_FirstFreeLane = ++i;\r
273 \r
274 #if 0\r
275         Lanes* l = &(this->m_Lanes);\r
276         int i = m_FirstFreeLane;\r
277         \r
278         QVector<QByteArray> ba;\r
279         const ShaString& ss = toPersistentSha(sha, ba);\r
280         const ShaVect& shaVec(fh->revOrder);\r
281 \r
282         for (uint cnt = shaVec.count(); i < cnt; ++i) {\r
283 \r
284                 const ShaString& curSha = shaVec[i];\r
285                 Rev* r = m_HashMap[curSha]const_cast<Rev*>(revLookup(curSha, fh));\r
286                 if (r->lanes.count() == 0)\r
287                         updateLanes(*r, *l, curSha);\r
288 \r
289                 if (curSha == ss)\r
290                         break;\r
291         }\r
292         fh->firstFreeLane = ++i;\r
293 #endif\r
294 }\r
295 \r
296 \r
297 void CLogDataVector::updateLanes(GitRev& c, Lanes& lns, CGitHash &sha) \r
298 {\r
299 // we could get third argument from c.sha(), but we are in fast path here\r
300 // and c.sha() involves a deep copy, so we accept a little redundancy\r
301 \r
302         if (lns.isEmpty())\r
303                 lns.init(sha);\r
304 \r
305         bool isDiscontinuity;\r
306         bool isFork = lns.isFork(sha, isDiscontinuity);\r
307         bool isMerge = (c.ParentsCount() > 1);\r
308         bool isInitial = (c.ParentsCount() == 0);\r
309 \r
310         if (isDiscontinuity)\r
311                 lns.changeActiveLane(sha); // uses previous isBoundary state\r
312 \r
313         lns.setBoundary(c.IsBoundary() == TRUE); // update must be here\r
314         TRACE(_T("%s %d"),c.m_CommitHash.ToString(),c.IsBoundary());\r
315 \r
316         if (isFork)\r
317                 lns.setFork(sha);\r
318         if (isMerge)\r
319                 lns.setMerge(c.m_ParentHash);\r
320         //if (c.isApplied)\r
321         //      lns.setApplied();\r
322         if (isInitial)\r
323                 lns.setInitial();\r
324 \r
325         lns.getLanes(c.m_Lanes); // here lanes are snapshotted\r
326 \r
327         CGitHash nextSha;\r
328         if( !isInitial) \r
329                 nextSha = c.m_ParentHash[0];\r
330 \r
331         lns.nextParent(nextSha);\r
332 \r
333         //if (c.isApplied)\r
334         //      lns.afterApplied();\r
335         if (isMerge)\r
336                 lns.afterMerge();\r
337         if (isFork)\r
338                 lns.afterFork();\r
339         if (lns.isBranch())\r
340                 lns.afterBranch();\r
341 \r
342 //      QString tmp = "", tmp2;\r
343 //      for (uint i = 0; i < c.lanes.count(); i++) {\r
344 //              tmp2.setNum(c.lanes[i]);\r
345 //              tmp.append(tmp2 + "-");\r
346 //      }\r
347 //      qDebug("%s %s",tmp.latin1(), c.sha.latin1());\r
348 }