Beispiel #1
0
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;
}
Beispiel #8
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;
}
Beispiel #9
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;
}
Beispiel #10
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);
		}
	}
}
Beispiel #11
0
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);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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);

	}