OSDN Git Service

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