void CFolderCrawler::AddDirectoryForUpdate(const CTGitPath& path)
{
	/* Index file changing*/
	if( GitStatus::IsExistIndexLockFile((CString&)path.GetWinPathString()))
		return;

	if (!CGitStatusCache::Instance().IsPathGood(path))
		return;
	{
		ATLTRACE(_T("AddDirectoryForUpdate %s\n"),path.GetWinPath());

		AutoLocker lock(m_critSec);

		m_foldersToUpdate.Push(path);

		//ATLASSERT(path.IsDirectory() || !path.Exists());
		// set this flag while we are sync'ed
		// with the worker thread
		m_bItemsAddedSinceLastCrawl = true;
	}
	//if (SetHoldoff())
		SetEvent(m_hWakeEvent);
}
/* Fetch is false, means fetch status from cache */
CStatusCacheEntry CGitStatusCache::GetStatusForPath(const CTGitPath& path, DWORD flags,  bool bFetch /* = true */)
{
    bool bRecursive = !!(flags & TGITCACHE_FLAGS_RECUSIVE_STATUS);

    // Check a very short-lived 'mini-cache' of the last thing we were asked for.
    long now = (long)GetTickCount();
    if(now-m_mostRecentExpiresAt < 0)
    {
        if(path.IsEquivalentToWithoutCase(m_mostRecentPath))
        {
            return m_mostRecentStatus;
        }
    }
    m_mostRecentPath = path;
    m_mostRecentExpiresAt = now+1000;

    if (IsPathGood(path))
    {
        // Stop the crawler starting on a new folder while we're doing this much more important task...
        // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath().
        CCrawlInhibitor crawlInhibit(&m_folderCrawler);

        CTGitPath dirpath = path.GetContainingDirectory();
        if ((dirpath.IsEmpty()) || (!m_shellCache.IsPathAllowed(dirpath.GetWinPath())))
            dirpath = path.GetDirectory();
        CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath);
        if (cachedDir != NULL)
        {
            //ATLTRACE(_T("GetStatusForMember %d\n"), bFetch);
            m_mostRecentStatus = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
            return m_mostRecentStatus;
        }
    }
    ATLTRACE(_T("ignored no good path %s\n"), path.GetWinPath());
    m_mostRecentStatus = CStatusCacheEntry();
    if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasGITAdminDir(path.GetWinPath(), true))
    {
        ATLTRACE(_T("force status %s\n"), path.GetWinPath());
        m_mostRecentStatus.ForceStatus(git_wc_status_normal);
    }
    return m_mostRecentStatus;
}
Beispiel #3
0
CTGitPath CTGitPath::GetContainingDirectory() const
{
	EnsureBackslashPathSet();

	CString sDirName = m_sBackslashPath.Left(m_sBackslashPath.ReverseFind('\\'));
	if(sDirName.GetLength() == 2 && sDirName[1] == ':')
	{
		// This is a root directory, which needs a trailing slash
		sDirName += '\\';
		if(sDirName == m_sBackslashPath)
		{
			// We were clearly provided with a root path to start with - we should return nothing now
			sDirName.Empty();
		}
	}
	if(sDirName.GetLength() == 1 && sDirName[0] == '\\')
	{
		// We have an UNC path and we already are the root
		sDirName.Empty();
	}
	CTGitPath retVal;
	retVal.SetFromWin(sDirName);
	return retVal;
}
Beispiel #4
0
void CGitStatusCache::RemoveCacheForPath(const CTGitPath& path)
{
    // Stop the crawler starting on a new folder
    CCrawlInhibitor crawlInhibit(&m_folderCrawler);
    CCachedDirectory::ItDir itMap;
    CCachedDirectory * dirtoremove = NULL;

    itMap = m_directoryCache.find(path);
    if ((itMap != m_directoryCache.end())&&(itMap->second))
        dirtoremove = itMap->second;
    if (dirtoremove == NULL)
        return;
    ATLASSERT(path.IsEquivalentToWithoutCase(dirtoremove->m_directoryPath));
    RemoveCacheForDirectory(dirtoremove);
}
Beispiel #5
0
bool CGitStatusCache::BlockPath(const CTGitPath& path, DWORD timeout /* = 0 */)
{
    if (timeout == 0)
        timeout = BLOCK_PATH_DEFAULT_TIMEOUT;

    if (timeout > BLOCK_PATH_MAX_TIMEOUT)
        timeout = BLOCK_PATH_MAX_TIMEOUT;

    timeout = GetTickCount() + (timeout * 1000);	// timeout is in seconds, but we need the milliseconds

    AutoLocker lock(m_NoWatchPathCritSec);
    m_NoWatchPaths[path.GetDirectory()] = timeout;

    return true;
}
Beispiel #6
0
VOID GetAnswerToRequest(const TGITCacheRequest* pRequest, TGITCacheResponse* pReply, DWORD* pResponseLength)
{
	CTGitPath path;
	*pResponseLength = 0;
	if(pRequest->flags & TGITCACHE_FLAGS_FOLDERISKNOWN)
	{
		path.SetFromWin(pRequest->path, !!(pRequest->flags & TGITCACHE_FLAGS_ISFOLDER));
	}
	else
	{
		path.SetFromWin(pRequest->path);
	}

	CAutoReadWeakLock readLock(CGitStatusCache::Instance().GetGuard(), 2000);
	if (readLock.IsAcquired())
	{
		CGitStatusCache::Instance().GetStatusForPath(path, pRequest->flags, false).BuildCacheResponse(*pReply, *pResponseLength);
	}
	else
	{
		CStatusCacheEntry entry;
		entry.BuildCacheResponse(*pReply, *pResponseLength);
	}
}
VOID GetAnswerToRequest(const TGITCacheRequest* pRequest, TGITCacheResponse* pReply, DWORD* pResponseLength)
{
	CTGitPath path;
	*pResponseLength = 0;
	if(pRequest->flags & TGITCACHE_FLAGS_FOLDERISKNOWN)
	{
		path.SetFromWin(pRequest->path, !!(pRequest->flags & TGITCACHE_FLAGS_ISFOLDER));
	}
	else
	{
		path.SetFromWin(pRequest->path);
	}

	if (CGitStatusCache::Instance().WaitToRead(2000))
	{
		CGitStatusCache::Instance().GetStatusForPath(path, pRequest->flags, false).BuildCacheResponse(*pReply, *pResponseLength);
		CGitStatusCache::Instance().Done();
	}
	else
	{
		CStatusCacheEntry entry;
		entry.BuildCacheResponse(*pReply, *pResponseLength);
	}
}
void CFolderCrawler::AddPathForUpdate(const CTGitPath& path)
{
	/* Index file changing*/
	if( GitStatus::IsExistIndexLockFile((CString&)path.GetWinPathString()))
		return;

	{
		AutoLocker lock(m_critSec);

		m_pathsToUpdate.Push(path);
		m_bPathsAddedSinceLastCrawl = true;
	}
	//if (SetHoldoff())
		SetEvent(m_hWakeEvent);
}
Beispiel #9
0
const_hookiterator CHooks::FindItem(hooktype t, const CString& workingTree) const
{
	hookkey key;
	CTGitPath path = workingTree;
	do
	{
		key.htype = t;
		key.path = path;
		auto it = find(key);
		if (it != end())
			return it;
		path = path.GetContainingDirectory();
	} while(!path.IsEmpty());
	// look for a script with a path as '*'
	key.htype = t;
	key.path = CTGitPath(L"*");
	auto it = find(key);
	if (it != end())
	{
		return it;
	}

	return end();
}
Beispiel #10
0
bool CDirectoryWatcher::RemovePathAndChildren(const CTGitPath& path)
{
	bool bRemoved = false;
	AutoLocker lock(m_critSec);
repeat:
	for (int i=0; i<watchedPaths.GetCount(); ++i)
	{
		if (path.IsAncestorOf(watchedPaths[i]))
		{
			watchedPaths.RemovePath(watchedPaths[i]);
			bRemoved = true;
			goto repeat;
		}
	}
	return bRemoved;
}
Beispiel #11
0
int CSendMailCombineable::SendAsSingleMail(const CTGitPath& path, CGitProgressList* instance)
{
	ASSERT(instance);

	CString pathfile(path.GetWinPathString());

	CString body;
	CStringArray attachments;
	if (m_bAttachment)
		attachments.Add(pathfile);
	else if (GetFileContents(pathfile, body))
	{
		instance->ReportError(_T("Could not open ") + pathfile);
		return -2;
	}

	return SendMail(path, instance, m_sSenderName, m_sSenderMail, m_sTo, m_sCC, m_sSubject, body, attachments);
}
void CFolderCrawler::AddPathForUpdate(const CTGitPath& path)
{
	/* Index file changing*/
	if( GitStatus::IsExistIndexLockFile((CString&)path.GetWinPathString()))
		return;

	if (!CGitStatusCache::Instance().IsPathGood(path))
		return;

	{
		AutoLocker lock(m_critSec);

		RemoveDuplicate(m_pathsToUpdate, path);
		m_pathsToUpdate.push_back(path);
		m_pathsToUpdate.back().SetCustomData(GetTickCount()+1000);
		m_bPathsAddedSinceLastCrawl = true;
	}
	//if (SetHoldoff())
		SetEvent(m_hWakeEvent);
}
Beispiel #13
0
int CSendMailPatch::SendAsSingleMail(CTGitPath &path, CGitProgressList * instance)
{
	ASSERT(instance);

	CString pathfile(path.GetWinPathString());
	CPatch patch;
	if (patch.Parse(pathfile))
	{
		instance->ReportError(_T("Could not open/parse ") + pathfile);
		return -2;
	}

	CString body;
	CStringArray attachments;
	if (m_bAttachment)
		attachments.Add(pathfile);
	else
		body = patch.m_strBody;

	return SendMail(path, instance, m_sSenderName, m_sSenderMail, m_sTo, m_sCC, patch.m_Subject, body, attachments);
}
bool CDirectoryWatcher::CloseHandlesForPath(const CTGitPath& path)
{
	if (watchInfoMap.size() == 0)
		return false;
	AutoLocker lock(m_critSec);
	for (std::map<HANDLE, CDirWatchInfo *>::iterator I = watchInfoMap.begin(); I != watchInfoMap.end(); ++I)
	{
		CDirectoryWatcher::CDirWatchInfo * info = I->second;
		CTGitPath p = CTGitPath(info->m_DirPath);
		if (path.IsAncestorOf(p))
		{
			RemovePathAndChildren(p);
			BlockPath(p);
		}
		info->CloseDirectoryHandle();
	}
	watchInfoMap.clear();
	if (m_hCompPort != INVALID_HANDLE_VALUE)
		CloseHandle(m_hCompPort);
	m_hCompPort = INVALID_HANDLE_VALUE;
	return true;
}
Beispiel #15
0
bool CDirectoryWatcher::CloseHandlesForPath(const CTGitPath& path)
{
	AutoLocker lock(m_critSec);
	CloseWatchHandles();

	if (watchInfoMap.empty())
		return false;

	for (TInfoMap::iterator I = watchInfoMap.begin(); I != watchInfoMap.end(); ++I)
	{
		CDirectoryWatcher::CDirWatchInfo * info = I->second;
		I->second = NULL;
		CTGitPath p = CTGitPath(info->m_DirPath);
		if (path.IsAncestorOf(p))
		{
			RemovePathAndChildren(p);
			BlockPath(p);
		}
		ScheduleForDeletion(info);
	}
	watchInfoMap.clear();
	return true;
}
Beispiel #16
0
CTGitPath CTempFiles::ConstructTempPath(const CTGitPath& path)
{
	DWORD len = ::GetTempPath(0, nullptr);
	auto temppath = std::make_unique<TCHAR[]>(len + 1);
	auto tempF = std::make_unique<TCHAR[]>(len + 50);
	::GetTempPath (len+1, temppath.get());
	CTGitPath tempfile;
	CString possibletempfile;
	if (path.IsEmpty())
	{
		::GetTempFileName(temppath.get(), L"tsm", 0, tempF.get());
		tempfile = CTGitPath (tempF.get());
	}
	else
	{
		int i=0;
		do
		{
			// use the UI path, which does unescaping for urls
			CString filename = path.GetUIFileOrDirectoryName();
			// remove illegal chars which could be present in urls
			filename.Remove('?');
			filename.Remove('*');
			filename.Remove('<');
			filename.Remove('>');
			filename.Remove('|');
			filename.Remove('"');
			// the inner loop assures that the resulting path is < MAX_PATH
			// if that's not possible without reducing the 'filename' to less than 5 chars, use a path
			// that's longer than MAX_PATH (in that case, we can't really do much to avoid longer paths)
			do
			{
				possibletempfile.Format(L"%s%s.tsm%3.3x.tmp%s", temppath.get(), (LPCTSTR)filename, i, (LPCTSTR)path.GetFileExtension());
				tempfile.SetFromWin(possibletempfile);
				filename = filename.Left(filename.GetLength()-1);
			} while (   (filename.GetLength() > 4)
					 && (tempfile.GetWinPathString().GetLength() >= MAX_PATH));
			i++;
		} while (PathFileExists(tempfile.GetWinPath()));
	}

	// caller has to actually grab the file path

	return tempfile;
}
Beispiel #17
0
CTGitPath CTempFiles::GetTempFilePath(bool bRemoveAtEnd, const CTGitPath& path /* = CTGitPath() */, const GitRev revision /* = GitRev() */)
{
	DWORD len = ::GetTempPath(0, NULL);
	TCHAR * temppath = new TCHAR[len+1];
	TCHAR * tempF = new TCHAR[len+50];
	::GetTempPath (len+1, temppath);
	CTGitPath tempfile;
	CString possibletempfile;
	if (path.IsEmpty())
	{
		::GetTempFileName (temppath, TEXT("git"), 0, tempF);
		tempfile = CTGitPath(tempF);
	}
	else
	{
		int i=0;
		do
		{
			if (!((GitRev&)revision).m_CommitHash.IsEmpty())
			{
				possibletempfile.Format(_T("%s%s-rev%s.git%3.3x.tmp%s"), temppath, (LPCTSTR)path.GetFileOrDirectoryName(), (LPCTSTR)((GitRev&)revision).m_CommitHash.ToString().Left(7), i, (LPCTSTR)path.GetFileExtension());
			}
			else
			{
				possibletempfile.Format(_T("%s%s.git%3.3x.tmp%s"), temppath, (LPCTSTR)path.GetFileOrDirectoryName(), i, (LPCTSTR)path.GetFileExtension());
			}
			tempfile.SetFromWin(possibletempfile);
			i++;
		} while (PathFileExists(tempfile.GetWinPath()));
	}
	//now create the temp file, so that subsequent calls to GetTempFile() return
	//different filenames.
	HANDLE hFile = CreateFile(tempfile.GetWinPath(), GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
	CloseHandle(hFile);
	delete [] temppath;
	delete [] tempF;
	if (bRemoveAtEnd)
		m_TempFileList.AddPath(tempfile);
	return tempfile;
}
Beispiel #18
0
bool CRemoteCacheLink::ReleaseLockForPath(const CTGitPath& path)
{
	EnsureCommandPipeOpen();
	if (m_hCommandPipe)
	{
		DWORD cbWritten;
		TGITCacheCommand cmd = { 0 };
		cmd.command = TGITCACHECOMMAND_RELEASE;
		wcsncpy_s(cmd.path, path.GetDirectory().GetWinPath(), _countof(cmd.path) - 1);
		BOOL fSuccess = WriteFile(
			m_hCommandPipe, // handle to pipe
			&cmd,           // buffer to write from
			sizeof(cmd),    // number of bytes to write
			&cbWritten,     // number of bytes written
			NULL);          // not overlapped I/O
		if (! fSuccess || sizeof(cmd) != cbWritten)
		{
			CloseCommandPipe();
			return false;
		}
		return true;
	}
	return false;
}
Beispiel #19
0
bool CFileDiffDlg::SortCompare(const CTGitPath& Data1, const CTGitPath& Data2)
{
	int result = 0;
	int d1, d2;
	switch (m_nSortedColumn)
	{
	case 0:		//path column
		result = Data1.GetWinPathString().Compare(Data2.GetWinPathString());
		break;
	case 1:		//extension column
		result = Data1.GetFileExtension().Compare(Data2.GetFileExtension());
		break;
	case 2:		//action column
		result = Data1.m_Action - Data2.m_Action;
		break;
	case 3:
		d1 = CSorter::A2L(Data1.m_StatAdd);
		d2 = CSorter::A2L(Data2.m_StatAdd);
		result = d1 - d2;
		break;
	case 4:
		d1 = CSorter::A2L(Data1.m_StatDel);;
		d2 = CSorter::A2L(Data2.m_StatDel);
		result = d1 - d2;
		break;
	default:
		break;
	}
	// sort by path name as second priority
	if (m_nSortedColumn != 0 && result == 0)
		result = Data1.GetWinPathString().Compare(Data2.GetWinPathString());

	if (!m_bAscending)
		result = -result;
	return result < 0;
}
Beispiel #20
0
int CGitDiff::Diff(const CTGitPath * pPath, const CTGitPath * pPath2, git_revnum_t rev1, git_revnum_t rev2, bool /*blame*/, bool /*unified*/, int jumpToLine)
{
	CString temppath;
	GetTempPath(temppath);

	// make sure we have HASHes here, otherwise filenames might be invalid
	if (rev1 != GIT_REV_ZERO)
	{
		CGitHash rev1Hash;
		if (g_Git.GetHash(rev1Hash, rev1))
		{
			MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev1 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		rev1 = rev1Hash.ToString();
	}
	if (rev2 != GIT_REV_ZERO)
	{
		CGitHash rev2Hash;
		if (g_Git.GetHash(rev2Hash, rev2))
		{
			MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev2 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		rev2 = rev2Hash.ToString();
	}

	CString file1;
	CString title1;
	CString cmd;

	if(pPath->IsDirectory() || pPath2->IsDirectory())
	{
		int result;
		// refresh if result = 1
		CTGitPath path = *pPath;
		CTGitPath path2 = *pPath2;
		while ((result = SubmoduleDiff(&path, &path2, rev1, rev2)) == 1)
		{
			path.SetFromGit(pPath->GetGitPathString());
			path2.SetFromGit(pPath2->GetGitPathString());
		}
		return result;
	}

	if(rev1 != GIT_REV_ZERO )
	{
		TCHAR szTempName[MAX_PATH] = {0};
		GetTempFileName(temppath, pPath->GetBaseFilename(), 0, szTempName);
		CString temp(szTempName);
		DeleteFile(szTempName);
		CreateDirectory(szTempName, NULL);
		// use original file extension, an external diff tool might need it
		file1.Format(_T("%s\\%s-%s-right%s"),
				temp,
				pPath->GetBaseFilename(),
				rev1.Left(g_Git.GetShortHASHLength()),
				pPath->GetFileExtension());
		title1 = pPath->GetFileOrDirectoryName() + _T(":") + rev1.Left(g_Git.GetShortHASHLength());
		g_Git.GetOneFile(rev1,*pPath,file1);
		::SetFileAttributes(file1, FILE_ATTRIBUTE_READONLY);
	}
	else
	{
		file1=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString();
		title1.Format( IDS_DIFF_WCNAME, pPath->GetFileOrDirectoryName() );
		if (!PathFileExists(file1))
		{
			CString sMsg;
			sMsg.Format(IDS_PROC_DIFFERROR_FILENOTINWORKINGTREE, file1);
			if (MessageBox(NULL, sMsg, _T("TortoiseGit"), MB_ICONEXCLAMATION | MB_YESNO) == IDNO)
				return 1;
			if (!CCommonAppUtils::FileOpenSave(file1, NULL, IDS_DIFF_WCNAME, IDS_COMMONFILEFILTER, true))
				return 1;
			title1.Format(IDS_DIFF_WCNAME, CTGitPath(file1).GetUIFileOrDirectoryName());
		}
	}

	CString file2;
	CString title2;
	if(rev2 != GIT_REV_ZERO)
	{
		TCHAR szTempName[MAX_PATH] = {0};
		GetTempFileName(temppath, pPath2->GetBaseFilename(), 0, szTempName);
		CString temp(szTempName);
		DeleteFile(szTempName);
		CreateDirectory(szTempName, NULL);
		CTGitPath fileName = *pPath2;
		if (pPath2->m_Action & CTGitPath::LOGACTIONS_REPLACED)
			fileName = CTGitPath(pPath2->GetGitOldPathString());

		// use original file extension, an external diff tool might need it
		file2.Format(_T("%s\\%s-%s-left%s"),
				temp,
				fileName.GetBaseFilename(),
				rev2.Left(g_Git.GetShortHASHLength()),
				fileName.GetFileExtension());
		title2 = fileName.GetFileOrDirectoryName() + _T(":") + rev2.Left(g_Git.GetShortHASHLength());
		g_Git.GetOneFile(rev2, fileName, file2);
		::SetFileAttributes(file2, FILE_ATTRIBUTE_READONLY);
	}
	else
	{
		file2=g_Git.m_CurrentDir+_T("\\")+pPath2->GetWinPathString();
		title2.Format( IDS_DIFF_WCNAME, pPath2->GetFileOrDirectoryName() );
	}

	if (pPath->m_Action == pPath->LOGACTIONS_ADDED)
	{
		CGitDiff::DiffNull(pPath, rev1, true, jumpToLine);
	}
	else if (pPath->m_Action == pPath->LOGACTIONS_DELETED)
	{
		CGitDiff::DiffNull(pPath, rev2, false, jumpToLine);
	}
	else
	{
		CAppUtils::DiffFlags flags;
		CAppUtils::StartExtDiff(file2,file1,
								title2,
								title1,
								g_Git.m_CurrentDir + _T("\\") + pPath2->GetWinPathString(),
								g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(),
								rev2,
								rev1,
								flags, jumpToLine);
	}
	return 0;
}
Beispiel #21
0
int GitRev::SafeFetchFullInfo(CGit *git)
{
	if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
	{
		this->m_Files.Clear();
		git->CheckAndInitDll();
		GIT_COMMIT commit;
		GIT_COMMIT_LIST list;
		GIT_HASH   parent;
		memset(&commit,0,sizeof(GIT_COMMIT));

		CAutoLocker lock(g_Git.m_critGitDllSec);

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

		int i=0;

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

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

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

			CTGitPath path;
			CString strnewname;
			CString stroldname;

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

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

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

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

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

				this->m_Action|=path.m_Action;

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


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

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

		CAutoLocker lock(g_Git.m_critGitDllSec);

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

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

			isRoot = false;

			CTGitPath path;
			CString strnewname;
			CString stroldname;

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

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

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

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

				m_SimpleFileList.push_back(strnewname);

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

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

	return 0;
}
Beispiel #23
0
bool PasteCopyCommand::Execute()
{
    CString sDroppath = parser.GetVal(_T("droptarget"));
    CTGitPath dropPath(sDroppath);
    ProjectProperties props;
    props.ReadProps(dropPath);
    if (dropPath.IsAdminDir())
        return FALSE;

    if(!dropPath.HasAdminDir(&g_Git.m_CurrentDir))
        return FALSE;
    //SVN svn;
    //SVNStatus status;
    unsigned long count = 0;
    CString sNewName;
    orgPathList.RemoveAdminPaths();
    CSysProgressDlg progress;
    progress.SetTitle(IDS_PROC_COPYING);
    progress.SetAnimation(IDR_MOVEANI);
    progress.SetTime(true);
    progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
    for(int nPath = 0; nPath < orgPathList.GetCount(); nPath++)
    {
        const CTGitPath& sourcePath = orgPathList[nPath];

        CTGitPath fullDropPath = dropPath;
        if (sNewName.IsEmpty())
            fullDropPath.AppendPathString(sourcePath.GetFileOrDirectoryName());
        else
            fullDropPath.AppendPathString(sNewName);

        // Check for a drop-on-to-ourselves
        if (sourcePath.IsEquivalentTo(fullDropPath))
        {
            // Offer a rename
            progress.Stop();
            CRenameDlg dlg;
            dlg.m_windowtitle.Format(IDS_PROC_NEWNAMECOPY, (LPCTSTR)sourcePath.GetUIFileOrDirectoryName());
            if (dlg.DoModal() != IDOK)
            {
                return FALSE;
            }
            // rebuild the progress dialog
            progress.EnsureValid();
            progress.SetTitle(IDS_PROC_COPYING);
            progress.SetAnimation(IDR_MOVEANI);
            progress.SetTime(true);
            progress.SetProgress(count, orgPathList.GetCount());
            progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
            // Rebuild the destination path, with the new name
            fullDropPath.SetFromUnknown(sDroppath);
            fullDropPath.AppendPathString(dlg.m_name);
        }

        //svn_wc_status_kind s = status.GetAllStatus(sourcePath);
        //if ((s == svn_wc_status_none)||(s == svn_wc_status_unversioned)||(s == svn_wc_status_ignored))
        {
            // source file is unversioned: move the file to the target, then add it
            CopyFile(sourcePath.GetWinPath(), fullDropPath.GetWinPath(), FALSE);
            CString cmd,output;
            cmd.Format(_T("git.exe add \"%s\""),fullDropPath.GetWinPath());
            if( g_Git.Run(cmd,&output,CP_ACP))
            {
                TRACE(_T("%s\n"), (LPCTSTR)output);
                CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_ICONERROR);
                return FALSE;		//get out of here
            }
            else
                CShellUpdater::Instance().AddPathForUpdate(fullDropPath);
        }
        //else
        //{
        //	if (!svn.Copy(CTSVNPathList(sourcePath), fullDropPath, SVNRev::REV_WC, SVNRev()))
        //	{
        //		TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
        //		CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
        //		return FALSE;		//get out of here
        //	}
        //	else
        //		CShellUpdater::Instance().AddPathForUpdate(fullDropPath);
        //}
        count++;
        if (progress.IsValid())
        {
            progress.FormatPathLine(1, IDS_PROC_COPYINGPROG, sourcePath.GetWinPath());
            progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, fullDropPath.GetWinPath());
            progress.SetProgress(count, orgPathList.GetCount());
        }
        if ((progress.IsValid())&&(progress.HasUserCancelled()))
        {
            CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);
            return false;
        }
    }
    return true;
}
Beispiel #24
0
bool DropMoveCommand::Execute()
{
	CString droppath = parser.GetVal(_T("droptarget"));
	CString ProjectTop;
	if (!CTGitPath(droppath).HasAdminDir(&ProjectTop))
		return FALSE;
	
	if (ProjectTop != g_Git.m_CurrentDir )
	{
		CMessageBox::Show(NULL,_T("Target and source must be the same git repository"),_T("TortoiseGit"),MB_OK);
		return FALSE;
	}

	droppath = droppath.Right(droppath.GetLength()-ProjectTop.GetLength()-1);

	unsigned long count = 0;
	pathList.RemoveAdminPaths();
	CString sNewName;

	if ((parser.HasKey(_T("rename")))&&(pathList.GetCount()==1))
	{
		// ask for a new name of the source item
		do 
		{
			CRenameDlg renDlg;
			renDlg.m_windowtitle.LoadString(IDS_PROC_MOVERENAME);
			renDlg.m_name = pathList[0].GetFileOrDirectoryName();
			if (renDlg.DoModal() != IDOK)
			{
				return FALSE;
			}
			sNewName = renDlg.m_name;
		} while(sNewName.IsEmpty() || PathFileExists(droppath+_T("\\")+sNewName));
	}
	CSysProgressDlg progress;
	if (progress.IsValid())
	{
		progress.SetTitle(IDS_PROC_MOVING);
		progress.SetAnimation(IDR_MOVEANI);
		progress.SetTime(true);
		progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
	}
	for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
	{
		CTGitPath destPath;
		if (sNewName.IsEmpty())
			destPath = CTGitPath(droppath+_T("\\")+pathList[nPath].GetFileOrDirectoryName());
		else
			destPath = CTGitPath(droppath+_T("\\")+sNewName);
		if (destPath.Exists())
		{
			CString name = pathList[nPath].GetFileOrDirectoryName();
			if (!sNewName.IsEmpty())
				name = sNewName;
			progress.Stop();
			CRenameDlg dlg;
			dlg.m_name = name;
			dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name);
			if (dlg.DoModal() != IDOK)
			{
				return FALSE;
			}
			destPath.SetFromWin(droppath+_T("\\")+dlg.m_name);
		} 
		CString cmd,out;
		
		cmd.Format(_T("git.exe mv -- \"%s\" \"%s\""),pathList[nPath].GetGitPathString(),destPath.GetGitPathString());
		if(g_Git.Run(cmd,&out,CP_ACP))
		{
			if (CMessageBox::Show(hwndExplorer, out, _T("TortoiseGit"), MB_YESNO)==IDYES)
			{
#if 0
					if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath, TRUE))
					{
						CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
						return FALSE;		//get out of here
					}
					CShellUpdater::Instance().AddPathForUpdate(destPath);
#endif
			}
			else
			{
				//TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
				CMessageBox::Show(hwndExplorer, _T("Cancel"), _T("TortoiseGit"), MB_ICONERROR);
				return FALSE;		//get out of here
			}
		} 
		else
			CShellUpdater::Instance().AddPathForUpdate(destPath);
		count++;
		if (progress.IsValid())
		{
			progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, pathList[nPath].GetWinPath());
			progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, destPath.GetWinPath());
			progress.SetProgress(count, pathList.GetCount());
		}
		if ((progress.IsValid())&&(progress.HasUserCancelled()))
		{
			CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);
			return FALSE;
		}
	}
	return true;
}
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev)
{
	if(Rev.IsEmpty())
		Rev = _T("HEAD");

	// enable blame for files which do not exist in current working tree
	if (!PathFileExists(lpszPathName) && Rev != _T("HEAD"))
	{
		if (!CDocument::OnOpenDocument(GetTempFile()))
			return FALSE;
	}
	else
	{
		if (!CDocument::OnOpenDocument(lpszPathName))
			return FALSE;
	}

	m_CurrentFileName = lpszPathName;

	m_Rev=Rev;

	// (SDI documents will reuse this document)
	if(!g_Git.CheckMsysGitDir())
	{
		CCommonAppUtils::RunTortoiseGitProc(_T(" /command:settings"));
		return FALSE;
	}
	CString topdir;
	if (!GitAdminDir::HasAdminDir(m_CurrentFileName, &topdir))
	{
		CString temp;
		temp.Format(IDS_CANNOTBLAMENOGIT, (LPCTSTR)m_CurrentFileName);
		MessageBox(nullptr, temp, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);
		return FALSE;
	}
	else
	{
		m_IsGitFile=TRUE;
		sOrigCWD = g_Git.m_CurrentDir = topdir;

		CString PathName = m_CurrentFileName;
		if(topdir[topdir.GetLength()-1] == _T('\\') ||
			topdir[topdir.GetLength()-1] == _T('/'))
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength());
		else
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1);

		CTGitPath path;
		path.SetFromWin(PathName);

		if(!g_Git.m_CurrentDir.IsEmpty())
			SetCurrentDirectory(g_Git.m_CurrentDir);

		try
		{
			// make sure all config files are read in order to check that none contains an error
			g_Git.GetConfigValue(_T("doesnot.exist"));
		}
		catch (char * libgiterr)
		{
			MessageBox(nullptr, CString(libgiterr), _T("TortoiseGitBlame"), MB_ICONERROR);
			return FALSE;
		}

		CString cmd, option;
		int dwDetectMovedOrCopiedLines = theApp.GetInt(_T("DetectMovedOrCopiedLines"), BLAME_DETECT_MOVED_OR_COPIED_LINES_DISABLED);
		int dwDetectMovedOrCopiedLinesNumCharactersWithinFile = theApp.GetInt(_T("DetectMovedOrCopiedLinesNumCharactersWithinFile"), BLAME_DETECT_MOVED_OR_COPIED_LINES_NUM_CHARACTERS_WITHIN_FILE_DEFAULT);
		int dwDetectMovedOrCopiedLinesNumCharactersFromFiles = theApp.GetInt(_T("DetectMovedOrCopiedLinesNumCharactersFromFiles"), BLAME_DETECT_MOVED_OR_COPIED_LINES_NUM_CHARACTERS_FROM_FILES_DEFAULT);
		switch(dwDetectMovedOrCopiedLines)
		{
		default:
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_DISABLED:
			option.Empty();
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_WITHIN_FILE:
			option.Format(_T("-M%d"), dwDetectMovedOrCopiedLinesNumCharactersWithinFile);
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_MODIFIED_FILES:
			option.Format(_T("-C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles);
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_EXISTING_FILES_AT_FILE_CREATION:
			option.Format(_T("-C -C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles);
			break;
		case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_EXISTING_FILES:
			option.Format(_T("-C -C -C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles);
			break;
		}

		if (theApp.GetInt(_T("IgnoreWhitespace"), 0) == 1)
			option += _T(" -w");

		cmd.Format(_T("git.exe blame -p %s %s -- \"%s\""), (LPCTSTR)option, (LPCTSTR)Rev, (LPCTSTR)path.GetGitPathString());
		m_BlameData.clear();
		BYTE_VECTOR err;
		if(g_Git.Run(cmd, &m_BlameData, &err))
		{
			CString str;
			if (!m_BlameData.empty())
				CGit::StringAppend(&str, &m_BlameData[0], CP_UTF8);
			if (!err.empty())
				CGit::StringAppend(&str, &err[0], CP_UTF8);
			MessageBox(nullptr, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);

			return FALSE;
		}

#ifdef USE_TEMPFILENAME
		if(!m_TempFileName.IsEmpty())
		{
			::DeleteFile(m_TempFileName);
			m_TempFileName.Empty();
		}

		m_TempFileName=GetTempFile();

		cmd.Format(_T("git.exe cat-file blob %s:\"%s\""), (LPCTSTR)Rev, (LPCTSTR)path.GetGitPathString());

		if(g_Git.RunLogFile(cmd, m_TempFileName))
		{
			CString str;
			str.Format(IDS_CHECKOUTFAILED, (LPCTSTR)path.GetGitPathString());
			MessageBox(nullptr, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);
			return FALSE;
		}
#endif
		m_GitPath = path;

		CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView());
		if (!pView)
		{
			CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
			if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView)))
			{
				pView = (CTortoiseGitBlameView*)pWnd;
			}
			else
			{
				return FALSE;
			}
		}
		pView->ParseBlame();

		BOOL bShowCompleteLog = (theApp.GetInt(_T("ShowCompleteLog"), 1) == 1);
		if (bShowCompleteLog && BlameIsLimitedToOneFilename(dwDetectMovedOrCopiedLines))
		{
			if (GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString(), m_Rev, (theApp.GetInt(_T("FollowRenames"), 0) == 1)))
				return FALSE;
		}
		else
		{
			std::set<CGitHash> hashes;
			pView->m_data.GetHashes(hashes);
			if (GetMainFrame()->m_wndOutput.LoadHistory(hashes))
				return FALSE;
		}

		pView->MapLineToLogIndex();
		pView->UpdateInfo();
		if (m_lLine > 0)
			pView->GotoLine(m_lLine);

		SetPathName(m_CurrentFileName, FALSE);
	}

	return TRUE;
}
Beispiel #26
0
bool CloneCommand::Execute()
{
	CTGitPath cloneDirectory;
	if (!parser.HasKey(_T("hasurlhandler")))
	{
		if (orgCmdLinePath.IsEmpty())
		{
			cloneDirectory.SetFromWin(sOrigCWD, true);
			DWORD len = ::GetTempPath(0, NULL);
			std::unique_ptr<TCHAR[]> tszPath(new TCHAR[len]);
			::GetTempPath(len, tszPath.get());
			if (_tcsncicmp(cloneDirectory.GetWinPath(), tszPath.get(), len-2 /* \\ and \0 */) == 0)
			{
				// if the current directory is set to a temp directory,
				// we don't use that but leave it empty instead.
				cloneDirectory.Reset();
			}
		}
		else
			cloneDirectory = orgCmdLinePath;
	}

	CCloneDlg dlg;
	dlg.m_Directory = cloneDirectory.GetWinPathString();

	if (parser.HasKey(_T("url")))
		dlg.m_URL = parser.GetVal(_T("url"));
	if (parser.HasKey(_T("exactpath")))
		dlg.m_bExactPath = TRUE;

	if(dlg.DoModal()==IDOK)
	{
		CString recursiveStr;
		if(dlg.m_bRecursive)
			recursiveStr = _T("--recursive");
		else
			recursiveStr = _T("");

		CString bareStr;
		if(dlg.m_bBare)
			bareStr = _T("--bare");
		else
			bareStr = _T("");

		CString nocheckoutStr;
		if (dlg.m_bNoCheckout)
			nocheckoutStr = _T("--no-checkout");

		CString branchStr;
		if (dlg.m_bBranch)
			branchStr = _T("--branch ") + dlg.m_strBranch;

		CString originStr;
		if (dlg.m_bOrigin)
			originStr = _T("--origin ") + dlg.m_strOrigin;

		if(dlg.m_bAutoloadPuttyKeyFile)
		{
			CAppUtils::LaunchPAgent(&dlg.m_strPuttyKeyFile);
		}

		CAppUtils::RemoveTrailSlash(dlg.m_Directory);
		if (!dlg.m_bSVN)
			CAppUtils::RemoveTrailSlash(dlg.m_URL);

		CString dir=dlg.m_Directory;
		CString url=dlg.m_URL;

		// is this a windows format UNC path, ie starts with \\?
		if (url.Find(_T("\\\\")) == 0)
		{
			// yes, change all \ to /
			// this should not be necessary but msysgit does not support the use \ here yet
			int atSign = url.Find(_T('@'));
			if (atSign > 0)
			{
				CString path = url.Mid(atSign);
				path.Replace(_T('\\'), _T('/'));
				url = url.Mid(0, atSign) + path;
			}
			else
				url.Replace( _T('\\'), _T('/'));
		}

		CString depth;
		if (dlg.m_bDepth)
		{
			depth.Format(_T(" --depth %d"),dlg.m_nDepth);
		}

		g_Git.m_CurrentDir = GetExistingDirectoryForClone(dlg.m_Directory);

		CString cmd;
		CString progressarg;

		int ver = CAppUtils::GetMsysgitVersion();

		if(ver >= 0x01070002) //above 1.7.0.2
			progressarg = _T("--progress");

		cmd.Format(_T("git.exe clone %s %s %s %s %s %s -v %s \"%s\" \"%s\""),
						nocheckoutStr,
						recursiveStr,
						bareStr,
						branchStr,
						originStr,
						progressarg,
						depth,
						url,
						dir);

		// Handle Git SVN-clone
		if(dlg.m_bSVN)
		{
			//g_Git.m_CurrentDir=dlg.m_Directory;
			cmd.Format(_T("git.exe svn clone \"%s\"  \"%s\""),
				url,dlg.m_Directory);

			if(dlg.m_bSVNTrunk)
				cmd+=_T(" -T ")+dlg.m_strSVNTrunk;

			if(dlg.m_bSVNBranch)
				cmd+=_T(" -b ")+dlg.m_strSVNBranchs;

			if(dlg.m_bSVNTags)
				cmd+=_T(" -t ")+dlg.m_strSVNTags;

			if(dlg.m_bSVNFrom)
			{
				CString str;
				str.Format(_T("%d:HEAD"),dlg.m_nSVNFrom);
				cmd+=_T(" -r ")+str;
			}

			if(dlg.m_bSVNUserName)
			{
				cmd+= _T(" --username ");
				cmd+=dlg.m_strUserName;
			}
		}
		else
		{
			if (g_Git.UsingLibGit2(CGit::GIT_CMD_CLONE))
			{
				CGitProgressDlg GitDlg;
				CTGitPathList list;
				g_Git.m_CurrentDir = dir;
				list.AddPath(CTGitPath(dir));
				GitDlg.SetCommand(CGitProgressList::GitProgress_Clone);
				GitDlg.SetUrl(url);
				GitDlg.SetPathList(list);
				GitDlg.SetIsBare(!!dlg.m_bBare);
				GitDlg.SetRefSpec(dlg.m_bBranch ? dlg.m_strBranch : CString());
				GitDlg.SetRemote(dlg.m_bOrigin ? dlg.m_strOrigin : CString());
				GitDlg.SetNoCheckout(!!dlg.m_bNoCheckout);
				GitDlg.DoModal();
				return !GitDlg.DidErrorsOccur();
			}
		}
		CProgressDlg progress;
		progress.m_GitCmd=cmd;
		progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_MENULOG)));
		progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_EXPLORE)));
		INT_PTR ret = progress.DoModal();

		if (dlg.m_bSVN)
			::DeleteFile(g_Git.m_CurrentDir + _T("\\sys$command"));

		if( progress.m_GitStatus == 0)
		{
			if(dlg.m_bAutoloadPuttyKeyFile)
			{
				g_Git.m_CurrentDir = dlg.m_Directory;
				SetCurrentDirectory(g_Git.m_CurrentDir);

				if(g_Git.SetConfigValue(_T("remote.origin.puttykeyfile"), dlg.m_strPuttyKeyFile, CONFIG_LOCAL, CP_UTF8))
				{
					CMessageBox::Show(NULL,_T("Fail set config remote.origin.puttykeyfile"),_T("TortoiseGit"),MB_OK|MB_ICONERROR);
					return FALSE;
				}
			}
			if (ret == IDC_PROGRESS_BUTTON1)
			{
				CString cmd = _T("/command:log");
				cmd += _T(" /path:\"") + dlg.m_Directory + _T("\"");
				CAppUtils::RunTortoiseGitProc(cmd);
				return TRUE;
			}
			if (ret == IDC_PROGRESS_BUTTON1 + 1)
			{
				ShellExecute(nullptr, _T("explore"), dlg.m_Directory, nullptr, nullptr, SW_SHOW);
				return TRUE;
			}
		}
		if(ret == IDOK)
			return TRUE;

	}
	return FALSE;
}
Beispiel #27
0
/* Fetch is false, means fetch status from cache */
CStatusCacheEntry CGitStatusCache::GetStatusForPath(const CTGitPath& path, DWORD flags,  bool bFetch /* = true */)
{
    bool bRecursive = !!(flags & TGITCACHE_FLAGS_RECUSIVE_STATUS);

    // Check a very short-lived 'mini-cache' of the last thing we were asked for.
    long now = (long)GetTickCount();
    if(now-m_mostRecentExpiresAt < 0)
    {
        if(path.IsEquivalentToWithoutCase(m_mostRecentPath))
        {
            return m_mostRecentStatus;
        }
    }
    {
        AutoLocker lock(m_critSec);
        m_mostRecentPath = path;
        m_mostRecentExpiresAt = now + 1000;
    }

    if (IsPathGood(path))
    {
        // Stop the crawler starting on a new folder while we're doing this much more important task...
        // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath().
        CCrawlInhibitor crawlInhibit(&m_folderCrawler);

        CTGitPath dirpath = path.GetContainingDirectory();
        if ((dirpath.IsEmpty()) || (!m_shellCache.IsPathAllowed(dirpath.GetWinPath())))
            dirpath = path.GetDirectory();
        CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath);
        if (cachedDir != NULL)
        {
            //ATLTRACE(_T("GetStatusForMember %d\n"), bFetch);
            CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
            {
                AutoLocker lock(m_critSec);
                m_mostRecentStatus = entry;
                return m_mostRecentStatus;
            }
        }
    }
    else
    {
        // path is blocked for some reason: return the cached status if we have one
        // we do here only a cache search, absolutely no disk access is allowed!
        CCachedDirectory::ItDir itMap = m_directoryCache.find(path.GetDirectory());
        if ((itMap != m_directoryCache.end())&&(itMap->second))
        {
            if (path.IsDirectory())
            {
                CStatusCacheEntry entry = itMap->second->GetOwnStatus(false);
                AutoLocker lock(m_critSec);
                m_mostRecentStatus = entry;
                return m_mostRecentStatus;
            }
            else
            {
                // We've found this directory in the cache
                CCachedDirectory * cachedDir = itMap->second;
                CStatusCacheEntry entry = cachedDir->GetCacheStatusForMember(path);
                {
                    AutoLocker lock(m_critSec);
                    m_mostRecentStatus = entry;
                    return m_mostRecentStatus;
                }
            }
        }
    }
    AutoLocker lock(m_critSec);
    ATLTRACE(_T("ignored no good path %s\n"), path.GetWinPath());
    m_mostRecentStatus = CStatusCacheEntry();
    if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasGITAdminDir(path.GetWinPath(), true))
    {
        ATLTRACE(_T("force status %s\n"), path.GetWinPath());
        m_mostRecentStatus.ForceStatus(git_wc_status_normal);
    }
    return m_mostRecentStatus;
}
Beispiel #28
0
int CGitDiff::DiffNull(const CTGitPath *pPath, git_revnum_t rev1, bool bIsAdd, int jumpToLine)
{
	CString temppath;
	GetTempPath(temppath);
	if (rev1 != GIT_REV_ZERO)
	{
		CGitHash rev1Hash;
		if (g_Git.GetHash(rev1Hash, rev1)) // make sure we have a HASH here, otherwise filenames might be invalid
		{
			MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev1 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		rev1 = rev1Hash.ToString();
	}
	CString file1;
	CString nullfile;
	CString cmd;

	if(pPath->IsDirectory())
	{
		int result;
		// refresh if result = 1
		CTGitPath path = *pPath;
		while ((result = SubmoduleDiffNull(&path, rev1)) == 1)
		{
			path.SetFromGit(pPath->GetGitPathString());
		}
		return result;
	}

	if(rev1 != GIT_REV_ZERO )
	{
		TCHAR szTempName[MAX_PATH] = {0};
		GetTempFileName(temppath, pPath->GetBaseFilename(), 0, szTempName);
		CString temp(szTempName);
		DeleteFile(szTempName);
		CreateDirectory(szTempName, NULL);
		file1.Format(_T("%s\\%s-%s%s"),
				temp,
				pPath->GetBaseFilename(),
				rev1.Left(g_Git.GetShortHASHLength()),
				pPath->GetFileExtension());

		g_Git.GetOneFile(rev1,*pPath,file1);
	}
	else
	{
		file1=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString();
	}

	// preserve FileExtension, needed especially for diffing deleted images (detection on new filename extension)
	CString tempfile=::GetTempFile() + pPath->GetFileExtension();
	CStdioFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );
	//file.WriteString();
	file.Close();
	::SetFileAttributes(tempfile, FILE_ATTRIBUTE_READONLY);

	CAppUtils::DiffFlags flags;

	if(bIsAdd)
		CAppUtils::StartExtDiff(tempfile,file1,
							pPath->GetGitPathString(),
							pPath->GetGitPathString() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()),
							g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(),
							git_revnum_t(GIT_REV_ZERO), rev1
							, flags, jumpToLine);
	else
		CAppUtils::StartExtDiff(file1,tempfile,
							pPath->GetGitPathString() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()),
							pPath->GetGitPathString(),
							g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(),
							rev1, git_revnum_t(GIT_REV_ZERO)
							, flags, jumpToLine);

	return 0;
}
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev)
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;

	m_CurrentFileName=lpszPathName;
	m_Rev=Rev;

	// (SDI documents will reuse this document)
	if(!g_Git.CheckMsysGitDir())
	{
		CMessageBox::Show(NULL,_T("MsysGit have not install or config fail"),_T("TortoiseGitBlame"),MB_OK);
		return FALSE;
	}

	GitAdminDir admindir;
	CString topdir;
	if(!admindir.HasAdminDir(lpszPathName,&topdir))
	{
		CMessageBox::Show(NULL,CString(lpszPathName)+_T(" is not controled by git\nJust Show File Context"),_T("TortoiseGitBlame"),MB_OK);
	}
	else
	{
		m_IsGitFile=TRUE;
		g_Git.m_CurrentDir=topdir;

		CString PathName=lpszPathName;
		if(topdir[topdir.GetLength()-1] == _T('\\') ||
			topdir[topdir.GetLength()-1] == _T('/'))
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength());
		else
			PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1);

		CTGitPath path;
		path.SetFromWin(PathName);

		if(!g_Git.m_CurrentDir.IsEmpty())
			SetCurrentDirectory(g_Git.m_CurrentDir);

		m_GitPath = path;
		GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString());

		CString cmd;

		if(Rev.IsEmpty())
			Rev=_T("HEAD");

		cmd.Format(_T("git.exe blame -s -l %s -- \"%s\""),Rev,path.GetGitPathString());
		m_BlameData.clear();
		BYTE_VECTOR err;
		if(g_Git.Run(cmd, &m_BlameData, &err))
		{
			CString str;
			g_Git.StringAppend(&str, &m_BlameData[0], CP_ACP);
			g_Git.StringAppend(&str, &err[0], CP_ACP);
			CMessageBox::Show(NULL,CString(_T("Blame Error")) + str,_T("TortoiseGitBlame"),MB_OK);

		}

		if(!m_TempFileName.IsEmpty())
		{
			::DeleteFile(m_TempFileName);
			m_TempFileName.Empty();
		}

		m_TempFileName=GetTempFile();

		if(Rev.IsEmpty())
			Rev=_T("HEAD");

		cmd.Format(_T("git.exe cat-file blob %s:\"%s\""),Rev,path.GetGitPathString());

		if(g_Git.RunLogFile(cmd, m_TempFileName))
		{
			CString str;
			str.Format(_T("Fail get file %s"), path.GetGitPathString());
			CMessageBox::Show(NULL,CString(_T("Blame Error")) + str,_T("TortoiseGitBlame"),MB_OK);
		}

		CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView());
		if(pView == NULL)
		{
			CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
			if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView)))
			{
				pView = (CTortoiseGitBlameView*)pWnd;
			}
			else
			{
				return FALSE;
			}
		}
		pView->UpdateInfo();
	}

	return TRUE;
}
Beispiel #30
0
bool BisectCommand::Execute()
{
	CTGitPath path = g_Git.m_CurrentDir;

	if (this->parser.HasKey(_T("start")) && !path.IsBisectActive())
	{
		bool autoClose = false;
		if (parser.HasVal(_T("closeonend")))
			autoClose = !!parser.GetLongVal(_T("closeonend"));

		CString lastGood, firstBad;
		if (parser.HasKey(_T("good")))
			lastGood = parser.GetVal(_T("good"));
		if (parser.HasKey(_T("bad")))
			firstBad = parser.GetVal(_T("bad"));

		return CAppUtils::BisectStart(lastGood, firstBad, autoClose);
	}
	else if ((this->parser.HasKey(_T("good")) || this->parser.HasKey(_T("bad")) || this->parser.HasKey(_T("reset"))) && path.IsBisectActive())
	{
		CString cmd = _T("git.exe bisect ");

		if (this->parser.HasKey(_T("good")))
			cmd += _T("good");
		else if (this->parser.HasKey(_T("bad")))
			cmd += _T("bad");
		else if (this->parser.HasKey(_T("reset")))
			cmd += _T("reset");

		if (this->parser.HasKey(_T("ref")) &&! this->parser.HasKey(_T("reset")))
		{
			cmd += _T(" ");
			cmd += this->parser.GetVal(_T("ref"));
		}

		CProgressDlg progress;
		theApp.m_pMainWnd = &progress;
		if (parser.HasVal(_T("closeonend")))
			progress.m_bAutoCloseOnSuccess = !!parser.GetLongVal(_T("closeonend"));
		progress.m_GitCmd = cmd;

		if (path.HasSubmodules())
				progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_PROC_SUBMODULESUPDATE)));

		int reset = -1;
		if (!this->parser.HasKey(_T("reset")))
			reset = (int)progress.m_PostCmdList.Add(_T("Bisect reset"));

		INT_PTR ret = progress.DoModal();
		if (path.HasSubmodules() && ret == IDC_PROGRESS_BUTTON1)
		{
			CString sCmd;
			sCmd.Format(_T("/command:subupdate /bkpath:\"%s\""), g_Git.m_CurrentDir);

			CAppUtils::RunTortoiseGitProc(sCmd);
			return true;
		}
		else if (reset >= 0 && ret == IDC_PROGRESS_BUTTON1 + reset)
		{
			CAppUtils::RunTortoiseGitProc(_T("/command:bisect /reset"));
			return true;
		}
		else if (ret == IDOK)
			return true;
	}
	else
	{
		CMessageBox::Show(NULL,_T("Operation unknown or not allowed."), _T("TortoiseGit"), MB_OK|MB_ICONINFORMATION);
	}
	return false;
}