int GitRev::GetParentFromHash(const CGitHash& hash) { CAutoLocker lock(g_Git.m_critGitDllSec); GIT_COMMIT commit; try { g_Git.CheckAndInitDll(); if (git_get_commit_from_hash(&commit, hash.m_hash)) { m_sErr = L"git_get_commit_from_hash failed for " + hash.ToString(); return -1; } } catch (char* msg) { m_sErr = L"Could not get parents of commit \"" + hash.ToString() + L"\".\nlibgit reports:\n" + CString(msg); return -1; } this->ParserParentFromCommit(&commit); git_free_commit(&commit); this->m_CommitHash=hash; return 0; }
TEST(CGitHash, Initial) { CGitHash empty; EXPECT_TRUE(empty.IsEmpty()); EXPECT_STREQ(L"0000000000000000000000000000000000000000", GIT_REV_ZERO); EXPECT_STREQ(GIT_REV_ZERO, empty.ToString()); EXPECT_TRUE(empty == empty); EXPECT_FALSE(empty != empty); CGitHash hash = CGitHash::FromHexStr("8d1861316061748cfee7e075dc138287978102ab"); EXPECT_FALSE(hash.IsEmpty()); EXPECT_STREQ(L"8d1861316061748cfee7e075dc138287978102ab", hash.ToString()); EXPECT_TRUE(hash == hash); EXPECT_FALSE(hash != hash); EXPECT_FALSE(hash == empty); EXPECT_TRUE(hash != empty); CGitHash hash2 = CGitHash::FromHexStr(L"8d1861316061748cfee7e075dc138287978102ab"); EXPECT_FALSE(hash2.IsEmpty()); EXPECT_STREQ(L"8d1861316061748cfee7e075dc138287978102ab", hash2.ToString()); EXPECT_TRUE(hash2 == hash); EXPECT_FALSE(hash2 != hash); EXPECT_FALSE(hash2 == empty); EXPECT_TRUE(hash2 != empty); hash2.Empty(); EXPECT_STREQ(GIT_REV_ZERO, hash2.ToString()); EXPECT_TRUE(hash2 == empty); EXPECT_FALSE(hash2 != empty); EXPECT_TRUE(hash2.IsEmpty()); unsigned char chararray[20] = { 0x8D, 0x18, 0x61, 0x31, 0x60, 0x61, 0x74, 0x8C, 0xFE, 0xE7, 0xE0, 0x75, 0xDC, 0x13, 0x82, 0x87, 0x97, 0x81, 0x02, 0xAB }; CGitHash hash3 = CGitHash::FromRaw(chararray); EXPECT_FALSE(hash3.IsEmpty()); EXPECT_STREQ(L"8d1861316061748cfee7e075dc138287978102ab", hash3.ToString()); EXPECT_TRUE(hash3 == hash); EXPECT_FALSE(hash3 != hash); EXPECT_FALSE(hash3 == empty); EXPECT_TRUE(hash3 != empty); CGitHash hash4; hash4 = CGitHash::FromHexStr(L"8d1861316061748cfee7e075dc138287978102ab"); EXPECT_TRUE(hash4 == hash); CGitHash hash5; hash5 = hash; EXPECT_TRUE(hash5 == hash); CGitHash hash6; hash6 = CGitHash::FromRaw(chararray); EXPECT_TRUE(hash6 == hash); CGitHash hash7 = CGitHash::FromHexStrTry(L"invalid"); EXPECT_TRUE(hash7.IsEmpty()); CGitHash hash8 = CGitHash::FromHexStrTry(L"01234567"); EXPECT_TRUE(hash8.IsEmpty()); }
void CRepositoryBrowser::OpenFile(const CString path, eOpenType mode, bool isSubmodule, CGitHash itemHash) { CTGitPath gitPath(path); CString temppath; CString file; GetTempPath(temppath); CGitHash hash; if (g_Git.GetHash(hash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); return; } file.Format(_T("%s%s_%s%s"), temppath, gitPath.GetBaseFilename(), hash.ToString().Left(g_Git.GetShortHASHLength()), gitPath.GetFileExtension()); if (isSubmodule) { file += _T(".txt"); CFile submoduleCommit(file, CFile::modeCreate | CFile::modeWrite); CStringA commitInfo = "Subproject commit " + CStringA(itemHash.ToString()); submoduleCommit.Write(commitInfo, commitInfo.GetLength()); } else if (g_Git.GetOneFile(m_sRevision, gitPath, file)) { CString out; out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, gitPath.GetGitPathString(), m_sRevision, file); MessageBox(out, _T("TortoiseGit"), MB_OK); return; } if (mode == ALTERNATIVEEDITOR) { CAppUtils::LaunchAlternativeEditor(file); return; } else if (mode == OPEN) { int ret = HINSTANCE_ERROR; ret = (int)ShellExecute(this->m_hWnd, NULL, file, NULL, NULL, SW_SHOW); if (ret > HINSTANCE_ERROR) return; } CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ") + file; CAppUtils::LaunchApplication(cmd, NULL, false); }
void CRepositoryBrowser::FileSaveAs(const CString path) { CTGitPath gitPath(path); CGitHash hash; if (g_Git.GetHash(hash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); return; } CString filename; filename.Format(_T("%s-%s%s"), gitPath.GetBaseFilename(), hash.ToString().Left(g_Git.GetShortHASHLength()), gitPath.GetFileExtension()); CFileDialog dlg(FALSE, NULL, filename, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, NULL); CString cmd, out; INT_PTR ret = dlg.DoModal(); SetCurrentDirectory(g_Git.m_CurrentDir); if (ret == IDOK) { filename = dlg.GetPathName(); if (g_Git.GetOneFile(m_sRevision, gitPath, filename)) { out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, gitPath.GetGitPathString(), m_sRevision, filename); MessageBox(out, _T("TortoiseGit"), MB_OK); return; } } }
void CRepositoryBrowser::FileSaveAs(const CString path) { CTGitPath gitPath(path); CGitHash hash; if (g_Git.GetHash(hash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); return; } CString filename; filename.Format(_T("%s-%s%s"), (LPCTSTR)gitPath.GetBaseFilename(), (LPCTSTR)hash.ToString().Left(g_Git.GetShortHASHLength()), (LPCTSTR)gitPath.GetFileExtension()); CFileDialog dlg(FALSE, nullptr, filename, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, nullptr); CString currentpath(g_Git.CombinePath(gitPath.GetContainingDirectory())); dlg.m_ofn.lpstrInitialDir = currentpath; CString cmd, out; INT_PTR ret = dlg.DoModal(); SetCurrentDirectory(g_Git.m_CurrentDir); if (ret == IDOK) { filename = dlg.GetPathName(); if (g_Git.GetOneFile(m_sRevision, gitPath, filename)) { out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, (LPCTSTR)gitPath.GetGitPathString(), (LPCTSTR)m_sRevision, (LPCTSTR)filename); MessageBox(g_Git.GetGitLastErr(out, CGit::GIT_CMD_GETONEFILE), _T("TortoiseGit"), MB_ICONERROR); return; } } }
TEST(CGitHash, ToString) { CGitHash hash = CGitHash::FromHexStr(L"0123456789abcdef0123456789abcdef01234567"); EXPECT_STREQ(L"0123456789abcdef0123456789abcdef01234567", hash.ToString()); EXPECT_STREQ(L"", hash.ToString(0)); EXPECT_STREQ(L"0", hash.ToString(1)); EXPECT_STREQ(L"01", hash.ToString(2)); EXPECT_STREQ(L"01234", hash.ToString(5)); EXPECT_STREQ(L"0123456", hash.ToString(7)); EXPECT_STREQ(L"0123456789", hash.ToString(10)); EXPECT_STREQ(L"0123456789abcdef0123", hash.ToString(20)); EXPECT_STREQ(L"0123456789abcdef0123456789abcdef01234567", hash.ToString(40)); }
int CLogDataVector::Fill(std::set<CGitHash>& hashes) { ATLASSERT(m_pLogCache); try { [] { git_init(); } (); } catch (const char* msg) { MessageBox(nullptr, _T("Could not initialize libgit.\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR); return -1; } std::set<GitRevLoglist*, SortByParentDate> revs; for (auto it = hashes.begin(); it != hashes.end(); ++it) { CGitHash hash = *it; GIT_COMMIT commit; try { CAutoLocker lock(g_Git.m_critGitDllSec); if (git_get_commit_from_hash(&commit, hash.m_hash)) { return -1; } } catch (char * msg) { MessageBox(nullptr, _T("Could not get commit \"") + hash.ToString() + _T("\".\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR); return -1; } GitRevLoglist* pRev = this->m_pLogCache->GetCacheData(hash); // right now this code is only used by TortoiseGitBlame, // as such git notes are not needed to be loaded pRev->ParserFromCommit(&commit); pRev->ParserParentFromCommit(&commit); git_free_commit(&commit); revs.insert(pRev); } for (auto it = revs.begin(); it != revs.end(); ++it) { GitRev *pRev = *it; this->push_back(pRev->m_CommitHash); m_HashMap[pRev->m_CommitHash] = (int)size() - 1; } return 0; }
int GitRev::GetCommitFromHash_withoutLock(const CGitHash& hash) { GIT_COMMIT commit; try { if (git_get_commit_from_hash(&commit, hash.m_hash)) { m_sErr = L"git_get_commit_from_hash failed for " + hash.ToString(); return -1; } } catch (char * msg) { m_sErr = L"Could not get commit \"" + hash.ToString() + L"\".\nlibgit reports:\n" + CString(msg); return -1; } this->ParserFromCommit(&commit); git_free_commit(&commit); m_sErr.Empty(); return 0; }
int GitRev::GetCommitFromHash_withoutLock(CGitHash &hash) { GIT_COMMIT commit; try { if (git_get_commit_from_hash(&commit, hash.m_hash)) return -1; } catch (char * msg) { MessageBox(NULL, _T("Could not get commit \"") + hash.ToString() + _T("\".\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR); return -1; } this->ParserFromCommit(&commit); git_free_commit(&commit); return 0; }
void CSyncDlg::OnBnClickedButtonApply() { CGitHash oldhash; if (g_Git.GetHash(oldhash, _T("HEAD"))) { MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR); return; } CImportPatchDlg dlg; CString cmd,output; if(dlg.DoModal() == IDOK) { int err=0; for (int i = 0; i < dlg.m_PathList.GetCount(); ++i) { cmd.Format(_T("git.exe am \"%s\""),dlg.m_PathList[i].GetGitPathString()); if (g_Git.Run(cmd, &output, CP_UTF8)) { CMessageBox::Show(NULL,output,_T("TortoiseGit"),MB_OK); err=1; break; } this->m_ctrlCmdOut.SetSel(-1,-1); this->m_ctrlCmdOut.ReplaceSel(cmd+_T("\n")); this->m_ctrlCmdOut.SetSel(-1,-1); this->m_ctrlCmdOut.ReplaceSel(output); } CGitHash newhash; if (g_Git.GetHash(newhash, _T("HEAD"))) { MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash after applying patches.")), _T("TortoiseGit"), MB_ICONERROR); return; } this->m_InLogList.Clear(); this->m_InChangeFileList.Clear(); if(newhash == oldhash) { this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false); this->m_InLogList.ShowText(_T("No commits get from patch")); this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true); } else { this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,true); this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true); CString range; range.Format(_T("%s..%s"), m_oldHash.ToString(), newhash.ToString()); this->AddDiffFileList(&m_InChangeFileList, &m_arInChangeList, newhash.ToString(), oldhash.ToString()); m_InLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE); this->FetchOutList(true); } this->m_ctrlTabCtrl.ShowTab(IDC_CMD_LOG-1,true); if(err) { this->ShowTab(IDC_CMD_LOG); } else { this->ShowTab(IDC_IN_LOGLIST); } } }
void CSyncDlg::PullComplete() { EnableControlButton(true); SwitchToInput(); this->FetchOutList(true); CGitHash newhash; if (g_Git.GetHash(newhash, _T("HEAD"))) MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash after pulling.")), _T("TortoiseGit"), MB_ICONERROR); if( this ->m_GitCmdStatus ) { CTGitPathList list; if(g_Git.ListConflictFile(list)) { this->m_ctrlCmdOut.SetSel(-1,-1); this->m_ctrlCmdOut.ReplaceSel(_T("Get conflict files fail\n")); this->ShowTab(IDC_CMD_LOG); return; } if (!list.IsEmpty()) { this->m_ConflictFileList.Clear(); CTGitPathList list; CTGitPath path; list.AddPath(path); this->m_ConflictFileList.GetStatus(&list,true); this->m_ConflictFileList.Show(CTGitPath::LOGACTIONS_UNMERGED, CTGitPath::LOGACTIONS_UNMERGED); this->ShowTab(IDC_IN_CONFLICT); } else this->ShowTab(IDC_CMD_LOG); } else { if(newhash == this->m_oldHash) { this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false); this->m_InLogList.ShowText(CString(MAKEINTRESOURCE(IDS_UPTODATE))); this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true); this->ShowTab(IDC_REFLIST); } else { this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,true); this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,true); this->AddDiffFileList(&m_InChangeFileList, &m_arInChangeList, newhash.ToString(), m_oldHash.ToString()); CString range; range.Format(_T("%s..%s"), m_oldHash.ToString(), newhash.ToString()); m_InLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE); this->ShowTab(IDC_IN_LOGLIST); } } }
void CGitBlameLogList::ContextMenuAction(int cmd, int /*FirstSelect*/, int /*LastSelect*/, CMenu * /*menu*/) { POSITION pos = GetFirstSelectedItemPosition(); int indexNext = GetNextSelectedItem(pos); if (indexNext < 0) return; CTortoiseGitBlameView *pView = DYNAMIC_DOWNCAST(CTortoiseGitBlameView,((CMainFrame*)::AfxGetApp()->GetMainWnd())->GetActiveView()); GitRevLoglist* pRev = &this->m_logEntries.GetGitRevAt(indexNext); switch (cmd & 0xFFFF) { case ID_BLAMEPREVIOUS: { int index = (cmd >> 16) & 0xFFFF; if (index > 0) index -= 1; CGitHash parentHash; std::vector<CString> parentFilenames; GetParentHash(pRev, index, parentHash, parentFilenames); for (size_t i = 0; i < parentFilenames.size(); ++i) { CString procCmd = _T("/path:\"") + pView->ResolveCommitFile(parentFilenames[i]) + _T("\" "); procCmd += _T(" /command:blame"); procCmd += _T(" /endrev:") + parentHash.ToString(); CCommonAppUtils::RunTortoiseGitProc(procCmd); } } break; case ID_GNUDIFF1: // fallthrough case ID_COMPAREWITHPREVIOUS: { int index = (cmd >> 16) & 0xFFFF; if (index > 0) index -= 1; CGitHash parentHash; std::vector<CString> parentFilenames; GetParentHash(pRev, index, parentHash, parentFilenames); for (size_t i = 0; i < parentFilenames.size(); ++i) { CString procCmd = _T("/path:\"") + pView->ResolveCommitFile(parentFilenames[i]) + _T("\" "); procCmd += _T(" /command:diff"); procCmd += _T(" /startrev:") + pRev->m_CommitHash.ToString(); procCmd += _T(" /endrev:") + parentHash.ToString(); if ((cmd & 0xFFFF) == ID_GNUDIFF1) procCmd += _T(" /unified"); CCommonAppUtils::RunTortoiseGitProc(procCmd); } } break; case ID_COPYCLIPBOARD: { CopySelectionToClipBoard(); } break; case ID_COPYHASH: { CopySelectionToClipBoard(ID_COPY_HASH); } break; case ID_EXPORT: RunTortoiseGitProcWithCurrentRev(_T("export"), pRev); break; case ID_CREATE_BRANCH: RunTortoiseGitProcWithCurrentRev(_T("branch"), pRev); break; case ID_CREATE_TAG: RunTortoiseGitProcWithCurrentRev(_T("tag"), pRev); break; case ID_SWITCHTOREV: RunTortoiseGitProcWithCurrentRev(_T("switch"), pRev); break; case ID_LOG: { CString procCmd; procCmd.Format(L"/command:log /path:\"%s\" /endrev:%s /rev:%s", (LPCTSTR)((CMainFrame*)::AfxGetApp()->GetMainWnd())->GetActiveView()->GetDocument()->GetPathName(), (LPCTSTR)pRev->m_CommitHash.ToString(), (LPCTSTR)pRev->m_CommitHash.ToString()); CCommonAppUtils::RunTortoiseGitProc(procCmd); } break; case ID_REPOBROWSE: RunTortoiseGitProcWithCurrentRev(_T("repobrowser"), pRev, ((CMainFrame*)::AfxGetApp()->GetMainWnd())->GetActiveView()->GetDocument()->GetPathName()); break; default: //CMessageBox::Show(nullptr, _T("Have not implemented"), _T("TortoiseGit"), MB_OK); break; } // switch (cmd) }
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; }
void CRepositoryBrowser::OpenFile(const CString path, eOpenType mode, bool isSubmodule, CGitHash itemHash) { CTGitPath gitPath(path); CString temppath; CString file; GetTempPath(temppath); CGitHash hash; if (g_Git.GetHash(hash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); return; } file.Format(_T("%s%s_%s%s"), (LPCTSTR)temppath, (LPCTSTR)gitPath.GetBaseFilename(), (LPCTSTR)hash.ToString().Left(g_Git.GetShortHASHLength()), (LPCTSTR)gitPath.GetFileExtension()); if (isSubmodule) { if (mode == OPEN && !GitAdminDir::IsBareRepo(g_Git.m_CurrentDir)) { CTGitPath subPath = CTGitPath(g_Git.m_CurrentDir); subPath.AppendPathString(gitPath.GetWinPathString()); CAutoRepository repo(subPath.GetGitPathString()); CAutoCommit commit; if (!repo || git_commit_lookup(commit.GetPointer(), repo, (const git_oid *)itemHash.m_hash)) { CString out; out.Format(IDS_REPOBROWSEASKSUBMODULEUPDATE, (LPCTSTR)itemHash.ToString(), (LPCTSTR)gitPath.GetGitPathString()); if (MessageBox(out, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) != IDYES) return; CString sCmd; sCmd.Format(_T("/command:subupdate /bkpath:\"%s\" /selectedpath:\"%s\""), (LPCTSTR)g_Git.m_CurrentDir, (LPCTSTR)gitPath.GetGitPathString()); CAppUtils::RunTortoiseGitProc(sCmd); return; } CString cmd; cmd.Format(_T("/command:repobrowser /path:\"%s\" /rev:%s"), (LPCTSTR)g_Git.CombinePath(path), (LPCTSTR)itemHash.ToString()); CAppUtils::RunTortoiseGitProc(cmd); return; } file += _T(".txt"); CFile submoduleCommit(file, CFile::modeCreate | CFile::modeWrite); CStringA commitInfo = "Subproject commit " + CStringA(itemHash.ToString()); submoduleCommit.Write(commitInfo, commitInfo.GetLength()); } else if (g_Git.GetOneFile(m_sRevision, gitPath, file)) { CString out; out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, (LPCTSTR)gitPath.GetGitPathString(), (LPCTSTR)m_sRevision, (LPCTSTR)file); MessageBox(g_Git.GetGitLastErr(out, CGit::GIT_CMD_GETONEFILE), _T("TortoiseGit"), MB_ICONERROR); return; } if (mode == ALTERNATIVEEDITOR) { CAppUtils::LaunchAlternativeEditor(file); return; } else if (mode == OPEN) { CAppUtils::ShellOpen(file); return; } CAppUtils::ShowOpenWithDialog(file); }
bool SVNFetchCommand::Execute() { CString cmd, out, err; cmd = _T("git.exe config svn-remote.svn.fetch"); if (!g_Git.Run(cmd, &out, &err, CP_UTF8)) { int start = out.Find(_T(':')); if( start >=0 ) out=out.Mid(start); if(out.Left(5) == _T(":refs")) out=out.Mid(6); start = 0; out=out.Tokenize(_T("\n"),start); } else { MessageBox(hwndExplorer, L"Found no SVN remote.", L"TortoiseGit", MB_OK | MB_ICONERROR); return false; } CGitHash upstreamOldHash; if (g_Git.GetHash(upstreamOldHash, out)) { MessageBox(hwndExplorer, g_Git.GetGitLastErr(_T("Could not get upstream hash.")), _T("TortoiseGit"), MB_ICONERROR); return false; } CProgressDlg progress; progress.m_GitCmd=_T("git.exe svn fetch"); CGitHash upstreamNewHash; // declare outside lambda, because it is captured by reference progress.m_PostCmdCallback = [&](DWORD status, PostCmdList& postCmdList) { if (status) return; if (g_Git.GetHash(upstreamNewHash, out)) { MessageBox(hwndExplorer, g_Git.GetGitLastErr(_T("Could not get upstream hash after fetching.")), _T("TortoiseGit"), MB_ICONERROR); return; } if (upstreamOldHash == upstreamNewHash) return; postCmdList.emplace_back(IDI_DIFF, _T("Fetched Diff"), [&] { CLogDlg dlg; dlg.SetParams(CTGitPath(_T("")), CTGitPath(_T("")), _T(""), upstreamOldHash.ToString() + _T("..") + upstreamNewHash.ToString(), 0); dlg.DoModal(); }); postCmdList.emplace_back(IDI_LOG, _T("Fetched Log"), [&] { CFileDiffDlg dlg; dlg.SetDiff(nullptr, upstreamNewHash.ToString(), upstreamOldHash.ToString()); dlg.DoModal(); }); }; return progress.DoModal() == IDOK; }
bool PullCommand::Execute() { if (!GitAdminDir().HasAdminDir(g_Git.m_CurrentDir)) { CMessageBox::Show(hwndExplorer, IDS_NOWORKINGCOPY, IDS_APPNAME, MB_ICONERROR); return false; } CPullFetchDlg dlg; dlg.m_IsPull=TRUE; if(dlg.DoModal()==IDOK) { CString url; url=dlg.m_RemoteURL; if(dlg.m_bAutoLoad) { CAppUtils::LaunchPAgent(NULL,&dlg.m_RemoteURL); } CString cmd; CGitHash hashOld; if (g_Git.GetHash(hashOld, _T("HEAD"))) { MessageBox(hwndExplorer, g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR); return false; } CString cmdRebase; if(dlg.m_bRebase) cmdRebase = "--rebase "; CString noff; CString ffonly; CString squash; CString nocommit; CString notags; if (!dlg.m_bFetchTags) notags = _T("--no-tags"); if(dlg.m_bNoFF) noff=_T("--no-ff"); if (dlg.m_bFFonly) ffonly = _T("--ff-only"); if(dlg.m_bSquash) squash=_T("--squash"); if(dlg.m_bNoCommit) nocommit=_T("--no-commit"); int ver = CAppUtils::GetMsysgitVersion(); if(ver >= 0x01070203) //above 1.7.0.2 cmdRebase += _T("--progress "); cmd.Format(_T("git.exe pull -v %s %s %s %s %s %s \"%s\" %s"), cmdRebase, noff, ffonly, squash, nocommit, notags, url, dlg.m_RemoteBranchName); CProgressDlg progress; progress.m_GitCmd = cmd; progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_PROC_PULL_DIFFS))); progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_PROC_PULL_LOG))); CTGitPath gitPath = g_Git.m_CurrentDir; if (gitPath.HasSubmodules()) progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_PROC_SUBMODULESUPDATE))); //progress.m_PostCmdList.Add(_T("Show Conflict")); if (parser.HasVal(_T("closeonend"))) progress.m_bAutoCloseOnSuccess = !!parser.GetLongVal(_T("closeonend")); INT_PTR ret = progress.DoModal(); if (ret == IDOK && progress.m_GitStatus == 1 && progress.m_LogText.Find(_T("CONFLICT")) >= 0 && CMessageBox::Show(NULL, IDS_SEECHANGES, IDS_APPNAME, MB_YESNO | MB_ICONINFORMATION) == IDYES) { CChangedDlg dlg; dlg.m_pathList.AddPath(CTGitPath()); dlg.DoModal(); return FALSE; } CGitHash hashNew; if (g_Git.GetHash(hashNew, L"HEAD")) { MessageBox(hwndExplorer, g_Git.GetGitLastErr(_T("Could not get HEAD hash after pulling.")), _T("TortoiseGit"), MB_ICONERROR); return FALSE; } if( ret == IDC_PROGRESS_BUTTON1) { if(hashOld == hashNew) { if(progress.m_GitStatus == 0) CMessageBox::Show(NULL, IDS_UPTODATE, IDS_APPNAME, MB_OK | MB_ICONINFORMATION); return TRUE; } CFileDiffDlg dlg; dlg.SetDiff(NULL, hashNew.ToString(), hashOld.ToString()); dlg.DoModal(); return TRUE; } else if ( ret == IDC_PROGRESS_BUTTON1 +1 ) { if(hashOld == hashNew) { if(progress.m_GitStatus == 0) CMessageBox::Show(NULL, IDS_UPTODATE, IDS_APPNAME, MB_OK | MB_ICONINFORMATION); return TRUE; } CLogDlg dlg; //dlg.SetParams(cmdLinePath); dlg.SetParams(CTGitPath(_T("")), CTGitPath(_T("")), _T(""), hashOld.ToString() + _T("..") + hashNew.ToString(), 0); // dlg.SetIncludeMerge(!!parser.HasKey(_T("merge"))); // val = parser.GetVal(_T("propspath")); // if (!val.IsEmpty()) // dlg.SetProjectPropertiesPath(CTSVNPath(val)); dlg.DoModal(); } else if (ret == IDC_PROGRESS_BUTTON1 + 2 && gitPath.HasSubmodules()) { CString sCmd; sCmd.Format(_T("/command:subupdate /bkpath:\"%s\""), g_Git.m_CurrentDir); CAppUtils::RunTortoiseGitProc(sCmd); } } return FALSE; }
int CRepositoryBrowser::ReadTree(CShadowFilesTree * treeroot) { CStringA gitdir = CUnicodeUtils::GetMulti(g_Git.m_CurrentDir, CP_UTF8); git_repository *repository = NULL; git_commit *commit = NULL; git_tree * tree = NULL; int ret = 0; do { ret = git_repository_open(&repository, gitdir.GetBuffer()); if (ret) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR); break; } if (m_sRevision == _T("HEAD")) { ret = git_repository_head_unborn(repository); if (ret == 1) // is orphan break; else if (ret != 0) { MessageBox(g_Git.GetLibGit2LastErr(_T("Could not check HEAD.")), _T("TortoiseGit"), MB_ICONERROR); break; } } CGitHash hash; if (g_Git.GetHash(hash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); break; } ret = git_commit_lookup(&commit, repository, (git_oid *) hash.m_hash); if (ret) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup commit.")), _T("TortoiseGit"), MB_ICONERROR); break; } ret = git_commit_tree(&tree, commit); if (ret) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not get tree of commit.")), _T("TortoiseGit"), MB_ICONERROR); break; } 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 (g_Git.GetMapHashToFriendName(map)) MessageBox(g_Git.GetGitLastErr(_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); } while(0); if (tree) git_tree_free(tree); if (commit) git_commit_free(commit); if (repository) git_repository_free(repository); return ret; }
void CRevisionGraphWnd::DrawTexts (GraphicsDevice& graphics, const CRect& /*logRect*/, const CSize& offset) { //COLORREF standardTextColor = GetSysColor(COLOR_WINDOWTEXT); if (m_nFontSize <= 0) return; // iterate over all visible nodes if (graphics.pDC) graphics.pDC->SetTextAlign (TA_CENTER | TA_TOP); CString fontname = CRegString(_T("Software\\TortoiseGit\\LogFontName"), _T("Courier New")); Gdiplus::Font font(fontname.GetBuffer(),(REAL)m_nFontSize,FontStyleRegular); SolidBrush blackbrush((ARGB)Color::Black); DWORD revGraphUseLocalForCur = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\Graph\\RevGraphUseLocalForCur")); node v; forall_nodes(v,m_Graph) { // get node and position String label=this->m_GraphAttr.labelNode(v); RectF noderect (GetNodeRect (v, offset)); // draw the revision text CGitHash hash = this->m_logEntries[v->index()]; double hight = noderect.Height / (m_HashMap[hash].size()?m_HashMap[hash].size():1); if(m_HashMap.find(hash) == m_HashMap.end() || m_HashMap[hash].size() == 0) { Color background; background.SetFromCOLORREF (GetSysColor(COLOR_WINDOW)); Gdiplus::Pen pen(background,1.0F); Color brightColor = LimitedScaleColor (background, RGB(255,0,0), 0.9f); Gdiplus::SolidBrush brush(brightColor); DrawRoundedRect(graphics, background,1, &pen, brightColor, &brush, noderect); if(graphics.graphics) { graphics.graphics->DrawString(hash.ToString().Left(g_Git.GetShortHASHLength()),-1, &font, Gdiplus::PointF(noderect.X + this->GetLeftRightMargin()*this->m_fZoomFactor,noderect.Y+this->GetTopBottomMargin()*m_fZoomFactor), &blackbrush); } if(graphics.pSVG) { graphics.pSVG->Text((int)(noderect.X + this->GetLeftRightMargin() * this->m_fZoomFactor), (int)(noderect.Y + this->GetTopBottomMargin() * m_fZoomFactor + m_nFontSize), CUnicodeUtils::GetUTF8(fontname), m_nFontSize, false, false, (ARGB)Color::Black, CUnicodeUtils::GetUTF8(hash.ToString().Left(g_Git.GetShortHASHLength()))); } if (graphics.pGraphviz) { CString shortHash = hash.ToString().Left(g_Git.GetShortHASHLength()); graphics.pGraphviz->DrawNode(_T("g") + shortHash, shortHash, fontname, m_nFontSize, background, brightColor, (int)noderect.Height); } }else { if (graphics.pGraphviz) { CString id = _T("g") + hash.ToString().Left(g_Git.GetShortHASHLength()); graphics.pGraphviz->BeginDrawTableNode(id, fontname, m_nFontSize, (int)noderect.Height); } for (int i = 0; i < m_HashMap[hash].size(); ++i) { CString shortname; CString str = m_HashMap[hash][i]; RectF rect; rect.X = (REAL)noderect.X; rect.Y = (REAL)(noderect.Y + hight*i); rect.Width = (REAL)noderect.Width; rect.Height = (REAL)hight; COLORREF colRef = RGB(224, 224, 224); if(CGit::GetShortName(str,shortname,_T("refs/heads/"))) { if (!revGraphUseLocalForCur && shortname == m_CurrentBranch) colRef = m_Colors.GetColor(CColors::CurrentBranch); else colRef = m_Colors.GetColor(CColors::LocalBranch); } else if(CGit::GetShortName(str,shortname,_T("refs/remotes/"))) { colRef = m_Colors.GetColor(CColors::RemoteBranch); } else if(CGit::GetShortName(str,shortname,_T("refs/tags/"))) { colRef = m_Colors.GetColor(CColors::Tag); } else if(CGit::GetShortName(str,shortname,_T("refs/stash"))) { colRef = m_Colors.GetColor(CColors::Stash); shortname=_T("stash"); } else if(CGit::GetShortName(str,shortname,_T("refs/bisect/"))) { if(shortname.Find(_T("good")) == 0) { colRef = m_Colors.GetColor(CColors::BisectGood); shortname = _T("good"); } if(shortname.Find(_T("bad")) == 0) { colRef = m_Colors.GetColor(CColors::BisectBad); shortname = _T("bad"); } }else if(CGit::GetShortName(str,shortname,_T("refs/notes/"))) { colRef = m_Colors.GetColor(CColors::NoteNode); } else { CGit::GetShortName(str, shortname, _T("refs/")); } Gdiplus::Color color(GetRValue(colRef), GetGValue(colRef), GetBValue(colRef)); Gdiplus::Pen pen(color); Gdiplus::SolidBrush brush(color); int mask =0; mask |= (i==0)? ROUND_UP:0; mask |= (i== m_HashMap[hash].size()-1)? ROUND_DOWN:0; this->DrawRoundedRect(graphics, color,1,&pen, color,&brush, rect,mask); if (graphics.graphics) { //graphics.graphics->FillRectangle(&SolidBrush(Gdiplus::Color(GetRValue(colRef), GetGValue(colRef), GetBValue(colRef))), // rect); graphics.graphics->DrawString(shortname.GetBuffer(),shortname.GetLength(), &font, Gdiplus::PointF((REAL)(noderect.X + this->GetLeftRightMargin()*m_fZoomFactor), (REAL)(noderect.Y + this->GetTopBottomMargin()*m_fZoomFactor+ hight*i)), &blackbrush); //graphics.graphics->DrawString(shortname.GetBuffer(), shortname.GetLength(), ::new Gdiplus::Font(graphics.pDC->m_hDC), PointF(noderect.X, noderect.Y + hight *i),NULL, NULL); } else if (graphics.pSVG) { graphics.pSVG->Text((int)(noderect.X + this->GetLeftRightMargin() * m_fZoomFactor), (int)(noderect.Y + this->GetTopBottomMargin() * m_fZoomFactor + hight * i + m_nFontSize), CUnicodeUtils::GetUTF8(fontname), m_nFontSize, false, false, (ARGB)Color::Black, CUnicodeUtils::GetUTF8(shortname)); } else if (graphics.pGraphviz) { graphics.pGraphviz->DrawTableNode(shortname, color); } } if (graphics.pGraphviz) { graphics.pGraphviz->EndDrawTableNode(); } } if ((m_SelectedEntry1 == v)) DrawMarker(graphics, noderect, mpLeft, 0, Color(0,0, 255), 1); if ((m_SelectedEntry2 == v)) DrawMarker(graphics, noderect, mpLeft, 0, Color(136,0, 21), 2); }