Replace NOERROR with S_OK
[TortoiseGit.git] / src / TortoiseShell / GITPropertyPage.cpp
blob811bc536ec295b4a043ac621f2da0b1f071c33b5
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseSVN
4 // Copyright (C) 2008-2012 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
22 #include "ShellExt.h"
23 #include "gitpropertypage.h"
24 #include "UnicodeUtils.h"
25 #include "PathUtils.h"
26 #include "GitStatus.h"
28 #define MAX_STRING_LENGTH 4096 //should be big enough
30 // Nonmember function prototypes
31 BOOL CALLBACK PageProc (HWND, UINT, WPARAM, LPARAM);
32 UINT CALLBACK PropPageCallbackProc ( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp );
34 /////////////////////////////////////////////////////////////////////////////
35 // Dialog procedures and other callback functions
37 BOOL CALLBACK PageProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
39 CGitPropertyPage * sheetpage;
41 if (uMessage == WM_INITDIALOG)
43 sheetpage = (CGitPropertyPage*) ((LPPROPSHEETPAGE) lParam)->lParam;
44 SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) sheetpage);
45 sheetpage->SetHwnd(hwnd);
47 else
49 sheetpage = (CGitPropertyPage*) GetWindowLongPtr (hwnd, GWLP_USERDATA);
52 if (sheetpage != 0L)
53 return sheetpage->PageProc(hwnd, uMessage, wParam, lParam);
54 else
55 return FALSE;
58 UINT CALLBACK PropPageCallbackProc ( HWND /*hwnd*/, UINT uMsg, LPPROPSHEETPAGE ppsp )
60 // Delete the page before closing.
61 if (PSPCB_RELEASE == uMsg)
63 CGitPropertyPage* sheetpage = (CGitPropertyPage*) ppsp->lParam;
64 if (sheetpage != NULL)
65 delete sheetpage;
67 return 1;
70 // *********************** CGitPropertyPage *************************
72 CGitPropertyPage::CGitPropertyPage(const std::vector<stdstring> &newFilenames)
73 :filenames(newFilenames)
77 CGitPropertyPage::~CGitPropertyPage(void)
81 void CGitPropertyPage::SetHwnd(HWND newHwnd)
83 m_hwnd = newHwnd;
86 BOOL CGitPropertyPage::PageProc (HWND /*hwnd*/, UINT uMessage, WPARAM wParam, LPARAM lParam)
88 switch (uMessage)
90 case WM_INITDIALOG:
92 InitWorkfileView();
93 return TRUE;
95 case WM_NOTIFY:
97 LPNMHDR point = (LPNMHDR)lParam;
98 int code = point->code;
100 // Respond to notifications.
102 if (code == PSN_APPLY)
105 SetWindowLongPtr (m_hwnd, DWLP_MSGRESULT, FALSE);
106 return TRUE;
109 case WM_DESTROY:
110 return TRUE;
112 case WM_COMMAND:
113 PageProcOnCommand(wParam);
114 break;
115 } // switch (uMessage)
116 return FALSE;
118 void CGitPropertyPage::PageProcOnCommand(WPARAM wParam)
120 if(HIWORD(wParam) != BN_CLICKED)
121 return;
123 if (LOWORD(wParam) == IDC_SHOWLOG)
125 STARTUPINFO startup;
126 PROCESS_INFORMATION process;
127 memset(&startup, 0, sizeof(startup));
128 startup.cb = sizeof(startup);
129 memset(&process, 0, sizeof(process));
130 CRegStdString tortoiseProcPath(_T("Software\\TortoiseGit\\ProcPath"), _T("TortoiseProc.exe"), false, HKEY_LOCAL_MACHINE);
131 stdstring gitCmd = _T(" /command:");
132 gitCmd += _T("log /path:\"");
133 gitCmd += filenames.front().c_str();
134 gitCmd += _T("\"");
135 if (CreateProcess(((stdstring)tortoiseProcPath).c_str(), const_cast<TCHAR*>(gitCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))
137 CloseHandle(process.hThread);
138 CloseHandle(process.hProcess);
142 void CGitPropertyPage::Time64ToTimeString(__time64_t time, TCHAR * buf, size_t buflen)
144 struct tm newtime;
145 SYSTEMTIME systime;
146 TCHAR timebuf[MAX_STRING_LENGTH];
147 TCHAR datebuf[MAX_STRING_LENGTH];
149 LCID locale = (WORD)CRegStdDWORD(_T("Software\\TortoiseGit\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
150 locale = MAKELCID(locale, SORT_DEFAULT);
152 *buf = '\0';
153 if (time)
155 _localtime64_s(&newtime, &time);
157 systime.wDay = (WORD)newtime.tm_mday;
158 systime.wDayOfWeek = (WORD)newtime.tm_wday;
159 systime.wHour = (WORD)newtime.tm_hour;
160 systime.wMilliseconds = 0;
161 systime.wMinute = (WORD)newtime.tm_min;
162 systime.wMonth = (WORD)newtime.tm_mon+1;
163 systime.wSecond = (WORD)newtime.tm_sec;
164 systime.wYear = (WORD)newtime.tm_year+1900;
165 if (CRegStdDWORD(_T("Software\\TortoiseGit\\LogDateFormat")) == 1)
166 GetDateFormat(locale, DATE_SHORTDATE, &systime, NULL, datebuf, MAX_STRING_LENGTH);
167 else
168 GetDateFormat(locale, DATE_LONGDATE, &systime, NULL, datebuf, MAX_STRING_LENGTH);
169 GetTimeFormat(locale, 0, &systime, NULL, timebuf, MAX_STRING_LENGTH);
170 *buf = '\0';
171 _tcsncat_s(buf, buflen, timebuf, MAX_STRING_LENGTH-1);
172 _tcsncat_s(buf, buflen, _T(", "), MAX_STRING_LENGTH-1);
173 _tcsncat_s(buf, buflen, datebuf, MAX_STRING_LENGTH-1);
177 void CGitPropertyPage::InitWorkfileView()
179 CString username;
180 CGit git;
181 if( filenames.size() ==0)
182 return;
184 CTGitPath path(filenames.front().c_str());
185 CString ProjectTopDir;
187 if(!path.HasAdminDir(&ProjectTopDir))
188 return;
190 git.SetCurrentDir(ProjectTopDir);
191 //can't git.exe when create process
192 git.Run(_T("git.exe config user.name"),&username,CP_ACP);
193 CString useremail;
194 git.Run(_T("git.exe config user.email"),&useremail,CP_ACP);
195 CString autocrlf;
196 git.Run(_T("git.exe config core.autocrlf"),&autocrlf,CP_ACP);
197 CString safecrlf;
198 git.Run(_T("git.exe config core.safecrlf"),&safecrlf,CP_ACP);
200 CString branch;
201 CString headhash;
202 CString remotebranch;
204 git.Run(_T("git.exe symbolic-ref HEAD"),&branch,CP_ACP);
205 CString cmd,log;
207 if(!branch.IsEmpty())
209 if( branch.Find(_T("refs/heads/"),0) >=0 )
211 CString remote;
212 branch=branch.Mid(11);
213 int start=0;
214 branch=branch.Tokenize(_T("\n"),start);
215 start=0;
216 branch=branch.Tokenize(_T("\r"),start);
217 cmd.Format(_T("git.exe config branch.%s.merge"),branch);
218 git.Run(cmd,&remotebranch,CP_ACP);
219 cmd.Format(_T("git.exe config branch.%s.remote"),branch);
220 git.Run(cmd,&remote,CP_ACP);
221 if((!remote.IsEmpty()) && (!remotebranch.IsEmpty()))
223 remotebranch=remotebranch.Mid(11);
224 remotebranch=remote+_T("/")+remotebranch;
229 TCHAR oldpath[MAX_PATH+1];
231 ::GetCurrentDirectory(MAX_PATH, oldpath);
233 ::SetCurrentDirectory(ProjectTopDir);
235 GitRev rev;
237 if (autocrlf.Trim().IsEmpty())
238 autocrlf = _T("false");
239 if (safecrlf.Trim().IsEmpty())
240 safecrlf = _T("false");
242 SetDlgItemText(m_hwnd,IDC_CONFIG_USERNAME,username.Trim());
243 SetDlgItemText(m_hwnd,IDC_CONFIG_USEREMAIL,useremail.Trim());
244 SetDlgItemText(m_hwnd,IDC_CONFIG_AUTOCRLF,autocrlf.Trim());
245 SetDlgItemText(m_hwnd,IDC_CONFIG_SAFECRLF,safecrlf.Trim());
247 SetDlgItemText(m_hwnd,IDC_SHELL_CURRENT_BRANCH,branch.Trim());
248 remotebranch.Trim().Replace(_T("\n"), _T("; "));
249 SetDlgItemText(m_hwnd,IDC_SHELL_REMOTE_BRANCH, remotebranch);
253 AutoLocker lock(g_Git.m_critGitDllSec);
254 g_Git.CheckAndInitDll();
255 rev.GetCommit(CString(_T("HEAD")));
257 SetDlgItemText(m_hwnd,IDC_HEAD_HASH,rev.m_CommitHash.ToString());
258 SetDlgItemText(m_hwnd,IDC_HEAD_SUBJECT,rev.GetSubject());
259 SetDlgItemText(m_hwnd,IDC_HEAD_AUTHOR,rev.GetAuthorName());
260 SetDlgItemText(m_hwnd,IDC_HEAD_DATE,rev.GetAuthorDate().Format(_T("%Y-%m-%d %H:%M:%S")));
262 if (filenames.size() == 1)
264 CTGitPath path(filenames.front().c_str());
265 CTGitPath relatepath;
266 CString strpath=path.GetWinPathString();
267 CString ProjectTopDir;
269 if(!path.HasAdminDir(&ProjectTopDir))
270 return;
272 if(ProjectTopDir[ProjectTopDir.GetLength()-1] == _T('\\'))
274 relatepath.SetFromWin( strpath.Right(strpath.GetLength()-ProjectTopDir.GetLength()));
276 else
278 relatepath.SetFromWin( strpath.Right(strpath.GetLength()-ProjectTopDir.GetLength()-1));
282 if(! relatepath.GetGitPathString().IsEmpty())
284 cmd=_T("-z --topo-order -n1 --parents -- \"");
285 cmd+=relatepath.GetGitPathString();
286 cmd+=_T("\"");
288 GIT_LOG handle;
291 if(git_open_log(&handle, CUnicodeUtils::GetUTF8(cmd).GetBuffer()))
292 break;
293 if(git_get_log_firstcommit(handle))
294 break;
296 GIT_COMMIT commit;
297 if (git_get_log_nextcommit(handle, &commit, 0))
298 break;
300 git_close_log(handle);
301 handle = NULL;
302 rev.ParserFromCommit(&commit);
303 git_free_commit(&commit);
305 }while(0);
306 if (handle != NULL) {
307 git_close_log(handle);
311 SetDlgItemText(m_hwnd,IDC_LAST_HASH,rev.m_CommitHash.ToString());
312 SetDlgItemText(m_hwnd,IDC_LAST_SUBJECT,rev.GetSubject());
313 SetDlgItemText(m_hwnd,IDC_LAST_AUTHOR,rev.GetAuthorName());
314 SetDlgItemText(m_hwnd,IDC_LAST_DATE,rev.GetAuthorDate().Format(_T("%Y-%m-%d %H:%M:%S")));
317 }catch(...)
320 ::SetCurrentDirectory(oldpath);
325 // CShellExt member functions (needed for IShellPropSheetExt)
326 STDMETHODIMP CShellExt::AddPages (LPFNADDPROPSHEETPAGE lpfnAddPage,
327 LPARAM lParam)
330 CString ProjectTopDir;
332 for (std::vector<stdstring>::iterator I = files_.begin(); I != files_.end(); ++I)
335 GitStatus svn = GitStatus();
336 if (svn.GetStatus(CTGitPath(I->c_str())) == (-2))
337 return S_OK; // file/directory not under version control
339 if (svn.status->entry == NULL)
340 return S_OK;
342 if( CTGitPath(I->c_str()).HasAdminDir(&ProjectTopDir))
343 break;
344 else
345 return S_OK;
348 if (files_.size() == 0)
349 return S_OK;
351 LoadLangDll();
352 PROPSHEETPAGE psp;
353 SecureZeroMemory(&psp, sizeof(PROPSHEETPAGE));
354 HPROPSHEETPAGE hPage;
355 CGitPropertyPage *sheetpage = new CGitPropertyPage(files_);
357 psp.dwSize = sizeof (psp);
358 psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USEICONID | PSP_USECALLBACK;
359 psp.hInstance = g_hResInst;
360 psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE);
361 psp.pszIcon = MAKEINTRESOURCE(IDI_APPSMALL);
362 psp.pszTitle = _T("Git");
363 psp.pfnDlgProc = (DLGPROC) PageProc;
364 psp.lParam = (LPARAM) sheetpage;
365 psp.pfnCallback = PropPageCallbackProc;
366 psp.pcRefParent = &g_cRefThisDll;
368 hPage = CreatePropertySheetPage (&psp);
370 if (hPage != NULL)
372 if (!lpfnAddPage (hPage, lParam))
374 delete sheetpage;
375 DestroyPropertySheetPage (hPage);
379 return S_OK;
382 STDMETHODIMP CShellExt::ReplacePage (UINT /*uPageID*/, LPFNADDPROPSHEETPAGE /*lpfnReplaceWith*/, LPARAM /*lParam*/)
384 return E_FAIL;