CShadowTree& CBrowseRefsDlg::GetTreeNode(CString refName, CShadowTree* pTreePos, bool bCreateIfNotExist) { if(pTreePos==NULL) { if(_wcsnicmp(refName, L"refs/", 5) == 0) refName=refName.Mid(5); pTreePos=&m_TreeRoot; } if(refName.IsEmpty()) return *pTreePos;//Found leaf CShadowTree* pNextTree=pTreePos->GetNextSub(refName,bCreateIfNotExist); if(pNextTree==NULL) { //Should not occur when all ref-names are valid and bCreateIfNotExist is true. ASSERT(!bCreateIfNotExist); return *pTreePos; } if(!refName.IsEmpty()) { //When the refName is not empty, this node is not a leaf, so lets add it to the tree control. //Leafs are for the list control. if(pNextTree->m_hTree==NULL) { //New tree. Create node in control. pNextTree->m_hTree=m_RefTreeCtrl.InsertItem(pNextTree->m_csRefName,pTreePos->m_hTree,NULL); m_RefTreeCtrl.SetItemData(pNextTree->m_hTree,(DWORD_PTR)pNextTree); } } return GetTreeNode(refName, pNextTree, bCreateIfNotExist); }
bool CBrowseRefsDlg::SelectRef(CString refName, bool bExactMatch) { if(!bExactMatch) { CString newRefName = GetFullRefName(refName); if(!newRefName.IsEmpty()) refName = newRefName; //else refName is not a valid ref. Try to select as good as possible. } if(_wcsnicmp(refName, L"refs/", 5) != 0) return false; // Not a ref name CShadowTree& treeLeafHead=GetTreeNode(refName,NULL,false); if(treeLeafHead.m_hTree != NULL) { //Not a leaf. Select tree node and return m_RefTreeCtrl.Select(treeLeafHead.m_hTree,TVGN_CARET); return true; } if(treeLeafHead.m_pParent==NULL) return false; //Weird... should not occur. //This is the current head. m_RefTreeCtrl.Select(treeLeafHead.m_pParent->m_hTree,TVGN_CARET); for(int indexPos = 0; indexPos < m_ListRefLeafs.GetItemCount(); ++indexPos) { CShadowTree* pCurrShadowTree = (CShadowTree*)m_ListRefLeafs.GetItemData(indexPos); if(pCurrShadowTree == &treeLeafHead) { m_ListRefLeafs.SetItemState(indexPos,LVIS_SELECTED,LVIS_SELECTED); m_ListRefLeafs.EnsureVisible(indexPos,FALSE); } } return true; }
HierarchyTreeScreenNode* ScreenMetadata::GetScreenNode() const { // Screen Node is one and only. return dynamic_cast<HierarchyTreeScreenNode*>(GetTreeNode(0)); }
void CBrowseRefsDlg::Refresh(CString selectRef) { remotes.clear(); if (g_Git.GetRemoteList(remotes)) MessageBox(CGit::GetLibGit2LastErr(_T("Could not get a list of remotes.")), _T("TortoiseGit"), MB_ICONERROR); if(!selectRef.IsEmpty()) { if(selectRef == "HEAD") { if (g_Git.GetCurrentBranchFromFile(g_Git.m_CurrentDir, selectRef)) selectRef.Empty(); else selectRef = L"refs/heads/" + selectRef; } } else { selectRef = GetSelectedRef(false, true); } m_RefTreeCtrl.DeleteAllItems(); m_ListRefLeafs.DeleteAllItems(); m_TreeRoot.m_ShadowTree.clear(); m_TreeRoot.m_csRefName = "refs"; m_TreeRoot.m_hTree=m_RefTreeCtrl.InsertItem(L"refs",NULL,NULL); m_RefTreeCtrl.SetItemData(m_TreeRoot.m_hTree,(DWORD_PTR)&m_TreeRoot); CString err; MAP_REF_GITREVREFBROWSER refMap; if (GitRevRefBrowser::GetGitRevRefMap(refMap, err, [&](const CString& refName) { //Use ref based on m_pickRef_Kind if (wcsncmp(refName, L"refs/heads/", 11) == 0 && !(m_pickRef_Kind & gPickRef_Head)) return false; //Skip if (wcsncmp(refName, L"refs/tags/", 10) == 0 && !(m_pickRef_Kind & gPickRef_Tag)) return false; //Skip if (wcsncmp(refName, L"refs/remotes/", 13) == 0 && !(m_pickRef_Kind & gPickRef_Remote)) return false; //Skip if (m_pickRef_Kind == gPickRef_Remote && wcsncmp(refName, L"refs/remotes/", 13) != 0) // do not show refs/stash if only remote branches are requested return false; return true; })) { MessageBox(_T("Get refs failed:") + err, _T("TortoiseGit"), MB_OK | MB_ICONERROR); } //Populate ref tree for (auto iterRefMap = refMap.cbegin(); iterRefMap != refMap.cend(); ++iterRefMap) { CShadowTree& treeLeaf = GetTreeNode(iterRefMap->first, nullptr, true); GitRevRefBrowser ref = iterRefMap->second; treeLeaf.m_csRefHash = ref.m_CommitHash.ToString(); treeLeaf.m_csUpstream = ref.m_UpstreamRef; CGit::GetShortName(treeLeaf.m_csUpstream, treeLeaf.m_csUpstream, L"refs/remotes/"); treeLeaf.m_csSubject = ref.GetSubject(); treeLeaf.m_csAuthor = ref.GetAuthorName(); treeLeaf.m_csDate = ref.GetAuthorDate(); treeLeaf.m_csDescription = ref.m_Description; } // always expand the tree first m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree, TVE_EXPAND); // try exact match first if (!selectRef.IsEmpty() && !SelectRef(selectRef, true)) SelectRef(selectRef, false); }
HierarchyTreePlatformNode* PlatformMetadata::GetPlatformNode() const { // Platform Node is one and only. return dynamic_cast<HierarchyTreePlatformNode*>(GetTreeNode(0)); }
void CBrowseRefsDlg::Refresh(CString selectRef) { // m_RefMap.clear(); // g_Git.GetMapHashToFriendName(m_RefMap); if(!selectRef.IsEmpty()) { if(selectRef == "HEAD") { selectRef = g_Git.GetSymbolicRef(selectRef, false); } } else { selectRef = GetSelectedRef(false, true); } m_RefTreeCtrl.DeleteAllItems(); m_ListRefLeafs.DeleteAllItems(); m_TreeRoot.m_ShadowTree.clear(); m_TreeRoot.m_csRefName = "refs"; m_TreeRoot.m_hTree=m_RefTreeCtrl.InsertItem(L"Refs",NULL,NULL); m_RefTreeCtrl.SetItemData(m_TreeRoot.m_hTree,(DWORD_PTR)&m_TreeRoot); CString allRefs, error; if (g_Git.Run(L"git.exe for-each-ref --format=" L"%(refname)%04" L"%(objectname)%04" L"%(authordate:relative)%04" L"%(subject)%04" L"%(authorname)%04" L"%(authordate:iso8601)%03", &allRefs, &error, CP_UTF8)) { CMessageBox::Show(NULL, CString(_T("Get refs failed\n")) + error, _T("TortoiseGit"), MB_OK | MB_ICONERROR); } int linePos=0; CString singleRef; MAP_STRING_STRING refMap; //First sort on ref name while(!(singleRef=allRefs.Tokenize(L"\03",linePos)).IsEmpty()) { singleRef.TrimLeft(L"\r\n"); int valuePos=0; CString refName=singleRef.Tokenize(L"\04",valuePos); if(refName.IsEmpty()) continue; CString refRest=singleRef.Mid(valuePos); //Use ref based on m_pickRef_Kind if (wcsncmp(refName, L"refs/heads/", 11) == 0 && !(m_pickRef_Kind & gPickRef_Head)) continue; //Skip if (wcsncmp(refName, L"refs/tags/", 10) == 0 && !(m_pickRef_Kind & gPickRef_Tag)) continue; //Skip if (wcsncmp(refName, L"refs/remotes/", 13) == 0 && !(m_pickRef_Kind & gPickRef_Remote)) continue; //Skip refMap[refName] = refRest; //Use } MAP_STRING_STRING descriptions = GetBranchDescriptions(); //Populate ref tree for(MAP_STRING_STRING::iterator iterRefMap=refMap.begin();iterRefMap!=refMap.end();++iterRefMap) { CShadowTree& treeLeaf=GetTreeNode(iterRefMap->first,NULL,true); CString values=iterRefMap->second; values.Replace(L"\04" L"\04",L"\04 \04");//Workaround Tokenize problem (treating 2 tokens as one) int valuePos=0; treeLeaf.m_csRefHash= values.Tokenize(L"\04",valuePos); if(valuePos < 0) continue; treeLeaf.m_csDate= values.Tokenize(L"\04",valuePos); if(valuePos < 0) continue; treeLeaf.m_csSubject= values.Tokenize(L"\04",valuePos); if(valuePos < 0) continue; treeLeaf.m_csAuthor= values.Tokenize(L"\04",valuePos); if(valuePos < 0) continue; treeLeaf.m_csDate_Iso8601= values.Tokenize(L"\04",valuePos); if (wcsncmp(iterRefMap->first, L"refs/heads/", 11) == 0) treeLeaf.m_csDescription = descriptions[treeLeaf.m_csRefName]; } // try exact match first if(selectRef.IsEmpty() || !(SelectRef(selectRef, true) || SelectRef(selectRef, false))) //Probably not on a branch. Select root node. m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree,TVE_EXPAND); }