예제 #1
0
int CGitIndexList::ReadIndex(CString dgitdir)
{
	this->clear();

	m_critRepoSec.Lock();
	if (repository.Open(dgitdir))
	{
		m_critRepoSec.Unlock();
		return -1;
	}

	// add config files
	CAutoConfig config(true);

	CString projectConfig = dgitdir + _T("config");
	CString globalConfig = g_Git.GetGitGlobalConfig();
	CString globalXDGConfig = g_Git.GetGitGlobalXDGConfig();
	CString systemConfig(CRegString(REG_SYSTEM_GITCONFIGPATH, _T(""), FALSE));

	git_config_add_file_ondisk(config, CGit::GetGitPathStringA(projectConfig), GIT_CONFIG_LEVEL_LOCAL, FALSE);
	git_config_add_file_ondisk(config, CGit::GetGitPathStringA(globalConfig), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
	git_config_add_file_ondisk(config, CGit::GetGitPathStringA(globalXDGConfig), GIT_CONFIG_LEVEL_XDG, FALSE);
	if (!systemConfig.IsEmpty())
		git_config_add_file_ondisk(config, CGit::GetGitPathStringA(systemConfig), GIT_CONFIG_LEVEL_SYSTEM, FALSE);

	git_repository_set_config(repository, config);

	CAutoIndex index;
	// load index in order to enumerate files
	if (git_repository_index(index.GetPointer(), repository))
	{
		repository.Free();
		m_critRepoSec.Unlock();
		return -1;
	}

	size_t ecount = git_index_entrycount(index);
	resize(ecount);
	for (size_t i = 0; i < ecount; ++i)
	{
		const git_index_entry *e = git_index_get_byindex(index, i);

		this->at(i).m_FileName.Empty();
		this->at(i).m_FileName = CUnicodeUtils::GetUnicode(e->path);
		this->at(i).m_FileName.MakeLower();
		this->at(i).m_ModifyTime = e->mtime.seconds;
		this->at(i).m_Flags = e->flags | e->flags_extended;
		this->at(i).m_IndexHash = e->id.id;
		this->at(i).m_Size = e->file_size;
	}

	g_Git.GetFileModifyTime(dgitdir + _T("index"), &this->m_LastModifyTime);
	std::sort(this->begin(), this->end(), SortIndex);

	m_critRepoSec.Unlock();

	return 0;
}
TEST_P(GitWCRevStatusCBasicGitWithEmptyRepositoryFixture, EmptyRepoStagedFile)
{
	CString file = m_Dir.GetTempDir() + L"\\somefile.txt";

	EXPECT_TRUE(CStringUtils::WriteStringToTextFile(file, L"something\n"));

	CAutoRepository repo;
	ASSERT_EQ(0, git_repository_open(repo.GetPointer(), CUnicodeUtils::GetUTF8(m_Dir.GetTempDir())));
	CAutoIndex index;
	ASSERT_EQ(0, git_repository_index(index.GetPointer(), repo));
	ASSERT_EQ(0, git_index_add_bypath(index, "somefile.txt"));
	ASSERT_EQ(0, git_index_write(index));

	GitWCRev_t GitStat3;
	EXPECT_TRUE(CStringUtils::WriteStringToTextFile(file, L"something\n"));
	EXPECT_EQ(0, GetStatus(m_Dir.GetTempDir(), GitStat3));
	EXPECT_TRUE(GitStat3.bIsGitItem);
	EXPECT_TRUE(GitStat3.bIsUnborn);
	EXPECT_STREQ("master", GitStat3.CurrentBranch.c_str());
	EXPECT_FALSE(GitStat3.bHasSubmodule);
	EXPECT_FALSE(GitStat3.HasMods);
	EXPECT_TRUE(GitStat3.HasUnversioned);
	EXPECT_EQ(0u, GitStat3.NumCommits);
	EXPECT_FALSE(GitStat3.bHasSubmoduleMods);
	EXPECT_FALSE(GitStat3.bHasSubmoduleNewCommits);
	EXPECT_FALSE(GitStat3.bHasSubmoduleUnversioned);
	EXPECT_FALSE(GitStat3.bIsTagged);
	EXPECT_STREQ(GIT_REV_ZERO_C, GitStat3.HeadHashReadable);
	EXPECT_STREQ("", GitStat3.HeadAuthor.c_str());

	GitWCRev_t GitStat4;
	EXPECT_EQ(0, GetStatus(file, GitStat4));
	EXPECT_FALSE(GitStat4.bIsGitItem);
	EXPECT_TRUE(GitStat4.bIsUnborn);
	EXPECT_STREQ("master", GitStat4.CurrentBranch.c_str());
	EXPECT_FALSE(GitStat4.bHasSubmodule);
	EXPECT_FALSE(GitStat4.HasMods);
	EXPECT_TRUE(GitStat4.HasUnversioned);
	EXPECT_EQ(0u, GitStat4.NumCommits);
	EXPECT_FALSE(GitStat4.bHasSubmoduleMods);
	EXPECT_FALSE(GitStat4.bHasSubmoduleNewCommits);
	EXPECT_FALSE(GitStat4.bHasSubmoduleUnversioned);
	EXPECT_FALSE(GitStat4.bIsTagged);
	EXPECT_STREQ(GIT_REV_ZERO_C, GitStat4.HeadHashReadable);
	EXPECT_STREQ("", GitStat4.HeadAuthor.c_str());
}
예제 #3
0
int CTGitPathList::FillBasedOnIndexFlags(unsigned short flag, CTGitPathList* list /*nullptr*/)
{
	Clear();
	CTGitPath path;

	CAutoRepository repository(g_Git.GetGitRepository());
	if (!repository)
		return -1;

	CAutoIndex index;
	if (git_repository_index(index.GetPointer(), repository))
		return -1;

	int count;
	if (list == nullptr)
		count = 1;
	else
		count = list->GetCount();
	for (int j = 0; j < count; ++j)
	{
		for (size_t i = 0, ecount = git_index_entrycount(index); i < ecount; ++i)
		{
			const git_index_entry *e = git_index_get_byindex(index, i);

			if (!e || !((e->flags | e->flags_extended) & flag) || !e->path)
				continue;

			CString one = CUnicodeUtils::GetUnicode(e->path);

			if (!(!list || (*list)[j].GetWinPathString().IsEmpty() || one == (*list)[j].GetGitPathString() || (PathIsDirectory(g_Git.CombinePath((*list)[j].GetWinPathString())) && one.Find((*list)[j].GetGitPathString() + _T("/")) == 0)))
				continue;

			//SetFromGit will clear all status
			path.SetFromGit(one);
			if ((e->flags | e->flags_extended) & GIT_IDXENTRY_SKIP_WORKTREE)
				path.m_Action = CTGitPath::LOGACTIONS_SKIPWORKTREE;
			else if ((e->flags | e->flags_extended) & GIT_IDXENTRY_VALID)
				path.m_Action = CTGitPath::LOGACTIONS_ASSUMEVALID;
			AddPath(path);
		}
	}
	RemoveDuplicates();
	return 0;
}
bool AddProgressCommand::SetFileMode(uint32_t mode)
{
	CAutoRepository repo(g_Git.GetGitRepository());
	if (!repo)
	{
		MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not open repository."), L"TortoiseGit", MB_ICONERROR);
		return false;
	}

	CAutoIndex index;
	if (git_repository_index(index.GetPointer(), repo))
	{
		MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not get index."), L"TortoiseGit", MB_ICONERROR);
		return false;
	}
	if (git_index_read(index, true))
	{
		MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not read index."), L"TortoiseGit", MB_ICONERROR);
		return false;
	}

	for (int i = 0; i < m_targetPathList.GetCount(); ++i)
	{
		if (m_targetPathList[i].IsDirectory())
			continue;
		CStringA filePathA = CUnicodeUtils::GetMulti(m_targetPathList[i].GetGitPathString(), CP_UTF8).TrimRight(L'/');
		auto entry = const_cast<git_index_entry*>(git_index_get_bypath(index, filePathA, 0));
		entry->mode = mode;
		if (git_index_add(index, entry))
		{
			MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not update index."), L"TortoiseGit", MB_ICONERROR);
			return false;
		}
	}

	if (git_index_write(index))
	{
		MessageBox(nullptr, g_Git.GetLibGit2LastErr(L"Could not write index."), L"TortoiseGit", MB_ICONERROR);
		return false;
	}

	return true;
}
예제 #5
0
TEST(libgit2, TGitPatches)
{
	CAutoTempDir tempdir;

	git_repository_init_options options = GIT_REPOSITORY_INIT_OPTIONS_INIT;
	options.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
	CAutoRepository repo;
	ASSERT_EQ(0, git_repository_init_ext(repo.GetPointer(), CUnicodeUtils::GetUTF8(tempdir.GetTempDir()), &options));

	CAutoConfig config;
	ASSERT_EQ(0, git_repository_config(config.GetPointer(), repo));
	EXPECT_EQ(0, git_config_set_string(config, "core.autocrlf", "true"));
	EXPECT_EQ(0, git_config_set_string(config, "core.safecrlf", "true"));

	CAutoRepository repo2(tempdir.GetTempDir());
	ASSERT_TRUE(repo2.IsValid());
	CAutoIndex index;
	ASSERT_EQ(0, git_repository_index(index.GetPointer(), repo2));

	CString testFile = tempdir.GetTempDir() + L"\\safecrlf-failure.txt";
	EXPECT_TRUE(CStringUtils::WriteStringToTextFile(testFile, L"crlf\r\ncrlf\r\n"));
	EXPECT_EQ(0, git_index_add_bypath(index, "safecrlf-failure.txt"));

	EXPECT_TRUE(CStringUtils::WriteStringToTextFile(testFile, L"lf\nlf\n"));
	EXPECT_EQ(-1, git_index_add_bypath(index, "safecrlf-failure.txt"));

	EXPECT_TRUE(CStringUtils::WriteStringToTextFile(testFile, L"crlf\r\ncr\rcrlf\r\n"));
	EXPECT_EQ(0, git_index_add_bypath(index, "safecrlf-failure.txt"));

	EXPECT_EQ(0, git_config_set_string(config, "core.autocrlf", "input"));
	CAutoRepository repo3(tempdir.GetTempDir());
	ASSERT_TRUE(repo3.IsValid());
	ASSERT_EQ(0, git_repository_index(index.GetPointer(), repo3));

	EXPECT_TRUE(CStringUtils::WriteStringToTextFile(testFile, L"crlf\r\ncrlf\r\n"));
	EXPECT_EQ(-1, git_index_add_bypath(index, "safecrlf-failure.txt"));
}
예제 #6
0
bool DiffCommand::Execute()
{
	bool bRet = false;
	CString path2 = CPathUtils::GetLongPathname(parser.GetVal(_T("path2")));
	bool bAlternativeTool = !!parser.HasKey(_T("alternative"));
//	bool bBlame = !!parser.HasKey(_T("blame"));
	if (path2.IsEmpty())
	{
		if (this->orgCmdLinePath.IsDirectory())
		{
			CChangedDlg dlg;
			dlg.m_pathList = CTGitPathList(cmdLinePath);
			dlg.DoModal();
			bRet = true;
		}
		else
		{
			if (cmdLinePath.IsEmpty())
				return false;
			CGitDiff diff;
			//diff.SetAlternativeTool(bAlternativeTool);
			if ( parser.HasKey(_T("startrev")) && parser.HasKey(_T("endrev")) )
			{
				if (parser.HasKey(_T("unified")))
					bRet = !!CAppUtils::StartShowUnifiedDiff(nullptr, cmdLinePath, git_revnum_t(parser.GetVal(_T("endrev"))), cmdLinePath, git_revnum_t(parser.GetVal(_T("startrev"))), bAlternativeTool);
				else
					bRet = !!diff.Diff(&cmdLinePath, &cmdLinePath, git_revnum_t(parser.GetVal(_T("startrev"))), git_revnum_t(parser.GetVal(_T("endrev"))), false, parser.HasKey(_T("unified")) == TRUE, parser.GetLongVal(_T("line")), bAlternativeTool);
			}
			else
			{
				// check if it is a newly added (but uncommitted) file
				git_wc_status_kind status = git_wc_status_none;
				CString topDir;
				if (orgCmdLinePath.HasAdminDir(&topDir))
				{
					CBlockCacheForPath cacheBlock(topDir);
					CAutoIndex index;
					CString adminDir;
					GitAdminDir::GetAdminDirPath(topDir, adminDir);
					if (!git_index_open(index.GetPointer(), CUnicodeUtils::GetUTF8(adminDir + _T("index"))))
						g_Git.Run(_T("git.exe update-index -- \"") + cmdLinePath.GetGitPathString() + _T("\""), nullptr); // make sure we get the right status
					GitStatus::GetFileStatus(topDir, cmdLinePath.GetWinPathString(), &status, true);
					if (index)
						git_index_write(index);
				}
				if (status == git_wc_status_added)
				{
					if (!g_Git.IsInitRepos())
					{
						// this might be a rename, try to find original name
						BYTE_VECTOR cmdout;
						g_Git.Run(_T("git.exe diff-index --raw HEAD -M -C -z --"), &cmdout);
						CTGitPathList changedFiles;
						changedFiles.ParserFromLog(cmdout);
						for (int i = 0; i < changedFiles.GetCount(); ++i)
						{
							if (changedFiles[i].GetGitPathString() == cmdLinePath.GetGitPathString())
							{
								if (!changedFiles[i].GetGitOldPathString().IsEmpty())
								{
									CTGitPath oldPath(changedFiles[i].GetGitOldPathString());
									if (parser.HasKey(_T("unified")))
										return !!CAppUtils::StartShowUnifiedDiff(nullptr, cmdLinePath, git_revnum_t(_T("HEAD")), cmdLinePath, git_revnum_t(GIT_REV_ZERO), bAlternativeTool);
									return !!diff.Diff(&cmdLinePath, &oldPath, git_revnum_t(GIT_REV_ZERO), git_revnum_t(_T("HEAD")), false, parser.HasKey(_T("unified")) == TRUE, parser.GetLongVal(_T("line")), bAlternativeTool);
								}
								break;
							}
						}
					}
					cmdLinePath.m_Action = cmdLinePath.LOGACTIONS_ADDED;
				}

				if (parser.HasKey(_T("unified")))
					bRet = !!CAppUtils::StartShowUnifiedDiff(nullptr, cmdLinePath, git_revnum_t(_T("HEAD")), cmdLinePath, git_revnum_t(GIT_REV_ZERO), bAlternativeTool);
				else
					bRet = !!diff.Diff(&cmdLinePath, &cmdLinePath, git_revnum_t(GIT_REV_ZERO), git_revnum_t(_T("HEAD")), false, parser.HasKey(_T("unified")) == TRUE, parser.GetLongVal(_T("line")), bAlternativeTool);
			}
		}
	}
	else
	{
		CGitDiff diff;
		if ( parser.HasKey(_T("startrev")) && parser.HasKey(_T("endrev")) && path2.Left(g_Git.m_CurrentDir.GetLength() + 1) == g_Git.m_CurrentDir + _T("\\"))
		{
			CTGitPath tgitPath2 = path2.Mid(g_Git.m_CurrentDir.GetLength() + 1);
			bRet = !!diff.Diff(&tgitPath2, &cmdLinePath, git_revnum_t(parser.GetVal(_T("startrev"))), git_revnum_t(parser.GetVal(_T("endrev"))), false, parser.HasKey(_T("unified")) == TRUE, parser.GetLongVal(_T("line")), bAlternativeTool);
		}
		else
		{
			bRet = CAppUtils::StartExtDiff(
				path2, orgCmdLinePath.GetWinPathString(), CString(), CString(),
				CString(), CString(), git_revnum_t(GIT_REV_ZERO), git_revnum_t(GIT_REV_ZERO),
				CAppUtils::DiffFlags().AlternativeTool(bAlternativeTool), parser.GetLongVal(_T("line")));
		}
	}

	return bRet;
}
예제 #7
0
int CGitIndexList::ReadIndex(CString dgitdir)
{
	this->clear();

	CAutoLocker lock(m_critRepoSec);
	if (repository.Open(dgitdir))
		return -1;

	// add config files
	CAutoConfig config(true);

	CString projectConfig = dgitdir + _T("config");
	CString globalConfig = g_Git.GetGitGlobalConfig();
	CString globalXDGConfig = g_Git.GetGitGlobalXDGConfig();
	CString systemConfig(CRegString(REG_SYSTEM_GITCONFIGPATH, _T(""), FALSE));
	CString programDataConfig(GetProgramDataGitConfig());

	git_config_add_file_ondisk(config, CGit::GetGitPathStringA(projectConfig), GIT_CONFIG_LEVEL_LOCAL, FALSE);
	git_config_add_file_ondisk(config, CGit::GetGitPathStringA(globalConfig), GIT_CONFIG_LEVEL_GLOBAL, FALSE);
	git_config_add_file_ondisk(config, CGit::GetGitPathStringA(globalXDGConfig), GIT_CONFIG_LEVEL_XDG, FALSE);
	if (!systemConfig.IsEmpty())
		git_config_add_file_ondisk(config, CGit::GetGitPathStringA(systemConfig), GIT_CONFIG_LEVEL_SYSTEM, FALSE);
	if (!programDataConfig.IsEmpty())
		git_config_add_file_ondisk(config, CGit::GetGitPathStringA(programDataConfig), GIT_CONFIG_LEVEL_PROGRAMDATA, FALSE);

	git_repository_set_config(repository, config);

	CAutoIndex index;
	// load index in order to enumerate files
	if (git_repository_index(index.GetPointer(), repository))
	{
		repository.Free();
		return -1;
	}

	m_bHasConflicts = FALSE;

	size_t ecount = git_index_entrycount(index);
	try
	{
		resize(ecount);
	}
	catch (const std::bad_alloc& ex)
	{
		repository.Free();
		CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Could not resize index-vector: %s\n", ex.what());
		return -1;
	}
	for (size_t i = 0; i < ecount; ++i)
	{
		const git_index_entry *e = git_index_get_byindex(index, i);

		this->at(i).m_FileName = CUnicodeUtils::GetUnicode(e->path);
		this->at(i).m_FileName.MakeLower();
		this->at(i).m_ModifyTime = e->mtime.seconds;
		this->at(i).m_Flags = e->flags;
		this->at(i).m_FlagsExtended = e->flags_extended;
		this->at(i).m_IndexHash = e->id.id;
		this->at(i).m_Size = e->file_size;
		m_bHasConflicts |= GIT_IDXENTRY_STAGE(e);
	}

	CGit::GetFileModifyTime(dgitdir + _T("index"), &this->m_LastModifyTime);
	std::sort(this->begin(), this->end(), SortIndex);

	return 0;
}
예제 #8
0
LRESULT CMainWindow::DoCommand(int id, LPARAM lParam)
{
    switch (id)
    {
    case ID_FILE_OPEN:
        {
            if (OpenDialog())
            {
                picWindow1.SetPic(leftpicpath, L"", true);
                picWindow2.SetPic(rightpicpath, L"", false);
                if (bOverlap)
                {
                    picWindow1.SetSecondPic(picWindow2.GetPic(), rightpictitle, rightpicpath);
                }
                else
                {
                    picWindow1.SetSecondPic();
                }
                RECT rect;
                GetClientRect(*this, &rect);
                PositionChildren(&rect);
                picWindow1.FitImageInWindow();
                picWindow2.FitImageInWindow();
            }
        }
        break;
    case ID_VIEW_IMAGEINFO:
        {
            bShowInfo = !bShowInfo;
            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= bShowInfo ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_IMAGEINFO, uCheck);

            picWindow1.ShowInfo(bShowInfo);
            picWindow2.ShowInfo(bShowInfo);
            picWindow3.ShowInfo(bShowInfo);

            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = bShowInfo ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_IMAGEINFO, (LPARAM)&tbi);
        }
        break;
    case ID_VIEW_OVERLAPIMAGES:
        {
            bOverlap = !bOverlap;
            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= bOverlap ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_OVERLAPIMAGES, uCheck);
            uCheck |= ((m_BlendType == CPicWindow::BLEND_ALPHA) && bOverlap) ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_BLENDALPHA, uCheck);
            UINT uEnabled = MF_BYCOMMAND;
            uEnabled |= bOverlap ? MF_ENABLED : MF_DISABLED | MF_GRAYED;
            EnableMenuItem(hMenu, ID_VIEW_BLENDALPHA, uEnabled);

            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = bOverlap ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_OVERLAPIMAGES, (LPARAM)&tbi);

            tbi.fsState = ((m_BlendType == CPicWindow::BLEND_ALPHA) && bOverlap) ? TBSTATE_CHECKED : 0;
            if (bOverlap)
                tbi.fsState |= TBSTATE_ENABLED;
            else
                tbi.fsState = 0;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_BLENDALPHA, (LPARAM)&tbi);

            if (bOverlap)
                tbi.fsState = 0;
            else
                tbi.fsState = bVertical ? TBSTATE_ENABLED | TBSTATE_CHECKED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_ARRANGEVERTICAL, (LPARAM)&tbi);

            if (bOverlap)
            {
                bLinkedPositions = true;
                picWindow1.LinkPositions(bLinkedPositions);
                picWindow2.LinkPositions(bLinkedPositions);
                tbi.fsState = TBSTATE_CHECKED;
            }
            else
                tbi.fsState = bLinkedPositions ? TBSTATE_ENABLED | TBSTATE_CHECKED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_LINKIMAGESTOGETHER, (LPARAM)&tbi);

            ShowWindow(picWindow2, bOverlap ? SW_HIDE : SW_SHOW);

            if (bOverlap)
            {
                picWindow1.StopTimer();
                picWindow2.StopTimer();
                picWindow1.SetSecondPic(picWindow2.GetPic(), rightpictitle, rightpicpath,
                    picWindow2.GetHPos(), picWindow2.GetVPos());
                picWindow1.SetBlendAlpha(m_BlendType, 0.5f);
            }
            else
            {
                picWindow1.SetSecondPic();
            }
            picWindow1.SetOverlapMode(bOverlap);
            picWindow2.SetOverlapMode(bOverlap);


            RECT rect;
            GetClientRect(*this, &rect);
            PositionChildren(&rect);

            return 0;
        }
        break;
    case ID_VIEW_BLENDALPHA:
        {
            if (m_BlendType == CPicWindow::BLEND_ALPHA)
                m_BlendType = CPicWindow::BLEND_XOR;
            else
                m_BlendType = CPicWindow::BLEND_ALPHA;

            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= ((m_BlendType == CPicWindow::BLEND_ALPHA) && bOverlap) ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_BLENDALPHA, uCheck);
            UINT uEnabled = MF_BYCOMMAND;
            uEnabled |= bOverlap ? MF_ENABLED : MF_DISABLED | MF_GRAYED;
            EnableMenuItem(hMenu, ID_VIEW_BLENDALPHA, uEnabled);

            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = ((m_BlendType == CPicWindow::BLEND_ALPHA) && bOverlap) ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_BLENDALPHA, (LPARAM)&tbi);
            picWindow1.SetBlendAlpha(m_BlendType, picWindow1.GetBlendAlpha());
            PositionChildren();
        }
        break;
    case ID_VIEW_TRANSPARENTCOLOR:
        {
            static COLORREF customColors[16] = {0};
            CHOOSECOLOR ccDlg = { 0 };
            ccDlg.lStructSize = sizeof(ccDlg);
            ccDlg.hwndOwner = m_hwnd;
            ccDlg.rgbResult = transparentColor;
            ccDlg.lpCustColors = customColors;
            ccDlg.Flags = CC_RGBINIT | CC_FULLOPEN;
            if(ChooseColor(&ccDlg))
            {
                transparentColor = ccDlg.rgbResult;
                picWindow1.SetTransparentColor(transparentColor);
                picWindow2.SetTransparentColor(transparentColor);
                picWindow3.SetTransparentColor(transparentColor);
                // The color picker takes the focus and we don't get it back.
                ::SetFocus(picWindow1);
            }
        }
        break;
    case ID_VIEW_FITIMAGEWIDTHS:
        {
            bFitWidths = !bFitWidths;
            picWindow1.FitWidths(bFitWidths);
            picWindow2.FitWidths(bFitWidths);
            picWindow3.FitWidths(bFitWidths);

            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= bFitWidths ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_FITIMAGEWIDTHS, uCheck);

            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = bFitWidths ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_FITIMAGEWIDTHS, (LPARAM)&tbi);
        }
        break;
    case ID_VIEW_FITIMAGEHEIGHTS:
        {
            bFitHeights = !bFitHeights;
            picWindow1.FitHeights(bFitHeights);
            picWindow2.FitHeights(bFitHeights);
            picWindow3.FitHeights(bFitHeights);

            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= bFitHeights ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_FITIMAGEHEIGHTS, uCheck);

            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = bFitHeights ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_FITIMAGEHEIGHTS, (LPARAM)&tbi);
        }
        break;
    case ID_VIEW_LINKIMAGESTOGETHER:
        {
            bLinkedPositions = !bLinkedPositions;
            picWindow1.LinkPositions(bLinkedPositions);
            picWindow2.LinkPositions(bLinkedPositions);
            picWindow3.LinkPositions(bLinkedPositions);

            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= bLinkedPositions ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_LINKIMAGESTOGETHER, uCheck);

            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = bLinkedPositions ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_LINKIMAGESTOGETHER, (LPARAM)&tbi);
        }
        break;
    case ID_VIEW_ALPHA0:
        picWindow1.SetBlendAlpha(m_BlendType, 0.0f);
        break;
    case ID_VIEW_ALPHA255:
        picWindow1.SetBlendAlpha(m_BlendType, 1.0f);
        break;
    case ID_VIEW_ALPHA127:
        picWindow1.SetBlendAlpha(m_BlendType, 0.5f);
        break;
    case ID_VIEW_ALPHATOGGLE:
        picWindow1.ToggleAlpha();
        break;
    case ID_VIEW_FITIMAGESINWINDOW:
        {
            picWindow1.FitImageInWindow();
            picWindow2.FitImageInWindow();
            picWindow3.FitImageInWindow();
        }
        break;
    case ID_VIEW_ORININALSIZE:
        {
            picWindow1.SetZoom(100, false);
            picWindow2.SetZoom(100, false);
            picWindow3.SetZoom(100, false);
            picWindow1.CenterImage();
            picWindow2.CenterImage();
            picWindow3.CenterImage();
        }
        break;
    case ID_VIEW_ZOOMIN:
        {
            picWindow1.Zoom(true, false);
            if ((!(bFitWidths || bFitHeights))&&(!bOverlap))
            {
                picWindow2.Zoom(true, false);
                picWindow3.Zoom(true, false);
            }
        }
        break;
    case ID_VIEW_ZOOMOUT:
        {
            picWindow1.Zoom(false, false);
            if ((!(bFitWidths || bFitHeights))&&(!bOverlap))
            {
                picWindow2.Zoom(false, false);
                picWindow3.Zoom(false, false);
            }
        }
        break;
    case ID_VIEW_ARRANGEVERTICAL:
        {
            bVertical = !bVertical;
            RECT rect;
            GetClientRect(*this, &rect);
            if (bVertical)
            {
                RECT tbRect;
                GetWindowRect(hwndTB, &tbRect);
                LONG tbHeight = tbRect.bottom-tbRect.top-1;
                if (selectionPaths.size() != 3)
                {
                    nSplitterPos = (rect.bottom-rect.top)/2+tbHeight;
                    nSplitterPos2 = 0;
                }
                else
                {
                    nSplitterPos = (rect.bottom-rect.top)/3+tbHeight;
                    nSplitterPos2 = (rect.bottom-rect.top)*2/3+tbHeight;
                }
            }
            else
            {
                if (selectionPaths.size() != 3)
                {
                    nSplitterPos = (rect.right-rect.left)/2;
                    nSplitterPos2 = 0;
                }
                else
                {
                    nSplitterPos = (rect.right-rect.left)/3;
                    nSplitterPos2 = (rect.right-rect.left)*2/3;
                }
            }
            HMENU hMenu = GetMenu(*this);
            UINT uCheck = MF_BYCOMMAND;
            uCheck |= bVertical ? MF_CHECKED : MF_UNCHECKED;
            CheckMenuItem(hMenu, ID_VIEW_ARRANGEVERTICAL, uCheck);
            // change the state of the toolbar button
            TBBUTTONINFO tbi;
            tbi.cbSize = sizeof(TBBUTTONINFO);
            tbi.dwMask = TBIF_STATE;
            tbi.fsState = bVertical ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;
            SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_ARRANGEVERTICAL, (LPARAM)&tbi);

            PositionChildren(&rect);
        }
        break;
    case ID_ABOUT:
        {
            CAboutDlg dlg(*this);
            dlg.DoModal(hInst, IDD_ABOUT, *this);
        }
        break;
    case SELECTBUTTON_ID:
        {
            HWND hSource = (HWND)lParam;
            FileType resolveWith;
            if (picWindow1 == hSource)
                resolveWith = FileTypeMine;
            else if (picWindow2 == hSource)
                resolveWith = FileTypeBase;
            else if (picWindow3 == hSource)
                resolveWith = FileTypeTheirs;
            else
                break;

            if (selectionResult.empty())
            {
                PostQuitMessage(resolveWith);
                break;
            }

            CopyFile(selectionPaths[resolveWith].c_str(), selectionResult.c_str(), FALSE);

            CAutoBuf projectRoot;
            if (git_repository_discover(projectRoot, CUnicodeUtils::GetUTF8(selectionResult.c_str()), FALSE, nullptr) < 0 && strstr(projectRoot->ptr, "/.git/"))
            {
                PostQuitMessage(resolveWith);
                break;
            }

            CAutoRepository repository(projectRoot->ptr);
            if (!repository)
            {
                PostQuitMessage(resolveWith);
                break;
            }

            CStringA subpath = CUnicodeUtils::GetUTF8(selectionResult.c_str()).Mid((int)strlen(git_repository_workdir(repository)));

            CAutoIndex index;
            if (git_repository_index(index.GetPointer(), repository) || (git_index_get_bypath(index, subpath, 1) == nullptr && git_index_get_bypath(index, subpath, 2) == nullptr))
            {
                PostQuitMessage(resolveWith);
                break;
            }

            CString sTemp;
            sTemp.Format(ResString(hResource, IDS_MARKASRESOLVED), (LPCTSTR)CPathUtils::GetFileNameFromPath(selectionResult.c_str()));
            if (MessageBox(m_hwnd, sTemp, L"TortoiseGitMerge", MB_YESNO | MB_ICONQUESTION) != IDYES)
                break;

            CString cmd;
            cmd.Format(L"\"%sTortoiseGitProc.exe\" /command:resolve /path:\"%s\" /closeonend:1 /noquestion /skipcheck /silent", (LPCTSTR)CPathUtils::GetAppDirectory(), selectionResult.c_str());
            if (resolveMsgWnd)
                cmd.AppendFormat(L" /resolvemsghwnd:%I64d /resolvemsgwparam:%I64d /resolvemsglparam:%I64d", (__int64)resolveMsgWnd, (__int64)resolveMsgWParam, (__int64)resolveMsgLParam);

            STARTUPINFO startup = { 0 };
            PROCESS_INFORMATION process = { 0 };
            startup.cb = sizeof(startup);

            if (!CreateProcess(nullptr, cmd.GetBuffer(), nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr, &startup, &process))
            {
                cmd.ReleaseBuffer();
                PostQuitMessage(resolveWith);
                break;
            }
            cmd.ReleaseBuffer();

            AllowSetForegroundWindow(process.dwProcessId);

            CloseHandle(process.hThread);
            CloseHandle(process.hProcess);

            PostQuitMessage(resolveWith);
        }
        break;
    case IDM_EXIT:
        ::PostQuitMessage(0);
        return 0;
        break;
    default:
        break;
    };
    return 1;
}
bool AddProgressCommand::Run(CGitProgressList* list, CString& sWindowTitle, int& m_itemCountTotal, int& m_itemCount)
{
	ATLASSERT(!(m_bExecutable && m_bSymlink));
	list->SetWindowTitle(IDS_PROGRS_TITLE_ADD, g_Git.CombinePath(m_targetPathList.GetCommonRoot().GetUIPathString()), sWindowTitle);
	list->SetBackgroundImage(IDI_ADD_BKG);
	if (m_bExecutable)
		list->ReportCmd(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_ADD_EXE)));
	else if (m_bSymlink)
		list->ReportCmd(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_ADD_LINK)));
	else
		list->ReportCmd(CString(MAKEINTRESOURCE(IDS_PROGRS_CMD_ADD)));

	m_itemCountTotal = m_targetPathList.GetCount();

	if (g_Git.UsingLibGit2(CGit::GIT_CMD_ADD))
	{
		CAutoRepository repo(g_Git.GetGitRepository());
		if (!repo)
		{
			list->ReportGitError();
			return false;
		}

		CAutoIndex index;
		if (git_repository_index(index.GetPointer(), repo))
		{
			list->ReportGitError();
			return false;
		}
		if (git_index_read(index, true))
		{
			list->ReportGitError();
			return false;
		}

		for (m_itemCount = 0; m_itemCount < m_itemCountTotal; ++m_itemCount)
		{
			CStringA filePathA = CUnicodeUtils::GetMulti(m_targetPathList[m_itemCount].GetGitPathString(), CP_UTF8).TrimRight(L'/');
			if (git_index_add_bypath(index, filePathA))
			{
				list->ReportGitError();
				return false;
			}

			if (!m_targetPathList[m_itemCount].IsDirectory() && (m_bExecutable || m_bSymlink))
			{
				auto entry = const_cast<git_index_entry*>(git_index_get_bypath(index, filePathA, 0));
				if (m_bExecutable)
					entry->mode = GIT_FILEMODE_BLOB_EXECUTABLE;
				else if (m_bSymlink)
					entry->mode = GIT_FILEMODE_LINK;
				if (git_index_add(index, entry))
				{
					list->ReportGitError();
					return false;
				}
			}

			list->AddNotify(new CGitProgressList::WC_File_NotificationData(m_targetPathList[m_itemCount], CGitProgressList::WC_File_NotificationData::git_wc_notify_add));

			if (list->IsCancelled() == TRUE)
			{
				list->ReportUserCanceled();
				return false;
			}
		}

		if (git_index_write(index))
		{
			list->ReportGitError();
			return false;
		}
	}
	else
	{
		CMassiveGitTask mgt(L"add -f");
		if (!mgt.ExecuteWithNotify(&m_targetPathList, list->m_bCancelled, CGitProgressList::WC_File_NotificationData::git_wc_notify_add, list))
			return false;
		if (m_bExecutable)
		{
			if (!SetFileMode(GIT_FILEMODE_BLOB_EXECUTABLE))
				return false;
		}
		else if (m_bSymlink)
		{
			if (!SetFileMode(GIT_FILEMODE_LINK))
				return false;
		}
	}

	CShellUpdater::Instance().AddPathsForUpdate(m_targetPathList);

	m_PostCmdCallback = [this](DWORD status, PostCmdList& postCmdList)
	{
		if (status)
			return;

		if (m_bShowCommitButtonAfterAdd)
			postCmdList.emplace_back(IDI_COMMIT, IDS_MENUCOMMIT, []
			{
				CString sCmd;
				sCmd.Format(L"/command:commit /path:\"%s\"", static_cast<LPCTSTR>(g_Git.m_CurrentDir));
				CAppUtils::RunTortoiseGitProc(sCmd);
			});
		if (!(m_bExecutable || m_bSymlink))
		{
			postCmdList.emplace_back(IDI_ADD, IDS_STATUSLIST_CONTEXT_ADD_EXE, [this] {
				SetFileMode(GIT_FILEMODE_BLOB_EXECUTABLE);
			});
			postCmdList.emplace_back(IDI_ADD, IDS_STATUSLIST_CONTEXT_ADD_LINK, [this] {
				SetFileMode(GIT_FILEMODE_LINK);
			});
		}
	};

	return true;
}
예제 #10
0
BOOL CGitPropertyPage::PageProc (HWND /*hwnd*/, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
	switch (uMessage)
	{
	case WM_INITDIALOG:
		{
			InitWorkfileView();
			return TRUE;
		}
	case WM_NOTIFY:
		{
			LPNMHDR point = (LPNMHDR)lParam;
			int code = point->code;
			//
			// Respond to notifications.
			//
			if (code == PSN_APPLY && m_bChanged)
			{
				do
				{
					CTGitPath path(filenames.front().c_str());
					CString projectTopDir;
					if(!path.HasAdminDir(&projectTopDir) || path.IsDirectory())
						break;

					int stripLength = projectTopDir.GetLength();
					if (projectTopDir[stripLength - 1] != _T('\\'))
						++stripLength;

					CAutoRepository repository(CUnicodeUtils::GetUTF8(projectTopDir));
					if (!repository)
						break;

					CAutoIndex index;
					if (git_repository_index(index.GetPointer(), repository))
						break;

					BOOL assumeValid = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), BM_GETCHECK, 0, 0);
					BOOL skipWorktree = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), BM_GETCHECK, 0, 0);
					BOOL executable = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_EXECUTABLE), BM_GETCHECK, 0, 0);
					BOOL symlink = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_SYMLINK), BM_GETCHECK, 0, 0);

					bool changed = false;

					for (auto it = filenames.cbegin(); it < filenames.cend(); ++it)
					{
						CTGitPath file;
						file.SetFromWin(CString(it->c_str()).Mid(stripLength));
						CStringA pathA = CUnicodeUtils::GetMulti(file.GetGitPathString(), CP_UTF8);
						size_t idx;
						if (!git_index_find(&idx, index, pathA))
						{
							git_index_entry *e = const_cast<git_index_entry *>(git_index_get_byindex(index, idx)); // HACK

							if (assumeValid == BST_CHECKED)
							{
								if (!(e->flags & GIT_IDXENTRY_VALID))
								{
									e->flags |= GIT_IDXENTRY_VALID;
									changed = true;
								}
							}
							else if (assumeValid != BST_INDETERMINATE)
							{
								if (e->flags & GIT_IDXENTRY_VALID)
								{
									e->flags &= ~GIT_IDXENTRY_VALID;
									changed = true;
								}
							}
							if (skipWorktree == BST_CHECKED)
							{
								if (!(e->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE))
								{
									e->flags_extended |= GIT_IDXENTRY_SKIP_WORKTREE;
									changed = true;
								}
							}
							else if (skipWorktree != BST_INDETERMINATE)
							{
								if (e->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE)
								{
									e->flags_extended &= ~GIT_IDXENTRY_SKIP_WORKTREE;
									changed = true;
								}
							}
							if (executable == BST_CHECKED)
							{
								if (!(e->mode & 0111))
								{
									e->mode |= 0111;
									changed = true;
								}
							}
							else if (executable != BST_INDETERMINATE)
							{
								if (e->mode & 0111)
								{
									e->mode &= ~0111;
									changed = true;
								}
							}
							if (symlink == BST_CHECKED)
							{
								if ((e->mode & GIT_FILEMODE_LINK) != GIT_FILEMODE_LINK)
								{
									e->mode |= GIT_FILEMODE_LINK;
									changed = true;
								}
							}
							else if (symlink != BST_INDETERMINATE)
							{
								if ((e->mode & GIT_FILEMODE_LINK) == GIT_FILEMODE_LINK)
								{
									e->mode &= ~GIT_FILEMODE_LINK;
									changed = true;
								}
							}
							if (changed)
								git_index_add(index, e);
						}
					}

					if (changed)
					{
						if (!git_index_write(index))
							m_bChanged = false;
					}
				} while (0);
			}
			SetWindowLongPtr (m_hwnd, DWLP_MSGRESULT, FALSE);
			return TRUE;
		}
		case WM_DESTROY:
			return TRUE;

		case WM_COMMAND:
		PageProcOnCommand(wParam);
		break;
	} // switch (uMessage)

	if (uMessage == m_UpdateLastCommit)
	{
		DisplayCommit((git_commit *)lParam, IDC_LAST_HASH, IDC_LAST_SUBJECT, IDC_LAST_AUTHOR, IDC_LAST_DATE);
		return TRUE;
	}

	return FALSE;
}
예제 #11
0
void CGitPropertyPage::InitWorkfileView()
{
	if (filenames.empty())
		return;

	CTGitPath path(filenames.front().c_str());

	CString ProjectTopDir;
	if(!path.HasAdminDir(&ProjectTopDir))
		return;

	CAutoRepository repository(CUnicodeUtils::GetUTF8(ProjectTopDir));
	if (!repository)
		return;

	CString username;
	CString useremail;
	CString autocrlf;
	CString safecrlf;

	CAutoConfig config(repository);
	if (config)
	{
		config.GetString(L"user.name", username);
		config.GetString(L"user.email", useremail);
		config.GetString(L"core.autocrlf", autocrlf);
		config.GetString(L"core.safecrlf", safecrlf);
	}

	CString branch;
	CString remotebranch;
	if (!git_repository_head_detached(repository))
	{
		CAutoReference head;
		if (git_repository_head_unborn(repository))
		{
			git_reference_lookup(head.GetPointer(), repository, "HEAD");
			branch = CUnicodeUtils::GetUnicode(git_reference_symbolic_target(head));
			if (branch.Find(_T("refs/heads/")) == 0)
				branch = branch.Mid(11); // 11 = len("refs/heads/")
		}
		else if (!git_repository_head(head.GetPointer(), repository))
		{
			const char * branchChar = git_reference_shorthand(head);
			branch = CUnicodeUtils::GetUnicode(branchChar);

			const char * branchFullChar = git_reference_name(head);
			CAutoBuf upstreambranchname;
			if (!git_branch_upstream_name(upstreambranchname, repository, branchFullChar))
			{
				remotebranch = CUnicodeUtils::GetUnicode(CStringA(upstreambranchname->ptr, (int)upstreambranchname->size));
				remotebranch = remotebranch.Mid(13); // 13=len("refs/remotes/")
			}
		}
	}
	else
		branch = _T("detached HEAD");

	if (autocrlf.Trim().IsEmpty())
		autocrlf = _T("false");
	if (safecrlf.Trim().IsEmpty())
		safecrlf = _T("false");

	SetDlgItemText(m_hwnd,IDC_CONFIG_USERNAME,username.Trim());
	SetDlgItemText(m_hwnd,IDC_CONFIG_USEREMAIL,useremail.Trim());
	SetDlgItemText(m_hwnd,IDC_CONFIG_AUTOCRLF,autocrlf.Trim());
	SetDlgItemText(m_hwnd,IDC_CONFIG_SAFECRLF,safecrlf.Trim());

	SetDlgItemText(m_hwnd,IDC_SHELL_CURRENT_BRANCH,branch.Trim());
	SetDlgItemText(m_hwnd,IDC_SHELL_REMOTE_BRANCH, remotebranch);

	git_oid oid;
	CAutoCommit HEADcommit;
	if (!git_reference_name_to_id(&oid, repository, "HEAD") && !git_commit_lookup(HEADcommit.GetPointer(), repository, &oid) && HEADcommit)
		DisplayCommit(HEADcommit, IDC_HEAD_HASH, IDC_HEAD_SUBJECT, IDC_HEAD_AUTHOR, IDC_HEAD_DATE);

	{
		int stripLength = ProjectTopDir.GetLength();
		if (ProjectTopDir[stripLength - 1] != _T('\\'))
			++stripLength;

		bool allAreFiles = true;
		for (auto it = filenames.cbegin(); it < filenames.cend(); ++it)
		{
			if (PathIsDirectory(it->c_str()))
			{
				allAreFiles = false;
				break;
			}
		}
		if (allAreFiles)
		{
			size_t assumevalid = 0;
			size_t skipworktree = 0;
			size_t executable = 0;
			size_t symlink = 0;
			do
			{
				CAutoIndex index;
				if (git_repository_index(index.GetPointer(), repository))
					break;

				for (auto it = filenames.cbegin(); it < filenames.cend(); ++it)
				{
					CTGitPath file;
					file.SetFromWin(CString(it->c_str()).Mid(stripLength));
					CStringA pathA = CUnicodeUtils::GetMulti(file.GetGitPathString(), CP_UTF8);
					size_t idx;
					if (!git_index_find(&idx, index, pathA))
					{
						const git_index_entry *e = git_index_get_byindex(index, idx);

						if (e->flags & GIT_IDXENTRY_VALID)
							++assumevalid;

						if (e->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE)
							++skipworktree;

						if (e->mode & 0111)
							++executable;

						if ((e->mode & GIT_FILEMODE_LINK) == GIT_FILEMODE_LINK)
							++symlink;
					}
					else
					{
						// do not show checkboxes for unversioned files
						ShowWindow(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), SW_HIDE);
						ShowWindow(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), SW_HIDE);
						ShowWindow(GetDlgItem(m_hwnd, IDC_EXECUTABLE), SW_HIDE);
						ShowWindow(GetDlgItem(m_hwnd, IDC_SYMLINK), SW_HIDE);
						break;
					}
				}
			} while (0);

			if (assumevalid != 0 && assumevalid != filenames.size())
			{
				SendMessage(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), BM_SETSTYLE, (DWORD)GetWindowLong(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), GWL_STYLE) & ~BS_AUTOCHECKBOX | BS_AUTO3STATE, 0);
				SendMessage(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), BM_SETCHECK, BST_INDETERMINATE, 0);
			}
			else
				SendMessage(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), BM_SETCHECK, (assumevalid == 0) ? BST_UNCHECKED : BST_CHECKED, 0);

			if (skipworktree != 0 && skipworktree != filenames.size())
			{
				SendMessage(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), BM_SETSTYLE, (DWORD)GetWindowLong(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), GWL_STYLE) & ~BS_AUTOCHECKBOX | BS_AUTO3STATE, 0);
				SendMessage(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), BM_SETCHECK, BST_INDETERMINATE, 0);
			}
			else
				SendMessage(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), BM_SETCHECK, (skipworktree == 0) ? BST_UNCHECKED : BST_CHECKED, 0);

			if (executable != 0 && executable != filenames.size())
			{
				SendMessage(GetDlgItem(m_hwnd, IDC_EXECUTABLE), BM_SETSTYLE, (DWORD)GetWindowLong(GetDlgItem(m_hwnd, IDC_EXECUTABLE), GWL_STYLE) & ~BS_AUTOCHECKBOX | BS_AUTO3STATE, 0);
				SendMessage(GetDlgItem(m_hwnd, IDC_EXECUTABLE), BM_SETCHECK, BST_INDETERMINATE, 0);
				EnableWindow(GetDlgItem(m_hwnd, IDC_SYMLINK), TRUE);
			}
			else
			{
				SendMessage(GetDlgItem(m_hwnd, IDC_EXECUTABLE), BM_SETCHECK, (executable == 0) ? BST_UNCHECKED : BST_CHECKED, 0);
				EnableWindow(GetDlgItem(m_hwnd, IDC_SYMLINK), (executable == 0) ? TRUE : FALSE);
			}

			if (symlink != 0 && symlink != filenames.size())
			{
				SendMessage(GetDlgItem(m_hwnd, IDC_SYMLINK), BM_SETSTYLE, (DWORD)GetWindowLong(GetDlgItem(m_hwnd, IDC_SYMLINK), GWL_STYLE) & ~BS_AUTOCHECKBOX | BS_AUTO3STATE, 0);
				SendMessage(GetDlgItem(m_hwnd, IDC_SYMLINK), BM_SETCHECK, BST_INDETERMINATE, 0);
				EnableWindow(GetDlgItem(m_hwnd, IDC_EXECUTABLE), TRUE);
			}
			else
			{
				SendMessage(GetDlgItem(m_hwnd, IDC_SYMLINK), BM_SETCHECK, (symlink == 0) ? BST_UNCHECKED : BST_CHECKED, 0);
				EnableWindow(GetDlgItem(m_hwnd, IDC_EXECUTABLE), (symlink == 0) ? TRUE : FALSE);
			}
		}
		else
		{
			ShowWindow(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), SW_HIDE);
			ShowWindow(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), SW_HIDE);
			ShowWindow(GetDlgItem(m_hwnd, IDC_EXECUTABLE), SW_HIDE);
			ShowWindow(GetDlgItem(m_hwnd, IDC_SYMLINK), SW_HIDE);
		}
	}

	if (filenames.size() == 1 && !PathIsDirectory(filenames[0].c_str()))
	{
		SetDlgItemText(m_hwnd, IDC_LAST_SUBJECT, CString(MAKEINTRESOURCE(IDS_LOADING)));
		_beginthread(LogThreadEntry, 0, this);
	}
	else
		ShowWindow(GetDlgItem(m_hwnd, IDC_STATIC_LASTMODIFIED), SW_HIDE);
}