Exemplo n.º 1
0
int CGitIndexFileMap::Check(const CString &gitdir, bool *isChanged)
{
	__int64 time;

	CString IndexFile = g_AdminDirMap.GetAdminDirConcat(gitdir, _T("index"));

	if (CGit::GetFileModifyTime(IndexFile, &time))
		return -1;

	SHARED_INDEX_PTR pIndex;
	pIndex = this->SafeGet(gitdir);

	if (!pIndex)
	{
		if(isChanged)
			*isChanged = true;
		return 0;
	}

	if (pIndex->m_LastModifyTime == time)
	{
		if (isChanged)
			*isChanged = false;
	}
	else
	{
		if (isChanged)
			*isChanged = true;
	}
	return 0;
}
Exemplo n.º 2
0
bool GitStatus::IsExistIndexLockFile(const CString &gitdir)
{
	CString sDirName= gitdir;

	if (!PathIsDirectory(sDirName))
	{
		int x = sDirName.ReverseFind(_T('\\'));
		if (x < 2)
			return false;

		sDirName = sDirName.Left(x);
	}

	for (;;)
	{
		if(PathFileExists(sDirName + _T("\\.git")))
		{
			if(PathFileExists(g_AdminDirMap.GetAdminDir(sDirName) + _T("index.lock")))
				return true;
			else
				return false;
		}

		int x = sDirName.ReverseFind(_T('\\'));
		if (x < 2)
			return false;

		sDirName = sDirName.Left(x);
	}
}
Exemplo n.º 3
0
int CGitIndexFileMap::Check(const CString &gitdir, bool *isChanged)
{
    __int64 time;
    int result;

    CString IndexFile = g_AdminDirMap.GetAdminDir(gitdir) + _T("index");

    /* Get data associated with "crt_stat.c": */
    result = g_Git.GetFileModifyTime(IndexFile, &time);

    if (result)
        return result;

    SHARED_INDEX_PTR pIndex;
    pIndex = this->SafeGet(gitdir);

    if (pIndex.get() == NULL)
    {
        if(isChanged)
            *isChanged = true;
        return 0;
    }

    if (pIndex->m_LastModifyTime == time)
    {
        if (isChanged)
            *isChanged = false;
    }
    else
    {
        if (isChanged)
            *isChanged = true;
    }
    return 0;
}
Exemplo n.º 4
0
bool CGitIgnoreList::CheckIgnoreChanged(const CString &gitdir, const CString &path, bool isDir)
{
	CString temp;
	temp = gitdir;
	temp += _T("\\");
	temp += path;

	temp.Replace(_T('/'), _T('\\'));

	if (!isDir)
	{
		int x = temp.ReverseFind(_T('\\'));
		if (x >= 2)
			temp = temp.Left(x);
	}

	while(!temp.IsEmpty())
	{
		CString tempOrig = temp;
		temp += _T("\\.git");

		if (CGit::GitPathFileExists(temp))
		{
			CString gitignore=temp;
			gitignore += _T("ignore");
			if (CheckFileChanged(gitignore))
				return true;

			CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig);
			CString wcglobalgitignore = adminDir + _T("info\\exclude");
			if (CheckFileChanged(wcglobalgitignore))
				return true;

			if (CheckAndUpdateCoreExcludefile(adminDir))
				return true;

			return false;
		}
		else
		{
			temp += _T("ignore");
			if (CheckFileChanged(temp))
				return true;
		}

		int found=0;
		int i;
		for (i = temp.GetLength() - 1; i >= 0; i--)
		{
			if(temp[i] == _T('\\'))
				++found;

			if(found == 2)
				break;
		}

		temp = temp.Left(i);
	}
	return true;
}
Exemplo n.º 5
0
bool GitStatus::IsExistIndexLockFile(CString sDirName)
{
	if (!PathIsDirectory(sDirName))
	{
		int x = sDirName.ReverseFind(_T('\\'));
		if (x < 2)
			return false;

		sDirName = sDirName.Left(x);
	}

	for (;;)
	{
		if (PathFileExists(CombinePath(sDirName, _T(".git"))))
		{
			if (PathFileExists(g_AdminDirMap.GetAdminDirConcat(sDirName, _T("index.lock"))))
				return true;

			return false;
		}

		int x = sDirName.ReverseFind(_T('\\'));
		if (x < 2)
			return false;

		sDirName = sDirName.Left(x);
	}
}
Exemplo n.º 6
0
int CGitIndexFileMap::LoadIndex(const CString &gitdir)
{
	SHARED_INDEX_PTR pIndex(new CGitIndexList);

	if (pIndex->ReadIndex(g_AdminDirMap.GetAdminDir(gitdir)))
		return -1;

	this->SafeSet(gitdir, pIndex);

	return 0;
}
Exemplo n.º 7
0
int CGitIgnoreList::LoadAllIgnoreFile(const CString &gitdir, const CString &path, bool isDir)
{
	CString temp(gitdir);
	temp += _T('\\');
	temp += path;

	temp.Replace(_T('/'), _T('\\'));

	if (!isDir)
	{
		int x = temp.ReverseFind(_T('\\'));
		if (x >= 2)
			temp.Truncate(x);
	}

	while (!temp.IsEmpty())
	{
		CString tempOrig = temp;
		temp += _T("\\.git");

		if (CGit::GitPathFileExists(temp))
		{
			CString gitignore = temp;
			gitignore += _T("ignore");
			if (CheckFileChanged(gitignore))
				FetchIgnoreFile(gitdir, gitignore, false);

			CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig);
			CString wcglobalgitignore = adminDir;
			wcglobalgitignore += _T("info\\exclude");
			if (CheckFileChanged(wcglobalgitignore))
			{
				FetchIgnoreFile(gitdir, wcglobalgitignore, true);
			}

			if (CheckAndUpdateCoreExcludefile(adminDir))
			{
				CString excludesFile;
				{
					CAutoReadLock lock(m_SharedMutex);
					excludesFile = m_CoreExcludesfiles[adminDir];
				}
				if (!excludesFile.IsEmpty())
					FetchIgnoreFile(gitdir, excludesFile, true);
			}

			return 0;
		}

		temp += _T("ignore");
		if (CheckFileChanged(temp))
			FetchIgnoreFile(gitdir, temp, false);

		int found = 0;
		int i;
		for (i = temp.GetLength() - 1; i >= 0; --i)
		{
			if(temp[i] == _T('\\'))
				++found;

			if(found == 2)
				break;
		}

		temp.Truncate(i);
	}
	return 0;
}
Exemplo n.º 8
0
int CGitHeadFileList::ReadHeadHash(const CString& gitdir)
{
	CAutoWriteLock lock(m_SharedMutex);
	m_Gitdir = g_AdminDirMap.GetAdminDir(gitdir);

	m_HeadFile = m_Gitdir;
	m_HeadFile += _T("HEAD");

	if( CGit::GetFileModifyTime(m_HeadFile, &m_LastModifyTimeHead))
		return -1;

	CAutoFile hfile = CreateFile(m_HeadFile,
		GENERIC_READ,
		FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
		nullptr,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		nullptr);

	if (!hfile)
		return -1;

	DWORD size = 0;
	unsigned char buffer[40];
	ReadFile(hfile, buffer, 4, &size, nullptr);
	if (size != 4)
		return -1;
	buffer[4] = 0;
	if (strcmp((const char*)buffer, "ref:") == 0)
	{
		m_HeadRefFile.Empty();
		DWORD filesize = GetFileSize(hfile, nullptr);
		if (filesize < 5)
			return -1;

		unsigned char *p = (unsigned char*)malloc(filesize - 4);
		if (!p)
			return -1;

		ReadFile(hfile, p, filesize - 4, &size, nullptr);
		CGit::StringAppend(&m_HeadRefFile, p, CP_UTF8, filesize - 4);
		free(p);

		CString ref = m_HeadRefFile.Trim();
		int start = 0;
		ref = ref.Tokenize(_T("\n"), start);
		m_HeadRefFile = m_Gitdir + m_HeadRefFile;
		m_HeadRefFile.Replace(_T('/'), _T('\\'));

		__int64 time;
		if (CGit::GetFileModifyTime(m_HeadRefFile, &time, nullptr))
		{
			m_HeadRefFile.Empty();
			if (GetPackRef(gitdir))
				return -1;
			if (m_PackRefMap.find(ref) == m_PackRefMap.end())
				return -1;

			m_Head = m_PackRefMap[ref];
			return 0;
		}

		CAutoFile href = CreateFile(m_HeadRefFile,
			GENERIC_READ,
			FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
			nullptr,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL,
			nullptr);

		if (!href)
		{
			m_HeadRefFile.Empty();

			if (GetPackRef(gitdir))
				return -1;

			if (m_PackRefMap.find(ref) == m_PackRefMap.end())
				return -1;

			m_Head = m_PackRefMap[ref];
			return 0;
		}

		ReadFile(href, buffer, 40, &size, nullptr);
		if (size != 40)
			return -1;

		m_Head.ConvertFromStrA((char*)buffer);

		m_LastModifyTimeRef = time;

		return 0;
	}

	ReadFile(hfile, buffer + 4, 40 - 4, &size, nullptr);
	if (size != 36)
		return -1;

	m_HeadRefFile.Empty();

	m_Head.ConvertFromStrA((char*)buffer);

	return 0;
}
Exemplo n.º 9
0
// This method is assumed to be called with m_SharedMutex locked.
int CGitHeadFileList::GetPackRef(const CString &gitdir)
{
	CString PackRef = g_AdminDirMap.GetAdminDirConcat(gitdir, _T("packed-refs"));

	__int64 mtime;
	if (CGit::GetFileModifyTime(PackRef, &mtime))
	{
		//packed refs is not existed
		this->m_PackRefFile.Empty();
		this->m_PackRefMap.clear();
		return 0;
	}
	else if(mtime == m_LastModifyTimePackRef)
		return 0;
	else
	{
		this->m_PackRefFile = PackRef;
		this->m_LastModifyTimePackRef = mtime;
	}

	m_PackRefMap.clear();

	CAutoFile hfile = CreateFile(PackRef,
		GENERIC_READ,
		FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
		nullptr,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		nullptr);

	if (!hfile)
		return -1;

	DWORD filesize = GetFileSize(hfile, nullptr);
	if (filesize == 0)
		return -1;

	DWORD size = 0;
	auto buff = std::make_unique<char[]>(filesize);
	ReadFile(hfile, buff.get(), filesize, &size, nullptr);

	if (size != filesize)
		return -1;

	for (DWORD i = 0; i < filesize;)
	{
		CString hash;
		CString ref;
		if (buff[i] == '#' || buff[i] == '^')
		{
			while (buff[i] != '\n')
			{
				++i;
				if (i == filesize)
					break;
			}
			++i;
		}

		if (i >= filesize)
			break;

		while (buff[i] != ' ')
		{
			hash.AppendChar(buff[i]);
			++i;
			if (i == filesize)
				break;
		}

		++i;
		if (i >= filesize)
			break;

		while (buff[i] != '\n')
		{
			ref.AppendChar(buff[i]);
			++i;
			if (i == filesize)
				break;
		}

		if (!ref.IsEmpty())
			m_PackRefMap[ref] = hash;

		while (buff[i] == '\n')
		{
			++i;
			if (i == filesize)
				break;
		}
	}
	return 0;
}
Exemplo n.º 10
0
int CGitIgnoreList::CheckIgnore(const CString &path, const CString &projectroot, bool isDir)
{
	CString temp = CombinePath(projectroot, path);
	temp.Replace(_T('/'), _T('\\'));

	CStringA patha = CUnicodeUtils::GetMulti(path, CP_UTF8);
	patha.Replace('\\', '/');

	int type = 0;
	if (isDir)
	{
		type = DT_DIR;

		// strip directory name
		// we do not need to check for a .ignore file inside a directory we might ignore
		int i = temp.ReverseFind(_T('\\'));
		if (i >= 0)
			temp.Truncate(i);
	}
	else
	{
		type = DT_REG;

		int x = temp.ReverseFind(_T('\\'));
		if (x >= 2)
			temp.Truncate(x);
	}

	int pos = patha.ReverseFind('/');
	const char * base = (pos >= 0) ? ((const char*)patha + pos + 1) : patha;

	int ret = -1;

	CAutoReadLock lock(m_SharedMutex);
	while (!temp.IsEmpty())
	{
		CString tempOrig = temp;
		temp += _T("\\.git");

		if (CGit::GitPathFileExists(temp))
		{
			CString gitignore = temp;
			gitignore += _T("ignore");
			if ((ret = CheckFileAgainstIgnoreList(gitignore, patha, base, type)) != -1)
				break;

			CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig);
			CString wcglobalgitignore = adminDir;
			wcglobalgitignore += _T("info\\exclude");
			if ((ret = CheckFileAgainstIgnoreList(wcglobalgitignore, patha, base, type)) != -1)
				break;

			CString excludesFile = m_CoreExcludesfiles[adminDir];
			if (!excludesFile.IsEmpty())
				ret = CheckFileAgainstIgnoreList(excludesFile, patha, base, type);

			break;
		}

		temp += _T("ignore");
		if ((ret = CheckFileAgainstIgnoreList(temp, patha, base, type)) != -1)
			break;

		int found = 0;
		int i;
		for (i = temp.GetLength() - 1; i >= 0; i--)
		{
			if (temp[i] == _T('\\'))
				++found;

			if (found == 2)
				break;
		}

		temp.Truncate(i);
	}

	return ret;
}
Exemplo n.º 11
0
void CDirectoryWatcher::WorkerThread()
{
	DWORD numBytes;
	CDirWatchInfo * pdi = NULL;
	LPOVERLAPPED lpOverlapped;
	WCHAR buf[READ_DIR_CHANGE_BUFFER_SIZE] = {0};
	WCHAR * pFound = NULL;
	while (m_bRunning)
	{
		CleanupWatchInfo();
		if (watchedPaths.GetCount())
		{
			// Any incoming notifications?

			pdi = NULL;
			numBytes = 0;
			InterlockedExchange(&m_bCleaned, FALSE);
			if ((!m_hCompPort)
				|| !GetQueuedCompletionStatus(m_hCompPort,
											  &numBytes,
											  (PULONG_PTR) &pdi,
											  &lpOverlapped,
											  600000 /*10 minutes*/))
			{
				// No. Still trying?

				if (!m_bRunning)
					return;

				ATLTRACE(_T(": restarting watcher\n"));
				m_hCompPort.CloseHandle();

				// We must sync the whole section because other threads may
				// receive "AddPath" calls that will delete the completion
				// port *while* we are adding references to it .

				AutoLocker lock(m_critSec);

				// Clear the list of watched objects and recreate that list.
				// This will also delete the old completion port

				ClearInfoMap();
				CleanupWatchInfo();

				for (int i=0; i<watchedPaths.GetCount(); ++i)
				{
					CTGitPath watchedPath = watchedPaths[i];

					CAutoFile hDir = CreateFile(watchedPath.GetWinPath(),
											FILE_LIST_DIRECTORY,
											FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
											NULL, //security attributes
											OPEN_EXISTING,
											FILE_FLAG_BACKUP_SEMANTICS | //required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME.
											FILE_FLAG_OVERLAPPED,
											NULL);
					if (!hDir)
					{
						// this could happen if a watched folder has been removed/renamed
						ATLTRACE(_T("CDirectoryWatcher: CreateFile failed. Can't watch directory %s\n"), watchedPaths[i].GetWinPath());
						watchedPaths.RemovePath(watchedPath);
						break;
					}

					DEV_BROADCAST_HANDLE NotificationFilter;
					SecureZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
					NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
					NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
					NotificationFilter.dbch_handle = hDir;
					// RegisterDeviceNotification sends a message to the UI thread:
					// make sure we *can* send it and that the UI thread isn't waiting on a lock
					int numPaths = watchedPaths.GetCount();
					size_t numWatch = watchInfoMap.size();
					lock.Unlock();
					NotificationFilter.dbch_hdevnotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
					lock.Lock();
					// since we released the lock to prevent a deadlock with the UI thread,
					// it could happen that new paths were added to watch, or another thread
					// could have cleared our info map.
					// if that happened, we have to restart watching all paths again.
					if ((numPaths != watchedPaths.GetCount()) || (numWatch != watchInfoMap.size()))
					{
						ClearInfoMap();
						CleanupWatchInfo();
						Sleep(200);
						break;
					}

					CDirWatchInfo * pDirInfo = new CDirWatchInfo(hDir, watchedPath);
					hDir.Detach();  // the new CDirWatchInfo object owns the handle now
					pDirInfo->m_hDevNotify = NotificationFilter.dbch_hdevnotify;


					HANDLE port = CreateIoCompletionPort(pDirInfo->m_hDir, m_hCompPort, (ULONG_PTR)pDirInfo, 0);
					if (port == NULL)
					{
						ATLTRACE(_T("CDirectoryWatcher: CreateIoCompletionPort failed. Can't watch directory %s\n"), watchedPath.GetWinPath());

						// we must close the directory handle to allow ClearInfoMap()
						// to close the completion port properly
						pDirInfo->CloseDirectoryHandle();

						ClearInfoMap();
						CleanupWatchInfo();
						delete pDirInfo;
						pDirInfo = NULL;

						watchedPaths.RemovePath(watchedPath);
						break;
					}
					m_hCompPort = port;

					if (!ReadDirectoryChangesW(pDirInfo->m_hDir,
												pDirInfo->m_Buffer,
												READ_DIR_CHANGE_BUFFER_SIZE,
												TRUE,
												FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
												&numBytes,// not used
												&pDirInfo->m_Overlapped,
												NULL))  //no completion routine!
					{
						ATLTRACE(_T("CDirectoryWatcher: ReadDirectoryChangesW failed. Can't watch directory %s\n"), watchedPath.GetWinPath());

						// we must close the directory handle to allow ClearInfoMap()
						// to close the completion port properly
						pDirInfo->CloseDirectoryHandle();

						ClearInfoMap();
						CleanupWatchInfo();
						delete pDirInfo;
						pDirInfo = NULL;
						watchedPaths.RemovePath(watchedPath);
						break;
					}

					ATLTRACE(_T("watching path %s\n"), pDirInfo->m_DirName.GetWinPath());
					watchInfoMap[pDirInfo->m_hDir] = pDirInfo;
				}
			}
			else
			{
				if (!m_bRunning)
					return;
				if (watchInfoMap.empty())
					continue;

				// NOTE: the longer this code takes to execute until ReadDirectoryChangesW
				// is called again, the higher the chance that we miss some
				// changes in the file system!
				if (pdi)
				{
					BOOL bRet = false;
					std::list<CTGitPath> notifyPaths;
					{
						AutoLocker lock(m_critSec);
						// in case the CDirectoryWatcher objects have been cleaned,
						// the m_bCleaned variable will be set to true here. If the
						// objects haven't been cleared, we can access them here.
						if (InterlockedExchange(&m_bCleaned, FALSE))
							continue;
						if (   (!pdi->m_hDir) || watchInfoMap.empty()
							|| (watchInfoMap.find(pdi->m_hDir) == watchInfoMap.end()))
						{
							continue;
						}
						PFILE_NOTIFY_INFORMATION pnotify = (PFILE_NOTIFY_INFORMATION)pdi->m_Buffer;
						DWORD nOffset = 0;

						do
						{
							pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset);

							if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
								break;

							nOffset = pnotify->NextEntryOffset;

							if (pnotify->FileNameLength >= (READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR)))
								continue;

							SecureZeroMemory(buf, READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR));
							_tcsncpy_s(buf, pdi->m_DirPath, _countof(buf) - 1);
							errno_t err = _tcsncat_s(buf + pdi->m_DirPath.GetLength(), READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileName, min(READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileNameLength/sizeof(TCHAR)));
							if (err == STRUNCATE)
							{
								continue;
							}
							buf[(pnotify->FileNameLength/sizeof(TCHAR))+pdi->m_DirPath.GetLength()] = 0;

							if (m_FolderCrawler)
							{
								if ((pFound = wcsstr(buf, L"\\tmp")) != NULL)
								{
									pFound += 4;
									if (((*pFound)=='\\')||((*pFound)=='\0'))
									{
										continue;
									}
								}
								if ((pFound = wcsstr(buf, L":\\RECYCLER\\")) != NULL)
								{
									if ((pFound-buf) < 5)
									{
										// a notification for the recycle bin - ignore it
										continue;
									}
								}
								if ((pFound = wcsstr(buf, L":\\$Recycle.Bin\\")) != NULL)
								{
									if ((pFound-buf) < 5)
									{
										// a notification for the recycle bin - ignore it
										continue;
									}
								}
								if (wcsstr(buf, L".tmp") != NULL)
								{
									// assume files with a .tmp extension are not versioned and interesting,
									// so ignore them.
									continue;
								}

								CTGitPath path;
								bool isIndex = false;
								if ((pFound = wcsstr(buf, L".git")) != NULL)
								{
									// omit repository data change except .git/index.lock- or .git/HEAD.lock-files
									if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
										break;

									path = g_AdminDirMap.GetWorkingCopy(CTGitPath(buf).GetContainingDirectory().GetWinPathString());

									if ((wcsstr(pFound, L"index.lock") != NULL || wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_ADDED)
									{
										CGitStatusCache::Instance().BlockPath(path);
										continue;
									}
									else if (((wcsstr(pFound, L"index.lock") != NULL || wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_REMOVED) || (((wcsstr(pFound, L"index") != NULL && wcsstr(pFound, L"index.lock") == NULL) || (wcsstr(pFound, L"HEAD") != NULL && wcsstr(pFound, L"HEAD.lock") != NULL)) && pnotify->Action == FILE_ACTION_MODIFIED) || ((wcsstr(pFound, L"index.lock") == NULL || wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_RENAMED_NEW_NAME))
									{
										isIndex = true;
										CGitStatusCache::Instance().BlockPath(path, 1);
									}
									else
									{
										continue;
									}
								}
								else
									path.SetFromUnknown(buf);

								if(!path.HasAdminDir() && !isIndex)
									continue;

								ATLTRACE(_T("change notification: %s\n"), buf);
								notifyPaths.push_back(path);
							}
						} while ((nOffset > 0)&&(nOffset < READ_DIR_CHANGE_BUFFER_SIZE));

						// setup next notification cycle
						SecureZeroMemory (pdi->m_Buffer, sizeof(pdi->m_Buffer));
						SecureZeroMemory (&pdi->m_Overlapped, sizeof(OVERLAPPED));
						bRet = ReadDirectoryChangesW(pdi->m_hDir,
							pdi->m_Buffer,
							READ_DIR_CHANGE_BUFFER_SIZE,
							TRUE,
							FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
							&numBytes,// not used
							&pdi->m_Overlapped,
							NULL); //no completion routine!
					}
					if (!notifyPaths.empty())
					{
						for (std::list<CTGitPath>::const_iterator nit = notifyPaths.begin(); nit != notifyPaths.end(); ++nit)
						{
							m_FolderCrawler->AddPathForUpdate(*nit);
						}
					}

					// any clean-up to do?

					CleanupWatchInfo();

					if (!bRet)
					{
						// Since the call to ReadDirectoryChangesW failed, just
						// wait a while. We don't want to have this thread
						// running using 100% CPU if something goes completely
						// wrong.
						Sleep(200);
					}
				}
			}
		}// if (watchedPaths.GetCount())
		else
			Sleep(200);
	}// while (m_bRunning)
}
Exemplo n.º 12
0
int CGitHeadFileList::ReadHeadHash(CString gitdir)
{
    int ret = 0;
    CAutoWriteLock lock(&this->m_SharedMutex);
    m_Gitdir = g_AdminDirMap.GetAdminDir(gitdir);

    m_HeadFile = m_Gitdir + _T("HEAD");

    if( g_Git.GetFileModifyTime(m_HeadFile, &m_LastModifyTimeHead))
        return -1;

    try
    {
        do
        {
            CAutoFile hfile = CreateFile(m_HeadFile,
                                         GENERIC_READ,
                                         FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
                                         NULL,
                                         OPEN_EXISTING,
                                         FILE_ATTRIBUTE_NORMAL,
                                         NULL);

            if (!hfile)
            {
                ret = -1;
                break;
            }

            DWORD size = 0;
            unsigned char buffer[40] ;
            ReadFile(hfile, buffer, 4, &size, NULL);
            if (size != 4)
            {
                ret = -1;
                break;
            }
            buffer[4]=0;
            if (strcmp((const char*)buffer,"ref:") == 0)
            {
                DWORD filesize = GetFileSize(hfile, NULL);
                if (filesize < 5)
                {
                    m_HeadRefFile.Empty();
                    ret = -1;
                    break;
                }

                unsigned char *p = (unsigned char*)malloc(filesize -4);

                ReadFile(hfile, p, filesize - 4, &size, NULL);

                m_HeadRefFile.Empty();
                g_Git.StringAppend(&this->m_HeadRefFile, p, CP_UTF8, filesize - 4);
                CString ref = this->m_HeadRefFile;
                ref = ref.Trim();
                int start = 0;
                ref = ref.Tokenize(_T("\n"), start);
                free(p);
                m_HeadRefFile = m_Gitdir + m_HeadRefFile.Trim();
                m_HeadRefFile.Replace(_T('/'),_T('\\'));

                __int64 time;
                if (g_Git.GetFileModifyTime(m_HeadRefFile, &time, NULL))
                {
                    m_HeadRefFile.Empty();
                    if (GetPackRef(gitdir))
                    {
                        ret = -1;
                        break;
                    }
                    if (this->m_PackRefMap.find(ref) == m_PackRefMap.end())
                    {
                        ret = -1;
                        break;
                    }
                    this ->m_Head = m_PackRefMap[ref];
                    ret = 0;
                    break;
                }

                CAutoFile href = CreateFile(m_HeadRefFile,
                                            GENERIC_READ,
                                            FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
                                            NULL,
                                            OPEN_EXISTING,
                                            FILE_ATTRIBUTE_NORMAL,
                                            NULL);

                if (!href)
                {
                    m_HeadRefFile.Empty();

                    if (GetPackRef(gitdir))
                    {
                        ret = -1;
                        break;
                    }

                    if (this->m_PackRefMap.find(ref) == m_PackRefMap.end())
                    {
                        ret = -1;
                        break;
                    }
                    this ->m_Head = m_PackRefMap[ref];
                    ret = 0;
                    break;
                }
                ReadFile(href, buffer, 40, &size, NULL);
                if (size != 40)
                {
                    ret = -1;
                    break;
                }
                this->m_Head.ConvertFromStrA((char*)buffer);

                this->m_LastModifyTimeRef = time;

            }
            else
            {
                ReadFile(hfile, buffer + 4, 40 - 4, &size, NULL);
                if(size != 36)
                {
                    ret = -1;
                    break;
                }
                m_HeadRefFile.Empty();

                this->m_Head.ConvertFromStrA((char*)buffer);
            }
        } while(0);
    }
    catch(...)
    {
        ret = -1;
    }

    return ret;
}
Exemplo n.º 13
0
// This method is assumed to be called with m_SharedMutex locked.
int CGitHeadFileList::GetPackRef(const CString &gitdir)
{
    CString PackRef = g_AdminDirMap.GetAdminDir(gitdir) + _T("packed-refs");

    __int64 mtime;
    if (g_Git.GetFileModifyTime(PackRef, &mtime))
    {
        //packed refs is not existed
        this->m_PackRefFile.Empty();
        this->m_PackRefMap.clear();
        return 0;
    }
    else if(mtime == m_LastModifyTimePackRef)
    {
        return 0;
    }
    else
    {
        this->m_PackRefFile = PackRef;
        this->m_LastModifyTimePackRef = mtime;
    }

    int ret = 0;
    {
        this->m_PackRefMap.clear();

        CAutoFile hfile = CreateFile(PackRef,
                                     GENERIC_READ,
                                     FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
                                     NULL,
                                     OPEN_EXISTING,
                                     FILE_ATTRIBUTE_NORMAL,
                                     NULL);
        do
        {
            if (!hfile)
            {
                ret = -1;
                break;
            }

            DWORD filesize = GetFileSize(hfile, NULL);
            if (filesize == 0)
            {
                ret = -1;
                break;
            }
            DWORD size =0;
            char *buff;
            buff = new char[filesize];

            ReadFile(hfile, buff, filesize, &size, NULL);

            if (size != filesize)
            {
                delete[] buff;
                ret = -1;
                break;
            }

            CString hash;
            CString ref;

            for(DWORD i=0; i<filesize;)
            {
                hash.Empty();
                ref.Empty();
                if (buff[i] == '#' || buff[i] == '^')
                {
                    while (buff[i] != '\n')
                    {
                        ++i;
                        if (i == filesize)
                            break;
                    }
                    ++i;
                }

                if (i >= filesize)
                    break;

                while (buff[i] != ' ')
                {
                    hash.AppendChar(buff[i]);
                    ++i;
                    if (i == filesize)
                        break;
                }

                ++i;
                if (i >= filesize)
                    break;

                while (buff[i] != '\n')
                {
                    ref.AppendChar(buff[i]);
                    ++i;
                    if (i == filesize)
                        break;
                }

                if (!ref.IsEmpty() )
                {
                    this->m_PackRefMap[ref] = hash;
                }

                while (buff[i] == '\n')
                {
                    ++i;
                    if (i == filesize)
                        break;
                }
            }

            delete[] buff;

        } while(0);
    }
    return ret;

}
Exemplo n.º 14
0
int CGitIgnoreList::CheckIgnore(const CString &path,const CString &projectroot)
{
    __int64 time = 0;
    bool dir = 0;
    CString temp = projectroot + _T("\\") + path;
    temp.Replace(_T('/'), _T('\\'));

    CStringA patha = CUnicodeUtils::GetMulti(path, CP_UTF8);
    patha.Replace('\\', '/');

    if(g_Git.GetFileModifyTime(temp, &time, &dir))
        return -1;

    int type = 0;
    if (dir)
    {
        type = DT_DIR;

        // strip directory name
        // we do not need to check for a .ignore file inside a directory we might ignore
        int i = temp.ReverseFind(_T('\\'));
        if (i >= 0)
            temp = temp.Left(i);
    }
    else
        type = DT_REG;

    char * base = NULL;
    int pos = patha.ReverseFind('/');
    base = pos >= 0 ? patha.GetBuffer() + pos + 1 : patha.GetBuffer();

    int ret = -1;

    CAutoReadLock lock(&this->m_SharedMutex);
    while (!temp.IsEmpty())
    {
        CString tempOrig = temp;
        temp += _T("\\.git");

        if (CGit::GitPathFileExists(temp))
        {
            CString gitignore = temp;
            gitignore += _T("ignore");
            if ((ret = CheckFileAgainstIgnoreList(gitignore, patha, base, type)) != -1)
                break;

            CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig);
            CString wcglobalgitignore = adminDir + _T("info\\exclude");
            if ((ret = CheckFileAgainstIgnoreList(wcglobalgitignore, patha, base, type)) != -1)
                break;

            m_SharedMutex.AcquireShared();
            CString excludesFile = m_CoreExcludesfiles[adminDir];
            m_SharedMutex.ReleaseShared();
            if (!excludesFile.IsEmpty())
                ret = CheckFileAgainstIgnoreList(excludesFile, patha, base, type);

            break;
        }
        else
        {
            temp += _T("ignore");
            if ((ret = CheckFileAgainstIgnoreList(temp, patha, base, type)) != -1)
                break;
        }

        int found = 0;
        int i;
        for (i = temp.GetLength() - 1; i >= 0; i--)
        {
            if (temp[i] == _T('\\'))
                ++found;

            if (found == 2)
                break;
        }

        temp = temp.Left(i);
    }

    patha.ReleaseBuffer();

    return ret;
}
Exemplo n.º 15
0
int CGitIgnoreList::LoadAllIgnoreFile(const CString &gitdir,const CString &path)
{
    CString temp;

    temp = gitdir;
    temp += _T("\\");
    temp += path;

    temp.Replace(_T('/'), _T('\\'));

    while (!temp.IsEmpty())
    {
        CString tempOrig = temp;
        temp += _T("\\.git");

        if (CGit::GitPathFileExists(temp))
        {
            CString gitignore = temp;
            gitignore += _T("ignore");
            if (CheckFileChanged(gitignore))
            {
                FetchIgnoreFile(gitdir, gitignore, false);
            }

            CString adminDir = g_AdminDirMap.GetAdminDir(tempOrig);
            CString wcglobalgitignore = adminDir + _T("info\\exclude");
            if (CheckFileChanged(wcglobalgitignore))
            {
                FetchIgnoreFile(gitdir, wcglobalgitignore, true);
            }

            if (CheckAndUpdateCoreExcludefile(adminDir))
            {
                m_SharedMutex.AcquireShared();
                CString excludesFile = m_CoreExcludesfiles[adminDir];
                m_SharedMutex.ReleaseShared();
                if (!excludesFile.IsEmpty())
                    FetchIgnoreFile(gitdir, excludesFile, true);
            }

            return 0;
        }
        else
        {
            temp += _T("ignore");
            if (CheckFileChanged(temp))
            {
                FetchIgnoreFile(gitdir, temp, false);
            }
        }

        int found = 0;
        int i;
        for (i = temp.GetLength() - 1; i >= 0; i--)
        {
            if(temp[i] == _T('\\'))
                ++found;

            if(found == 2)
                break;
        }

        temp = temp.Left(i);
    }
    return 0;
}