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;
}
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;
		}
	}
}
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;
		}
	}
}
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;
}
TEST(CGitHash, MatchesPrefix)
{
	CString prefix = L"3012b757c23d16cc915acf60f5e3922d0409187a";
	CGitHash hash = CGitHash::FromHexStr(prefix);
	CGitHash prefixHash = CGitHash::FromHexStr(prefix);
	EXPECT_TRUE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));

	prefix = L"";
	prefixHash = CGitHash::FromHexStr(L"0000000000000000000000000000000000000000");
	EXPECT_TRUE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));

	prefix = L"3012b757";
	prefixHash = CGitHash::FromHexStr(L"3012b75700000000000000000000000000000000");
	EXPECT_TRUE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));

	prefix = L"3012b758";
	prefixHash = CGitHash::FromHexStr(L"3012b75800000000000000000000000000000000");
	EXPECT_FALSE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));

	prefix = L"a0";
	prefixHash = CGitHash::FromHexStr(L"a000000000000000000000000000000000000000");
	EXPECT_FALSE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));

	prefix = L"3012b75";
	prefixHash = CGitHash::FromHexStr(L"3012b75000000000000000000000000000000000");
	EXPECT_TRUE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));

	prefix = L"3012b76";
	prefixHash = CGitHash::FromHexStr(L"3012b76000000000000000000000000000000000");
	EXPECT_FALSE(hash.MatchesPrefix(prefixHash, prefix, prefix.GetLength()));
}
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));
}
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);
}
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());
}
Beispiel #9
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 #10
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 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);

	}
Beispiel #12
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 #13
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);
		}
	}
}
Beispiel #14
0
void CSyncDlg::OnBnClickedButtonPull()
{
	int CurrentEntry;
	CurrentEntry = (int)this->m_ctrlPull.GetCurrentEntry();
	this->m_regPullButton = CurrentEntry;

	this->m_bAbort=false;
	this->m_GitCmdList.clear();
	m_ctrlCmdOut.SetWindowTextW(_T(""));
	m_LogText = "";

	this->UpdateData();
	UpdateCombox();

	if (g_Git.GetHash(m_oldHash, _T("HEAD")))
	{
		MessageBox(g_Git.GetGitLastErr(_T("Could not get HEAD hash.")), _T("TortoiseGit"), MB_ICONERROR);
		return;
	}

	m_refList.Clear();
	m_newHashMap.clear();
	m_oldHashMap.clear();

	if( CurrentEntry == 0)
	{
		CGitHash localBranchHash;
		if (g_Git.GetHash(localBranchHash, m_strLocalBranch))
		{
			MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + m_strLocalBranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return;
		}
		if (localBranchHash != m_oldHash)
		{
			CMessageBox::Show(NULL, IDS_PROC_SYNC_PULLWRONGBRANCH, IDS_APPNAME, MB_OK | MB_ICONERROR);
			return;
		}
	}

	if(this->m_strURL.IsEmpty())
	{
		CMessageBox::Show(NULL, IDS_PROC_GITCONFIG_URLEMPTY, IDS_APPNAME, MB_OK | MB_ICONERROR);
		return;
	}

	if (m_bAutoLoadPuttyKey && CurrentEntry != 3) // CurrentEntry (Remote Update) handles this on its own)
	{
		CAppUtils::LaunchPAgent(NULL,&this->m_strURL);
	}

	this->SwitchToRun();

	CString force;
	if(this->m_bForce)
		force = _T(" --force ");

	CString cmd;

	ShowTab(IDC_CMD_LOG);

	this->m_ctrlTabCtrl.ShowTab(IDC_REFLIST-1,true);
	this->m_ctrlTabCtrl.ShowTab(IDC_IN_LOGLIST-1,false);
	this->m_ctrlTabCtrl.ShowTab(IDC_IN_CHANGELIST-1,false);
	this->m_ctrlTabCtrl.ShowTab(IDC_IN_CONFLICT-1,false);

	///Pull
	if(CurrentEntry == 0) //Pull
	{
		CString remotebranch;
		remotebranch = m_strRemoteBranch;

		if(!IsURL())
		{
			CString configName;
			configName.Format(L"branch.%s.merge", this->m_strLocalBranch);
			CString pullBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));

			configName.Format(L"branch.%s.remote", m_strLocalBranch);
			CString pullRemote = g_Git.GetConfigValue(configName);

			if(pullBranch == remotebranch && pullRemote == this->m_strURL)
				remotebranch.Empty();
		}

		if(m_Gitverion >= 0x01070203) //above 1.7.0.2
			force += _T("--progress ");

		cmd.Format(_T("git.exe pull -v %s \"%s\" %s"),
				force,
				m_strURL,
				remotebranch);

		m_CurrentCmd = GIT_COMMAND_PULL;
		m_GitCmdList.push_back(cmd);

		m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
		if (m_pThread==NULL)
		{
		//		ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
		}
		else
		{
			m_pThread->m_bAutoDelete = TRUE;
			m_pThread->ResumeThread();
		}

	}

	///Fetch
	if(CurrentEntry == 1 || CurrentEntry ==2 ) //Fetch
	{
		CString remotebranch;
		if(this->IsURL() || m_strRemoteBranch.IsEmpty())
		{
			remotebranch=this->m_strRemoteBranch;

		}
		else
		{
			remotebranch.Format(_T("remotes/%s/%s"),
								m_strURL,m_strRemoteBranch);
			CGitHash remoteBranchHash;
			g_Git.GetHash(remoteBranchHash, remotebranch);
			if (remoteBranchHash.IsEmpty())
				remotebranch=m_strRemoteBranch;
			else
				remotebranch=m_strRemoteBranch+_T(":")+remotebranch;
		}

		if(CurrentEntry == 1)
			m_CurrentCmd = GIT_COMMAND_FETCH;
		else
			m_CurrentCmd = GIT_COMMAND_FETCHANDREBASE;

		if (g_Git.UsingLibGit2(CGit::GIT_CMD_FETCH))
		{
			CString refspec;
			// current libgit2 only supports well formated refspec
			refspec.Format(_T("refs/heads/%s:refs/remotes/%s/%s"), m_strRemoteBranch, m_strURL, m_strRemoteBranch);
			m_GitProgressList.SetUrl(m_strURL);
			m_GitProgressList.SetRefSpec(refspec);
			m_GitProgressList.SetCommand(CGitProgressList::GitProgress_Fetch);
			m_GitProgressList.Init();
			ShowTab(IDC_CMD_GIT_PROG);
		}
		else
		{
			if(m_Gitverion >= 0x01070203) //above 1.7.0.2
				force += _T("--progress ");

			cmd.Format(_T("git.exe fetch -v %s \"%s\" %s"),
					force,
					m_strURL,
					remotebranch);

			m_GitCmdList.push_back(cmd);

			m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
			if (m_pThread==NULL)
			{
			//		ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
			}
			else
			{
				m_pThread->m_bAutoDelete = TRUE;
				m_pThread->ResumeThread();
			}
		}
	}

	///Remote Update
	if(CurrentEntry == 3)
	{
		if (m_bAutoLoadPuttyKey)
		{
			STRING_VECTOR list;
			if (!g_Git.GetRemoteList(list))
			{
				for (size_t i = 0; i < list.size(); ++i)
					CAppUtils::LaunchPAgent(NULL, &list[i]);
			}
		}

		m_CurrentCmd = GIT_COMMAND_REMOTE;
		cmd=_T("git.exe remote update");
		m_GitCmdList.push_back(cmd);

		InterlockedExchange(&m_bBlock, TRUE);

		m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
		if (m_pThread==NULL)
		{
		//		ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
			InterlockedExchange(&m_bBlock, FALSE);
		}
		else
		{
			m_pThread->m_bAutoDelete = TRUE;
			m_pThread->ResumeThread();
		}
	}

	///Cleanup stale remote banches
	if(CurrentEntry == 4)
	{
		m_CurrentCmd = GIT_COMMAND_REMOTE;
		cmd.Format(_T("git.exe remote prune \"%s\""), m_strURL);
		m_GitCmdList.push_back(cmd);

		InterlockedExchange(&m_bBlock, TRUE);

		m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
		if (m_pThread==NULL)
		{
		//		ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
			InterlockedExchange(&m_bBlock, FALSE);
		}
		else
		{
			m_pThread->m_bAutoDelete = TRUE;
			m_pThread->ResumeThread();
		}
	}
}
Beispiel #15
0
void CSyncDlg::FetchOutList(bool force)
{
	if(!m_bInited)
		return;
	m_OutChangeFileList.Clear();
	this->m_OutLogList.Clear();

	CString remote;
	this->m_ctrlURL.GetWindowText(remote);
	CString remotebranch;
	this->m_ctrlRemoteBranch.GetWindowText(remotebranch);
	remotebranch=remote+_T("/")+remotebranch;
	CGitHash remotebranchHash;
	g_Git.GetHash(remotebranchHash, remotebranch);

	if(IsURL())
	{
		CString str;
		str.LoadString(IDS_PROC_SYNC_PUSH_UNKNOWN);
		m_OutLogList.ShowText(str);
		this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
		m_OutLocalBranch.Empty();
		m_OutRemoteBranch.Empty();

		this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
		return ;

	}
	else if(remotebranchHash.IsEmpty())
	{
		CString str;
		str.Format(IDS_PROC_SYNC_PUSH_UNKNOWNBRANCH, remotebranch);
		m_OutLogList.ShowText(str);
		this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
		m_OutLocalBranch.Empty();
		m_OutRemoteBranch.Empty();

		this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
		return ;
	}
	else
	{
		CString localbranch;
		localbranch=this->m_ctrlLocalBranch.GetString();

		if(localbranch != m_OutLocalBranch || m_OutRemoteBranch != remotebranch || force)
		{
			m_OutLogList.ClearText();

			CGitHash base, localBranchHash;
			bool isFastForward = g_Git.IsFastForward(remotebranch, localbranch, &base);

			if (g_Git.GetHash(localBranchHash, localbranch))
			{
				MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of \"") + localbranch + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
				return;
			}
			if (remotebranchHash == localBranchHash)
			{
				CString str;
				str.Format(IDS_PROC_SYNC_COMMITSAHEAD, 0, remotebranch);
				m_OutLogList.ShowText(str);
				this->m_ctrlStatus.SetWindowText(str);
				this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,FALSE);
				this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
			}
			else if (isFastForward || m_bForce)
			{
				CString range;
				range.Format(_T("%s..%s"), g_Git.FixBranchName(remotebranch), g_Git.FixBranchName(localbranch));
				//fast forward
				m_OutLogList.FillGitLog(nullptr, &range, CGit::LOG_INFO_STAT | CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE);
				CString str;
				str.Format(IDS_PROC_SYNC_COMMITSAHEAD, m_OutLogList.GetItemCount(), remotebranch);
				this->m_ctrlStatus.SetWindowText(str);

				if (isFastForward)
					AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, remotebranch);
				else
				{
					AddDiffFileList(&m_OutChangeFileList, &m_arOutChangeList, localbranch, base.ToString());
				}

				this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID()-1,TRUE);
				this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(TRUE);
			}
			else
			{
				CString str;
				str.Format(IDS_PROC_SYNC_NOFASTFORWARD, localbranch, remotebranch);
				m_OutLogList.ShowText(str);
				this->m_ctrlStatus.SetWindowText(str);
				this->m_ctrlTabCtrl.ShowTab(m_OutChangeFileList.GetDlgCtrlID() - 1, FALSE);
				this->GetDlgItem(IDC_BUTTON_EMAIL)->EnableWindow(FALSE);
			}
		}
		this->m_OutLocalBranch=localbranch;
		this->m_OutRemoteBranch=remotebranch;
	}

}
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 #18
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;
}
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();
}
Beispiel #20
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 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)
}