コード例 #1
0
ファイル: RebaseDlg.cpp プロジェクト: murank/TortoiseGitMod
int CRebaseDlg::CheckNextCommitIsSquash()
{
	int index;
	if(m_CommitList.m_IsOldFirst)
		index=m_CurrentRebaseIndex+1;
	else
		index=m_CurrentRebaseIndex-1;

	GitRev *curRev;
	do
	{
		if(index<0)
			return -1;
		if(index>= m_CommitList.GetItemCount())
			return -1;

		curRev=(GitRev*)m_CommitList.m_arShownList[index];

		if( curRev->GetAction(&m_CommitList)&CTGitPath::LOGACTIONS_REBASE_SQUASH )
			return 0;
		if( curRev->GetAction(&m_CommitList)&CTGitPath::LOGACTIONS_REBASE_SKIP)
		{
			if(m_CommitList.m_IsOldFirst)
				index++;
			else
				index--;
		}
		else
			return -1;

	}while(curRev->GetAction(&m_CommitList)&CTGitPath::LOGACTIONS_REBASE_SKIP);

	return -1;

}
コード例 #2
0
ファイル: FileDiffDlg.cpp プロジェクト: murank/TortoiseGitMod
void CFileDiffDlg::OnTimer(UINT_PTR nIDEvent)
{
	if (m_bThreadRunning)
		return;

	if( nIDEvent == IDT_FILTER)
	{
		CString sFilterText;
		KillTimer(IDT_FILTER);
		m_cFilter.GetWindowText(sFilterText);

		m_cFileList.SetRedraw(FALSE);
		m_cFileList.DeleteAllItems();

		Filter(sFilterText);

		m_cFileList.SetRedraw(TRUE);

		__super::OnTimer(nIDEvent);
	}

	if( nIDEvent == IDT_INPUT)
	{
		KillTimer(IDT_INPUT);
		TRACE(_T("Input Timer\r\n"));

		GitRev gitrev;
		CString str;
		int mask = 0;
		this->m_ctrRev1Edit.GetWindowText(str);
		if( !gitrev.GetCommit(str) )
		{
			this->m_rev1=gitrev;
			mask |= 0x1;
		}

		this->m_ctrRev2Edit.GetWindowText(str);

		if( !gitrev.GetCommit(str) )
		{
			this->m_rev2=gitrev;
			mask |= 0x2;
		}

		this->SetURLLabels(mask);

		if(mask == 0x3)
		{

			InterlockedExchange(&m_bThreadRunning, TRUE);
			if (AfxBeginThread(DiffThreadEntry, this)==NULL)
			{
				InterlockedExchange(&m_bThreadRunning, FALSE);
				CMessageBox::Show(NULL, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);
			}
		}
	}
}
コード例 #3
0
bool LogCommand::Execute()
{
	//the log command line looks like this:
	//command:log path:<path_to_file_or_directory_to_show_the_log_messages> [startrev:<startrevision>] [endrev:<endrevision>]

	CString val = parser.GetVal(_T("startrev"));
	if ( val.IsEmpty() )
	{
		// support deprecated parameter prior 1.5.0
		val = parser.GetVal(_T("revstart"));
	}
	GitRev revstart ;
	val = parser.GetVal(_T("endrev"));
	if ( val.IsEmpty() )
	{
		// support deprecated parameter prior 1.5.0
		val = parser.GetVal(_T("revend"));
	}
	GitRev revend ;
	val = parser.GetVal(_T("limit"));
	int limit = _tstoi(val);
	val = parser.GetVal(_T("pegrev"));
	if ( val.IsEmpty() )
	{
		// support deprecated parameter prior 1.5.0
		val = parser.GetVal(_T("revpeg"));
	}

	GitRev pegrev;

#if 0
	SVNRev pegrev = val.IsEmpty() ? SVNRev() : SVNRev(val);
	if (!revstart.IsValid())
		revstart = SVNRev::REV_HEAD;
	if (!revend.IsValid())
		revend = 0;
#endif

	if (limit == 0)
	{
		CRegDWORD reg = CRegDWORD(_T("Software\\TortoiseGit\\NumberOfLogs"), 100);
		limit = (int)(LONG)reg;
	}
	
	CLogDlg dlg;
	theApp.m_pMainWnd = &dlg;
	//dlg.SetParams(cmdLinePath);
	dlg.SetParams(cmdLinePath, pegrev, revstart, revend, limit);
//	dlg.SetIncludeMerge(!!parser.HasKey(_T("merge")));
//	val = parser.GetVal(_T("propspath"));
//	if (!val.IsEmpty())
//		dlg.SetProjectPropertiesPath(CTSVNPath(val));
	dlg.DoModal();			
	return true;
}
コード例 #4
0
void CLogDataVector::updateLanes(GitRev& c, Lanes& lns, CGitHash &sha)
{
// we could get third argument from c.sha(), but we are in fast path here
// and c.sha() involves a deep copy, so we accept a little redundancy

	if (lns.isEmpty())
		lns.init(sha);

	bool isDiscontinuity;
	bool isFork = lns.isFork(sha, isDiscontinuity);
	bool isMerge = (c.ParentsCount() > 1);
	bool isInitial = (c.ParentsCount() == 0);

	if (isDiscontinuity)
		lns.changeActiveLane(sha); // uses previous isBoundary state

	lns.setBoundary(c.IsBoundary() == TRUE); // update must be here
	TRACE(_T("%s %d"),c.m_CommitHash.ToString(),c.IsBoundary());

	if (isFork)
		lns.setFork(sha);
	if (isMerge)
		lns.setMerge(c.m_ParentHash);
	//if (c.isApplied)
	//	lns.setApplied();
	if (isInitial)
		lns.setInitial();

	lns.getLanes(c.m_Lanes); // here lanes are snapshotted

	CGitHash nextSha;
	if( !isInitial)
		nextSha = c.m_ParentHash[0];

	lns.nextParent(nextSha);

	//if (c.isApplied)
	//	lns.afterApplied();
	if (isMerge)
		lns.afterMerge();
	if (isFork)
		lns.afterFork();
	if (lns.isBranch())
		lns.afterBranch();

//	QString tmp = "", tmp2;
//	for (uint i = 0; i < c.lanes.count(); i++) {
//		tmp2.setNum(c.lanes[i]);
//		tmp.append(tmp2 + "-");
//	}
//	qDebug("%s %s",tmp.latin1(), c.sha.latin1());
}
コード例 #5
0
int CLogDataVector::ParserFromRefLog(CString ref)
{
	if(g_Git.m_IsUseGitDLL)
	{
		git_for_each_reflog_ent(CUnicodeUtils::GetUTF8(ref),AddTolist,this);
		for(int i=0;i<size();i++)
		{
			m_pLogCache->m_HashMap[at(i)].m_Ref.Format(_T("%s{%d}"), ref,i);
		}

	}
	else
	{

		CString cmd, out;
		GitRev rev;
		cmd.Format(_T("git.exe reflog show %s"),ref);
		if (g_Git.Run(cmd, &out, NULL, CP_UTF8))
			return -1;

		int pos=0;
		while(pos>=0)
		{
			CString one=out.Tokenize(_T("\n"),pos);
			int ref=one.Find(_T(' '),0);
			if(ref<0)
				continue;

			rev.Clear();

			rev.m_CommitHash=g_Git.GetHash(one.Left(ref));
			int action=one.Find(_T(' '),ref+1);
			int message;
			if(action>0)
			{
				rev.m_Ref=one.Mid(ref+1,action-ref-2);
				message=one.Find(_T(":"),action);
				if(message>0)
				{
					rev.m_RefAction=one.Mid(action+1,message-action-1);
					rev.GetSubject()=one.Right(one.GetLength()-message-1);
				}
			}

			this->m_pLogCache->m_HashMap[rev.m_CommitHash]=rev;

			this->push_back(rev.m_CommitHash);

		}
	}
	return 0;
}
コード例 #6
0
ファイル: RebaseDlg.cpp プロジェクト: murank/TortoiseGitMod
void CRebaseDlg::FillLogMessageCtrl()
{
	int selCount = m_CommitList.GetSelectedCount();
	if (selCount == 1 && (m_RebaseStage == CHOOSE_BRANCH || m_RebaseStage == CHOOSE_COMMIT_PICK_MODE))
	{
		POSITION pos = m_CommitList.GetFirstSelectedItemPosition();
		int selIndex = m_CommitList.GetNextSelectedItem(pos);
		GitRev* pLogEntry = reinterpret_cast<GitRev *>(m_CommitList.m_arShownList.SafeGetAt(selIndex));
		m_FileListCtrl.UpdateWithGitPathList(pLogEntry->GetFiles(&m_CommitList));
		m_FileListCtrl.m_CurrentVersion = pLogEntry->m_CommitHash;
		m_FileListCtrl.Show(GITSLC_SHOWVERSIONED);
		m_LogMessageCtrl.Call(SCI_SETREADONLY, FALSE);
		m_LogMessageCtrl.SetText(pLogEntry->GetSubject() + _T("\n") + pLogEntry->GetBody());
		m_LogMessageCtrl.Call(SCI_SETREADONLY, TRUE);
	}
}
コード例 #7
0
int AddTolist(unsigned char * /*osha1*/, unsigned char *nsha1, const char * /*name*/, unsigned long /*time*/, int /*sz*/, const char *msg, void *data)
{
	CLogDataVector *vector = (CLogDataVector*)data;
	GitRev rev;
	rev.m_CommitHash=(char*)nsha1;

	CString one;
	g_Git.StringAppend(&one, (BYTE *)msg);

	int message=one.Find(_T(":"),0);
	if(message>0)
	{
		rev.m_RefAction=one.Left(message);
		rev.GetSubject()=one.Mid(message+1);
	}

	vector->m_pLogCache->m_HashMap[rev.m_CommitHash]=rev;
	vector->insert(vector->begin(),rev.m_CommitHash);

	return 0;
}
コード例 #8
0
ファイル: RefLogDlg.cpp プロジェクト: 15375514460/TortoiseGit
int AddToRefLoglist(unsigned char * /*osha1*/, unsigned char *nsha1, const char * /*name*/, unsigned long time, int /*sz*/, const char *msg, void *data)
{
	std::vector<GitRev> *vector = (std::vector<GitRev> *)data;
	GitRev rev;
	rev.m_CommitHash = (char *)nsha1;
	rev.GetCommitterDate() = CTime(time);

	CString one;
	g_Git.StringAppend(&one, (BYTE *)msg);

	int message = one.Find(_T(":"), 0);
	if (message > 0)
	{
		rev.m_RefAction = one.Left(message);
		rev.GetSubject() = one.Mid(message + 1);
	}

	vector->insert(vector->begin(), rev); 

	return 0;
}
コード例 #9
0
ファイル: RebaseDlg.cpp プロジェクト: murank/TortoiseGitMod
void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)
{
	if(pBranch)
	{
		CString text=pBranch->GetString();
		CString tooltip;

		GitRev rev;
		rev.GetCommit(text);

		tooltip.Format(_T("CommitHash:%s\nCommit by: %s  %s\n <b>%s</b> \n %s"),
			rev.m_CommitHash.ToString(),
			rev.GetAuthorName(),
			CLoglistUtils::FormatDateAndTime(rev.GetAuthorDate(), DATE_LONGDATE),
			rev.GetSubject(),
			rev.GetBody());

		pBranch->DisableTooltip();
		this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);
	}
}
コード例 #10
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;
}
コード例 #11
0
ファイル: RebaseDlg.cpp プロジェクト: murank/TortoiseGitMod
int CRebaseDlg::DoRebase()
{
	CString cmd,out;
	if(m_CurrentRebaseIndex <0)
		return 0;
	if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )
		return 0;

	GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
	int mode=pRev->GetAction(&m_CommitList) & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;
	CString nocommit;

	if( mode== CTGitPath::LOGACTIONS_REBASE_SKIP)
	{
		pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
		return 0;
	}

	if( mode != CTGitPath::LOGACTIONS_REBASE_PICK )
	{
		this->m_SquashMessage+= pRev->GetSubject();
		this->m_SquashMessage+= _T("\n");
		this->m_SquashMessage+= pRev->GetBody();
	}
	else
		this->m_SquashMessage.Empty();

	if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
		nocommit=_T(" --no-commit ");

	CString log;
	log.Format(_T("%s %d: %s"),CTGitPath::GetActionName(mode),this->GetCurrentCommitID(),pRev->m_CommitHash.ToString());
	AddLogString(log);
	AddLogString(pRev->GetSubject());
	if (pRev->GetSubject().IsEmpty())
	{
		CMessageBox::Show(m_hWnd, _T("Found an empty commit message. You have to enter one or rebase cannot proceed."), _T("TortoiseGit"), MB_OK | MB_ICONEXCLAMATION);
		mode = CTGitPath::LOGACTIONS_REBASE_EDIT;
	}

	cmd.Format(_T("git.exe cherry-pick %s %s"),nocommit,pRev->m_CommitHash.ToString());

	if(g_Git.Run(cmd,&out,CP_UTF8))
	{
		AddLogString(out);
		CTGitPathList list;
		if(g_Git.ListConflictFile(list))
		{
			AddLogString(_T("Get conflict files fail"));
			return -1;
		}
		if(list.GetCount() == 0 )
		{
			if(mode ==  CTGitPath::LOGACTIONS_REBASE_PICK)
			{
				pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
				return 0;
			}
			if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)
			{
				this->m_RebaseStage = REBASE_EDIT ;
				return -1; // Edit return -1 to stop rebase.
			}
			// Squash Case
			if(CheckNextCommitIsSquash())
			{   // no squash
				// let user edit last commmit message
				this->m_RebaseStage = REBASE_SQUASH_EDIT;
				return -1;
			}
		}
		if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
			m_RebaseStage = REBASE_SQUASH_CONFLICT;
		else
			m_RebaseStage = REBASE_CONFLICT;
		return -1;

	}
	else
	{
		AddLogString(out);
		if(mode ==  CTGitPath::LOGACTIONS_REBASE_PICK)
		{
			pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
			return 0;
		}
		if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)
		{
			this->m_RebaseStage = REBASE_EDIT ;
			return -1; // Edit return -1 to stop rebase.
		}

		// Squash Case
		if(CheckNextCommitIsSquash())
		{   // no squash
			// let user edit last commmit message
			this->m_RebaseStage = REBASE_SQUASH_EDIT;
			return -1;
		}
		else if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
			pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
	}

	return 0;
}
コード例 #12
0
ファイル: RefLogDlg.cpp プロジェクト: 15375514460/TortoiseGit
int ParserFromRefLog(CString ref, std::vector<GitRev> &refloglist)
{
	refloglist.clear();
	if (g_Git.m_IsUseLibGit2)
	{
		CAutoRepository repo(g_Git.GetGitRepository());
		if (!repo)
		{
			MessageBox(nullptr, CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}

		CAutoReflog reflog;
		if (git_reflog_read(reflog.GetPointer(), repo, CUnicodeUtils::GetUTF8(ref)) < 0)
		{
			MessageBox(nullptr, CGit::GetLibGit2LastErr(_T("Could not read reflog.")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}

		for (size_t i = 0; i < git_reflog_entrycount(reflog); ++i)
		{
			const git_reflog_entry *entry = git_reflog_entry_byindex(reflog, i);
			if (!entry)
				continue;

			GitRev rev;
			rev.m_CommitHash = (char *)git_reflog_entry_id_new(entry)->id;
			rev.m_Ref.Format(_T("%s@{%d}"), ref, i);
			rev.GetCommitterDate() = CTime(git_reflog_entry_committer(entry)->when.time);
			if (git_reflog_entry_message(entry) != nullptr)
			{
				CString one;
				g_Git.StringAppend(&one, (BYTE *)git_reflog_entry_message(entry));
				int message = one.Find(_T(":"), 0);
				if (message > 0)
				{
					rev.m_RefAction = one.Left(message);
					rev.GetSubject() = one.Mid(message + 1);
				}
			}
			refloglist.push_back(rev); 
		}
	}
	else if (g_Git.m_IsUseGitDLL)
	{
		git_for_each_reflog_ent(CUnicodeUtils::GetUTF8(ref), AddToRefLoglist, &refloglist);
		for (size_t i = 0; i < refloglist.size(); ++i)
			refloglist[i].m_Ref.Format(_T("%s@{%d}"), ref, i);
	}
	else
	{
		CString cmd, out;
		GitRev rev;
		cmd.Format(_T("git.exe reflog show --pretty=\"%%H %%gD: %%gs\" --date=raw %s"), ref);
		if (g_Git.Run(cmd, &out, NULL, CP_UTF8))
			return -1;

		int i = 0;
		CString prefix = ref + _T("@{");
		int pos = 0;
		while (pos >= 0)
		{
			CString one = out.Tokenize(_T("\n"), pos);
			int refPos = one.Find(_T(' '), 0);
			if (refPos < 0)
				continue;

			rev.Clear();

			CString hashStr = one.Left(refPos);
			rev.m_CommitHash = hashStr;
			rev.m_Ref.Format(_T("%s@{%d}"), ref, i++);
			int prefixPos = one.Find(prefix, refPos + 1);
			if (prefixPos != refPos + 1)
				continue;

			int spacePos = one.Find(_T(' '), prefixPos + prefix.GetLength() + 1);
			if (spacePos < 0)
				continue;

			CString timeStr = one.Mid(prefixPos + prefix.GetLength(), spacePos - prefixPos - prefix.GetLength());
			rev.GetCommitterDate() = CTime(_ttoi(timeStr));
			int action = one.Find(_T("}: "), spacePos + 1);
			if (action > 0)
			{
				action += 2;
				int message = one.Find(_T(":"), action);
				if (message > 0)
				{
					rev.m_RefAction = one.Mid(action + 1, message - action - 1);
					rev.GetSubject() = one.Right(one.GetLength() - message - 1);
				}
			}

			refloglist.push_back(rev);
		}
	}
	return 0;
}
コード例 #13
0
void CTortoiseGitBlameData::ParseBlameOutput(BYTE_VECTOR &data, CGitHashMap & HashToRev, DWORD dateFormat, bool bRelativeTimes)
{
	std::map<CGitHash, CString> hashToFilename;

	std::vector<CGitHash>		hashes;
	std::vector<int>			originalLineNumbers;
	std::vector<CString>		filenames;
	std::vector<BYTE_VECTOR>	rawLines;
	std::vector<CString>		authors;
	std::vector<CString>		dates;

	CGitHash hash;
	int originalLineNumber = 0;
	int finalLineNumber = 0;
	int numberOfSubsequentLines = 0;
	CString filename;

	int pos = 0;
	bool expectHash = true;
	while (pos >= 0 && (size_t)pos < data.size())
	{
		if (data[pos] == 0)
		{
			++pos;
			continue;
		}

		int lineBegin = pos;
		int lineEnd = data.find('\n', lineBegin);
		if (lineEnd < 0)
			lineEnd = (int)data.size();

		if (lineEnd > lineBegin)
		{
			if (data[lineBegin] != '\t')
			{
				if (expectHash)
				{
					expectHash = false;
					if (lineEnd - lineBegin > 40)
					{
						hash.ConvertFromStrA((char*)&data[lineBegin]);

						int hashEnd = lineBegin + 40;
						int originalLineNumberBegin = hashEnd + 1;
						int originalLineNumberEnd = data.find(' ', originalLineNumberBegin);
						if (originalLineNumberEnd >= 0)
						{
							originalLineNumber = atoi(CStringA((LPCSTR)&data[originalLineNumberBegin], originalLineNumberEnd - originalLineNumberBegin));
							int finalLineNumberBegin = originalLineNumberEnd + 1;
							int finalLineNumberEnd = (numberOfSubsequentLines == 0) ? data.find(' ', finalLineNumberBegin) : lineEnd;
							if (finalLineNumberEnd >= 0)
							{
								finalLineNumber = atoi(CStringA((LPCSTR)&data[finalLineNumberBegin], finalLineNumberEnd - finalLineNumberBegin));
								if (numberOfSubsequentLines == 0)
								{
									int numberOfSubsequentLinesBegin = finalLineNumberEnd + 1;
									int numberOfSubsequentLinesEnd = lineEnd;
									numberOfSubsequentLines = atoi(CStringA((LPCSTR)&data[numberOfSubsequentLinesBegin], numberOfSubsequentLinesEnd - numberOfSubsequentLinesBegin));
								}
							}
							else
							{
								// parse error
								finalLineNumber = 0;
								numberOfSubsequentLines = 0;
							}
						}
						else
						{
							// parse error
							finalLineNumber = 0;
							numberOfSubsequentLines = 0;
						}

						auto it = hashToFilename.find(hash);
						if (it != hashToFilename.end())
							filename = it->second;
						else
							filename.Empty();
					}
					else
					{
						// parse error
						finalLineNumber = 0;
						numberOfSubsequentLines = 0;
					}
				}
				else
				{
					int tokenBegin = lineBegin;
					int tokenEnd = data.find(' ', tokenBegin);
					if (tokenEnd >= 0)
					{
						if (!strncmp("filename", (const char*)&data[tokenBegin], tokenEnd - tokenBegin))
						{
							int filenameBegin = tokenEnd + 1;
							int filenameEnd = lineEnd;
							CStringA filenameA = CStringA((LPCSTR)&data[filenameBegin], filenameEnd - filenameBegin);
							filename = UnquoteFilename(filenameA);
							auto r = hashToFilename.insert(std::make_pair(hash, filename));
							if (!r.second)
							{
								r.first->second = filename;
							}
						}
					}
				}
			}
			else
			{
				expectHash = true;
				// remove <TAB> at start
				BYTE_VECTOR line;
				if (lineEnd - 1 > lineBegin)
					line.append(&data[lineBegin + 1], lineEnd-lineBegin - 1);

				hashes.push_back(hash);
				filenames.push_back(filename);
				originalLineNumbers.push_back(originalLineNumber);
				rawLines.push_back(line);
				--numberOfSubsequentLines;
			}
		}
		pos = lineEnd + 1;
	}

	for (auto it = hashes.begin(), it_end = hashes.end(); it != it_end; ++it)
	{
		CGitHash hash = *it;
		CString err;
		GitRev* pRev = GetRevForHash(HashToRev, hash, &err);
		if (pRev)
		{
			authors.push_back(pRev->GetAuthorName());
			dates.push_back(CLoglistUtils::FormatDateAndTime(pRev->GetAuthorDate(), dateFormat, true, bRelativeTimes));
		}
		else
		{
			MessageBox(nullptr, err, _T("TortoiseGit"), MB_ICONERROR);
			authors.push_back(CString());
			dates.push_back(CString());
		}
	}

	m_Hash.swap(hashes);
	m_OriginalLineNumbers.swap(originalLineNumbers);
	m_Filenames.swap(filenames);
	m_RawLines.swap(rawLines);

	m_Authors.swap(authors);
	m_Dates.swap(dates);
	// reset detected and applied encoding
	m_encode = -1;
	m_Utf8Lines.clear();
}
コード例 #14
0
ファイル: LogDataVector.cpp プロジェクト: 3F/tortoisegit-mdc
//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)
			break;

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

		CGitHash hash = (char*)commit.m_hash ;

		GitRev *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.Empty();
			g_Git.StringAppend(&pRev->m_Notes,(BYTE*)pNote);
		}

		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))
		{
			try
			{
				pRev->SafeFetchFullInfo(&g_Git);
			}
			catch (char * g_last_error)
			{
				MessageBox(NULL, _T("Could not fetch full info of a commit.\nlibgit reports:\n") + CString(g_last_error), _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;
}
コード例 #15
0
void CTortoiseGitBlameData::ParseBlameOutput(BYTE_VECTOR &data, CGitHashMap & HashToRev, DWORD dateFormat, bool bRelativeTimes)
{
	std::unordered_map<CGitHash, CString> hashToFilename;

	std::vector<CGitHash>		hashes;
	std::vector<int>			originalLineNumbers;
	std::vector<CString>		filenames;
	std::vector<BYTE_VECTOR>	rawLines;
	std::vector<CString>		authors;
	std::vector<CString>		dates;

	CGitHash hash;
	int originalLineNumber = 0;
	int numberOfSubsequentLines = 0;
	CString filename;

	size_t pos = 0;
	bool expectHash = true;
	while (pos < data.size())
	{
		if (data[pos] == 0)
		{
			++pos;
			continue;
		}

		size_t lineBegin = pos;
		size_t lineEnd = data.find('\n', lineBegin);
		if (lineEnd == BYTE_VECTOR::npos)
			lineEnd = data.size();

		if (lineEnd > lineBegin)
		{
			if (data[lineBegin] != '\t')
			{
				if (expectHash)
				{
					expectHash = false;
					if (lineEnd - lineBegin > 2 * GIT_HASH_SIZE)
					{
						hash = CGitHash::FromHexStr(reinterpret_cast<char*>(&data[lineBegin]));

						size_t hashEnd = lineBegin + 2 * GIT_HASH_SIZE;
						size_t originalLineNumberBegin = hashEnd + 1;
						size_t originalLineNumberEnd = data.find(' ', originalLineNumberBegin);
						if (originalLineNumberEnd != BYTE_VECTOR::npos)
						{
							originalLineNumber = atoi(CStringA(reinterpret_cast<LPCSTR>(&data[originalLineNumberBegin]), static_cast<int>(originalLineNumberEnd - originalLineNumberBegin)));
							size_t finalLineNumberBegin = originalLineNumberEnd + 1;
							size_t finalLineNumberEnd = (numberOfSubsequentLines == 0) ? data.find(' ', finalLineNumberBegin) : lineEnd;
							if (finalLineNumberEnd != BYTE_VECTOR::npos)
							{
								if (numberOfSubsequentLines == 0)
								{
									size_t numberOfSubsequentLinesBegin = finalLineNumberEnd + 1;
									size_t numberOfSubsequentLinesEnd = lineEnd;
									numberOfSubsequentLines = atoi(CStringA(reinterpret_cast<LPCSTR>(&data[numberOfSubsequentLinesBegin]), static_cast<int>(numberOfSubsequentLinesEnd - numberOfSubsequentLinesBegin)));
								}
							}
							else
							{
								// parse error
								numberOfSubsequentLines = 0;
							}
						}
						else
						{
							// parse error
							numberOfSubsequentLines = 0;
						}

						auto it = hashToFilename.find(hash);
						if (it != hashToFilename.end())
							filename = it->second;
						else
							filename.Empty();
					}
					else
					{
						// parse error
						numberOfSubsequentLines = 0;
					}
				}
				else
				{
					size_t tokenBegin = lineBegin;
					size_t tokenEnd = data.find(' ', tokenBegin);
					if (tokenEnd != BYTE_VECTOR::npos)
					{
						if (!strncmp("filename", reinterpret_cast<const char*>(&data[tokenBegin]), tokenEnd - tokenBegin))
						{
							size_t filenameBegin = tokenEnd + 1;
							size_t filenameEnd = lineEnd;
							CStringA filenameA = CStringA(reinterpret_cast<LPCSTR>(&data[filenameBegin]), static_cast<int>(filenameEnd - filenameBegin));
							filename = UnquoteFilename(filenameA);
							auto r = hashToFilename.emplace(hash, filename);
							if (!r.second)
							{
								r.first->second = filename;
							}
						}
					}
				}
			}
			else
			{
				expectHash = true;
				// remove <TAB> at start
				BYTE_VECTOR line;
				if (lineEnd - 1 > lineBegin)
					line.append(&data[lineBegin + 1], lineEnd-lineBegin - 1);

				while (!line.empty() && line[line.size() - 1] == 13)
					line.pop_back();

				hashes.push_back(hash);
				filenames.push_back(filename);
				originalLineNumbers.push_back(originalLineNumber);
				rawLines.push_back(line);
				--numberOfSubsequentLines;
			}
		}
		pos = lineEnd + 1;
	}

	for (const auto& hash2 : hashes)
	{
		CString err;
		GitRev* pRev = GetRevForHash(HashToRev, hash2, &err);
		if (pRev)
		{
			authors.push_back(pRev->GetAuthorName());
			dates.push_back(CLoglistUtils::FormatDateAndTime(pRev->GetAuthorDate(), dateFormat, true, bRelativeTimes));
		}
		else
		{
			MessageBox(nullptr, err, L"TortoiseGit", MB_ICONERROR);
			authors.emplace_back();
			dates.emplace_back();
		}
	}

	m_Hash.swap(hashes);
	m_OriginalLineNumbers.swap(originalLineNumbers);
	m_Filenames.swap(filenames);
	m_RawLines.swap(rawLines);

	m_Authors.swap(authors);
	m_Dates.swap(dates);
	// reset detected and applied encoding
	m_encode = -1;
	m_Utf8Lines.clear();
}
コード例 #16
0
ファイル: PropertiesWnd.cpp プロジェクト: hfeeki/TortoiseGit
void CPropertiesWnd::UpdateProperties(GitRev *rev)
{
	if(rev)
	{
		m_CommitHash->SetValue(rev->m_CommitHash.ToString());
		m_AuthorName->SetValue(rev->GetAuthorName());
		m_AuthorDate->SetValue(rev->GetAuthorDate().Format(_T("%Y-%m-%d %H:%M")));
		m_AuthorEmail->SetValue(rev->GetAuthorEmail());

		m_CommitterName->SetValue(rev->GetAuthorName());
		m_CommitterEmail->SetValue(rev->GetCommitterEmail());
		m_CommitterDate->SetValue(rev->GetCommitterDate().Format(_T("%Y-%m-%d %H:%M")));

		m_Subject->SetValue(rev->GetSubject());
		m_Body->SetValue(rev->GetBody().Trim());

		RemoveParent();

		m_ParentGroup;

		CLogDataVector		*pLogEntry = &((CMainFrame*)AfxGetApp()->GetMainWnd())->m_wndOutput.m_LogList.m_logEntries;

		for (unsigned int i = 0; i < rev->m_ParentHash.size(); ++i)
		{
			CString str;
			CString parentsubject;

			GitRev *p =NULL;

			if( pLogEntry->m_pLogCache->m_HashMap.find(rev->m_ParentHash[i]) == pLogEntry->m_pLogCache->m_HashMap.end())
			{
				p=NULL;
			}
			else
			{
				p= &pLogEntry->m_pLogCache->m_HashMap[rev->m_ParentHash[i]] ;
			}
			if(p)
				parentsubject=p->GetSubject();

			str.Format(_T("%d - %s \n %s"),i,rev->m_ParentHash[i].ToString(),parentsubject);

			CMFCPropertyGridProperty*pProtery=new CMFCPropertyGridProperty(
											rev->m_ParentHash[i].ToString().Left(8),
												parentsubject,
												str
											);
			pProtery->AllowEdit(FALSE);
			m_ParentGroup->AddSubItem(pProtery);
		}
		m_ParentGroup->Expand();
		for (int i = 0; i < m_BaseInfoGroup->GetSubItemsCount(); ++i)
			m_BaseInfoGroup->GetSubItem(i)->SetDescription(m_BaseInfoGroup->GetSubItem(i)->GetValue());

	}
	else
	{
		m_CommitHash->SetValue(_T(""));
		m_AuthorName->SetValue(_T(""));
		m_AuthorDate->SetValue(_T(""));
		m_AuthorEmail->SetValue(_T(""));

		m_CommitterName->SetValue(_T(""));
		m_CommitterEmail->SetValue(_T(""));
		m_CommitterDate->SetValue(_T(""));

		m_Subject->SetValue(_T(""));
		m_Body->SetValue(_T(""));

		RemoveParent();

		for (int i = 0; i < m_BaseInfoGroup->GetSubItemsCount(); ++i)
			m_BaseInfoGroup->GetSubItem(i)->SetDescription(_T(""));
	}
	this->Invalidate();
	m_wndPropList.Invalidate();
}
コード例 #17
0
void GetRevParsingTests()
{
	GitRev rev;
	EXPECT_TRUE(rev.m_CommitHash.IsEmpty());
	EXPECT_EQ(0, rev.GetCommit(_T("HEAD")));
	EXPECT_STREQ(_T("7c3cbfe13a929d2291a574dca45e4fd2d2ac1aa6"), rev.m_CommitHash.ToString());
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-07 18:03:58"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-07 18:03:58"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Changed ASCII file"), rev.GetSubject());
	EXPECT_STREQ(_T(""), rev.GetBody());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	EXPECT_EQ(0, rev.ParentsCount());
	EXPECT_EQ(0, rev.GetParentFromHash(rev.m_CommitHash));
	ASSERT_EQ(1, rev.ParentsCount());
	EXPECT_STREQ(_T("1fc3c9688e27596d8717b54f2939dc951568f6cb"), rev.m_ParentHash[0].ToString());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	EXPECT_EQ(0, rev.GetCommit(GitRev::GetWorkingCopy()));
	EXPECT_TRUE(rev.m_CommitHash.IsEmpty());
	EXPECT_STREQ(_T(""), rev.GetAuthorName());
	EXPECT_STREQ(_T(""), rev.GetAuthorEmail());
	EXPECT_STREQ(_T(""), rev.GetCommitterName());
	EXPECT_STREQ(_T(""), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("Working Copy"), rev.GetSubject());
	EXPECT_STREQ(_T(""), rev.GetBody());
	EXPECT_EQ(0, rev.ParentsCount());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	EXPECT_EQ(0, rev.GetCommit(_T("aa5b97f89cea6863222823c8289ce392d06d1691")));
	EXPECT_STREQ(_T("aa5b97f89cea6863222823c8289ce392d06d1691"), rev.m_CommitHash.ToString());
	EXPECT_STREQ(_T("Another dummy with ümlaut"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-14 22:30:06"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Another dummy with ümlaut"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-14 22:30:06"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Subject line"), rev.GetSubject());
	EXPECT_STREQ(_T("\nalso some more lines\n\nhere in body\n\nSigned-off-by: Another dummy with ümlaut <*****@*****.**>\n"), rev.GetBody());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	EXPECT_TRUE(rev.m_CommitHash.IsEmpty());
	EXPECT_EQ(0, rev.GetCommit(_T("1fc3c9688e27596d8717b54f2939dc951568f6cb")));
	EXPECT_STREQ(_T("1fc3c9688e27596d8717b54f2939dc951568f6cb"), rev.m_CommitHash.ToString());
	EXPECT_STREQ(_T("Some other User"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-07 18:03:39"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-07 18:03:39"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Added an ascii file"), rev.GetSubject());
	EXPECT_STREQ(_T(""), rev.GetBody());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	EXPECT_EQ(-1, rev.GetCommit(_T("does-not-exist")));
	EXPECT_FALSE(rev.GetLastErr().IsEmpty());
	EXPECT_TRUE(rev.m_CommitHash.IsEmpty());
	rev.Clear();
	CGitHash hash(_T("aa5b97f89cea6863222823c8289ce392d06d1691"));
	EXPECT_EQ(0, rev.GetCommitFromHash(hash));
	EXPECT_EQ(hash, rev.m_CommitHash);
	EXPECT_STREQ(_T("Another dummy with ümlaut"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-14 22:30:06"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Another dummy with ümlaut"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-14 22:30:06"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Subject line"), rev.GetSubject());
	EXPECT_STREQ(_T("\nalso some more lines\n\nhere in body\n\nSigned-off-by: Another dummy with ümlaut <*****@*****.**>\n"), rev.GetBody());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	EXPECT_EQ(0, rev.GetCommit(_T("8d1ebbcc7eeb63af10ff8bcf7712afb9fcc90b8a")));
	EXPECT_STREQ(_T("8d1ebbcc7eeb63af10ff8bcf7712afb9fcc90b8a"), rev.m_CommitHash.ToString());
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-04 17:50:24"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-04 17:50:24"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Merge branch 'for-merge' into subdir/branch"), rev.GetSubject());
	EXPECT_STREQ(_T(""), rev.GetBody());
	EXPECT_EQ(0, rev.ParentsCount());
	EXPECT_EQ(0, rev.GetParentFromHash(rev.m_CommitHash));
	ASSERT_EQ(2, rev.ParentsCount());
	EXPECT_STREQ(_T("3686b9cf74f1a4ef96d6bfe736595ef9abf0fb8d"), rev.m_ParentHash[0].ToString());
	EXPECT_STREQ(_T("1ce788330fd3a306c8ad37654063ceee13a7f172"), rev.m_ParentHash[1].ToString());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	EXPECT_TRUE(rev.m_CommitHash.IsEmpty());
	EXPECT_EQ(0, rev.GetCommit(_T("844309789a13614b52d5e7cbfe6350dd73d1dc72"))); // root-commit
	EXPECT_STREQ(_T("844309789a13614b52d5e7cbfe6350dd73d1dc72"), rev.m_CommitHash.ToString());
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-04 17:35:13"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-04 17:35:13"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("added ansi file"), rev.GetSubject());
	EXPECT_STREQ(_T(""), rev.GetBody());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	EXPECT_EQ(0, rev.ParentsCount());
	EXPECT_EQ(0, rev.GetParentFromHash(rev.m_CommitHash));
	EXPECT_EQ(0, rev.ParentsCount());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	rev.Clear();
	// GPG signed commit which was also amended with different dates
	EXPECT_EQ(0, rev.GetCommit(_T("subdir/branch")));
	EXPECT_STREQ(_T("4c5c93d2a0b368bc4570d5ec02ab03b9c4334d44"), rev.m_CommitHash.ToString());
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetAuthorName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetAuthorEmail());
	EXPECT_STREQ(_T("2015-03-16 12:52:29"), rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Sven Strickroth"), rev.GetCommitterName());
	EXPECT_STREQ(_T("*****@*****.**"), rev.GetCommitterEmail());
	EXPECT_STREQ(_T("2015-03-16 13:06:08"), rev.GetCommitterDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(_T("Several actions"), rev.GetSubject());
	EXPECT_STREQ(_T("\n* amended with different date\n* make utf16-be-nobom.txt a symlink ti ascii.txt\n* remove utf8-bom.txt\n* Copied ascii.txt\n\nSigned-off-by: Sven Strickroth <*****@*****.**>\n"), rev.GetBody());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
	EXPECT_EQ(0, rev.ParentsCount());
	EXPECT_EQ(0, rev.GetParentFromHash(rev.m_CommitHash));
	ASSERT_EQ(1, rev.ParentsCount());
	EXPECT_STREQ(_T("aa5b97f89cea6863222823c8289ce392d06d1691"), rev.m_ParentHash[0].ToString());
	EXPECT_TRUE(rev.GetLastErr().IsEmpty());
}
コード例 #18
0
ファイル: RefLogDlg.cpp プロジェクト: 15375514460/TortoiseGit
LRESULT CRefLogDlg::OnFindDialogMessage(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
	ASSERT(m_pFindDialog != NULL);

	if (m_RefList.m_arShownList.IsEmpty())
		return 0;

	// If the FR_DIALOGTERM flag is set,
	// invalidate the handle identifying the dialog box.
	if (m_pFindDialog->IsTerminating())
	{
			m_pFindDialog = NULL;
			return 0;
	}

	// If the FR_FINDNEXT flag is set,
	// call the application-defined search routine
	// to search for the requested string.
	if (m_pFindDialog->FindNext())
	{
		//read data from dialog
		CString findString = m_pFindDialog->GetFindString();

		bool bFound = false;
		bool bCaseSensitive = !!(m_pFindDialog->m_nFlags & FR_MATCHCASE);

		if (!bCaseSensitive)
			findString.MakeLower();

		int i = m_nSearchLine;
		if (i < 0 || i >= m_RefList.m_arShownList.GetCount())
			i = 0;

		do
		{
			GitRev * data = (GitRev*)m_RefList.m_arShownList.SafeGetAt(i);

			CString str;
			str += data->m_Ref;
			str += _T("\n");
			str += data->m_RefAction;
			str += _T("\n");
			str += data->m_CommitHash.ToString();
			str += _T("\n");
			str += data->GetSubject();
			str += _T("\n");
			str += data->GetBody();
			str += _T("\n");

			if (!bCaseSensitive)
				str.MakeLower();

			if (str.Find(findString) >= 0)
				bFound = true;

			++i;
			if(!bFound && i >= m_RefList.m_arShownList.GetCount())
				i=0;
		} while (i != m_nSearchLine && (!bFound));

		if (bFound)
		{
			m_RefList.SetHotItem(i - 1);
			m_RefList.EnsureVisible(i - 1, FALSE);
			m_nSearchLine = i;
		}
		else
			MessageBox(_T("\"") + findString + _T("\" ") + CString(MAKEINTRESOURCE(IDS_NOTFOUND)), _T("TortoiseGit"), MB_ICONINFORMATION);
	}

	return 0;
}