Merge branch 'restructure-tree'
[TortoiseGit.git] / src / TortoiseProc / Blame.cpp
blob33658f92881f5d1f0189f9a929bed506b0d3dc08
1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-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.
19 #include "stdafx.h"
20 #include "TortoiseProc.h"
21 #include "Blame.h"
22 #include "ProgressDlg.h"
23 #include "TGitPath.h"
24 #include "Registry.h"
25 #include "UnicodeUtils.h"
26 #include "TempFile.h"
28 CBlame::CBlame()
30 m_bCancelled = FALSE;
31 m_lowestrev = -1;
32 m_highestrev = -1;
33 m_nCounter = 0;
34 m_nHeadRev = -1;
35 m_bNoLineNo = false;
37 CBlame::~CBlame()
39 // m_progressDlg.Stop();
42 BOOL CBlame::BlameCallback(LONG linenumber, git_revnum_t revision, const CString& author, const CString& date,
43 git_revnum_t merged_revision, const CString& merged_author, const CString& merged_date, const CString& merged_path,
44 const CStringA& line)
47 #if 0
48 CStringA infolineA;
49 CStringA fulllineA;
50 git_revnum_t origrev = revision;
52 if (((m_lowestrev < 0)||(m_lowestrev > revision))&&(revision >= 0))
53 m_lowestrev = revision;
54 if (m_highestrev < revision)
55 m_highestrev = revision;
57 CStringA dateA(date);
58 CStringA authorA(author);
59 CStringA pathA(merged_path);
60 TCHAR c = ' ';
61 if (!merged_author.IsEmpty() && (merged_revision > 0))
63 dateA = CStringA(merged_date);
64 authorA = CStringA(merged_author);
65 revision = merged_revision;
66 c = 'G';
67 m_bHasMerges = true;
70 if (pathA.Find(' ') >= 60)
72 // the merge path has spaces in it:
73 // TortoiseBlame can't deal with such paths if the space is after
74 // the 60 char which is reserved for the path length in the blame file
75 // To avoid these problems, we escape the space
76 // (not the best solution, but it works)
77 pathA.Replace(" ", "%20");
79 if (authorA.GetLength() > 30 )
80 authorA = authorA.Left(30);
81 if (m_bNoLineNo)
82 infolineA.Format("%c %6ld %6ld %-30s %-60s %-30s ", c, revision, origrev, (LPCSTR)dateA, (LPCSTR)pathA, (LPCSTR)authorA);
83 else
84 infolineA.Format("%c %6ld %6ld %6ld %-30s %-60s %-30s ", c, linenumber, revision, origrev, (LPCSTR)dateA, (LPCSTR)pathA, (LPCSTR)authorA);
85 fulllineA = line;
86 fulllineA.TrimRight("\r\n");
87 fulllineA += "\n";
88 if (m_saveFile.m_hFile != INVALID_HANDLE_VALUE)
90 m_saveFile.WriteString(infolineA);
91 m_saveFile.WriteString(fulllineA);
93 else
94 return FALSE;
95 #endif
96 return TRUE;
99 #if 0
100 BOOL CBlame::Log(git_revnum_t revision, const CString& /*author*/, const CString& /*date*/, const CString& message, LogChangedPathArray * /*cpaths*/, apr_time_t /*time*/, int /*filechanges*/, BOOL /*copies*/, DWORD /*actions*/, BOOL /*children*/)
102 m_progressDlg.SetProgress(m_highestrev - revision, m_highestrev);
103 if (m_saveLog.m_hFile != INVALID_HANDLE_VALUE)
105 CStringA msgutf8 = CUnicodeUtils::GetUTF8(message);
106 int length = msgutf8.GetLength();
107 m_saveLog.Write(&revision, sizeof(LONG));
108 m_saveLog.Write(&length, sizeof(int));
109 m_saveLog.Write((LPCSTR)msgutf8, length);
111 return TRUE;
113 #endif
115 BOOL CBlame::Cancel()
117 // if (m_progressDlg.HasUserCancelled())
118 // m_bCancelled = TRUE;
119 return m_bCancelled;
122 CString CBlame::BlameToTempFile(const CTGitPath& path, GitRev startrev, GitRev endrev, GitRev pegrev,
123 CString& logfile, const CString& options, BOOL includemerge,
124 BOOL showprogress, BOOL ignoremimetype)
126 #if 0
127 // if the user specified to use another tool to show the blames, there's no
128 // need to fetch the log later: only TortoiseBlame uses those logs to give
129 // the user additional information for the blame.
130 BOOL extBlame = CRegDWORD(_T("Software\\TortoiseGit\\TextBlame"), FALSE);
132 CString temp;
133 m_sSavePath = CTempFiles::Instance().GetTempFilePath(false).GetWinPathString();
134 if (m_sSavePath.IsEmpty())
135 return _T("");
136 temp = path.GetFileExtension();
137 if (!temp.IsEmpty() && !extBlame)
138 m_sSavePath += temp;
139 if (!m_saveFile.Open(m_sSavePath, CFile::typeText | CFile::modeReadWrite | CFile::modeCreate))
140 return _T("");
141 CString headline;
142 m_bNoLineNo = false;
143 headline.Format(_T("%c %-6s %-6s %-6s %-30s %-60s %-30s %-s \n"), ' ', _T("line"), _T("rev"), _T("rev"), _T("date"), _T("path"), _T("author"), _T("content"));
144 m_saveFile.WriteString(headline);
145 m_saveFile.WriteString(_T("\n"));
146 m_progressDlg.SetTitle(IDS_BLAME_PROGRESSTITLE);
147 m_progressDlg.SetAnimation(IDR_DOWNLOAD);
148 m_progressDlg.SetShowProgressBar(TRUE);
149 if (showprogress)
151 m_progressDlg.ShowModeless(CWnd::FromHandle(hWndExplorer));
153 m_progressDlg.FormatNonPathLine(1, IDS_BLAME_PROGRESSINFO);
154 m_progressDlg.FormatNonPathLine(2, IDS_BLAME_PROGRESSINFOSTART);
155 m_progressDlg.SetCancelMsg(IDS_BLAME_PROGRESSCANCEL);
156 m_progressDlg.SetTime(FALSE);
157 m_nHeadRev = endrev;
158 if (m_nHeadRev < 0)
159 m_nHeadRev = GetHEADRevision(path);
160 m_progressDlg.SetProgress(0, m_nHeadRev);
162 m_bHasMerges = false;
163 BOOL bBlameSuccesful = this->Blame(path, startrev, endrev, pegrev, options, !!ignoremimetype, !!includemerge);
164 if ( !bBlameSuccesful && !pegrev.IsValid() )
166 // retry with the end rev as peg rev
167 if (this->Blame(path, startrev, endrev, endrev, options, !!ignoremimetype, !!includemerge))
169 bBlameSuccesful = TRUE;
170 pegrev = endrev;
173 if (!bBlameSuccesful)
175 m_saveFile.Close();
176 DeleteFile(m_sSavePath);
177 m_sSavePath.Empty();
179 else if (!extBlame)
181 m_progressDlg.FormatNonPathLine(2, IDS_BLAME_PROGRESSLOGSTART);
182 m_progressDlg.SetProgress(0, m_highestrev);
183 logfile = CTempFiles::Instance().GetTempFilePath(false).GetWinPathString();
184 if (!m_saveLog.Open(logfile, CFile::typeBinary | CFile::modeReadWrite | CFile::modeCreate))
186 logfile.Empty();
187 return m_sSavePath;
189 BOOL bRet = ReceiveLog(CTGitPathList(path), pegrev, m_nHeadRev, m_lowestrev, 0, FALSE, m_bHasMerges, false);
190 if (!bRet)
192 m_saveLog.Close();
193 DeleteFile(logfile);
194 logfile.Empty();
196 else
198 m_saveLog.Close();
201 m_progressDlg.Stop();
202 if (m_saveFile.m_hFile != INVALID_HANDLE_VALUE)
203 m_saveFile.Close();
204 #endif;
205 return m_sSavePath;
207 #if 0
208 BOOL CBlame::Notify(const CTGitPath& /*path*/, svn_wc_notify_action_t /*action*/,
209 svn_node_kind_t /*kind*/, const CString& /*mime_type*/,
210 svn_wc_notify_state_t /*content_state*/,
211 svn_wc_notify_state_t /*prop_state*/, LONG rev,
212 const svn_lock_t * /*lock*/, svn_wc_notify_lock_state_t /*lock_state*/,
213 svn_error_t * /*err*/, apr_pool_t * /*pool*/)
215 m_progressDlg.FormatNonPathLine(2, IDS_BLAME_PROGRESSINFO2, rev, m_nHeadRev);
216 m_progressDlg.SetProgress(rev, m_nHeadRev);
217 return TRUE;
219 #endif
220 bool CBlame::BlameToFile(const CTGitPath& path, GitRev startrev, GitRev endrev, GitRev peg,
221 const CTGitPath& tofile, const CString& options, BOOL ignoremimetype, BOOL includemerge)
223 CString temp;
224 if (!m_saveFile.Open(tofile.GetWinPathString(), CFile::typeText | CFile::modeReadWrite | CFile::modeCreate))
225 return false;
226 m_bNoLineNo = true;
227 m_nHeadRev = endrev;
228 if (m_nHeadRev < 0)
229 m_nHeadRev = GetHEADRevision(path);
231 BOOL bBlameSuccesful = this->Blame(path, startrev, endrev, peg, options, !!ignoremimetype, !!includemerge);
232 if ( !bBlameSuccesful && !peg.IsValid() )
234 // retry with the end rev as peg rev
235 if (this->Blame(path, startrev, endrev, endrev, options, !!ignoremimetype, !!includemerge))
237 bBlameSuccesful = TRUE;
238 peg = endrev;
242 if (!bBlameSuccesful)
244 m_saveFile.Close();
245 return false;
248 if (m_saveFile.m_hFile != INVALID_HANDLE_VALUE)
249 m_saveFile.Close();
251 return true;