// ReadTree is/must only be executed on an empty list int CGitHeadFileList::ReadTree() { CAutoWriteLock lock(m_SharedMutex); ATLASSERT(empty()); CAutoRepository repository(m_Gitdir); CAutoCommit commit; CAutoTree tree; bool ret = repository; ret = ret && !git_commit_lookup(commit.GetPointer(), repository, (const git_oid*)m_Head.m_hash); ret = ret && !git_commit_tree(tree.GetPointer(), commit); try { ret = ret && !ReadTreeRecursive(*repository, tree, "", CGitHeadFileList::CallBack, this); } catch (const std::bad_alloc& ex) { CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Catched exception inside ReadTreeRecursive: %s\n", ex.what()); return -1; } if (!ret) { clear(); m_LastModifyTimeHead = 0; return -1; } std::sort(this->begin(), this->end(), SortTree); m_TreeHash = git_commit_id(commit)->id; return 0; }
// ReadTree is/must only be executed on an empty list int CGitHeadFileList::ReadTree() { CAutoWriteLock lock(m_SharedMutex); ATLASSERT(empty()); CAutoRepository repository(m_Gitdir); CAutoCommit commit; CAutoTree tree; bool ret = repository; ret = ret && !git_commit_lookup(commit.GetPointer(), repository, (const git_oid*)m_Head.m_hash); ret = ret && !git_commit_tree(tree.GetPointer(), commit); ret = ret && !ReadTreeRecursive(*repository, tree, "", CGitHeadFileList::CallBack, this); if (!ret) { clear(); m_LastModifyTimeHead = 0; return -1; } std::sort(this->begin(), this->end(), SortTree); m_TreeHash = git_commit_id(commit)->id; return 0; }
int CRepositoryBrowser::ReadTree(CShadowFilesTree * treeroot, const CString& root) { CWaitCursor wait; CAutoRepository repository(g_Git.GetGitRepository()); if (!repository) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR); return -1; } if (m_sRevision == _T("HEAD")) { int ret = git_repository_head_unborn(repository); if (ret == 1) // is orphan return ret; else if (ret != 0) { MessageBox(g_Git.GetLibGit2LastErr(_T("Could not check HEAD.")), _T("TortoiseGit"), MB_ICONERROR); return ret; } } CGitHash hash; if (CGit::GetHash(repository, hash, m_sRevision)) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); return -1; } CAutoCommit commit; if (git_commit_lookup(commit.GetPointer(), repository, (git_oid *)hash.m_hash)) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup commit.")), _T("TortoiseGit"), MB_ICONERROR); return -1; } CAutoTree tree; if (git_commit_tree(tree.GetPointer(), commit)) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not get tree of commit.")), _T("TortoiseGit"), MB_ICONERROR); return -1; } if (!root.IsEmpty()) { CAutoTreeEntry treeEntry; if (git_tree_entry_bypath(treeEntry.GetPointer(), tree, CUnicodeUtils::GetUTF8(root))) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup path.")), _T("TortoiseGit"), MB_ICONERROR); return -1; } if (git_tree_entry_type(treeEntry) != GIT_OBJ_TREE) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup path.")), _T("TortoiseGit"), MB_ICONERROR); return -1; } CAutoObject object; if (git_tree_entry_to_object(object.GetPointer(), repository, treeEntry)) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup path.")), _T("TortoiseGit"), MB_ICONERROR); return -1; } tree = (git_tree*)object.Detach(); } treeroot->m_hash = CGitHash((char *)git_tree_id(tree)->id); ReadTreeRecursive(*repository, tree, treeroot); // try to resolve hash to a branch name if (m_sRevision == hash.ToString()) { MAP_HASH_NAME map; if (CGit::GetMapHashToFriendName(repository, map)) MessageBox(g_Git.GetLibGit2LastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR); if (!map[hash].empty()) m_sRevision = map[hash].at(0); } this->GetDlgItem(IDC_BUTTON_REVISION)->SetWindowText(m_sRevision); return 0; }
static git_commit* FindFileRecentCommit(git_repository* repository, const CString& path) { CAutoRevwalk walk; if (git_revwalk_new(walk.GetPointer(), repository)) return nullptr; CStringA pathA = CUnicodeUtils::GetUTF8(path); if (pathA.GetLength() >= MAX_PATH) return nullptr; const char *pathC = pathA; char folder[MAX_PATH] = {0}, file[MAX_PATH] = {0}; const char *slash = strrchr(pathC, '/'); if (slash) { strncpy(folder, pathC, slash - pathC + 1); folder[slash - pathC + 1] = '\0'; strcpy(file, slash + 1); } else { folder[0] = '\0'; strcpy(file, pathC); } TreewalkStruct treewalkstruct = { folder, file }; if (git_revwalk_push_head(walk)) return nullptr; git_oid oid; CAutoCommit commit; while (!git_revwalk_next(&oid, walk)) { if (git_commit_lookup(commit.GetPointer(), repository, &oid)) return nullptr; CAutoTree tree; if (git_commit_tree(tree.GetPointer(), commit)) return nullptr; memset(&treewalkstruct.oid.id, 0, sizeof(treewalkstruct.oid.id)); int ret = git_tree_walk(tree, GIT_TREEWALK_PRE, TreewalkCB_FindFileRecentCommit, &treewalkstruct); if (ret < 0 && ret != GIT_EUSER) return nullptr; // check if file not found if (git_oid_iszero(&treewalkstruct.oid)) return nullptr; bool diff = true; // for merge point, check if it is different to all parents, if yes then there are real change in the merge point. // if no parent then of course it is different for (unsigned int i = 0; i < git_commit_parentcount(commit); ++i) { CAutoCommit commit2; if (git_commit_parent(commit2.GetPointer(), commit, i)) return nullptr; CAutoTree tree2; if (git_commit_tree(tree2.GetPointer(), commit2)) return nullptr; TreewalkStruct treewalkstruct2 = { folder, file }; memset(&treewalkstruct2.oid.id, 0, sizeof(treewalkstruct2.oid.id)); int ret = git_tree_walk(tree2, GIT_TREEWALK_PRE, TreewalkCB_FindFileRecentCommit, &treewalkstruct2); if (ret < 0 && ret != GIT_EUSER) return nullptr; if (!git_oid_cmp(&treewalkstruct.oid, &treewalkstruct2.oid)) diff = false; else if (git_revwalk_hide(walk, git_commit_parent_id(commit, i))) return nullptr; } if (diff) break; } return commit.Detach(); }