BOOL CTortoiseProcApp::InitInstance() { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": InitInstance\n")); CheckUpgrade(); CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); CMFCButton::EnableWindowsTheming(); CHistoryCombo::m_nGitIconIndex = SYS_IMAGE_LIST().AddIcon((HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_GITCONFIG), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE)); Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL); //set the resource dll for the required language CRegDWORD loc = CRegDWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033); long langId = loc; { CString langStr; langStr.Format(_T("%ld"), langId); CCrashReport::Instance().AddUserInfoToReport(L"LanguageID", langStr); } CString langDll; CStringA langpath = CStringA(CPathUtils::GetAppParentDirectory()); langpath += "Languages"; do { langDll.Format(_T("%sLanguages\\TortoiseProc%ld.dll"), (LPCTSTR)CPathUtils::GetAppParentDirectory(), langId); CString sVer = _T(STRPRODUCTVER); CString sFileVer = CPathUtils::GetVersionFromFile(langDll); if (sFileVer == sVer) { HINSTANCE hInst = LoadLibrary(langDll); if (hInst != NULL) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Load Language DLL %s\n"), langDll); AfxSetResourceHandle(hInst); break; } } { DWORD lid = SUBLANGID(langId); lid--; if (lid > 0) { langId = MAKELANGID(PRIMARYLANGID(langId), lid); } else langId = 0; } } while (langId != 0); TCHAR buf[6] = { 0 }; _tcscpy_s(buf, _T("en")); langId = loc; // MFC uses a help file with the same name as the application by default, // which means we have to change that default to our language specific help files CString sHelppath = CPathUtils::GetAppDirectory() + _T("TortoiseGit_en.chm"); free((void*)m_pszHelpFilePath); m_pszHelpFilePath=_tcsdup(sHelppath); sHelppath = CPathUtils::GetAppParentDirectory() + _T("Languages\\TortoiseGit_en.chm"); do { CString sLang = _T("_"); if (GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO639LANGNAME, buf, _countof(buf))) { sLang += buf; sHelppath.Replace(_T("_en"), sLang); if (PathFileExists(sHelppath)) { free((void*)m_pszHelpFilePath); m_pszHelpFilePath=_tcsdup(sHelppath); break; } } sHelppath.Replace(sLang, _T("_en")); if (GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO3166CTRYNAME, buf, _countof(buf))) { sLang += _T("_"); sLang += buf; sHelppath.Replace(_T("_en"), sLang); if (PathFileExists(sHelppath)) { free((void*)m_pszHelpFilePath); m_pszHelpFilePath=_tcsdup(sHelppath); break; } } sHelppath.Replace(sLang, _T("_en")); DWORD lid = SUBLANGID(langId); lid--; if (lid > 0) { langId = MAKELANGID(PRIMARYLANGID(langId), lid); } else langId = 0; } while (langId); CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Set Help Filename %s\n"), m_pszHelpFilePath); setlocale(LC_ALL, ""); if (!g_Git.CheckMsysGitDir()) { UINT ret = CMessageBox::Show(NULL, IDS_PROC_NOMSYSGIT, IDS_APPNAME, 3, IDI_HAND, IDS_PROC_SETMSYSGITPATH, IDS_PROC_GOTOMSYSGITWEBSITE, IDS_ABORTBUTTON); if(ret == 2) { ShellExecute(NULL, NULL, _T("http://msysgit.github.io/"), NULL, NULL, SW_SHOW); } else if(ret == 1) { // open settings dialog CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROC_SETTINGS_TITLE)), new CSetMainPage(), this->GetMainWnd()).DoModal(); } return FALSE; } if (CAppUtils::GetMsysgitVersion() < 0x01070a00) { 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); if (ret == 1) { CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore" ShellExecute(NULL, NULL, _T("http://msysgit.github.io/"), NULL, NULL, SW_SHOW); return FALSE; } else if (ret == 2) { CMessageBox::RemoveRegistryKey(_T("OldMsysgitVersionWarning")); // only store answer if it is "Ignore" return FALSE; } } { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Registering Crash Report ...\n")); CCrashReport::Instance().AddUserInfoToReport(L"msysGitDir", CGit::ms_LastMsysGitDir); CString versionString; versionString.Format(_T("%d"), CGit::ms_LastMsysGitVersion); CCrashReport::Instance().AddUserInfoToReport(L"msysGitVersion", versionString); } CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Initializing UI components ...\n")); // InitCommonControls() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. INITCOMMONCONTROLSEX used = { sizeof(INITCOMMONCONTROLSEX), ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES | ICC_DATE_CLASSES | ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES | ICC_LISTVIEW_CLASSES | ICC_NATIVEFNTCTL_CLASS | ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES }; InitCommonControlsEx(&used); AfxOleInit(); AfxEnableControlContainer(); AfxInitRichEdit5(); CWinAppEx::InitInstance(); SetRegistryKey(_T("TortoiseGit")); AfxGetApp()->m_pszProfileName = _tcsdup(_T("TortoiseProc")); // w/o this ResizableLib will store data under TortoiseGitProc which is not compatible with older versions CCmdLineParser parser(AfxGetApp()->m_lpCmdLine); hWndExplorer = NULL; CString sVal = parser.GetVal(_T("hwnd")); if (!sVal.IsEmpty()) hWndExplorer = (HWND)_wcstoui64(sVal, nullptr, 16); while (GetParent(hWndExplorer)!=NULL) hWndExplorer = GetParent(hWndExplorer); if (!IsWindow(hWndExplorer)) { hWndExplorer = NULL; } // if HKCU\Software\TortoiseGit\Debug is not 0, show our command line // in a message box if (CRegDWORD(_T("Software\\TortoiseGit\\Debug"), FALSE)==TRUE) AfxMessageBox(AfxGetApp()->m_lpCmdLine, MB_OK | MB_ICONINFORMATION); if (parser.HasKey(_T("urlhandler"))) { CString url = parser.GetVal(_T("urlhandler")); if (url.Find(_T("tgit://clone/")) == 0) { url = url.Mid(13); // 21 = "tgit://clone/".GetLength() } else if (url.Find(_T("github-windows://openRepo/")) == 0) { url = url.Mid(26); // 26 = "github-windows://openRepo/".GetLength() int questioMark = url.Find('?'); if (questioMark > 0) url = url.Left(questioMark); } else if (url.Find(_T("smartgit://cloneRepo/")) == 0) { url = url.Mid(21); // 21 = "smartgit://cloneRepo/".GetLength() } else { CMessageBox::Show(NULL, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR); return FALSE; } CString newCmd; newCmd.Format(_T("/command:clone /url:\"%s\" /hasurlhandler"), url); parser = CCmdLineParser(newCmd); } if ( parser.HasKey(_T("path")) && parser.HasKey(_T("pathfile"))) { CMessageBox::Show(NULL, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR); return FALSE; } CTGitPath cmdLinePath; CTGitPathList pathList; if (g_sGroupingUUID.IsEmpty()) g_sGroupingUUID = parser.GetVal(L"groupuuid"); if ( parser.HasKey(_T("pathfile")) ) { CString sPathfileArgument = CPathUtils::GetLongPathname(parser.GetVal(_T("pathfile"))); cmdLinePath.SetFromUnknown(sPathfileArgument); if (pathList.LoadFromFile(cmdLinePath)==false) return FALSE; // no path specified! if ( parser.HasKey(_T("deletepathfile")) ) { // We can delete the temporary path file, now that we've loaded it ::DeleteFile(cmdLinePath.GetWinPath()); } // This was a path to a temporary file - it's got no meaning now, and // anybody who uses it again is in for a problem... cmdLinePath.Reset(); } else { CString sPathArgument = CPathUtils::GetLongPathname(parser.GetVal(_T("path"))); if (parser.HasKey(_T("expaths"))) { // an /expaths param means we're started via the buttons in our Win7 library // and that means the value of /expaths is the current directory, and // the selected paths are then added as additional parameters but without a key, only a value // because of the "strange treatment of quotation marks and backslashes by CommandLineToArgvW" // we have to escape the backslashes first. Since we're only dealing with paths here, that's // a save bet. // Without this, a command line like: // /command:commit /expaths:"D:\" "D:\Utils" // would fail because the "D:\" is treated as the backslash being the escape char for the quotation // mark and we'd end up with: // argv[1] = /command:commit // argv[2] = /expaths:D:" D:\Utils // See here for more details: http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx CString cmdLine = GetCommandLineW(); cmdLine.Replace(L"\\", L"\\\\"); int nArgs = 0; LPWSTR *szArglist = CommandLineToArgvW(cmdLine, &nArgs); if (szArglist) { // argument 0 is the process path, so start with 1 for (int i = 1; i < nArgs; ++i) { if (szArglist[i][0] != '/') { if (!sPathArgument.IsEmpty()) sPathArgument += '*'; sPathArgument += szArglist[i]; } } sPathArgument.Replace(L"\\\\", L"\\"); } LocalFree(szArglist); } if (sPathArgument.IsEmpty() && parser.HasKey(L"path")) { CMessageBox::Show(hWndExplorer, IDS_ERR_INVALIDPATH, IDS_APPNAME, MB_ICONERROR); return FALSE; } int asterisk = sPathArgument.Find('*'); cmdLinePath.SetFromUnknown(asterisk >= 0 ? sPathArgument.Left(asterisk) : sPathArgument); pathList.LoadFromAsteriskSeparatedString(sPathArgument); } if (pathList.IsEmpty()) { pathList.AddPath(CTGitPath::CTGitPath(g_Git.m_CurrentDir)); } // Set CWD to temporary dir, and restore it later { DWORD len = GetCurrentDirectory(0, NULL); if (len) { std::unique_ptr<TCHAR[]> originalCurrentDirectory(new TCHAR[len]); if (GetCurrentDirectory(len, originalCurrentDirectory.get())) { sOrigCWD = originalCurrentDirectory.get(); sOrigCWD = CPathUtils::GetLongPathname(sOrigCWD); } } TCHAR pathbuf[MAX_PATH] = {0}; GetTortoiseGitTempPath(MAX_PATH, pathbuf); SetCurrentDirectory(pathbuf); } CheckForNewerVersion(); CAutoGeneralHandle TGitMutex = ::CreateMutex(NULL, FALSE, _T("TortoiseGitProc.exe")); if (!g_Git.SetCurrentDir(cmdLinePath.GetWinPathString(), parser.HasKey(_T("submodule")) == TRUE)) { for (int i = 0; i < pathList.GetCount(); ++i) if(g_Git.SetCurrentDir(pathList[i].GetWinPath())) break; } if(!g_Git.m_CurrentDir.IsEmpty()) { sOrigCWD = g_Git.m_CurrentDir; SetCurrentDirectory(g_Git.m_CurrentDir); } if (g_sGroupingUUID.IsEmpty()) { CRegStdDWORD groupSetting = CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepo"), 3); switch (DWORD(groupSetting)) { case 1: case 2: // implemented differently to TortoiseSVN atm break; case 3: case 4: { CString wcroot; if (g_GitAdminDir.HasAdminDir(g_Git.m_CurrentDir, true, &wcroot)) { git_oid oid; CStringA wcRootA(wcroot + CPathUtils::GetAppDirectory()); if (!git_odb_hash(&oid, wcRootA, wcRootA.GetLength(), GIT_OBJ_BLOB)) { CStringA hash; git_oid_tostr(hash.GetBufferSetLength(GIT_OID_HEXSZ + 1), GIT_OID_HEXSZ + 1, &oid); hash.ReleaseBuffer(); g_sGroupingUUID = hash; } ProjectProperties pp; pp.ReadProps(); CString icon = pp.sIcon; icon.Replace('/', '\\'); if (icon.IsEmpty()) g_bGroupingRemoveIcon = true; g_sGroupingIcon = icon; } } } } CString sAppID = GetTaskIDPerUUID(g_sGroupingUUID).c_str(); InitializeJumpList(sAppID); EnsureGitLibrary(false); { CString err; try { // requires CWD to be set CGit::m_LogEncode = CAppUtils::GetLogOutputEncode(); // make sure all config files are read in order to check that none contains an error g_Git.GetConfigValue(_T("doesnot.exist")); } catch (char* msg) { err = CString(msg); } if (!err.IsEmpty()) { 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))); if (choice == 1) { // open the config file with alternative editor CAppUtils::LaunchAlternativeEditor(g_Git.GetGitLocalConfig()); } else if (choice == 2) { // open the global config file with alternative editor CAppUtils::LaunchAlternativeEditor(g_Git.GetGitGlobalConfig()); } return FALSE; } } // execute the requested command CommandServer server; Command * cmd = server.GetCommand(parser.GetVal(_T("command"))); if (cmd) { cmd->SetExplorerHwnd(hWndExplorer); cmd->SetParser(parser); cmd->SetPaths(pathList, cmdLinePath); retSuccess = cmd->Execute(); delete cmd; } // Look for temporary files left around by TortoiseSVN and // remove them. But only delete 'old' files because some // apps might still be needing the recent ones. { DWORD len = GetTortoiseGitTempPath(0, NULL); std::unique_ptr<TCHAR[]> path(new TCHAR[len + 100]); len = GetTortoiseGitTempPath (len + 100, path.get()); if (len != 0) { CDirFileEnum finder(path.get()); FILETIME systime_; ::GetSystemTimeAsFileTime(&systime_); __int64 systime = (((_int64)systime_.dwHighDateTime)<<32) | ((__int64)systime_.dwLowDateTime); bool isDir; CString filepath; while (finder.NextFile(filepath, &isDir)) { HANDLE hFile = ::CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, isDir ? FILE_FLAG_BACKUP_SEMANTICS : NULL, NULL); if (hFile != INVALID_HANDLE_VALUE) { FILETIME createtime_; if (::GetFileTime(hFile, &createtime_, NULL, NULL)) { ::CloseHandle(hFile); __int64 createtime = (((_int64)createtime_.dwHighDateTime)<<32) | ((__int64)createtime_.dwLowDateTime); if ((createtime + 864000000000) < systime) //only delete files older than a day { ::SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL); if (isDir) ::RemoveDirectory(filepath); else ::DeleteFile(filepath); } } else ::CloseHandle(hFile); } } } } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }
void CBrowseRefsDlg::ShowContextMenu(CPoint point, HTREEITEM hTreePos, VectorPShadowTree& selectedLeafs) { CIconMenu popupMenu; popupMenu.CreatePopupMenu(); bool bAddSeparator = false; CString remoteName; if(selectedLeafs.size()==1) { bAddSeparator = true; bool bShowReflogOption = false; bool bShowFetchOption = false; bool bShowRenameOption = false; bool bShowCreateBranchOption = false; bool bShowEditBranchDescriptionOption = false; CString fetchFromCmd; if(selectedLeafs[0]->IsFrom(L"refs/heads/")) { bShowReflogOption = true; bShowRenameOption = true; bShowEditBranchDescriptionOption = true; } else if(selectedLeafs[0]->IsFrom(L"refs/remotes/")) { bShowReflogOption = true; bShowFetchOption = true; bShowCreateBranchOption = true; CString remoteBranch; if (SplitRemoteBranchName(selectedLeafs[0]->GetRefName(), remoteName, remoteBranch)) bShowFetchOption = false; else fetchFromCmd.Format(IDS_PROC_BROWSEREFS_FETCHFROM, (LPCTSTR)remoteName); } else if(selectedLeafs[0]->IsFrom(L"refs/tags/")) { } CString temp; temp.LoadString(IDS_MENULOG); popupMenu.AppendMenuIcon(eCmd_ViewLog, temp, IDI_LOG); popupMenu.AppendMenuIcon(eCmd_RepoBrowser, IDS_LOG_BROWSEREPO, IDI_REPOBROWSE); if(bShowReflogOption) { temp.LoadString(IDS_MENUREFLOG); popupMenu.AppendMenuIcon(eCmd_ShowReflog, temp, IDI_LOG); } popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = false; if(bShowFetchOption) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_Fetch, fetchFromCmd, IDI_PULL); } if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = false; if (m_bHasWC) { CString str; if (selectedLeafs[0]->GetRefName() != _T("refs/heads/") + g_Git.GetCurrentBranch()) { str.Format(IDS_LOG_POPUP_MERGEREV, (LPCTSTR)g_Git.GetCurrentBranch()); popupMenu.AppendMenuIcon(eCmd_Merge, str, IDI_MERGE); } popupMenu.AppendMenuIcon(eCmd_Switch, CString(MAKEINTRESOURCE(IDS_SWITCH_TO_THIS)), IDI_SWITCH); popupMenu.AppendMenu(MF_SEPARATOR); } if(bShowCreateBranchOption) { bAddSeparator = true; temp.LoadString(IDS_MENUBRANCH); popupMenu.AppendMenuIcon(eCmd_CreateBranch, temp, IDI_COPY); } if (bShowEditBranchDescriptionOption) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_EditBranchDescription, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_EDITDESCRIPTION)), IDI_RENAME); } if(bShowRenameOption) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_Rename, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_RENAME)), IDI_RENAME); } if (m_bHasWC && selectedLeafs[0]->IsFrom(L"refs/heads/")) { if (bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = true; if (!selectedLeafs[0]->m_csUpstream.IsEmpty()) popupMenu.AppendMenuIcon(eCmd_UpstreamDrop, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_DROPTRACKEDBRANCH))); popupMenu.AppendMenuIcon(eCmd_UpstreamSet, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_SETTRACKEDBRANCH))); } } else if(selectedLeafs.size() == 2) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_Diff, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_COMPAREREFS)), IDI_DIFF); popupMenu.AppendMenuIcon(eCmd_UnifiedDiff, CString(MAKEINTRESOURCE(IDS_LOG_POPUP_GNUDIFF)), IDI_DIFF); CString menu; menu.Format(IDS_SHOWLOG_OF, (LPCTSTR)GetTwoSelectedRefs(selectedLeafs, m_sLastSelected, _T(".."))); popupMenu.AppendMenuIcon(eCmd_ViewLogRange, menu, IDI_LOG); menu.Format(IDS_SHOWLOG_OF, (LPCTSTR)GetTwoSelectedRefs(selectedLeafs, m_sLastSelected, _T("..."))); popupMenu.AppendMenuIcon(eCmd_ViewLogRangeReachableFromOnlyOne, menu, IDI_LOG); } if(!selectedLeafs.empty()) { if(AreAllFrom(selectedLeafs, L"refs/remotes/")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString menuItemName; if(selectedLeafs.size() == 1) menuItemName.LoadString(IDS_PROC_BROWSEREFS_DELETEREMOTEBRANCH); else menuItemName.Format(IDS_PROC_BROWSEREFS_DELETEREMOTEBRANCHES, selectedLeafs.size()); popupMenu.AppendMenuIcon(eCmd_DeleteRemoteBranch, menuItemName, IDI_DELETE); bAddSeparator = true; } else if(AreAllFrom(selectedLeafs, L"refs/heads/")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString menuItemName; if(selectedLeafs.size() == 1) menuItemName.LoadString(IDS_PROC_BROWSEREFS_DELETEBRANCH); else menuItemName.Format(IDS_PROC_BROWSEREFS_DELETEBRANCHES, selectedLeafs.size()); popupMenu.AppendMenuIcon(eCmd_DeleteBranch, menuItemName, IDI_DELETE); bAddSeparator = true; } else if(AreAllFrom(selectedLeafs, L"refs/tags/")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString menuItemName; if(selectedLeafs.size() == 1) menuItemName.LoadString(IDS_PROC_BROWSEREFS_DELETETAG); else menuItemName.Format(IDS_PROC_BROWSEREFS_DELETETAGS, selectedLeafs.size()); popupMenu.AppendMenuIcon(eCmd_DeleteTag, menuItemName, IDI_DELETE); bAddSeparator = true; } } if(hTreePos!=NULL && selectedLeafs.empty()) { CShadowTree* pTree=(CShadowTree*)m_RefTreeCtrl.GetItemData(hTreePos); if(pTree->IsFrom(L"refs/remotes")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); popupMenu.AppendMenuIcon(eCmd_ManageRemotes, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_MANAGEREMOTES)), IDI_SETTINGS); bAddSeparator = true; if(selectedLeafs.empty()) { CString remoteBranch; if (SplitRemoteBranchName(pTree->GetRefName(), remoteName, remoteBranch)) remoteName = _T(""); int pos = findVectorPosition(remotes, remoteName); if (pos >= 0) { CString temp; temp.Format(IDS_PROC_BROWSEREFS_FETCHFROM, (LPCTSTR)remoteName); popupMenu.AppendMenuIcon(eCmd_Fetch, temp, IDI_PULL); temp.LoadString(IDS_DELETEREMOTETAG); popupMenu.AppendMenuIcon(eCmd_DeleteRemoteTag | (pos << 16), temp, IDI_DELETE); } } } if(pTree->IsFrom(L"refs/heads")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString temp; temp.LoadString(IDS_MENUBRANCH); popupMenu.AppendMenuIcon(eCmd_CreateBranch, temp, IDI_COPY); } if(pTree->IsFrom(L"refs/tags")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString temp; temp.LoadString(IDS_MENUTAG); popupMenu.AppendMenuIcon(eCmd_CreateTag, temp, IDI_TAG); temp.LoadString(IDS_PROC_BROWSEREFS_DELETEALLTAGS); popupMenu.AppendMenuIcon(eCmd_DeleteAllTags, temp, IDI_DELETE); if (!remotes.empty()) { popupMenu.AppendMenu(MF_SEPARATOR); int i = 0; for (auto it = remotes.cbegin(); it != remotes.cend(); ++it, ++i) { temp.Format(IDS_DELETEREMOTETAGON, (LPCTSTR)*it); popupMenu.AppendMenuIcon(eCmd_DeleteRemoteTag | (i << 16), temp, IDI_DELETE); } } } } int selection = popupMenu.TrackPopupMenuEx(TPM_LEFTALIGN | TPM_RETURNCMD, point.x, point.y, this, 0); switch ((eCmd)(selection & 0xFFFF)) { case eCmd_ViewLog: { CLogDlg dlg; dlg.SetRange(g_Git.FixBranchName(selectedLeafs[0]->GetRefName())); dlg.DoModal(); } break; case eCmd_ViewLogRange: { CLogDlg dlg; dlg.SetRange(GetTwoSelectedRefs(selectedLeafs, m_sLastSelected, _T(".."))); dlg.DoModal(); } break; case eCmd_ViewLogRangeReachableFromOnlyOne: { CLogDlg dlg; dlg.SetRange(GetTwoSelectedRefs(selectedLeafs, m_sLastSelected, _T("..."))); dlg.DoModal(); } break; case eCmd_RepoBrowser: CAppUtils::RunTortoiseGitProc(_T("/command:repobrowser /path:\"") + g_Git.m_CurrentDir + _T("\" /rev:") + selectedLeafs[0]->GetRefName()); break; case eCmd_DeleteBranch: case eCmd_DeleteRemoteBranch: { if(ConfirmDeleteRef(selectedLeafs)) DoDeleteRefs(selectedLeafs); Refresh(); } break; case eCmd_DeleteTag: { if(ConfirmDeleteRef(selectedLeafs)) DoDeleteRefs(selectedLeafs); Refresh(); } break; case eCmd_ShowReflog: { CRefLogDlg refLogDlg(this); refLogDlg.m_CurrentBranch = selectedLeafs[0]->GetRefName(); refLogDlg.DoModal(); } break; case eCmd_Fetch: { CAppUtils::Fetch(remoteName); Refresh(); } break; case eCmd_DeleteRemoteTag: { CDeleteRemoteTagDlg deleteRemoteTagDlg; int remoteInx = selection >> 16; if (remoteInx < 0 || remoteInx >= remotes.size()) return; deleteRemoteTagDlg.m_sRemote = remotes[remoteInx]; deleteRemoteTagDlg.DoModal(); } break; case eCmd_Merge: { CString ref = selectedLeafs[0]->GetRefName(); CAppUtils::Merge(&ref); } break; case eCmd_Switch: { CAppUtils::Switch(selectedLeafs[0]->GetRefName()); } break; case eCmd_Rename: { POSITION pos = m_ListRefLeafs.GetFirstSelectedItemPosition(); if(pos != NULL) m_ListRefLeafs.EditLabel(m_ListRefLeafs.GetNextSelectedItem(pos)); } break; case eCmd_AddRemote: { CAddRemoteDlg(this).DoModal(); Refresh(); } break; case eCmd_ManageRemotes: { CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROCS_TITLE_GITREMOTESETTINGS)), new CSettingGitRemote(), this).DoModal(); // CSettingGitRemote W_Remotes(m_cmdPath); // W_Remotes.DoModal(); Refresh(); } break; case eCmd_CreateBranch: { CString *commitHash = NULL; if (selectedLeafs.size() == 1) commitHash = &(selectedLeafs[0]->m_csRefHash); CAppUtils::CreateBranchTag(false, commitHash); Refresh(); } break; case eCmd_CreateTag: { CAppUtils::CreateBranchTag(true); Refresh(); } break; case eCmd_DeleteAllTags: { for (int i = 0; i < m_ListRefLeafs.GetItemCount(); ++i) { m_ListRefLeafs.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); selectedLeafs.push_back((CShadowTree*)m_ListRefLeafs.GetItemData(i)); } if (ConfirmDeleteRef(selectedLeafs)) DoDeleteRefs(selectedLeafs); Refresh(); } break; case eCmd_Diff: { CFileDiffDlg dlg; dlg.SetDiff( NULL, selectedLeafs[1]->GetRefName() + L"^{}", selectedLeafs[0]->GetRefName() + L"^{}"); dlg.DoModal(); } break; case eCmd_UnifiedDiff: { CAppUtils::StartShowUnifiedDiff(nullptr, CTGitPath(), selectedLeafs[0]->m_csRefHash, CTGitPath(), selectedLeafs[1]->m_csRefHash); } break; case eCmd_EditBranchDescription: { CInputDlg dlg; dlg.m_sHintText.LoadString(IDS_PROC_BROWSEREFS_EDITDESCRIPTION); dlg.m_sInputText = selectedLeafs[0]->m_csDescription; dlg.m_sTitle.LoadString(IDS_PROC_BROWSEREFS_EDITDESCRIPTION); dlg.m_bUseLogWidth = true; if(dlg.DoModal() == IDOK) { CString key; key.Format(_T("branch.%s.description"), (LPCTSTR)selectedLeafs[0]->GetRefsHeadsName()); dlg.m_sInputText.Replace(_T("\r"), _T("")); dlg.m_sInputText.Trim(); if (dlg.m_sInputText.IsEmpty()) g_Git.UnsetConfigValue(key); else g_Git.SetConfigValue(key, dlg.m_sInputText); Refresh(); } } break; case eCmd_UpstreamDrop: { CString key; key.Format(_T("branch.%s.remote"), (LPCTSTR)selectedLeafs[0]->GetRefsHeadsName()); g_Git.UnsetConfigValue(key); key.Format(_T("branch.%s.merge"), (LPCTSTR)selectedLeafs[0]->GetRefsHeadsName()); g_Git.UnsetConfigValue(key); } Refresh(); break; case eCmd_UpstreamSet: { CString newRef = CBrowseRefsDlg::PickRef(false, _T(""), gPickRef_Remote, false); if (newRef.IsEmpty() || newRef.Find(_T("refs/remotes/")) != 0) return; CString remote, branch; if (SplitRemoteBranchName(newRef, remote, branch)) return; CString key; key.Format(_T("branch.%s.remote"), (LPCTSTR)selectedLeafs[0]->GetRefsHeadsName()); g_Git.SetConfigValue(key, remote); key.Format(_T("branch.%s.merge"), (LPCTSTR)selectedLeafs[0]->GetRefsHeadsName()); g_Git.SetConfigValue(key, _T("refs/heads/") + branch); Refresh(); } break; } }
void CBrowseRefsDlg::ShowContextMenu(CPoint point, HTREEITEM hTreePos, VectorPShadowTree& selectedLeafs) { CIconMenu popupMenu; popupMenu.CreatePopupMenu(); bool bAddSeparator = false; CString remoteName; if(selectedLeafs.size()==1) { bAddSeparator = true; bool bShowReflogOption = false; bool bShowFetchOption = false; bool bShowSwitchOption = false; bool bShowRenameOption = false; bool bShowCreateBranchOption = false; bool bShowEditBranchDescriptionOption = false; CString fetchFromCmd; if(selectedLeafs[0]->IsFrom(L"refs/heads")) { bShowReflogOption = true; bShowSwitchOption = true; bShowRenameOption = true; bShowEditBranchDescriptionOption = true; } else if(selectedLeafs[0]->IsFrom(L"refs/remotes")) { bShowReflogOption = true; bShowFetchOption = true; bShowCreateBranchOption = true; int dummy = 0;//Needed for tokenize remoteName = selectedLeafs[0]->GetRefName(); remoteName = remoteName.Mid(13); remoteName = remoteName.Tokenize(L"/", dummy); fetchFromCmd.Format(IDS_PROC_BROWSEREFS_FETCHFROM, remoteName); } else if(selectedLeafs[0]->IsFrom(L"refs/tags")) { } CString temp; temp.LoadString(IDS_MENULOG); popupMenu.AppendMenuIcon(eCmd_ViewLog, temp, IDI_LOG); popupMenu.AppendMenuIcon(eCmd_RepoBrowser, IDS_LOG_BROWSEREPO, IDI_REPOBROWSE); if(bShowReflogOption) { temp.LoadString(IDS_MENUREFLOG); popupMenu.AppendMenuIcon(eCmd_ShowReflog, temp, IDI_LOG); } popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = false; if(bShowFetchOption) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_Fetch, fetchFromCmd, IDI_PULL); } if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); bAddSeparator = false; if (m_bHasWC) { popupMenu.AppendMenuIcon(eCmd_Switch, CString(MAKEINTRESOURCE(IDS_SWITCH_TO_THIS)), IDI_SWITCH); popupMenu.AppendMenu(MF_SEPARATOR); } if(bShowCreateBranchOption) { bAddSeparator = true; temp.LoadString(IDS_MENUBRANCH); popupMenu.AppendMenuIcon(eCmd_CreateBranch, temp, IDI_COPY); } if (bShowEditBranchDescriptionOption) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_EditBranchDescription, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_EDITDESCRIPTION)), IDI_RENAME); } if(bShowRenameOption) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_Rename, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_RENAME)), IDI_RENAME); } } else if(selectedLeafs.size() == 2) { bAddSeparator = true; popupMenu.AppendMenuIcon(eCmd_Diff, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_COMPAREREFS)), IDI_DIFF); } if(!selectedLeafs.empty()) { if(AreAllFrom(selectedLeafs, L"refs/remotes/")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString menuItemName; if(selectedLeafs.size() == 1) menuItemName.LoadString(IDS_PROC_BROWSEREFS_DELETEREMOTEBRANCH); else menuItemName.Format(IDS_PROC_BROWSEREFS_DELETEREMOTEBRANCHES, selectedLeafs.size()); popupMenu.AppendMenuIcon(eCmd_DeleteRemoteBranch, menuItemName, IDI_DELETE); bAddSeparator = true; } else if(AreAllFrom(selectedLeafs, L"refs/heads/")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString menuItemName; if(selectedLeafs.size() == 1) menuItemName.LoadString(IDS_PROC_BROWSEREFS_DELETEBRANCH); else menuItemName.Format(IDS_PROC_BROWSEREFS_DELETEBRANCHES, selectedLeafs.size()); popupMenu.AppendMenuIcon(eCmd_DeleteBranch, menuItemName, IDI_DELETE); bAddSeparator = true; } else if(AreAllFrom(selectedLeafs, L"refs/tags/")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString menuItemName; if(selectedLeafs.size() == 1) menuItemName.LoadString(IDS_PROC_BROWSEREFS_DELETETAG); else menuItemName.Format(IDS_PROC_BROWSEREFS_DELETETAGS, selectedLeafs.size()); popupMenu.AppendMenuIcon(eCmd_DeleteTag, menuItemName, IDI_DELETE); bAddSeparator = true; } } if(hTreePos!=NULL && selectedLeafs.empty()) { CShadowTree* pTree=(CShadowTree*)m_RefTreeCtrl.GetItemData(hTreePos); if(pTree->IsFrom(L"refs/remotes")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); popupMenu.AppendMenuIcon(eCmd_ManageRemotes, CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_MANAGEREMOTES)), IDI_SETTINGS); bAddSeparator = true; if(selectedLeafs.empty()) { int dummy = 0;//Needed for tokenize remoteName = pTree->GetRefName(); remoteName = remoteName.Mid(13); remoteName = remoteName.Tokenize(L"/", dummy); if(!remoteName.IsEmpty()) { CString temp; temp.Format(IDS_PROC_BROWSEREFS_FETCHFROM, remoteName); popupMenu.AppendMenuIcon(eCmd_Fetch, temp, IDI_PULL); temp.LoadString(IDS_DELETEREMOTETAG); popupMenu.AppendMenuIcon(eCmd_DeleteRemoteTag, temp, IDI_DELETE); } } } if(pTree->IsFrom(L"refs/heads")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString temp; temp.LoadString(IDS_MENUBRANCH); popupMenu.AppendMenuIcon(eCmd_CreateBranch, temp, IDI_COPY); } if(pTree->IsFrom(L"refs/tags")) { if(bAddSeparator) popupMenu.AppendMenu(MF_SEPARATOR); CString temp; temp.LoadString(IDS_MENUTAG); popupMenu.AppendMenuIcon(eCmd_CreateTag, temp, IDI_TAG); } } eCmd cmd=(eCmd)popupMenu.TrackPopupMenuEx(TPM_LEFTALIGN|TPM_RETURNCMD, point.x, point.y, this, 0); switch(cmd) { case eCmd_ViewLog: { CLogDlg dlg; dlg.SetStartRef(selectedLeafs[0]->GetRefName()); dlg.DoModal(); } break; case eCmd_RepoBrowser: CAppUtils::RunTortoiseProc(_T("/command:repobrowser /path:\"") + g_Git.m_CurrentDir + _T("\" /rev:") + selectedLeafs[0]->GetRefName()); break; case eCmd_DeleteBranch: case eCmd_DeleteRemoteBranch: { if(ConfirmDeleteRef(selectedLeafs)) DoDeleteRefs(selectedLeafs, true); Refresh(); } break; case eCmd_DeleteTag: { if(ConfirmDeleteRef(selectedLeafs)) DoDeleteRefs(selectedLeafs, true); Refresh(); } break; case eCmd_ShowReflog: { CRefLogDlg refLogDlg(this); refLogDlg.m_CurrentBranch = selectedLeafs[0]->GetRefName(); refLogDlg.DoModal(); } break; case eCmd_Fetch: { CAppUtils::Fetch(remoteName); Refresh(); } break; case eCmd_DeleteRemoteTag: { CDeleteRemoteTagDlg deleteRemoteTagDlg; deleteRemoteTagDlg.m_sRemote = remoteName; deleteRemoteTagDlg.DoModal(); } break; case eCmd_Switch: { CAppUtils::Switch(selectedLeafs[0]->GetRefName()); } break; case eCmd_Rename: { POSITION pos = m_ListRefLeafs.GetFirstSelectedItemPosition(); if(pos != NULL) m_ListRefLeafs.EditLabel(m_ListRefLeafs.GetNextSelectedItem(pos)); } break; case eCmd_AddRemote: { CAddRemoteDlg(this).DoModal(); Refresh(); } break; case eCmd_ManageRemotes: { CSinglePropSheetDlg(CString(MAKEINTRESOURCE(IDS_PROCS_TITLE_GITREMOTESETTINGS)), new CSettingGitRemote(g_Git.m_CurrentDir), this).DoModal(); // CSettingGitRemote W_Remotes(m_cmdPath); // W_Remotes.DoModal(); Refresh(); } break; case eCmd_CreateBranch: { CString *commitHash = NULL; if (selectedLeafs.size() == 1) commitHash = &(selectedLeafs[0]->m_csRefHash); CAppUtils::CreateBranchTag(false, commitHash); Refresh(); } break; case eCmd_CreateTag: { CAppUtils::CreateBranchTag(true); Refresh(); } break; case eCmd_Diff: { CFileDiffDlg dlg; dlg.SetDiff( NULL, selectedLeafs[0]->m_csRefHash, selectedLeafs[1]->m_csRefHash); dlg.DoModal(); } break; case eCmd_EditBranchDescription: { CInputDlg dlg; dlg.m_sHintText = CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_EDITDESCRIPTION)); dlg.m_sInputText = selectedLeafs[0]->m_csDescription; dlg.m_sTitle = CString(MAKEINTRESOURCE(IDS_PROC_BROWSEREFS_EDITDESCRIPTION)); dlg.m_bUseLogWidth = true; if(dlg.DoModal() == IDOK) { CString key; key.Format(_T("branch.%s.description"), selectedLeafs[0]->m_csRefName); dlg.m_sInputText.Replace(_T("\r"), _T("")); dlg.m_sInputText.Trim(); if (dlg.m_sInputText.IsEmpty()) g_Git.UnsetConfigValue(key); else g_Git.SetConfigValue(key, dlg.m_sInputText); Refresh(); } } break; } }