Exemple #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;
}
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;
}
Exemple #3
0
int GitRev::GetCommitFromHash_withoutLock(CGitHash &hash)
{
	GIT_COMMIT commit;
	if(git_get_commit_from_hash( &commit, hash.m_hash))
		return -1;

	this->ParserFromCommit(&commit);
	git_free_commit(&commit);

	return 0;
}
int CLogDataVector::Fill(std::unordered_set<CGitHash>& hashes)
{
	ATLASSERT(m_pLogCache);
	try
	{
		[] { git_init(); } ();
	}
	catch (const char* msg)
	{
		MessageBox(nullptr, L"Could not initialize libgit.\nlibgit reports:\n" + CString(msg), L"TortoiseGit", MB_ICONERROR);
		return -1;
	}

	std::set<GitRevLoglist*, SortByParentDate> revs;

	for (const auto& hash : hashes)
	{
		GIT_COMMIT commit;
		try
		{
			CAutoLocker lock(g_Git.m_critGitDllSec);
			if (git_get_commit_from_hash(&commit, hash.ToRaw()))
				return -1;
		}
		catch (char * msg)
		{
			MessageBox(nullptr, L"Could not get commit \"" + hash.ToString() + L"\".\nlibgit reports:\n" + CString(msg), L"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 (const auto& pRev : revs)
	{
		this->push_back(pRev->m_CommitHash);
		m_HashMap[pRev->m_CommitHash] = static_cast<int>(size()) - 1;
	}

	return 0;
}
Exemple #5
0
int GitRev::GetParentFromHash(CGitHash &hash)
{
	CAutoLocker lock(g_Git.m_critGitDllSec);

	g_Git.CheckAndInitDll();

	GIT_COMMIT commit;
	if(git_get_commit_from_hash( &commit, hash.m_hash))
		return -1;

	this->ParserParentFromCommit(&commit);
	git_free_commit(&commit);

	this->m_CommitHash=hash;

	return 0;
}
Exemple #6
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;
}
Exemple #7
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;
}
Exemple #8
0
int GitRev::SafeFetchFullInfo(CGit *git)
{
	if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
	{
		this->m_Files.Clear();
		git->CheckAndInitDll();
		GIT_COMMIT commit;
		GIT_COMMIT_LIST list;
		GIT_HASH   parent;
		memset(&commit,0,sizeof(GIT_COMMIT));

		CAutoLocker lock(g_Git.m_critGitDllSec);

		try
		{
			if (git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))
				return -1;
		}
		catch (char *)
		{
			return -1;
		}

		int i=0;

		git_get_commit_first_parent(&commit,&list);
		bool isRoot = (list==NULL);

		while(git_get_commit_next_parent(&list,parent) == 0 || isRoot)
		{
			GIT_FILE file=0;
			int count=0;

			try
			{
				if (isRoot)
					git_root_diff(git->GetGitDiff(), this->m_CommitHash.m_hash, &file, &count, 1);
				else
					git_diff(git->GetGitDiff(), parent, commit.m_hash, &file, &count, 1);
			}
			catch (char *)
			{
				git_free_commit(&commit);
				return -1;
			}
			isRoot = false;

			CTGitPath path;
			CString strnewname;
			CString stroldname;

			for (int j = 0; j < count; ++j)
			{
				path.Reset();
				char *newname;
				char *oldname;

				strnewname.Empty();
				stroldname.Empty();

				int mode,IsBin,inc,dec;
				git_get_diff_file(git->GetGitDiff(),file,j,&newname,&oldname,
						&mode,&IsBin,&inc,&dec);

				git->StringAppend(&strnewname, (BYTE*)newname, CP_UTF8);
				git->StringAppend(&stroldname, (BYTE*)oldname, CP_UTF8);

				path.SetFromGit(strnewname,&stroldname);
				path.ParserAction((BYTE)mode);
				path.m_ParentNo = i;

				this->m_Action|=path.m_Action;

				if(IsBin)
				{
					path.m_StatAdd=_T("-");
					path.m_StatDel=_T("-");
				}
				else
				{
					path.m_StatAdd.Format(_T("%d"),inc);
					path.m_StatDel.Format(_T("%d"),dec);
				}
				m_Files.AddPath(path);
			}
			git_diff_flush(git->GetGitDiff());
			++i;
		}


		InterlockedExchange(&m_IsUpdateing,FALSE);
		InterlockedExchange(&m_IsFull,TRUE);
		git_free_commit(&commit);
	}

	return 0;
}
Exemple #9
0
int GitRev::SafeGetSimpleList(CGit *git)
{
	if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
	{
		m_SimpleFileList.clear();
		git->CheckAndInitDll();
		GIT_COMMIT commit;
		GIT_COMMIT_LIST list;
		GIT_HASH   parent;
		memset(&commit,0,sizeof(GIT_COMMIT));

		CAutoLocker lock(g_Git.m_critGitDllSec);

		try
		{
			if(git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))
				return -1;
		}
		catch (char *)
		{
			return -1;
		}

		int i=0;
		bool isRoot = this->m_ParentHash.empty();
		git_get_commit_first_parent(&commit,&list);
		while(git_get_commit_next_parent(&list,parent) == 0 || isRoot)
		{
			GIT_FILE file=0;
			int count=0;
			try
			{
				if(isRoot)
					git_root_diff(git->GetGitSimpleListDiff(), commit.m_hash, &file, &count, 0);
				else
					git_diff(git->GetGitSimpleListDiff(), parent, commit.m_hash, &file, &count, 0);
			}
			catch (char *)
			{
				return -1;
			}

			isRoot = false;

			CTGitPath path;
			CString strnewname;
			CString stroldname;

			for (int j = 0; j < count; ++j)
			{
				path.Reset();
				char *newname;
				char *oldname;

				strnewname.Empty();
				stroldname.Empty();

				int mode,IsBin,inc,dec;
				try
				{
					git_get_diff_file(git->GetGitSimpleListDiff(), file, j, &newname, &oldname, &mode, &IsBin, &inc, &dec);
				}
				catch (char *)
				{
					return -1;
				}

				git->StringAppend(&strnewname, (BYTE*)newname, CP_UTF8);

				m_SimpleFileList.push_back(strnewname);

			}
			git_diff_flush(git->GetGitSimpleListDiff());
			++i;
		}

		InterlockedExchange(&m_IsUpdateing,FALSE);
		InterlockedExchange(&m_IsSimpleListReady, TRUE);
		git_free_commit(&commit);
	}

	return 0;
}
//CLogDataVector Class
int CLogDataVector::ParserFromLog(CTGitPath *path ,int count ,int infomask,CString *from,CString *to)
{
	// only enable --follow on files
	if ((path == NULL || path->IsDirectory()) && (infomask & CGit::LOG_INFO_FOLLOW))
		infomask = infomask ^ CGit::LOG_INFO_FOLLOW;

	CString hash;
	CString cmd=g_Git.GetLogCmd(hash,path,count,infomask,from,to,true);

	if(g_Git.IsInitRepos())
		return 0;

	git_init();

	GIT_LOG handle;
	if(git_open_log(&handle,CUnicodeUtils::GetMulti(cmd,CP_ACP).GetBuffer()))
	{
		return -1;
	}

	git_get_log_firstcommit(handle);

	GIT_COMMIT commit;

	GitRev rev;

	while (git_get_log_nextcommit(handle, &commit, infomask & CGit::LOG_INFO_FOLLOW) == 0)
	{
		if (commit.m_ignore == 1)
		{
			git_free_commit(&commit);
			continue;
		}

		CGitHash hash = (char*)commit.m_hash ;
		rev.Clear();

		GitRev *pRev = this->m_pLogCache->GetCacheData(hash);

		char *note=NULL;
		git_get_notes(commit.m_hash,&note);
		if(note)
		{
			pRev->m_Notes.Empty();
			g_Git.StringAppend(&pRev->m_Notes,(BYTE*)note);
		}

		if(pRev == NULL || !pRev->m_IsFull)
		{
			pRev->ParserFromCommit(&commit);
			pRev->ParserParentFromCommit(&commit);
			git_free_commit(&commit);
			//Must call free commit before SafeFetchFullInfo, commit parent is rewrite by log.
			//file list will wrong if parent rewrite.
			pRev->SafeFetchFullInfo(&g_Git);

		}
		else
		{
			ASSERT(pRev->m_CommitHash == hash);
			pRev->ParserParentFromCommit(&commit);
			git_free_commit(&commit);
		}

		this->push_back(pRev->m_CommitHash);

		m_HashMap[rev.m_CommitHash]=size()-1;

	}

	git_close_log(handle);

	return 0;
}
//CLogDataVector Class
int CLogDataVector::ParserFromLog(CTGitPath* path, DWORD count, DWORD infomask, CString* range)
{
	ATLASSERT(m_pLogCache);
	// only enable --follow on files
	if ((!path || path->IsDirectory()) && (infomask & CGit::LOG_INFO_FOLLOW))
		infomask = infomask ^ CGit::LOG_INFO_FOLLOW;

	CString gitrange = L"HEAD";
	if (range != nullptr)
		gitrange = *range;
	CFilterData filter;
	if (count == 0)
		filter.m_NumberOfLogsScale = CFilterData::SHOW_NO_LIMIT;
	else
	{
		filter.m_NumberOfLogs = count;
		filter.m_NumberOfLogsScale = CFilterData::SHOW_LAST_N_COMMITS;
	}
	CString cmd = g_Git.GetLogCmd(gitrange, path, infomask, &filter, m_logOrderBy);

	if (!g_Git.CanParseRev(gitrange))
		return -1;

	try
	{
		[] { git_init(); } ();
	}
	catch (const char* msg)
	{
		MessageBox(nullptr, L"Could not initialize libgit.\nlibgit reports:\n" + CString(msg), L"TortoiseGit", MB_ICONERROR);
		return -1;
	}

	GIT_LOG handle;
	try
	{
		CAutoLocker lock(g_Git.m_critGitDllSec);
		if (git_open_log(&handle, CUnicodeUtils::GetMulti(cmd, CP_UTF8)))
			return -1;
	}
	catch (char* msg)
	{
		MessageBox(nullptr, L"Could not open log.\nlibgit reports:\n" + CString(msg), L"TortoiseGit", MB_ICONERROR);
		return -1;
	}

	try
	{
		CAutoLocker lock(g_Git.m_critGitDllSec);
		[&]{ git_get_log_firstcommit(handle); }();
	}
	catch (char* msg)
	{
		MessageBox(nullptr, L"Could not get first commit.\nlibgit reports:\n" + CString(msg), L"TortoiseGit", MB_ICONERROR);
		return -1;
	}

	int ret = 0;
	while (ret == 0)
	{
		GIT_COMMIT commit;

		try
		{
			CAutoLocker lock(g_Git.m_critGitDllSec);
			[&]{ ret = git_get_log_nextcommit(handle, &commit, infomask & CGit::LOG_INFO_FOLLOW); }();
		}
		catch (char* msg)
		{
			MessageBox(nullptr, L"Could not get next commit.\nlibgit reports:\n" + CString(msg), L"TortoiseGit", MB_ICONERROR);
			break;
		}

		if (ret)
		{
			if (ret != -2) // other than end of revision walking
				MessageBox(nullptr, (L"Could not get next commit.\nlibgit returns:" + std::to_wstring(ret)).c_str(), L"TortoiseGit", MB_ICONERROR);
			break;
		}

		if (commit.m_ignore == 1)
		{
			git_free_commit(&commit);
			continue;
		}

		CGitHash hash = CGitHash::FromRaw(commit.m_hash);

		GitRevLoglist* pRev = this->m_pLogCache->GetCacheData(hash);

		char *pNote = nullptr;
		{
			CAutoLocker lock(g_Git.m_critGitDllSec);
			git_get_notes(commit.m_hash, &pNote);
		}
		if (pNote)
		{
			pRev->m_Notes = CUnicodeUtils::GetUnicode(pNote);
			free(pNote);
			pNote = nullptr;
		}

		pRev->ParserFromCommit(&commit);
		pRev->ParserParentFromCommit(&commit);
		git_free_commit(&commit);
		// Must call free commit before SafeFetchFullInfo, commit parent is rewrite by log.
		// file list will wrong if parent rewrite.

		if (!pRev->m_IsFull && (infomask & CGit::LOG_INFO_FULL_DIFF))
		{
			if (pRev->SafeFetchFullInfo(&g_Git))
			{
				MessageBox(nullptr, pRev->GetLastErr(), L"TortoiseGit", MB_ICONERROR);
				return -1;
			}
		}

		this->push_back(pRev->m_CommitHash);

		m_HashMap[pRev->m_CommitHash] = static_cast<int>(size()) - 1;
	}

	{
		CAutoLocker lock(g_Git.m_critGitDllSec);
		git_close_log(handle);
	}

	return 0;
}
//CLogDataVector Class
int CLogDataVector::ParserFromLog(CTGitPath *path, int count, int infomask, CString *range)
{
	// only enable --follow on files
	if ((path == NULL || path->IsDirectory()) && (infomask & CGit::LOG_INFO_FOLLOW))
		infomask = infomask ^ CGit::LOG_INFO_FOLLOW;

	CString gitrange = _T("HEAD");
	if (range != nullptr)
		gitrange = *range;
	CString cmd = g_Git.GetLogCmd(gitrange, path, count, infomask, true);

	if (!g_Git.CanParseRev(gitrange))
		return 0;

	try
	{
		[] { git_init(); } ();
	}
	catch (const char* msg)
	{
		MessageBox(NULL, _T("Could not initialize libgit.\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	GIT_LOG handle;
	try
	{
		CAutoLocker lock(g_Git.m_critGitDllSec);
		if (git_open_log(&handle,CUnicodeUtils::GetMulti(cmd, CP_UTF8).GetBuffer()))
		{
			return -1;
		}
	}
	catch (char* msg)
	{
		MessageBox(NULL, _T("Could not open log.\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	try
	{
		CAutoLocker lock(g_Git.m_critGitDllSec);
		[&]{ git_get_log_firstcommit(handle); }();
	}
	catch (char* msg)
	{
		MessageBox(NULL, _T("Could not get first commit.\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
		return -1;
	}

	int ret = 0;
	while (ret == 0)
	{
		GIT_COMMIT commit;

		try
		{
			CAutoLocker lock(g_Git.m_critGitDllSec);
			[&]{ ret = git_get_log_nextcommit(handle, &commit, infomask & CGit::LOG_INFO_FOLLOW); }();
		}
		catch (char* msg)
		{
			MessageBox(NULL, _T("Could not get next commit.\nlibgit reports:\n") + CString(msg), _T("TortoiseGit"), MB_ICONERROR);
			break;
		}

		if (ret)
		{
			if (ret != -2) // other than end of revision walking
				MessageBox(nullptr, (_T("Could not get next commit.\nlibgit returns:") + std::to_wstring(ret)).c_str(), _T("TortoiseGit"), MB_ICONERROR);
			break;
		}

		if (commit.m_ignore == 1)
		{
			git_free_commit(&commit);
			continue;
		}

		CGitHash hash = (char*)commit.m_hash ;

		GitRevLoglist* pRev = this->m_pLogCache->GetCacheData(hash);

		char *pNote = nullptr;
		{
			CAutoLocker lock(g_Git.m_critGitDllSec);
			git_get_notes(commit.m_hash, &pNote);
		}
		if (pNote)
		{
			pRev->m_Notes = CUnicodeUtils::GetUnicode(pNote);
			free(pNote);
			pNote = nullptr;
		}

		ASSERT(pRev->m_CommitHash == hash);
		pRev->ParserFromCommit(&commit);
		pRev->ParserParentFromCommit(&commit);
		git_free_commit(&commit);
		// Must call free commit before SafeFetchFullInfo, commit parent is rewrite by log.
		// file list will wrong if parent rewrite.

		if (!pRev->m_IsFull && (infomask & CGit::LOG_INFO_FULL_DIFF))
		{
			if (pRev->SafeFetchFullInfo(&g_Git))
			{
				MessageBox(nullptr, pRev->GetLastErr(), _T("TortoiseGit"), MB_ICONERROR);
				return -1;
			}
		}

		this->push_back(pRev->m_CommitHash);

		m_HashMap[pRev->m_CommitHash] = (int)size() - 1;

	}

	{
		CAutoLocker lock(g_Git.m_critGitDllSec);
		git_close_log(handle);
	}

	return 0;
}