1 // TortoiseGit - 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
29 #include "TortoiseProc.h"
30 #include "GitLogListBase.h"
32 //#include "VssStyle.h"
37 #include "GITProgressDlg.h"
38 #include "ProgressDlg.h"
39 //#include "RepositoryBrowser.h"
40 //#include "CopyDlg.h"
41 //#include "StatGraphDlg.h"
43 #include "MessageBox.h"
46 #include "PathUtils.h"
47 #include "StringUtils.h"
48 #include "UnicodeUtils.h"
50 //#include "GitInfo.h"
51 //#include "GitDiff.h"
53 //#include "RevisionRangeDlg.h"
54 //#include "BrowseFolder.h"
55 //#include "BlameDlg.h"
57 //#include "GitHelpers.h"
58 #include "GitStatus.h"
59 //#include "LogDlgHelper.h"
60 //#include "CachedLogInfo.h"
61 //#include "RepositoryInfo.h"
62 //#include "EditPropertiesDlg.h"
63 #include "FileDiffDlg.h"
67 void CLogDataVector::ClearAll()
78 m_RawLogStart
.clear();
81 //CLogDataVector Class
82 int CLogDataVector::ParserFromLog(CTGitPath
*path
,int count
,int infomask
,CString
*from
,CString
*to
)
84 // only enable --follow on files
85 if ((path
== NULL
|| path
->IsDirectory()) && (infomask
& CGit::LOG_INFO_FOLLOW
))
86 infomask
= infomask
^ CGit::LOG_INFO_FOLLOW
;
89 CString cmd
=g_Git
.GetLogCmd(hash
,path
,count
,infomask
,from
,to
,true);
91 if(g_Git
.IsInitRepos())
97 if (git_open_log(&handle
,CUnicodeUtils::GetMulti(cmd
, CP_UTF8
).GetBuffer()))
102 git_get_log_firstcommit(handle
);
108 while (git_get_log_nextcommit(handle
, &commit
, infomask
& CGit::LOG_INFO_FOLLOW
) == 0)
110 if (commit
.m_ignore
== 1)
112 git_free_commit(&commit
);
116 CGitHash hash
= (char*)commit
.m_hash
;
119 GitRev
*pRev
= this->m_pLogCache
->GetCacheData(hash
);
122 git_get_notes(commit
.m_hash
,¬e
);
125 pRev
->m_Notes
.Empty();
126 g_Git
.StringAppend(&pRev
->m_Notes
,(BYTE
*)note
);
129 if(pRev
== NULL
|| !pRev
->m_IsFull
)
131 pRev
->ParserFromCommit(&commit
);
132 pRev
->ParserParentFromCommit(&commit
);
133 git_free_commit(&commit
);
134 //Must call free commit before SafeFetchFullInfo, commit parent is rewrite by log.
135 //file list will wrong if parent rewrite.
136 pRev
->SafeFetchFullInfo(&g_Git
);
141 ASSERT(pRev
->m_CommitHash
== hash
);
142 pRev
->ParserParentFromCommit(&commit
);
143 git_free_commit(&commit
);
146 this->push_back(pRev
->m_CommitHash
);
148 m_HashMap
[rev
.m_CommitHash
]=size()-1;
152 git_close_log(handle
);
157 int AddTolist(unsigned char * /*osha1*/, unsigned char *nsha1
, const char * /*name*/, unsigned long /*time*/, int /*sz*/, const char *msg
, void *data
)
159 CLogDataVector
*vector
= (CLogDataVector
*)data
;
161 rev
.m_CommitHash
=(char*)nsha1
;
164 g_Git
.StringAppend(&one
, (BYTE
*)msg
);
166 int message
=one
.Find(_T(":"),0);
169 rev
.m_RefAction
=one
.Left(message
);
170 rev
.GetSubject()=one
.Mid(message
+1);
173 vector
->m_pLogCache
->m_HashMap
[rev
.m_CommitHash
]=rev
;
174 vector
->insert(vector
->begin(),rev
.m_CommitHash
);
179 int CLogDataVector::ParserFromRefLog(CString ref
)
181 if(g_Git
.m_IsUseGitDLL
)
183 git_for_each_reflog_ent(CUnicodeUtils::GetUTF8(ref
),AddTolist
,this);
184 for(int i
=0;i
<size();i
++)
186 m_pLogCache
->m_HashMap
[at(i
)].m_Ref
.Format(_T("%s{%d}"), ref
,i
);
195 cmd
.Format(_T("git.exe reflog show %s"),ref
);
196 if (g_Git
.Run(cmd
, &out
, NULL
, CP_UTF8
))
202 CString one
=out
.Tokenize(_T("\n"),pos
);
203 int ref
=one
.Find(_T(' '),0);
209 rev
.m_CommitHash
=g_Git
.GetHash(one
.Left(ref
));
210 int action
=one
.Find(_T(' '),ref
+1);
214 rev
.m_Ref
=one
.Mid(ref
+1,action
-ref
-2);
215 message
=one
.Find(_T(":"),action
);
218 rev
.m_RefAction
=one
.Mid(action
+1,message
-action
-1);
219 rev
.GetSubject()=one
.Right(one
.GetLength()-message
-1);
223 this->m_pLogCache
->m_HashMap
[rev
.m_CommitHash
]=rev
;
225 this->push_back(rev
.m_CommitHash
);
232 void CLogDataVector::setLane(CGitHash
& sha
)
234 Lanes
* l
= &(this->m_Lns
);
235 int i
= m_FirstFreeLane
;
237 // QVector<QByteArray> ba;
238 // const ShaString& ss = toPersistentSha(sha, ba);
239 // const ShaVect& shaVec(fh->revOrder);
241 for (int cnt
= size(); i
< cnt
; ++i
) {
243 GitRev
* r
= & this->GetGitRevAt(i
);
244 CGitHash curSha
=r
->m_CommitHash
;
246 if (r
->m_Lanes
.size() == 0)
247 updateLanes(*r
, *l
, curSha
);
252 m_FirstFreeLane
= ++i
;
255 Lanes
* l
= &(this->m_Lanes
);
256 int i
= m_FirstFreeLane
;
258 QVector
<QByteArray
> ba
;
259 const ShaString
& ss
= toPersistentSha(sha
, ba
);
260 const ShaVect
& shaVec(fh
->revOrder
);
262 for (uint cnt
= shaVec
.count(); i
< cnt
; ++i
) {
264 const ShaString
& curSha
= shaVec
[i
];
265 Rev
* r
= m_HashMap
[curSha
]const_cast<Rev
*>(revLookup(curSha
, fh
));
266 if (r
->lanes
.count() == 0)
267 updateLanes(*r
, *l
, curSha
);
272 fh
->firstFreeLane
= ++i
;
277 void CLogDataVector::updateLanes(GitRev
& c
, Lanes
& lns
, CGitHash
&sha
)
279 // we could get third argument from c.sha(), but we are in fast path here
280 // and c.sha() involves a deep copy, so we accept a little redundancy
285 bool isDiscontinuity
;
286 bool isFork
= lns
.isFork(sha
, isDiscontinuity
);
287 bool isMerge
= (c
.ParentsCount() > 1);
288 bool isInitial
= (c
.ParentsCount() == 0);
291 lns
.changeActiveLane(sha
); // uses previous isBoundary state
293 lns
.setBoundary(c
.IsBoundary() == TRUE
); // update must be here
294 TRACE(_T("%s %d"),c
.m_CommitHash
.ToString(),c
.IsBoundary());
299 lns
.setMerge(c
.m_ParentHash
);
305 lns
.getLanes(c
.m_Lanes
); // here lanes are snapshotted
309 nextSha
= c
.m_ParentHash
[0];
311 lns
.nextParent(nextSha
);
314 // lns.afterApplied();
322 // QString tmp = "", tmp2;
323 // for (uint i = 0; i < c.lanes.count(); i++) {
324 // tmp2.setNum(c.lanes[i]);
325 // tmp.append(tmp2 + "-");
327 // qDebug("%s %s",tmp.latin1(), c.sha.latin1());