Do not quit TortoiseGitProc after running Bisect Start from log list
[TortoiseGit.git] / src / TortoiseProc / TortoiseProc.cpp
blobc67795cd06ea8bd5be8e3bb4f9ea51731a49908f
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2014 - TortoiseGit
4 // Copyright (C) 2003-2008, 2012-2014 - TortoiseSVN
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"
21 #include "TortoiseProc.h"
22 #include "SysImageList.h"
23 #include "..\Utils\CrashReport.h"
24 #include "CmdLineParser.h"
25 #include "Hooks.h"
26 #include "AppUtils.h"
27 #include "PathUtils.h"
28 #include "StringUtils.h"
29 #include "UnicodeUtils.h"
30 #include "MessageBox.h"
31 #include "DirFileEnum.h"
32 #include "GitAdminDir.h"
33 #include "Git.h"
34 #include "SmartHandle.h"
35 #include "Commands\Command.h"
36 #include "..\version.h"
37 #include "JumpListHelpers.h"
38 #include "SinglePropSheetDlg.h"
39 #include "Settings\setmainpage.h"
40 #include "Libraries.h"
41 #include "TaskbarUUID.h"
42 #include "ProjectProperties.h"
43 #include "HistoryCombo.h"
44 #include <math.h>
46 #define STRUCT_IOVEC_DEFINED
48 #ifdef _DEBUG
49 #define new DEBUG_NEW
50 #endif
52 #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
54 BEGIN_MESSAGE_MAP(CTortoiseProcApp, CWinAppEx)
55 ON_COMMAND(ID_HELP, CWinAppEx::OnHelp)
56 END_MESSAGE_MAP()
58 //////////////////////////////////////////////////////////////////////////
60 CTortoiseProcApp::CTortoiseProcApp()
62 SetDllDirectory(L"");
63 // prevent from inheriting %GIT_DIR% from parent process by resetting it,
64 // use MSVC function instead of Windows API because MSVC runtime caches environment variables
65 _tputenv(_T("GIT_DIR="));
66 CCrashReport::Instance().AddUserInfoToReport(L"CommandLine", GetCommandLine());
67 EnableHtmlHelp();
68 SYS_IMAGE_LIST();
69 CHooks::Create();
70 m_bLoadUserToolbars = FALSE;
71 m_bSaveState = FALSE;
72 retSuccess = false;
73 m_gdiplusToken = NULL;
74 #if defined (_WIN64) && _MSC_VER >= 1800
75 _set_FMA3_enable(0);
76 #endif
79 CTortoiseProcApp::~CTortoiseProcApp()
81 CHooks::Destroy();
82 SYS_IMAGE_LIST().Cleanup();
85 // The one and only CTortoiseProcApp object
86 CTortoiseProcApp theApp;
87 CString sOrigCWD;
88 CString g_sGroupingUUID;
89 CString g_sGroupingIcon;
90 bool g_bGroupingRemoveIcon = false;
91 HWND hWndExplorer;
93 #if ENABLE_CRASHHANLDER
94 CCrashReportTGit crasher(L"TortoiseGit " _T(APP_X64_STRING), TGIT_VERMAJOR, TGIT_VERMINOR, TGIT_VERMICRO, TGIT_VERBUILD, TGIT_VERDATE);
95 #endif
97 // CTortoiseProcApp initialization
99 BOOL CTortoiseProcApp::InitInstance()
101 CheckUpgrade();
102 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
103 CMFCButton::EnableWindowsTheming();
104 CHistoryCombo::m_nGitIconIndex = SYS_IMAGE_LIST().AddIcon((HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_GITCONFIG), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
106 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
107 Gdiplus::GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL);
109 //set the resource dll for the required language
110 CRegDWORD loc = CRegDWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);
111 long langId = loc;
113 CString langStr;
114 langStr.Format(_T("%ld"), langId);
115 CCrashReport::Instance().AddUserInfoToReport(L"LanguageID", langStr);
117 CString langDll;
118 CStringA langpath = CStringA(CPathUtils::GetAppParentDirectory());
119 langpath += "Languages";
120 HINSTANCE hInst = NULL;
123 langDll.Format(_T("%sLanguages\\TortoiseProc%ld.dll"), (LPCTSTR)CPathUtils::GetAppParentDirectory(), langId);
125 hInst = LoadLibrary(langDll);
127 CString sVer = _T(STRPRODUCTVER);
128 CString sFileVer = CPathUtils::GetVersionFromFile(langDll);
129 if (sFileVer.Compare(sVer)!=0)
131 FreeLibrary(hInst);
132 hInst = NULL;
134 if (hInst != NULL)
136 AfxSetResourceHandle(hInst);
138 else
140 DWORD lid = SUBLANGID(langId);
141 lid--;
142 if (lid > 0)
144 langId = MAKELANGID(PRIMARYLANGID(langId), lid);
146 else
147 langId = 0;
149 } while ((hInst == NULL) && (langId != 0));
150 TCHAR buf[6] = { 0 };
151 _tcscpy_s(buf, _T("en"));
152 langId = loc;
153 // MFC uses a help file with the same name as the application by default,
154 // which means we have to change that default to our language specific help files
155 CString sHelppath = CPathUtils::GetAppDirectory() + _T("TortoiseGit_en.chm");
156 free((void*)m_pszHelpFilePath);
157 m_pszHelpFilePath=_tcsdup(sHelppath);
158 sHelppath = CPathUtils::GetAppParentDirectory() + _T("Languages\\TortoiseGit_en.chm");
161 CString sLang = _T("_");
162 if (GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO639LANGNAME, buf, _countof(buf)))
164 sLang += buf;
165 sHelppath.Replace(_T("_en"), sLang);
166 if (PathFileExists(sHelppath))
168 free((void*)m_pszHelpFilePath);
169 m_pszHelpFilePath=_tcsdup(sHelppath);
170 break;
173 sHelppath.Replace(sLang, _T("_en"));
174 if (GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO3166CTRYNAME, buf, _countof(buf)))
176 sLang += _T("_");
177 sLang += buf;
178 sHelppath.Replace(_T("_en"), sLang);
179 if (PathFileExists(sHelppath))
181 free((void*)m_pszHelpFilePath);
182 m_pszHelpFilePath=_tcsdup(sHelppath);
183 break;
186 sHelppath.Replace(sLang, _T("_en"));
188 DWORD lid = SUBLANGID(langId);
189 lid--;
190 if (lid > 0)
192 langId = MAKELANGID(PRIMARYLANGID(langId), lid);
194 else
195 langId = 0;
196 } while (langId);
197 setlocale(LC_ALL, "");
199 if (!g_Git.CheckMsysGitDir())
201 UINT ret = CMessageBox::Show(NULL, IDS_PROC_NOMSYSGIT, IDS_APPNAME, 3, IDI_HAND, IDS_PROC_SETMSYSGITPATH, IDS_PROC_GOTOMSYSGITWEBSITE, IDS_ABORTBUTTON);
202 if(ret == 2)
204 ShellExecute(NULL, NULL, _T("http://msysgit.github.io/"), NULL, NULL, SW_SHOW);
206 else if(ret == 1)
208 // open settings dialog
209 CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROC_SETTINGS_TITLE)), new CSetMainPage(), this->GetMainWnd()).DoModal();
211 return FALSE;
213 if (CAppUtils::GetMsysgitVersion() < 0x01070a00)
215 int ret = CMessageBox::ShowCheck(NULL, IDS_PROC_OLDMSYSGIT, IDS_APPNAME, 1, IDI_EXCLAMATION, IDS_PROC_GOTOMSYSGITWEBSITE, IDS_ABORTBUTTON, IDS_IGNOREBUTTON, _T("OldMsysgitVersionWarning"), IDS_PROC_NOTSHOWAGAINIGNORE);
216 if (ret == 1)
218 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore"
219 ShellExecute(NULL, NULL, _T("http://msysgit.github.io/"), NULL, NULL, SW_SHOW);
220 return FALSE;
222 else if (ret == 2)
224 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore"
225 return FALSE;
230 CCrashReport::Instance().AddUserInfoToReport(L"msysGitDir", CGit::ms_LastMsysGitDir);
231 CString versionString;
232 versionString.Format(_T("%d"), CGit::ms_LastMsysGitVersion);
233 CCrashReport::Instance().AddUserInfoToReport(L"msysGitVersion", versionString);
236 // InitCommonControls() is required on Windows XP if an application
237 // manifest specifies use of ComCtl32.dll version 6 or later to enable
238 // visual styles. Otherwise, any window creation will fail.
240 INITCOMMONCONTROLSEX used = {
241 sizeof(INITCOMMONCONTROLSEX),
242 ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES | ICC_DATE_CLASSES |
243 ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES | ICC_LISTVIEW_CLASSES |
244 ICC_NATIVEFNTCTL_CLASS | ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS |
245 ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS |
246 ICC_USEREX_CLASSES | ICC_WIN95_CLASSES
248 InitCommonControlsEx(&used);
249 AfxOleInit();
250 AfxEnableControlContainer();
251 AfxInitRichEdit5();
252 CWinAppEx::InitInstance();
253 SetRegistryKey(_T("TortoiseGit"));
254 AfxGetApp()->m_pszProfileName = _tcsdup(_T("TortoiseProc")); // w/o this ResizableLib will store data under TortoiseGitProc which is not compatible with older versions
256 CCmdLineParser parser(AfxGetApp()->m_lpCmdLine);
258 hWndExplorer = NULL;
259 CString sVal = parser.GetVal(_T("hwnd"));
260 if (!sVal.IsEmpty())
261 hWndExplorer = (HWND)_wcstoui64(sVal, nullptr, 16);
263 while (GetParent(hWndExplorer)!=NULL)
264 hWndExplorer = GetParent(hWndExplorer);
265 if (!IsWindow(hWndExplorer))
267 hWndExplorer = NULL;
270 // if HKCU\Software\TortoiseGit\Debug is not 0, show our command line
271 // in a message box
272 if (CRegDWORD(_T("Software\\TortoiseGit\\Debug"), FALSE)==TRUE)
273 AfxMessageBox(AfxGetApp()->m_lpCmdLine, MB_OK | MB_ICONINFORMATION);
275 if (parser.HasKey(_T("urlhandler")))
277 CString url = parser.GetVal(_T("urlhandler"));
278 if (url.Find(_T("tgit://clone/")) == 0)
280 url = url.Mid(13); // 21 = "tgit://clone/".GetLength()
282 else if (url.Find(_T("github-windows://openRepo/")) == 0)
284 url = url.Mid(26); // 26 = "github-windows://openRepo/".GetLength()
285 int questioMark = url.Find('?');
286 if (questioMark > 0)
287 url = url.Left(questioMark);
289 else if (url.Find(_T("smartgit://cloneRepo/")) == 0)
291 url = url.Mid(21); // 21 = "smartgit://cloneRepo/".GetLength()
293 else
295 CMessageBox::Show(NULL, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR);
296 return FALSE;
298 CString newCmd;
299 newCmd.Format(_T("/command:clone /url:\"%s\" /hasurlhandler"), url);
300 parser = CCmdLineParser(newCmd);
303 if ( parser.HasKey(_T("path")) && parser.HasKey(_T("pathfile")))
305 CMessageBox::Show(NULL, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR);
306 return FALSE;
309 CTGitPath cmdLinePath;
310 CTGitPathList pathList;
311 if (g_sGroupingUUID.IsEmpty())
312 g_sGroupingUUID = parser.GetVal(L"groupuuid");
313 if ( parser.HasKey(_T("pathfile")) )
316 CString sPathfileArgument = CPathUtils::GetLongPathname(parser.GetVal(_T("pathfile")));
318 cmdLinePath.SetFromUnknown(sPathfileArgument);
319 if (pathList.LoadFromFile(cmdLinePath)==false)
320 return FALSE; // no path specified!
321 if ( parser.HasKey(_T("deletepathfile")) )
323 // We can delete the temporary path file, now that we've loaded it
324 ::DeleteFile(cmdLinePath.GetWinPath());
326 // This was a path to a temporary file - it's got no meaning now, and
327 // anybody who uses it again is in for a problem...
328 cmdLinePath.Reset();
331 else
334 CString sPathArgument = CPathUtils::GetLongPathname(parser.GetVal(_T("path")));
335 if (parser.HasKey(_T("expaths")))
337 // an /expaths param means we're started via the buttons in our Win7 library
338 // and that means the value of /expaths is the current directory, and
339 // the selected paths are then added as additional parameters but without a key, only a value
341 // because of the "strange treatment of quotation marks and backslashes by CommandLineToArgvW"
342 // we have to escape the backslashes first. Since we're only dealing with paths here, that's
343 // a save bet.
344 // Without this, a command line like:
345 // /command:commit /expaths:"D:\" "D:\Utils"
346 // would fail because the "D:\" is treated as the backslash being the escape char for the quotation
347 // mark and we'd end up with:
348 // argv[1] = /command:commit
349 // argv[2] = /expaths:D:" D:\Utils
350 // See here for more details: http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
351 CString cmdLine = GetCommandLineW();
352 cmdLine.Replace(L"\\", L"\\\\");
353 int nArgs = 0;
354 LPWSTR *szArglist = CommandLineToArgvW(cmdLine, &nArgs);
355 if (szArglist)
357 // argument 0 is the process path, so start with 1
358 for (int i = 1; i < nArgs; ++i)
360 if (szArglist[i][0] != '/')
362 if (!sPathArgument.IsEmpty())
363 sPathArgument += '*';
364 sPathArgument += szArglist[i];
367 sPathArgument.Replace(L"\\\\", L"\\");
369 LocalFree(szArglist);
371 if (sPathArgument.IsEmpty() && parser.HasKey(L"path"))
373 CMessageBox::Show(hWndExplorer, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR);
374 return FALSE;
376 int asterisk = sPathArgument.Find('*');
377 cmdLinePath.SetFromUnknown(asterisk >= 0 ? sPathArgument.Left(asterisk) : sPathArgument);
378 pathList.LoadFromAsteriskSeparatedString(sPathArgument);
381 if (pathList.IsEmpty()) {
382 pathList.AddPath(CTGitPath::CTGitPath(g_Git.m_CurrentDir));
385 // Set CWD to temporary dir, and restore it later
387 DWORD len = GetCurrentDirectory(0, NULL);
388 if (len)
390 std::unique_ptr<TCHAR[]> originalCurrentDirectory(new TCHAR[len]);
391 if (GetCurrentDirectory(len, originalCurrentDirectory.get()))
393 sOrigCWD = originalCurrentDirectory.get();
394 sOrigCWD = CPathUtils::GetLongPathname(sOrigCWD);
397 TCHAR pathbuf[MAX_PATH] = {0};
398 GetTortoiseGitTempPath(MAX_PATH, pathbuf);
399 SetCurrentDirectory(pathbuf);
402 CheckForNewerVersion();
404 CAutoGeneralHandle TGitMutex = ::CreateMutex(NULL, FALSE, _T("TortoiseGitProc.exe"));
405 if (!g_Git.SetCurrentDir(cmdLinePath.GetWinPathString(), parser.HasKey(_T("submodule")) == TRUE))
407 for (int i = 0; i < pathList.GetCount(); ++i)
408 if(g_Git.SetCurrentDir(pathList[i].GetWinPath()))
409 break;
412 if(!g_Git.m_CurrentDir.IsEmpty())
414 sOrigCWD = g_Git.m_CurrentDir;
415 SetCurrentDirectory(g_Git.m_CurrentDir);
418 if (g_sGroupingUUID.IsEmpty())
420 CRegStdDWORD groupSetting = CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepo"), 3);
421 switch (DWORD(groupSetting))
423 case 1:
424 case 2:
425 // implemented differently to TortoiseSVN atm
426 break;
427 case 3:
428 case 4:
430 CString wcroot;
431 if (g_GitAdminDir.HasAdminDir(g_Git.m_CurrentDir, true, &wcroot))
433 git_oid oid;
434 CStringA wcRootA(wcroot + CPathUtils::GetAppDirectory());
435 if (!git_odb_hash(&oid, wcRootA, wcRootA.GetLength(), GIT_OBJ_BLOB))
437 CStringA hash;
438 git_oid_tostr(hash.GetBufferSetLength(GIT_OID_HEXSZ + 1), GIT_OID_HEXSZ + 1, &oid);
439 hash.ReleaseBuffer();
440 g_sGroupingUUID = hash;
442 ProjectProperties pp;
443 pp.ReadProps();
444 CString icon = pp.sIcon;
445 icon.Replace('/', '\\');
446 if (icon.IsEmpty())
447 g_bGroupingRemoveIcon = true;
448 g_sGroupingIcon = icon;
454 CString sAppID = GetTaskIDPerUUID(g_sGroupingUUID).c_str();
455 InitializeJumpList(sAppID);
456 EnsureGitLibrary(false);
459 CString err;
462 // requires CWD to be set
463 CGit::m_LogEncode = CAppUtils::GetLogOutputEncode();
465 // make sure all config files are read in order to check that none contains an error
466 g_Git.GetConfigValue(_T("doesnot.exist"));
468 catch (char* msg)
470 err = CString(msg);
473 if (!err.IsEmpty())
475 UINT choice = CMessageBox::Show(hWndExplorer, err, _T("TortoiseGit"), 1, IDI_ERROR, CString(MAKEINTRESOURCE(IDS_PROC_EDITLOCALGITCONFIG)), CString(MAKEINTRESOURCE(IDS_PROC_EDITGLOBALGITCONFIG)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON)));
476 if (choice == 1)
478 // open the config file with alternative editor
479 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitLocalConfig());
481 else if (choice == 2)
483 // open the global config file with alternative editor
484 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitGlobalConfig());
486 return FALSE;
490 // execute the requested command
491 CommandServer server;
492 Command * cmd = server.GetCommand(parser.GetVal(_T("command")));
493 if (cmd)
495 cmd->SetExplorerHwnd(hWndExplorer);
497 cmd->SetParser(parser);
498 cmd->SetPaths(pathList, cmdLinePath);
500 retSuccess = cmd->Execute();
501 delete cmd;
504 // Look for temporary files left around by TortoiseSVN and
505 // remove them. But only delete 'old' files because some
506 // apps might still be needing the recent ones.
508 DWORD len = GetTortoiseGitTempPath(0, NULL);
509 std::unique_ptr<TCHAR[]> path(new TCHAR[len + 100]);
510 len = GetTortoiseGitTempPath (len + 100, path.get());
511 if (len != 0)
513 CDirFileEnum finder(path.get());
514 FILETIME systime_;
515 ::GetSystemTimeAsFileTime(&systime_);
516 __int64 systime = (((_int64)systime_.dwHighDateTime)<<32) | ((__int64)systime_.dwLowDateTime);
517 bool isDir;
518 CString filepath;
519 while (finder.NextFile(filepath, &isDir))
521 HANDLE hFile = ::CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, isDir ? FILE_FLAG_BACKUP_SEMANTICS : NULL, NULL);
522 if (hFile != INVALID_HANDLE_VALUE)
524 FILETIME createtime_;
525 if (::GetFileTime(hFile, &createtime_, NULL, NULL))
527 ::CloseHandle(hFile);
528 __int64 createtime = (((_int64)createtime_.dwHighDateTime)<<32) | ((__int64)createtime_.dwLowDateTime);
529 if ((createtime + 864000000000) < systime) //only delete files older than a day
531 ::SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL);
532 if (isDir)
533 ::RemoveDirectory(filepath);
534 else
535 ::DeleteFile(filepath);
538 else
539 ::CloseHandle(hFile);
545 // Since the dialog has been closed, return FALSE so that we exit the
546 // application, rather than start the application's message pump.
547 return FALSE;
550 void CTortoiseProcApp::CheckUpgrade()
552 CRegString regVersion = CRegString(_T("Software\\TortoiseGit\\CurrentVersion"));
553 CString sVersion = regVersion;
554 if (sVersion.Compare(_T(STRPRODUCTVER))==0)
555 return;
556 // we're starting the first time with a new version!
558 LONG lVersion = 0;
559 int pos = sVersion.Find('.');
560 if (pos > 0)
562 lVersion = (_ttol(sVersion.Left(pos))<<24);
563 lVersion |= (_ttol(sVersion.Mid(pos+1))<<16);
564 pos = sVersion.Find('.', pos+1);
565 lVersion |= (_ttol(sVersion.Mid(pos+1))<<8);
567 else
569 pos = sVersion.Find(',');
570 if (pos > 0)
572 lVersion = (_ttol(sVersion.Left(pos))<<24);
573 lVersion |= (_ttol(sVersion.Mid(pos+1))<<16);
574 pos = sVersion.Find(',', pos+1);
575 lVersion |= (_ttol(sVersion.Mid(pos+1))<<8);
579 // generic cleanup
580 if (CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2"), TRUE) != TRUE)
582 if (CMessageBox::Show(nullptr, _T("You have disabled the usage of libgit2 in TortoiseGit.\n\nThis might be the case in order to resolve an issue in an older TortoiseGit version.\n\nDo you want to restore the default value (i.e., enable it)?"), _T("TortoiseGit"), MB_ICONQUESTION | MB_YESNO) == IDYES)
583 CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2")).removeValue();
586 if (CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2_mask")).exists())
588 if (CMessageBox::Show(nullptr, _T("You have a non-default setting of UseLibgit2_mask in your registry.\n\nThis might be the case in order to resolve an issue in an older TortoiseGit version.\n\nDo you want to restore the default value (i.e., remove custom setting from registry)?"), _T("TortoiseGit"), MB_ICONQUESTION | MB_YESNO) == IDYES)
589 CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2_mask")).removeValue();
592 // version specific updates
593 if (lVersion <= 0x01080802)
595 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\CleanTypeDlgWindowPlacement")).removeValue();
598 if (lVersion <= 0x01080801)
600 CRegStdDWORD(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs")).removeValue();
601 CRegStdString(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Order")).removeValue();
602 CRegStdString(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Width")).removeValue();
605 if (lVersion <= 0x01080401)
607 if (CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI"), FALSE) == TRUE)
608 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\DeliveryType")) = 1;
609 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI")).removeValue();
612 if (lVersion <= 0x01080202)
614 // upgrade to 1.8.3: force recreation of all diff scripts.
615 CAppUtils::SetupDiffScripts(true, CString());
618 if (lVersion <= 0x01080100)
620 if (CRegStdDWORD(_T("Software\\TortoiseGit\\LogTopoOrder"), TRUE) == FALSE)
621 CRegStdDWORD(_T("Software\\TortoiseGit\\LogOrderBy")) = 0;
623 // smoothly migrate broken msysgit path settings
624 CString oldmsysGitSetting = CRegString(REG_MSYSGIT_PATH);
625 oldmsysGitSetting.TrimRight(_T("\\"));
626 CString right = oldmsysGitSetting.Right(4);
627 if (oldmsysGitSetting.GetLength() > 4 && oldmsysGitSetting.Right(4) == _T("\\cmd"))
629 CString newPath = oldmsysGitSetting.Mid(0, oldmsysGitSetting.GetLength() - 3) + _T("bin");
630 if (PathFileExists(newPath + _T("\\git.exe")))
632 CRegString(REG_MSYSGIT_PATH) = newPath;
633 g_Git.m_bInitialized = FALSE;
634 g_Git.CheckMsysGitDir();
639 if (lVersion <= 0x01040000)
641 CRegStdDWORD(_T("Software\\TortoiseGit\\OwnerdrawnMenus")).removeValue();
644 if (lVersion <= 0x01070600)
646 CoInitialize(NULL);
647 EnsureGitLibrary();
648 CoUninitialize();
649 CRegStdDWORD(_T("Software\\TortoiseGit\\ConvertBase")).removeValue();
650 CRegStdDWORD(_T("Software\\TortoiseGit\\DiffProps")).removeValue();
651 if (CRegStdDWORD(_T("Software\\TortoiseGit\\CheckNewer"), TRUE) == FALSE)
652 CRegStdDWORD(_T("Software\\TortoiseGit\\VersionCheck")) = FALSE;
653 CRegStdDWORD(_T("Software\\TortoiseGit\\CheckNewer")).removeValue();
656 CAppUtils::SetupDiffScripts(false, CString());
658 // set the current version so we don't come here again until the next update!
659 regVersion = _T(STRPRODUCTVER);
662 void CTortoiseProcApp::InitializeJumpList(const CString& appid)
664 // for Win7 : use a custom jump list
665 CoInitialize(NULL);
666 SetAppID(appid);
667 DeleteJumpList(appid);
668 DoInitializeJumpList(appid);
669 CoUninitialize();
672 void CTortoiseProcApp::DoInitializeJumpList(const CString& appid)
674 ATL::CComPtr<ICustomDestinationList> pcdl;
675 HRESULT hr = pcdl.CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER);
676 if (FAILED(hr))
677 return;
679 hr = pcdl->SetAppID(appid);
680 if (FAILED(hr))
681 return;
683 UINT uMaxSlots;
684 ATL::CComPtr<IObjectArray> poaRemoved;
685 hr = pcdl->BeginList(&uMaxSlots, IID_PPV_ARGS(&poaRemoved));
686 if (FAILED(hr))
687 return;
689 ATL::CComPtr<IObjectCollection> poc;
690 hr = poc.CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER);
691 if (FAILED(hr))
692 return;
694 CString sTemp = CString(MAKEINTRESOURCE(IDS_MENUSETTINGS));
695 CStringUtils::RemoveAccelerators(sTemp);
697 ATL::CComPtr<IShellLink> psl;
698 hr = CreateShellLink(_T("/command:settings"), (LPCTSTR)sTemp, 20, &psl);
699 if (SUCCEEDED(hr)) {
700 poc->AddObject(psl);
702 sTemp = CString(MAKEINTRESOURCE(IDS_MENUHELP));
703 CStringUtils::RemoveAccelerators(sTemp);
704 psl.Release(); // Need to release the object before calling operator&()
705 hr = CreateShellLink(_T("/command:help"), (LPCTSTR)sTemp, 19, &psl);
706 if (SUCCEEDED(hr)) {
707 poc->AddObject(psl);
710 ATL::CComPtr<IObjectArray> poa;
711 hr = poc.QueryInterface(&poa);
712 if (SUCCEEDED(hr)) {
713 pcdl->AppendCategory((LPCTSTR)CString(MAKEINTRESOURCE(IDS_PROC_TASKS)), poa);
714 pcdl->CommitList();
718 int CTortoiseProcApp::ExitInstance()
720 Gdiplus::GdiplusShutdown(m_gdiplusToken);
722 CWinAppEx::ExitInstance();
723 if (retSuccess)
724 return 0;
725 return -1;
728 void CTortoiseProcApp::CheckForNewerVersion()
730 // check for newer versions
731 if (CRegDWORD(_T("Software\\TortoiseGit\\VersionCheck"), TRUE) != FALSE)
733 time_t now;
734 struct tm ptm;
736 time(&now);
737 if ((now != 0) && (localtime_s(&ptm, &now)==0))
739 #if PREVIEW
740 // Check daily for new preview releases
741 CRegDWORD oldday = CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerDay"), (DWORD)-1);
742 if (((DWORD)oldday) == -1)
743 oldday = ptm.tm_yday;
744 else
746 if ((DWORD)oldday != (DWORD)ptm.tm_yday)
748 oldday = ptm.tm_yday;
749 #else
750 int week = 0;
751 // we don't calculate the real 'week of the year' here
752 // because just to decide if we should check for an update
753 // that's not needed.
754 week = ptm.tm_yday / 7;
756 CRegDWORD oldweek = CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeek"), (DWORD)-1);
757 if (((DWORD)oldweek) == -1)
758 oldweek = week; // first start of TortoiseProc, no update check needed
759 else
761 if ((DWORD)week != oldweek)
763 oldweek = week;
764 #endif
765 CAppUtils::RunTortoiseGitProc(_T("/command:updatecheck"), false, false);