Replace msysgit.github.io with git-for-windows.github.io
[TortoiseGit.git] / src / TortoiseProc / TortoiseProc.cpp
blob3444621ce8ceca6bc84513b25ad435dbc215dde6
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2015 - 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 "gitindex.h"
45 #include <math.h>
46 #include "SendMail.h"
48 #define STRUCT_IOVEC_DEFINED
50 #ifdef _DEBUG
51 #define new DEBUG_NEW
52 #endif
54 #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
56 BEGIN_MESSAGE_MAP(CTortoiseProcApp, CWinAppEx)
57 ON_COMMAND(ID_HELP, CWinAppEx::OnHelp)
58 END_MESSAGE_MAP()
60 //////////////////////////////////////////////////////////////////////////
62 CTortoiseProcApp::CTortoiseProcApp()
64 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Constructor\n"));
65 SetDllDirectory(L"");
66 // prevent from inheriting %GIT_DIR% from parent process by resetting it,
67 // use MSVC function instead of Windows API because MSVC runtime caches environment variables
68 _tputenv(_T("GIT_DIR="));
69 CCrashReport::Instance().AddUserInfoToReport(L"CommandLine", GetCommandLine());
70 EnableHtmlHelp();
71 SYS_IMAGE_LIST();
72 CHooks::Create();
73 git_libgit2_init();
74 CGit::SetGit2CredentialCallback(CAppUtils::Git2GetUserPassword);
75 CGit::SetGit2CertificateCheckCertificate(CAppUtils::Git2CertificateCheck);
76 m_bLoadUserToolbars = FALSE;
77 m_bSaveState = FALSE;
78 retSuccess = false;
79 m_gdiplusToken = NULL;
80 #if defined (_WIN64) && _MSC_VER >= 1800
81 _set_FMA3_enable(0);
82 #endif
85 CTortoiseProcApp::~CTortoiseProcApp()
87 CHooks::Destroy();
88 SYS_IMAGE_LIST().Cleanup();
89 git_libgit2_shutdown();
92 // The one and only CTortoiseProcApp object
93 CTortoiseProcApp theApp;
94 CString sOrigCWD;
95 CString g_sGroupingUUID;
96 CString g_sGroupingIcon;
97 bool g_bGroupingRemoveIcon = false;
98 HWND hWndExplorer;
99 CGitIndexFileMap g_IndexFileMap;
101 #if ENABLE_CRASHHANLDER
102 CCrashReportTGit crasher(L"TortoiseGit " _T(APP_X64_STRING), TGIT_VERMAJOR, TGIT_VERMINOR, TGIT_VERMICRO, TGIT_VERBUILD, TGIT_VERDATE);
103 #endif
105 // CTortoiseProcApp initialization
107 BOOL CTortoiseProcApp::InitInstance()
109 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": InitInstance\n"));
110 CheckUpgrade();
111 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
112 CMFCButton::EnableWindowsTheming();
113 CHistoryCombo::m_nGitIconIndex = SYS_IMAGE_LIST().AddIcon((HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_GITCONFIG), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
115 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
116 Gdiplus::GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL);
118 //set the resource dll for the required language
119 CRegDWORD loc = CRegDWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);
120 long langId = loc;
122 CString langStr;
123 langStr.Format(_T("%ld"), langId);
124 CCrashReport::Instance().AddUserInfoToReport(L"LanguageID", langStr);
126 CString langDll;
127 CStringA langpath = CStringA(CPathUtils::GetAppParentDirectory());
128 langpath += "Languages";
131 langDll.Format(_T("%sLanguages\\TortoiseProc%ld.dll"), (LPCTSTR)CPathUtils::GetAppParentDirectory(), langId);
133 CString sVer = _T(STRPRODUCTVER);
134 CString sFileVer = CPathUtils::GetVersionFromFile(langDll);
135 if (sFileVer == sVer)
137 HINSTANCE hInst = LoadLibrary(langDll);
138 if (hInst != NULL)
140 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Load Language DLL %s\n"), langDll);
141 AfxSetResourceHandle(hInst);
142 break;
146 DWORD lid = SUBLANGID(langId);
147 lid--;
148 if (lid > 0)
150 langId = MAKELANGID(PRIMARYLANGID(langId), lid);
152 else
153 langId = 0;
155 } while (langId != 0);
156 TCHAR buf[6] = { 0 };
157 _tcscpy_s(buf, _T("en"));
158 langId = loc;
159 // MFC uses a help file with the same name as the application by default,
160 // which means we have to change that default to our language specific help files
161 CString sHelppath = CPathUtils::GetAppDirectory() + _T("TortoiseGit_en.chm");
162 free((void*)m_pszHelpFilePath);
163 m_pszHelpFilePath=_tcsdup(sHelppath);
164 sHelppath = CPathUtils::GetAppParentDirectory() + _T("Languages\\TortoiseGit_en.chm");
167 CString sLang = _T("_");
168 if (GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO639LANGNAME, buf, _countof(buf)))
170 sLang += buf;
171 sHelppath.Replace(_T("_en"), sLang);
172 if (PathFileExists(sHelppath))
174 free((void*)m_pszHelpFilePath);
175 m_pszHelpFilePath=_tcsdup(sHelppath);
176 break;
179 sHelppath.Replace(sLang, _T("_en"));
180 if (GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO3166CTRYNAME, buf, _countof(buf)))
182 sLang += _T("_");
183 sLang += buf;
184 sHelppath.Replace(_T("_en"), sLang);
185 if (PathFileExists(sHelppath))
187 free((void*)m_pszHelpFilePath);
188 m_pszHelpFilePath=_tcsdup(sHelppath);
189 break;
192 sHelppath.Replace(sLang, _T("_en"));
194 DWORD lid = SUBLANGID(langId);
195 lid--;
196 if (lid > 0)
198 langId = MAKELANGID(PRIMARYLANGID(langId), lid);
200 else
201 langId = 0;
202 } while (langId);
203 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Set Help Filename %s\n"), m_pszHelpFilePath);
204 setlocale(LC_ALL, "");
206 if (!g_Git.CheckMsysGitDir())
208 UINT ret = CMessageBox::Show(NULL, IDS_PROC_NOMSYSGIT, IDS_APPNAME, 3, IDI_HAND, IDS_PROC_SETMSYSGITPATH, IDS_PROC_GOTOMSYSGITWEBSITE, IDS_ABORTBUTTON);
209 if(ret == 2)
211 ShellExecute(nullptr, _T("open"), _T("https://git-for-windows.github.io/"), nullptr, nullptr, SW_SHOW);
213 else if(ret == 1)
215 // open settings dialog
216 CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROC_SETTINGS_TITLE)), new CSetMainPage(), this->GetMainWnd()).DoModal();
218 return FALSE;
220 if (CAppUtils::GetMsysgitVersion() < 0x01090500)
222 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);
223 if (ret == 1)
225 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore"
226 ShellExecute(nullptr, _T("open"), _T("https://git-for-windows.github.io/"), nullptr, nullptr, SW_SHOW);
227 return FALSE;
229 else if (ret == 2)
231 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore"
232 return FALSE;
237 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Registering Crash Report ...\n"));
238 CCrashReport::Instance().AddUserInfoToReport(L"msysGitDir", CGit::ms_LastMsysGitDir);
239 CString versionString;
240 versionString.Format(_T("%d"), CGit::ms_LastMsysGitVersion);
241 CCrashReport::Instance().AddUserInfoToReport(L"msysGitVersion", versionString);
244 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Initializing UI components ...\n"));
245 // InitCommonControls() is required on Windows XP if an application
246 // manifest specifies use of ComCtl32.dll version 6 or later to enable
247 // visual styles. Otherwise, any window creation will fail.
249 INITCOMMONCONTROLSEX used = {
250 sizeof(INITCOMMONCONTROLSEX),
251 ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES | ICC_DATE_CLASSES |
252 ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES | ICC_LISTVIEW_CLASSES |
253 ICC_NATIVEFNTCTL_CLASS | ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS |
254 ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS |
255 ICC_USEREX_CLASSES | ICC_WIN95_CLASSES
257 InitCommonControlsEx(&used);
258 AfxOleInit();
259 AfxEnableControlContainer();
260 AfxInitRichEdit5();
261 CWinAppEx::InitInstance();
262 SetRegistryKey(_T("TortoiseGit"));
263 AfxGetApp()->m_pszProfileName = _tcsdup(_T("TortoiseProc")); // w/o this ResizableLib will store data under TortoiseGitProc which is not compatible with older versions
265 CCmdLineParser parser(AfxGetApp()->m_lpCmdLine);
267 hWndExplorer = NULL;
268 CString sVal = parser.GetVal(_T("hwnd"));
269 if (!sVal.IsEmpty())
270 hWndExplorer = (HWND)_wcstoui64(sVal, nullptr, 16);
272 while (GetParent(hWndExplorer)!=NULL)
273 hWndExplorer = GetParent(hWndExplorer);
274 if (!IsWindow(hWndExplorer))
276 hWndExplorer = NULL;
279 // if HKCU\Software\TortoiseGit\Debug is not 0, show our command line
280 // in a message box
281 if (CRegDWORD(_T("Software\\TortoiseGit\\Debug"), FALSE)==TRUE)
282 AfxMessageBox(AfxGetApp()->m_lpCmdLine, MB_OK | MB_ICONINFORMATION);
284 if (parser.HasKey(_T("urlhandler")))
286 CString url = parser.GetVal(_T("urlhandler"));
287 if (url.Find(_T("tgit://clone/")) == 0)
289 url = url.Mid(13); // 21 = "tgit://clone/".GetLength()
291 else if (url.Find(_T("github-windows://openRepo/")) == 0)
293 url = url.Mid(26); // 26 = "github-windows://openRepo/".GetLength()
294 int questioMark = url.Find('?');
295 if (questioMark > 0)
296 url = url.Left(questioMark);
298 else if (url.Find(_T("smartgit://cloneRepo/")) == 0)
300 url = url.Mid(21); // 21 = "smartgit://cloneRepo/".GetLength()
302 else
304 CMessageBox::Show(NULL, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR);
305 return FALSE;
307 CString newCmd;
308 newCmd.Format(_T("/command:clone /url:\"%s\" /hasurlhandler"), (LPCTSTR)url);
309 parser = CCmdLineParser(newCmd);
312 if ( parser.HasKey(_T("path")) && parser.HasKey(_T("pathfile")))
314 CMessageBox::Show(NULL, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR);
315 return FALSE;
318 CTGitPath cmdLinePath;
319 CTGitPathList pathList;
320 if (g_sGroupingUUID.IsEmpty())
321 g_sGroupingUUID = parser.GetVal(L"groupuuid");
322 if ( parser.HasKey(_T("pathfile")) )
325 CString sPathfileArgument = CPathUtils::GetLongPathname(parser.GetVal(_T("pathfile")));
327 cmdLinePath.SetFromUnknown(sPathfileArgument);
328 if (pathList.LoadFromFile(cmdLinePath)==false)
329 return FALSE; // no path specified!
330 if ( parser.HasKey(_T("deletepathfile")) )
332 // We can delete the temporary path file, now that we've loaded it
333 ::DeleteFile(cmdLinePath.GetWinPath());
335 // This was a path to a temporary file - it's got no meaning now, and
336 // anybody who uses it again is in for a problem...
337 cmdLinePath.Reset();
340 else
343 CString sPathArgument = CPathUtils::GetLongPathname(parser.GetVal(_T("path")));
344 if (parser.HasKey(_T("expaths")))
346 // an /expaths param means we're started via the buttons in our Win7 library
347 // and that means the value of /expaths is the current directory, and
348 // the selected paths are then added as additional parameters but without a key, only a value
350 // because of the "strange treatment of quotation marks and backslashes by CommandLineToArgvW"
351 // we have to escape the backslashes first. Since we're only dealing with paths here, that's
352 // a save bet.
353 // Without this, a command line like:
354 // /command:commit /expaths:"D:\" "D:\Utils"
355 // would fail because the "D:\" is treated as the backslash being the escape char for the quotation
356 // mark and we'd end up with:
357 // argv[1] = /command:commit
358 // argv[2] = /expaths:D:" D:\Utils
359 // See here for more details: http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
360 CString cmdLine = GetCommandLineW();
361 cmdLine.Replace(L"\\", L"\\\\");
362 int nArgs = 0;
363 LPWSTR *szArglist = CommandLineToArgvW(cmdLine, &nArgs);
364 if (szArglist)
366 // argument 0 is the process path, so start with 1
367 for (int i = 1; i < nArgs; ++i)
369 if (szArglist[i][0] != '/')
371 if (!sPathArgument.IsEmpty())
372 sPathArgument += '*';
373 sPathArgument += szArglist[i];
376 sPathArgument.Replace(L"\\\\", L"\\");
378 LocalFree(szArglist);
380 if (sPathArgument.IsEmpty() && parser.HasKey(L"path"))
382 CMessageBox::Show(hWndExplorer, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR);
383 return FALSE;
385 int asterisk = sPathArgument.Find('*');
386 cmdLinePath.SetFromUnknown(asterisk >= 0 ? sPathArgument.Left(asterisk) : sPathArgument);
387 pathList.LoadFromAsteriskSeparatedString(sPathArgument);
390 if (pathList.IsEmpty()) {
391 pathList.AddPath(CTGitPath::CTGitPath(g_Git.m_CurrentDir));
394 // Set CWD to temporary dir, and restore it later
396 DWORD len = GetCurrentDirectory(0, NULL);
397 if (len)
399 std::unique_ptr<TCHAR[]> originalCurrentDirectory(new TCHAR[len]);
400 if (GetCurrentDirectory(len, originalCurrentDirectory.get()))
402 sOrigCWD = originalCurrentDirectory.get();
403 sOrigCWD = CPathUtils::GetLongPathname(sOrigCWD);
406 TCHAR pathbuf[MAX_PATH] = {0};
407 GetTortoiseGitTempPath(MAX_PATH, pathbuf);
408 SetCurrentDirectory(pathbuf);
411 CheckForNewerVersion();
413 CAutoGeneralHandle TGitMutex = ::CreateMutex(NULL, FALSE, _T("TortoiseGitProc.exe"));
414 if (!g_Git.SetCurrentDir(cmdLinePath.GetWinPathString(), parser.HasKey(_T("submodule")) == TRUE))
416 for (int i = 0; i < pathList.GetCount(); ++i)
417 if(g_Git.SetCurrentDir(pathList[i].GetWinPath()))
418 break;
421 if(!g_Git.m_CurrentDir.IsEmpty())
423 sOrigCWD = g_Git.m_CurrentDir;
424 SetCurrentDirectory(g_Git.m_CurrentDir);
427 if (g_sGroupingUUID.IsEmpty())
429 CRegStdDWORD groupSetting = CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepo"), 3);
430 switch (DWORD(groupSetting))
432 case 1:
433 case 2:
434 // implemented differently to TortoiseSVN atm
435 break;
436 case 3:
437 case 4:
439 CString wcroot;
440 if (GitAdminDir::HasAdminDir(g_Git.m_CurrentDir, true, &wcroot))
442 git_oid oid;
443 CStringA wcRootA(wcroot + CPathUtils::GetAppDirectory());
444 if (!git_odb_hash(&oid, wcRootA, wcRootA.GetLength(), GIT_OBJ_BLOB))
446 CStringA hash;
447 git_oid_tostr(hash.GetBufferSetLength(GIT_OID_HEXSZ + 1), GIT_OID_HEXSZ + 1, &oid);
448 hash.ReleaseBuffer();
449 g_sGroupingUUID = hash;
451 ProjectProperties pp;
452 pp.ReadProps();
453 CString icon = pp.sIcon;
454 icon.Replace('/', '\\');
455 if (icon.IsEmpty())
456 g_bGroupingRemoveIcon = true;
457 g_sGroupingIcon = icon;
463 CString sAppID = GetTaskIDPerUUID(g_sGroupingUUID).c_str();
464 InitializeJumpList(sAppID);
465 EnsureGitLibrary(false);
468 CString err;
471 // requires CWD to be set
472 CGit::m_LogEncode = CAppUtils::GetLogOutputEncode();
474 // make sure all config files are read in order to check that none contains an error
475 g_Git.GetConfigValue(_T("doesnot.exist"));
477 catch (char* msg)
479 err = CString(msg);
482 if (!err.IsEmpty())
484 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)));
485 if (choice == 1)
487 // open the config file with alternative editor
488 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitLocalConfig());
490 else if (choice == 2)
492 // open the global config file with alternative editor
493 CAppUtils::LaunchAlternativeEditor(g_Git.GetGitGlobalConfig());
495 return FALSE;
499 // execute the requested command
500 CommandServer server;
501 Command * cmd = server.GetCommand(parser.GetVal(_T("command")));
502 if (cmd)
504 cmd->SetExplorerHwnd(hWndExplorer);
506 cmd->SetParser(parser);
507 cmd->SetPaths(pathList, cmdLinePath);
509 retSuccess = cmd->Execute();
510 delete cmd;
513 // Look for temporary files left around by TortoiseSVN and
514 // remove them. But only delete 'old' files because some
515 // apps might still be needing the recent ones.
517 DWORD len = GetTortoiseGitTempPath(0, NULL);
518 std::unique_ptr<TCHAR[]> path(new TCHAR[len + 100]);
519 len = GetTortoiseGitTempPath (len + 100, path.get());
520 if (len != 0)
522 CDirFileEnum finder(path.get());
523 FILETIME systime_;
524 ::GetSystemTimeAsFileTime(&systime_);
525 __int64 systime = (((_int64)systime_.dwHighDateTime)<<32) | ((__int64)systime_.dwLowDateTime);
526 bool isDir;
527 CString filepath;
528 while (finder.NextFile(filepath, &isDir))
530 HANDLE hFile = ::CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, isDir ? FILE_FLAG_BACKUP_SEMANTICS : NULL, NULL);
531 if (hFile != INVALID_HANDLE_VALUE)
533 FILETIME createtime_;
534 if (::GetFileTime(hFile, &createtime_, NULL, NULL))
536 ::CloseHandle(hFile);
537 __int64 createtime = (((_int64)createtime_.dwHighDateTime)<<32) | ((__int64)createtime_.dwLowDateTime);
538 if ((createtime + 864000000000) < systime) //only delete files older than a day
540 ::SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL);
541 if (isDir)
542 ::RemoveDirectory(filepath);
543 else
544 ::DeleteFile(filepath);
547 else
548 ::CloseHandle(hFile);
554 // Since the dialog has been closed, return FALSE so that we exit the
555 // application, rather than start the application's message pump.
556 return FALSE;
559 void CTortoiseProcApp::CheckUpgrade()
561 CRegString regVersion = CRegString(_T("Software\\TortoiseGit\\CurrentVersion"));
562 CString sVersion = regVersion;
563 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Current TGit Version %s\n"), (LPCTSTR)sVersion);
564 if (sVersion.Compare(_T(STRPRODUCTVER))==0)
565 return;
566 // we're starting the first time with a new version!
568 LONG lVersion = 0;
569 int 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);
577 else
579 pos = sVersion.Find(',');
580 if (pos > 0)
582 lVersion = (_ttol(sVersion.Left(pos))<<24);
583 lVersion |= (_ttol(sVersion.Mid(pos+1))<<16);
584 pos = sVersion.Find(',', pos+1);
585 lVersion |= (_ttol(sVersion.Mid(pos+1))<<8);
589 // generic cleanup
590 if (CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2"), TRUE) != TRUE)
592 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)
593 CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2")).removeValue();
596 if (CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2_mask")).exists())
598 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)
599 CRegStdDWORD(_T("Software\\TortoiseGit\\UseLibgit2_mask")).removeValue();
602 CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning"));
604 srand((unsigned)time(0));
605 CRegDWORD checkNewerWeekDay = CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeekDay"), 0);
606 if (!checkNewerWeekDay.exists())
607 checkNewerWeekDay = rand() % 7;
609 // version specific updates
610 if (lVersion <= 0x01080802)
612 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\CleanTypeDlgWindowPlacement")).removeValue();
615 if (lVersion <= 0x01080801)
617 CRegStdDWORD(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs")).removeValue();
618 CRegStdString(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Order")).removeValue();
619 CRegStdString(_T("Software\\TortoiseGit\\StatusColumns\\BrowseRefs_Width")).removeValue();
622 if (lVersion <= 0x01080401)
624 if (CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI"), FALSE) == TRUE)
625 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\DeliveryType")) = SEND_MAIL_MAPI;
626 CRegStdDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\UseMAPI")).removeValue();
629 if (lVersion <= 0x01080202)
631 // upgrade to 1.8.3: force recreation of all diff scripts.
632 CAppUtils::SetupDiffScripts(true, CString());
635 if (lVersion <= 0x01080100)
637 if (CRegStdDWORD(_T("Software\\TortoiseGit\\LogTopoOrder"), TRUE) == FALSE)
638 CRegStdDWORD(_T("Software\\TortoiseGit\\LogOrderBy")) = 0;
640 // smoothly migrate broken msysgit path settings
641 CString oldmsysGitSetting = CRegString(REG_MSYSGIT_PATH);
642 oldmsysGitSetting.TrimRight(_T("\\"));
643 CString right = oldmsysGitSetting.Right(4);
644 if (oldmsysGitSetting.GetLength() > 4 && oldmsysGitSetting.Right(4) == _T("\\cmd"))
646 CString newPath = oldmsysGitSetting.Mid(0, oldmsysGitSetting.GetLength() - 3) + _T("bin");
647 if (PathFileExists(newPath + _T("\\git.exe")))
649 CRegString(REG_MSYSGIT_PATH) = newPath;
650 g_Git.m_bInitialized = FALSE;
651 g_Git.CheckMsysGitDir();
656 if (lVersion <= 0x01040000)
658 CRegStdDWORD(_T("Software\\TortoiseGit\\OwnerdrawnMenus")).removeValue();
661 if (lVersion <= 0x01070600)
663 CoInitialize(NULL);
664 EnsureGitLibrary();
665 CoUninitialize();
666 CRegStdDWORD(_T("Software\\TortoiseGit\\ConvertBase")).removeValue();
667 CRegStdDWORD(_T("Software\\TortoiseGit\\DiffProps")).removeValue();
668 if (CRegStdDWORD(_T("Software\\TortoiseGit\\CheckNewer"), TRUE) == FALSE)
669 CRegStdDWORD(_T("Software\\TortoiseGit\\VersionCheck")) = FALSE;
670 CRegStdDWORD(_T("Software\\TortoiseGit\\CheckNewer")).removeValue();
673 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Setting up diff scripts ...\n"));
674 CAppUtils::SetupDiffScripts(false, CString());
676 // set the current version so we don't come here again until the next update!
677 regVersion = _T(STRPRODUCTVER);
680 void CTortoiseProcApp::InitializeJumpList(const CString& appid)
682 // for Win7 : use a custom jump list
683 CoInitialize(NULL);
684 SetAppID(appid);
685 DeleteJumpList(appid);
686 DoInitializeJumpList(appid);
687 CoUninitialize();
690 void CTortoiseProcApp::DoInitializeJumpList(const CString& appid)
692 ATL::CComPtr<ICustomDestinationList> pcdl;
693 HRESULT hr = pcdl.CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER);
694 if (FAILED(hr))
695 return;
697 hr = pcdl->SetAppID(appid);
698 if (FAILED(hr))
699 return;
701 UINT uMaxSlots;
702 ATL::CComPtr<IObjectArray> poaRemoved;
703 hr = pcdl->BeginList(&uMaxSlots, IID_PPV_ARGS(&poaRemoved));
704 if (FAILED(hr))
705 return;
707 ATL::CComPtr<IObjectCollection> poc;
708 hr = poc.CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER);
709 if (FAILED(hr))
710 return;
712 CString sTemp = CString(MAKEINTRESOURCE(IDS_MENUSETTINGS));
713 CStringUtils::RemoveAccelerators(sTemp);
715 ATL::CComPtr<IShellLink> psl;
716 hr = CreateShellLink(_T("/command:settings"), (LPCTSTR)sTemp, 20, &psl);
717 if (SUCCEEDED(hr)) {
718 poc->AddObject(psl);
720 sTemp = CString(MAKEINTRESOURCE(IDS_MENUHELP));
721 CStringUtils::RemoveAccelerators(sTemp);
722 psl.Release(); // Need to release the object before calling operator&()
723 hr = CreateShellLink(_T("/command:help"), (LPCTSTR)sTemp, 19, &psl);
724 if (SUCCEEDED(hr)) {
725 poc->AddObject(psl);
728 ATL::CComPtr<IObjectArray> poa;
729 hr = poc.QueryInterface(&poa);
730 if (SUCCEEDED(hr)) {
731 pcdl->AppendCategory((LPCTSTR)CString(MAKEINTRESOURCE(IDS_PROC_TASKS)), poa);
732 pcdl->CommitList();
736 int CTortoiseProcApp::ExitInstance()
738 Gdiplus::GdiplusShutdown(m_gdiplusToken);
740 CWinAppEx::ExitInstance();
741 if (retSuccess)
742 return 0;
743 return -1;
746 void CTortoiseProcApp::CheckForNewerVersion()
748 // check for newer versions
749 if (CRegDWORD(_T("Software\\TortoiseGit\\VersionCheck"), TRUE) != FALSE)
751 time_t now;
752 struct tm ptm;
754 time(&now);
755 if ((now != 0) && (localtime_s(&ptm, &now)==0))
757 #if PREVIEW
758 // Check daily for new preview releases
759 CRegDWORD oldday = CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerDay"), (DWORD)-1);
760 if (((DWORD)oldday) == -1)
761 oldday = ptm.tm_yday;
762 else
764 if ((DWORD)oldday != (DWORD)ptm.tm_yday)
766 oldday = ptm.tm_yday;
767 #else
768 int week = 0;
769 // we don't calculate the real 'week of the year' here
770 // because just to decide if we should check for an update
771 // that's not needed.
772 week = (ptm.tm_yday + CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeekDay"), 0)) / 7;
774 CRegDWORD oldweek = CRegDWORD(_T("Software\\TortoiseGit\\CheckNewerWeek"), (DWORD)-1);
775 if (((DWORD)oldweek) == -1)
776 oldweek = week; // first start of TortoiseProc, no update check needed
777 else
779 if ((DWORD)week != oldweek)
781 oldweek = week;
782 #endif
783 CAppUtils::RunTortoiseGitProc(_T("/command:updatecheck"), false, false);