Пример #1
0
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;
}
Пример #2
0
bool ResetProgressCommand::Run(CGitProgressList* list, CString& sWindowTitle, int& /*m_itemCountTotal*/, int& /*m_itemCount*/)
{
	if (!g_Git.UsingLibGit2(CGit::GIT_CMD_RESET))
	{
		// should never run to here
		ASSERT(0);
		return false;
	}

	list->SetWindowTitle(IDS_PROGRS_TITLE_RESET, g_Git.m_CurrentDir, sWindowTitle);
	list->SetBackgroundImage(IDI_UPDATE_BKG);
	int resetTypesResource[] = { IDS_RESET_SOFT, IDS_RESET_MIXED, IDS_RESET_HARD };
	list->ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_TITLE_RESET)) + L' ' + CString(MAKEINTRESOURCE(resetTypesResource[m_resetType])) + L' ' + m_revision);

	list->ShowProgressBar();
	CAutoRepository repo(g_Git.GetGitRepository());
	if (!repo)
	{
		list->ReportGitError();
		return false;
	}

	CGitProgressList::Payload cbpayload = { list, repo };
	git_checkout_options checkout_options = GIT_CHECKOUT_OPTIONS_INIT;

	CBlockCacheForPath block(g_Git.m_CurrentDir);
	CAutoObject target;
	if (git_revparse_single(target.GetPointer(), repo, CUnicodeUtils::GetUTF8(m_revision)))
		goto error;
	checkout_options.progress_payload = &cbpayload;
	checkout_options.progress_cb = [](const char*, size_t completed_steps, size_t total_steps, void* payload)
	{
		CGitProgressList::Payload* cbpayload = (CGitProgressList::Payload*)payload;
		cbpayload->list->m_itemCountTotal = (int)total_steps;
		cbpayload->list->m_itemCount = (int)completed_steps;
	};
	checkout_options.notify_cb = [](git_checkout_notify_t, const char* pPath, const git_diff_file*, const git_diff_file*, const git_diff_file*, void* payload) -> int
	{
		CGitProgressList* list = (CGitProgressList*)payload;
		CString path(CUnicodeUtils::GetUnicode(pPath));
		if (DWORD(CRegDWORD(L"Software\\TortoiseGit\\RevertWithRecycleBin", TRUE)))
		{
			if (!CTGitPath(g_Git.CombinePath(path)).Delete(true, true))
			{
				list->ReportError(L"Could move \"" + path + L"\" to recycle bin");
				return GIT_EUSER;
			}
		}
		list->AddNotify(new CGitProgressList::WC_File_NotificationData(path, CGitProgressList::WC_File_NotificationData::git_wc_notify_checkout));
		return 0;
	};
	checkout_options.notify_flags = GIT_CHECKOUT_NOTIFY_UPDATED;
	checkout_options.notify_payload = list;
	if (git_reset(repo, target, (git_reset_t)(m_resetType + 1), &checkout_options))
		goto error;

	// Not setting m_PostCmdCallback here, as clone is only called from AppUtils.cpp

	return true;

error:
	list->ReportGitError();
	return false;
}
Пример #3
0
bool CatCommand::Execute()
{
	if (!GitAdminDir::IsWorkingTreeOrBareRepo(g_Git.m_CurrentDir))
	{
		CMessageBox::Show(GetExplorerHWND(), IDS_NOGITREPO, IDS_APPNAME, MB_ICONERROR);
		return false;
	}

	CString savepath = CPathUtils::GetLongPathname(parser.GetVal(L"savepath"));
	CString revision = parser.GetVal(L"revision");

	if (g_Git.UsingLibGit2(CGit::GIT_CMD_GETONEFILE))
	{
		CAutoRepository repo(g_Git.GetGitRepository());
		if (!repo)
		{
			::DeleteFile(savepath);
			MessageBox(GetExplorerHWND(), g_Git.GetLibGit2LastErr(L"Could not open repository."), L"TortoiseGit", MB_ICONERROR);
			return false;
		}

		CAutoObject obj;
		if (git_revparse_single(obj.GetPointer(), repo, CUnicodeUtils::GetUTF8(revision)))
		{
			::DeleteFile(savepath);
			MessageBox(GetExplorerHWND(), g_Git.GetLibGit2LastErr(L"Could not parse revision."), L"TortoiseGit", MB_ICONERROR);
			return false;
		}

		if (git_object_type(obj) == GIT_OBJECT_BLOB)
		{
			CAutoFILE file = _wfsopen(savepath, L"wb", SH_DENYRW);
			if (file == nullptr)
			{
				::DeleteFile(savepath);
				MessageBox(GetExplorerHWND(), L"Could not open file for writing.", L"TortoiseGit", MB_ICONERROR);
				return false;
			}

			CAutoBuf buf;
			if (git_blob_filtered_content(buf, reinterpret_cast<git_blob*>(static_cast<git_object*>(obj)), CUnicodeUtils::GetUTF8(cmdLinePath.GetGitPathString()), 0))
			{
				::DeleteFile(savepath);
				MessageBox(GetExplorerHWND(), g_Git.GetLibGit2LastErr(L"Could not get filtered content."), L"TortoiseGit", MB_ICONERROR);
				return false;
			}
			if (fwrite(buf->ptr, sizeof(char), buf->size, file) != buf->size)
			{
				::DeleteFile(savepath);
				CString err = CFormatMessageWrapper();
				CMessageBox::Show(GetExplorerHWND(), L"Could not write to file: " + err, L"TortoiseGit", MB_ICONERROR);
				return false;
			}
			return true;
		}

		if (g_Git.GetOneFile(revision, cmdLinePath, savepath))
		{
			MessageBox(GetExplorerHWND(), g_Git.GetGitLastErr(L"Could get file.", CGit::GIT_CMD_GETONEFILE), L"TortoiseGit", MB_ICONERROR);
			return false;
		}
		return true;
	}

	CString cmd, output, err;
	cmd.Format(L"git.exe cat-file -t %s", static_cast<LPCTSTR>(revision));

	if (g_Git.Run(cmd, &output, &err, CP_UTF8))
	{
		::DeleteFile(savepath);
		MessageBox(GetExplorerHWND(), output + L'\n' + err, L"TortoiseGit", MB_ICONERROR);
		return false;
	}

	if (CStringUtils::StartsWith(output, L"blob"))
		cmd.Format(L"git.exe cat-file -p %s", static_cast<LPCTSTR>(revision));
	else
		cmd.Format(L"git.exe show %s -- \"%s\"", static_cast<LPCTSTR>(revision), static_cast<LPCTSTR>(this->cmdLinePath.GetWinPathString()));

	if (g_Git.RunLogFile(cmd, savepath, &err))
	{
		::DeleteFile(savepath);
		MessageBox(GetExplorerHWND(), L"Cat file failed:\n" + err, L"TortoiseGit", MB_ICONERROR);
		return false;
	}
	return true;
}