ulong Board::GetAttackMask(int square, int attackerType) const { switch (attackerType) { case PieceTypes::Pawn: return 0; case PieceTypes::Knight: return MoveGenerator::knightAttacks[square]; case PieceTypes::Bishop: return MoveGenerator::diagA1H8Attacks[square][GetDiagA1H8Status(square)] | MoveGenerator::diagA8H1Attacks[square][GetDiagA8H1Status(square)]; case PieceTypes::Rook: return MoveGenerator::rankAttacks[square][GetRankStatus(square)] | MoveGenerator::fileAttacks[square][GetFileStatus(square)]; case PieceTypes::Queen: return MoveGenerator::rankAttacks[square][GetRankStatus(square)] | MoveGenerator::fileAttacks[square][GetFileStatus(square)] | MoveGenerator::diagA1H8Attacks[square][GetDiagA1H8Status(square)] | MoveGenerator::diagA8H1Attacks[square][GetDiagA8H1Status(square)]; case PieceTypes::King: return MoveGenerator::kingAttacks[square]; default: return 0; } }
bool UniStdioFile::DoOpen(LPCTSTR filename, LPCTSTR mode) { Close(); m_filepath = filename; m_filename = filename; // TODO: Make canonical ? // Fails if file doesn't exist (when we are creating new file) // But we don't care since size is set to 0 anyway. GetFileStatus(); m_fp = _tfopen(m_filepath.c_str(), mode); if (!m_fp) return false; DWORD sizehi = (DWORD)(m_filesize >> 32); if (sizehi) { // TODO: We could do this in MSC_VER 7+ I think LastErrorCustom(_T("UniStdioFile cannot handle files over 4 gigabytes")); return false; } m_lineno = 0; return true; }
bool FProvider::UpdateFileStateCache(const TArray<FFileState>& InStates) { for (auto StateIt(InStates.CreateConstIterator()); StateIt; StateIt++) { FFileStateRef FileState = GetFileStateFromCache(StateIt->GetFilename()); FileState->SetFileStatus(StateIt->GetFileStatus()); FileState->SetTimeStamp(StateIt->GetTimeStamp()); } return InStates.Num() > 0; }
void GitStatus::GetStatus(const CTGitPath& path, bool /*update*/ /* = false */, bool noignore /* = false */, bool /*noexternals*/ /* = false */) { // NOTE: unlike the SVN version this one does not cache the enumerated files, because in practice no code in all of // Tortoise uses this, all places that call GetStatus create a temp GitStatus object which gets destroyed right // after the call again CString sProjectRoot; if ( !path.HasAdminDir(&sProjectRoot) ) return; bool isfull = ((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? ShellCache::dll : ShellCache::exe) == ShellCache::dllFull); int err = 0; { LPCTSTR lpszSubPath = NULL; CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength()); lpszSubPath = sSubPath; // skip initial slash if necessary if (*lpszSubPath == _T('\\')) ++lpszSubPath; } m_status.prop_status = m_status.text_status = git_wc_status_none; m_status.assumeValid = false; m_status.skipWorktree = false; if(path.IsDirectory()) { err = GetDirStatus(sProjectRoot,lpszSubPath,&m_status.text_status , isfull, false,!noignore, NULL, NULL); if (m_status.text_status == git_wc_status_added || m_status.text_status == git_wc_status_deleted) // fix for issue #1769; a folder is either modified, conflicted or normal m_status.text_status = git_wc_status_modified; } else { err = GetFileStatus(sProjectRoot, lpszSubPath, &m_status.text_status ,isfull, false,!noignore, NULL,NULL, &m_status.assumeValid, &m_status.skipWorktree); } } // Error present if function is not under version control if (err) { status = NULL; return; } status = &m_status; }
// static method git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth) { git_wc_status_kind statuskind; // git_client_ctx_t * ctx; // apr_pool_t * pool; // git_error_t * err; BOOL err; BOOL isDir; CString sProjectRoot; isDir = path.IsDirectory(); if (!path.HasAdminDir(&sProjectRoot)) return git_wc_status_none; // pool = git_pool_create (NULL); // create the memory pool // git_error_clear(git_client_create_context(&ctx, pool)); // git_revnum_t youngest = Git_INVALID_REVNUM; // git_opt_revision_t rev; // rev.kind = git_opt_revision_unspecified; statuskind = git_wc_status_none; const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { if (sProjectRoot.GetLength() == 3 && sProjectRoot[1] == _T(':')) sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength()); else sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/); } bool isfull = ((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? ShellCache::dll : ShellCache::exe) == ShellCache::dllFull); if(isDir) { err = GetDirStatus(sProjectRoot,sSubPath,&statuskind, isfull,bIsRecursive,isfull,NULL, NULL); } else { err = GetFileStatus(sProjectRoot,sSubPath,&statuskind,isfull, false,isfull, NULL,NULL); } return statuskind; }
bool Board::IsSquareAttacked(int square, int attackerColor) const { ulong colorMask = colorBitBoards[attackerColor]; ulong attackMask = MoveGenerator::rankAttacks[square][GetRankStatus(square)]; ulong attackers = (pieceBitBoards[PieceTypes::Queen] | pieceBitBoards[PieceTypes::Rook]) & colorMask; if ((attackers & attackMask) != 0) { return true; } attackMask = MoveGenerator::fileAttacks[square][GetFileStatus(square)]; if ((attackers & attackMask) != 0) { return true; } attackMask = MoveGenerator::diagA1H8Attacks[square][GetDiagA1H8Status(square)]; attackers = (pieceBitBoards[PieceTypes::Queen] | pieceBitBoards[PieceTypes::Bishop]) & colorMask; if ((attackers & attackMask) != 0) { return true; } attackMask = MoveGenerator::diagA8H1Attacks[square][GetDiagA8H1Status(square)]; if ((attackers & attackMask) != 0) { return true; } if ((MoveGenerator::knightAttacks[square] & pieceBitBoards[PieceTypes::Knight] & colorMask) != 0) { return true; } if ((MoveGenerator::kingAttacks[square] & pieceBitBoards[PieceTypes::King] & colorMask) != 0) { return true; } if ((MoveGenerator::pawnAttacks[square][attackerColor] & pieceBitBoards[PieceTypes::Pawn] & colorMask) != 0) { return true; } return false; }
// static method git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth, bool * assumeValid, bool * skipWorktree) { git_wc_status_kind statuskind; BOOL err; BOOL isDir; CString sProjectRoot; isDir = path.IsDirectory(); if (!path.HasAdminDir(&sProjectRoot)) return git_wc_status_none; // rev.kind = git_opt_revision_unspecified; statuskind = git_wc_status_none; const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { if (sProjectRoot.GetLength() == 3 && sProjectRoot[1] == _T(':')) sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength()); else sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/); } bool isfull = ((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? ShellCache::dll : ShellCache::exe) == ShellCache::dllFull); if(isDir) { err = GetDirStatus(sProjectRoot,sSubPath,&statuskind, isfull,bIsRecursive,isfull,NULL, NULL); // folders must not be displayed as added or deleted only as modified (this is for Shell Overlay-Modes) if (statuskind == git_wc_status_unversioned && sSubPath.IsEmpty()) statuskind = git_wc_status_normal; else if (statuskind == git_wc_status_deleted || statuskind == git_wc_status_added) statuskind = git_wc_status_modified; } else { err = GetFileStatus(sProjectRoot, sSubPath, &statuskind, isfull, false, isfull, NULL, NULL, assumeValid, skipWorktree); } return statuskind; }
ulong Board::GetPinRestrictionMask(int square, int color) { int attackerColor = OtherColor(color); int kingSquare = GetKingSquare(color); int kingRow = GetRow(kingSquare); int kingCol = GetCol(kingSquare); int pieceRow = GetRow(square); int pieceCol = GetCol(square); int dr = pieceRow - kingRow; int dc = pieceCol - kingCol; ulong defenderKing = 1ULL << kingSquare; if(dr == 0) { ulong rankAttacks = MoveGenerator::rankAttacks[square][GetRankStatus(square)]; ulong defenderKing = 1ULL << kingSquare; if((defenderKing & rankAttacks) != 0) { ulong attackers = GetPieceBitBoard(Pieces::GetPiece(PieceTypes::Rook, attackerColor)) | GetPieceBitBoard(Pieces::GetPiece(PieceTypes::Queen, attackerColor)); if((rankAttacks & attackers) != 0) { return rankAttacks; } } } else if(dc == 0) { ulong fileAttacks = MoveGenerator::fileAttacks[square][GetFileStatus(square)]; if((defenderKing & fileAttacks) != 0) { ulong attackers = GetPieceBitBoard(Pieces::GetPiece(PieceTypes::Rook, attackerColor)) | GetPieceBitBoard(Pieces::GetPiece(PieceTypes::Queen, attackerColor)); if((fileAttacks & attackers) != 0) { return fileAttacks; } } } else if(dr == dc || dr == -dc) { ulong diagAttacks = 0; if(dr == dc) { diagAttacks = MoveGenerator::diagA1H8Attacks[square][GetDiagA1H8Status(square)]; } else { diagAttacks = MoveGenerator::diagA8H1Attacks[square][GetDiagA8H1Status(square)]; } if((defenderKing & diagAttacks) != 0) { ulong attackers = GetPieceBitBoard(Pieces::GetPiece(PieceTypes::Bishop, attackerColor)) | GetPieceBitBoard(Pieces::GetPiece(PieceTypes::Queen, attackerColor)); if((diagAttacks & attackers) != 0) { return diagAttacks; } } } return ~(0ULL); }
ulong Board::GetSquareAttackers(int square, int attackerColor) const { ulong attackPieces = 0; ulong attackMask = MoveGenerator::rankAttacks[square][GetRankStatus(square)] | MoveGenerator::fileAttacks[square][GetFileStatus(square)]; ulong attackers = pieceBitBoards[PieceTypes::Queen] | pieceBitBoards[PieceTypes::Rook]; attackPieces |= attackers & attackMask; attackMask = MoveGenerator::diagA1H8Attacks[square][GetDiagA1H8Status(square)] | MoveGenerator::diagA8H1Attacks[square][GetDiagA8H1Status(square)]; attackers = pieceBitBoards[PieceTypes::Queen] | pieceBitBoards[PieceTypes::Bishop]; attackPieces |= attackers & attackMask; attackPieces |= MoveGenerator::knightAttacks[square] & pieceBitBoards[PieceTypes::Knight]; attackPieces |= MoveGenerator::kingAttacks[square] & pieceBitBoards[PieceTypes::King]; attackPieces |= MoveGenerator::pawnAttacks[square][attackerColor] & pieceBitBoards[PieceTypes::Pawn]; return attackPieces & colorBitBoards[attackerColor]; }
int Board::GetFileStatus(int square) const { return GetFileStatus(square, occupiedSquares); }
int CGitIndexList::GetStatus(const CString& gitdir, CString path, git_wc_status_kind* status, BOOL IsFull, BOOL /*IsRecursive*/, FILL_STATUS_CALLBACK callback, void *pData, CGitHash *pHash, bool * assumeValid, bool * skipWorktree) { __int64 time, filesize = 0; bool isDir = false; if (!status) return 0; git_wc_status_kind dirstatus = git_wc_status_none; int result; if (path.IsEmpty()) result = CGit::GetFileModifyTime(gitdir, &time, &isDir); else result = CGit::GetFileModifyTime(CombinePath(gitdir, path), &time, &isDir, &filesize); if (result) { *status = git_wc_status_deleted; if (callback && assumeValid && skipWorktree) callback(CombinePath(gitdir, path), git_wc_status_deleted, false, pData, *assumeValid, *skipWorktree); return 0; } if (!isDir) { GetFileStatus(gitdir, path, status, time, filesize, callback, pData, pHash, assumeValid, skipWorktree); return 0; } if (!path.IsEmpty() && path.Right(1) != _T('\\')) path += _T('\\'); int len = path.GetLength(); for (auto it = cbegin(), itend = cend(); it != itend; ++it) { if (!((*it).m_FileName.GetLength() > len && wcsncmp((*it).m_FileName, path, len) == 0)) continue; if (!IsFull) { *status = git_wc_status_normal; if (callback) callback(CombinePath(gitdir, path), *status, false, pData, ((*it).m_Flags & GIT_IDXENTRY_VALID) && !((*it).m_FlagsExtended & GIT_IDXENTRY_SKIP_WORKTREE), ((*it).m_FlagsExtended & GIT_IDXENTRY_SKIP_WORKTREE) != 0); return 0; } result = CGit::GetFileModifyTime(CombinePath(gitdir, (*it).m_FileName), &time, nullptr, &filesize); if (result) continue; *status = git_wc_status_none; if (assumeValid) *assumeValid = false; if (skipWorktree) *skipWorktree = false; GetFileStatus(gitdir, (*it).m_FileName, status, time, filesize, callback, pData, nullptr, assumeValid, skipWorktree); // if a file is assumed valid, we need to inform the caller, otherwise the assumevalid flag might not get to the explorer on first open of a repository if (callback && assumeValid && skipWorktree && (*assumeValid || *skipWorktree)) callback(CombinePath(gitdir, path), *status, false, pData, *assumeValid, *skipWorktree); if (*status != git_wc_status_none) { if (dirstatus == git_wc_status_none) dirstatus = git_wc_status_normal; if (*status != git_wc_status_normal) dirstatus = git_wc_status_modified; } } /* End For */ if (dirstatus != git_wc_status_none) *status = dirstatus; else *status = git_wc_status_unversioned; if (callback) callback(CombinePath(gitdir, path), *status, false, pData, false, false); return 0; }
/** @brief Internal implementation of Open */ bool UniMemFile::DoOpen(LPCTSTR filename, DWORD dwOpenAccess, DWORD dwOpenShareMode, DWORD dwOpenCreationDispostion, DWORD dwMappingProtect, DWORD dwMapViewAccess) { Close(); m_filename = filename; m_filepath = m_filename; // TODO: Make canonical ? m_handle = CreateFile(m_filename.c_str(), dwOpenAccess, dwOpenShareMode, NULL, dwOpenCreationDispostion, 0, 0); if (m_handle == INVALID_HANDLE_VALUE) { LastError(_T("CreateFile"), GetLastError()); return false; } m_lineno = 0; // GetFileStatus requires file be "open", which means nonnegative line number if (!GetFileStatus()) return false; m_lineno = -1; DWORD sizehi = (DWORD)(m_filesize >> 32); DWORD sizelo = (DWORD)(m_filesize & 0xFFFFFFFF); if (sizehi || sizelo > 0x7FFFFFFF) { LastErrorCustom(_T("UniMemFile cannot handle files over 2 gigabytes")); return false; } if (sizelo == 0) { // Allow opening empty file, but memory mapping doesn't work on such // m_base and m_current are 0 from the Close call above // so ReadString will correctly return empty EOF immediately m_lineno = 0; return true; } LPSECURITY_ATTRIBUTES lpAttributes = NULL; // default security LPCTSTR lpName = NULL; // nameless mapping m_hMapping = CreateFileMapping(m_handle, lpAttributes, dwMappingProtect, sizehi, sizelo, lpName); if (!m_hMapping) { LastError(_T("CreateFileMapping"), GetLastError()); return false; } DWORD dwFileOffsetHigh = 0; DWORD dwFileOffsetLow = 0; SIZE_T dwNumberOfBytesToMap = sizelo; m_base = (LPBYTE)MapViewOfFile(m_hMapping, dwMapViewAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap); if (!m_base) { LastError(_T("MapViewOfFile"), GetLastError()); return false; } m_data = m_base; m_current = m_base; m_lineno = 0; return true; }
int CGitIndexList::GetStatus(const CString &gitdir,const CString &pathParam, git_wc_status_kind *status, BOOL IsFull, BOOL /*IsRecursive*/, FILL_STATUS_CALLBACK callback, void *pData, CGitHash *pHash, bool * assumeValid, bool * skipWorktree) { __int64 time; bool isDir = false; CString path = pathParam; if (status) { git_wc_status_kind dirstatus = git_wc_status_none; int result; if (path.IsEmpty()) result = g_Git.GetFileModifyTime(gitdir, &time, &isDir); else result = g_Git.GetFileModifyTime(gitdir + _T("\\") + path, &time, &isDir); if (result) { *status = git_wc_status_deleted; if (callback && assumeValid && skipWorktree) callback(gitdir + _T("\\") + path, git_wc_status_deleted, false, pData, *assumeValid, *skipWorktree); return 0; } if (isDir) { if (!path.IsEmpty()) { if (path.Right(1) != _T("\\")) path += _T("\\"); } int len = path.GetLength(); for (size_t i = 0; i < size(); ++i) { if (at(i).m_FileName.GetLength() > len) { if (at(i).m_FileName.Left(len) == path) { if (!IsFull) { *status = git_wc_status_normal; if (callback) callback(gitdir + _T("\\") + path, *status, false, pData, (at(i).m_Flags & GIT_IDXENTRY_VALID) && !(at(i).m_Flags & GIT_IDXENTRY_SKIP_WORKTREE), (at(i).m_Flags & GIT_IDXENTRY_SKIP_WORKTREE) != 0); return 0; } else { result = g_Git.GetFileModifyTime(gitdir+_T("\\") + at(i).m_FileName, &time); if (result) continue; *status = git_wc_status_none; if (assumeValid) *assumeValid = false; if (skipWorktree) *skipWorktree = false; GetFileStatus(gitdir, at(i).m_FileName, status, time, callback, pData, NULL, assumeValid, skipWorktree); // if a file is assumed valid, we need to inform the caller, otherwise the assumevalid flag might not get to the explorer on first open of a repository if (callback && assumeValid && skipWorktree && (*assumeValid || *skipWorktree)) callback(gitdir + _T("\\") + path, *status, false, pData, *assumeValid, *skipWorktree); if (*status != git_wc_status_none) { if (dirstatus == git_wc_status_none) { dirstatus = git_wc_status_normal; } if (*status != git_wc_status_normal) { dirstatus = git_wc_status_modified; } } } } } } /* End For */ if (dirstatus != git_wc_status_none) { *status = dirstatus; } else { *status = git_wc_status_unversioned; } if(callback) callback(gitdir + _T("\\") + path, *status, false, pData, false, false); return 0; } else { GetFileStatus(gitdir, path, status, time, callback, pData, pHash, assumeValid, skipWorktree); } } return 0; }
git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false */, bool noignore /* = false */, bool /*noexternals*/ /* = false */) { // NOTE: unlike the SVN version this one does not cache the enumerated files, because in practice no code in all of // Tortoise uses this, all places that call GetStatus create a temp GitStatus object which gets destroyed right // after the call again // apr_hash_t * statushash; // apr_hash_t * exthash; // apr_array_header_t * statusarray; // const sort_item* item; // git_error_clear(m_err); // statushash = apr_hash_make(m_pool); // exthash = apr_hash_make(m_pool); git_revnum_t youngest = GIT_INVALID_REVNUM; // git_opt_revision_t rev; // rev.kind = git_opt_revision_unspecified; CString sProjectRoot; if ( !path.HasAdminDir(&sProjectRoot) ) return youngest; struct hashbaton_t hashbaton; // hashbaton.hash = statushash; // hashbaton.exthash = exthash; hashbaton.pThis = this; bool isfull = ((DWORD)CRegStdDWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? ShellCache::dll : ShellCache::exe) == ShellCache::dllFull); { LPCTSTR lpszSubPath = NULL; CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength()); lpszSubPath = sSubPath; // skip initial slash if necessary if (*lpszSubPath == _T('\\')) lpszSubPath++; } m_status.prop_status = m_status.text_status = git_wc_status_none; if(path.IsDirectory()) { m_err = GetDirStatus(sProjectRoot,CString(lpszSubPath),&m_status.text_status , isfull, false,!noignore, NULL, NULL); } else { m_err = GetFileStatus(sProjectRoot,CString(lpszSubPath),&m_status.text_status ,isfull, false,!noignore, NULL,NULL); } } // Error present if function is not under version control if (m_err) /*|| (apr_hash_count(statushash) == 0)*/ { status = NULL; return GIT_INVALID_REVNUM; } // Convert the unordered hash to an ordered, sorted array /*statusarray = sort_hash (statushash, sort_compare_items_as_paths, m_pool);*/ // only the first entry is needed (no recurse) // item = &APR_ARRAY_IDX (statusarray, 0, const sort_item); // status = (git_wc_status2_t *) item->value; status = &m_status; if (update) { // done to match TSVN functionality of this function (not sure if any code uses the reutrn val) // if TGit does not need this, then change the return type of function youngest = g_Git.GetHash(_T("HEAD")); } return youngest; }
int CGitStatus::GetStatus(const CString &gitdir, const CString &path, git_wc_status_kind *status, BOOL IsFull, BOOL IsRecursive , FIll_STATUS_CALLBACK callback , void *pData) { int result; __int64 time; bool dir; git_wc_status_kind dirstatus = git_wc_status_none; if (status) { g_Git.GetFileModifyTime(path, &time, &dir); if(path.IsEmpty()) result = _tstat64( gitdir, &buf ); else result = _tstat64( gitdir+_T("\\")+path, &buf ); if(result) return -1; if(buf.st_mode & _S_IFDIR) { if(!path.IsEmpty()) { if( path.Right(1) != _T("\\")) path += _T("\\"); } int len = path.GetLength(); for (int i = 0; i < size(); i++) { if (at(i).m_FileName.GetLength() > len) { if (at(i).m_FileName.Left(len) == path) { if(!IsFull) { *status = git_wc_status_normal; if(callback) callback(gitdir + _T("\\") + path, *status, pData); return 0; } else { result = _tstat64(gitdir + _T("\\") + at(i).m_FileName, &buf); if (result) continue; *status = git_wc_status_none; GetFileStatus(gitdir, at(i).m_FileName, status, buf, callback, pData); if (*status != git_wc_status_none) { if (dirstatus == git_wc_status_none) { dirstatus = git_wc_status_normal; } if (*status != git_wc_status_normal) { dirstatus = git_wc_status_modified; } } } } } } if (dirstatus != git_wc_status_none) { *status = dirstatus; } else { *status = git_wc_status_unversioned; } if(callback) callback(gitdir + _T("\\") + path, *status, pData); return 0; } else { GetFileStatus(gitdir, path, status, buf, callback, pData); } } return 0; }
int GitStatus::EnumDirStatus(const CString &gitdir, const CString &subpath, git_wc_status_kind * status,BOOL IsFul, BOOL IsRecursive, BOOL IsIgnore, FILL_STATUS_CALLBACK callback, void *pData) { try { CString path =subpath; path.Replace(_T('\\'),_T('/')); if(!path.IsEmpty()) if(path[path.GetLength()-1] != _T('/')) path += _T('/'); //Add trail / to show it is directory, not file name. CString lowcasepath = path; lowcasepath.MakeLower(); std::vector<CGitFileName> filelist; GetFileList(gitdir, subpath, filelist); if(status) { g_IndexFileMap.CheckAndUpdate(gitdir,true); g_HeadFileMap.CheckHeadAndUpdate(gitdir); SHARED_INDEX_PTR indexptr = g_IndexFileMap.SafeGet(gitdir); SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir); std::vector<CGitFileName>::iterator it; // new git working tree has no index file if (indexptr.get() == NULL) { for (it = filelist.begin(); it < filelist.end(); ++it) { CString casepath = path + it->m_CaseFileName; bool bIsDir = false; if (it->m_FileName.GetLength() > 0 && it->m_FileName[it->m_FileName.GetLength() - 1] == _T('/')) bIsDir = true; if (IsIgnore) { if (g_IgnoreList.CheckIgnoreChanged(gitdir, casepath, bIsDir)) g_IgnoreList.LoadAllIgnoreFile(gitdir, casepath, bIsDir); if (g_IgnoreList.IsIgnore(casepath, gitdir, bIsDir)) *status = git_wc_status_ignored; else if (bIsDir) continue; else *status = git_wc_status_unversioned; } else if (bIsDir) continue; else *status = git_wc_status_unversioned; if(callback) callback(gitdir + _T("/") + casepath, *status, bIsDir, pData, false, false); } return 0; } CString onepath; CString casepath; for (it = filelist.begin(); it < filelist.end(); ++it) { casepath=onepath = path; onepath.MakeLower(); onepath += it->m_FileName; casepath += it->m_CaseFileName; bool bIsDir = false; if (!onepath.IsEmpty() && onepath[onepath.GetLength() - 1] == _T('/')) bIsDir = true; int matchLength = -1; if (bIsDir) matchLength = onepath.GetLength(); int pos = SearchInSortVector(*indexptr, onepath, matchLength); int posintree = SearchInSortVector(*treeptr, onepath, matchLength); if(pos <0 && posintree<0) { if (onepath.IsEmpty()) continue; if(!IsIgnore) { *status = git_wc_status_unversioned; if(callback) callback(gitdir + _T("/") + casepath, *status, bIsDir, pData, false, false); continue; } if (g_IgnoreList.CheckIgnoreChanged(gitdir, casepath, bIsDir)) g_IgnoreList.LoadAllIgnoreFile(gitdir, casepath, bIsDir); if (g_IgnoreList.IsIgnore(casepath, gitdir, bIsDir)) *status = git_wc_status_ignored; else *status = git_wc_status_unversioned; if(callback) callback(gitdir + _T("/") + casepath, *status, bIsDir, pData, false, false); } else if(pos <0 && posintree>=0) /* check if file delete in index */ { *status = git_wc_status_deleted; if(callback) callback(gitdir + _T("/") + casepath, *status, bIsDir, pData, false, false); } else if(pos >=0 && posintree <0) /* Check if file added */ { *status = git_wc_status_added; if(callback) callback(gitdir + _T("/") + casepath, *status, bIsDir, pData, false, false); } else { if (onepath.IsEmpty()) continue; if (bIsDir) { *status = git_wc_status_normal; if(callback) callback(gitdir + _T("/") + casepath, *status, bIsDir, pData, false, false); } else { bool assumeValid = false; bool skipWorktree = false; git_wc_status_kind filestatus; GetFileStatus(gitdir, casepath, &filestatus, IsFul, IsRecursive, IsIgnore, callback, pData, &assumeValid, &skipWorktree); } } }/*End of For*/ /* Check deleted file in system */ int start=0, end=0; int pos = SearchInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength()); // match path prefix, (sub)folders end with slash std::map<CString, bool> skipWorktreeMap; if (GetRangeInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos) == 0) { CGitIndexList::iterator it; CString oldstring; for (it = indexptr->begin() + start; it <= indexptr->begin() + end; ++it) { int commonPrefixLength = lowcasepath.GetLength(); int index = (*it).m_FileName.Find(_T('/'), commonPrefixLength); if(index<0) index = (*it).m_FileName.GetLength(); else ++index; // include slash at the end for subfolders, so that we do not match files by mistake CString filename = (*it).m_FileName.Mid(commonPrefixLength, index - commonPrefixLength); if(oldstring != filename) { oldstring = filename; if (SearchInSortVector(filelist, filename, filename.GetLength()) < 0) { bool skipWorktree = false; *status = git_wc_status_deleted; if (((*it).m_Flags & GIT_IDXENTRY_SKIP_WORKTREE) != 0) { skipWorktreeMap[filename] = true; skipWorktree = true; *status = git_wc_status_normal; } if(callback) callback(gitdir + _T("/") + (*it).m_FileName, *status, false, pData, false, skipWorktree); } } } } start = end =0; pos = SearchInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength()); // match path prefix, (sub)folders end with slash if (GetRangeInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos) == 0) { CGitHeadFileList::iterator it; CString oldstring; for (it = treeptr->begin() + start; it <= treeptr->begin() + end; ++it) { int commonPrefixLength = lowcasepath.GetLength(); int index = (*it).m_FileName.Find(_T('/'), commonPrefixLength); if(index<0) index = (*it).m_FileName.GetLength(); else ++index; // include slash at the end for subfolders, so that we do not match files by mistake CString filename = (*it).m_FileName.Mid(commonPrefixLength, index - commonPrefixLength); if (oldstring != filename && skipWorktreeMap[filename] != true) { oldstring = filename; if (SearchInSortVector(filelist, filename, filename.GetLength()) < 0) { *status = git_wc_status_deleted; if(callback) callback(gitdir + _T("/") + (*it).m_FileName, *status, false, pData, false, false); } } } } }/*End of if status*/ }catch(...) { return -1; } return 0; }
int CGitIndexList::GetStatus(const CString &gitdir,const CString &pathParam, git_wc_status_kind *status, BOOL IsFull, BOOL IsRecursive, FIll_STATUS_CALLBACK callback,void *pData, CGitHash *pHash) { int result; git_wc_status_kind dirstatus = git_wc_status_none; __int64 time; bool isDir = false; CString path = pathParam; if (status) { if (path.IsEmpty()) result = g_Git.GetFileModifyTime(gitdir, &time, &isDir); else result = g_Git.GetFileModifyTime(gitdir + _T("\\") + path, &time, &isDir); if (result) { *status = git_wc_status_deleted; if (callback) callback(gitdir + _T("\\") + path, git_wc_status_deleted, false, pData); return 0; } if (isDir) { if (!path.IsEmpty()) { if (path.Right(1) != _T("\\")) path += _T("\\"); } int len = path.GetLength(); for (int i = 0; i < size(); i++) { if (at(i).m_FileName.GetLength() > len) { if (at(i).m_FileName.Left(len) == path) { if (!IsFull) { *status = git_wc_status_normal; if (callback) callback(gitdir + _T("\\") + path, *status, false, pData); return 0; } else { result = g_Git.GetFileModifyTime(gitdir+_T("\\") + at(i).m_FileName, &time); if (result) continue; *status = git_wc_status_none; GetFileStatus(gitdir, at(i).m_FileName, status, time, callback, pData); if (*status != git_wc_status_none) { if (dirstatus == git_wc_status_none) { dirstatus = git_wc_status_normal; } if (*status != git_wc_status_normal) { dirstatus = git_wc_status_modified; } } } } } } /* End For */ if (dirstatus != git_wc_status_none) { *status = dirstatus; } else { *status = git_wc_status_unversioned; } if(callback) callback(gitdir + _T("\\") + path, *status, false, pData); return 0; } else { GetFileStatus(gitdir, path, status, time, callback, pData, pHash); } } return 0; }
int GitStatus::GetDirStatus(const CString &gitdir, const CString &subpath, git_wc_status_kind * status, BOOL IsFul, BOOL IsRecursive, BOOL IsIgnore, FILL_STATUS_CALLBACK callback, void *pData) { try { CString path =subpath; path.Replace(_T('\\'),_T('/')); if(!path.IsEmpty()) if(path[path.GetLength()-1] != _T('/')) path += _T('/'); //Add trail / to show it is directory, not file name. CString lowcasepath = path; lowcasepath.MakeLower(); if(status) { g_IndexFileMap.CheckAndUpdate(gitdir, true); SHARED_INDEX_PTR indexptr = g_IndexFileMap.SafeGet(gitdir); if (indexptr == NULL) { *status = git_wc_status_unversioned; return 0; } int pos = SearchInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength()); //Not In Version Contorl if(pos<0) { if(!IsIgnore) { *status = git_wc_status_unversioned; if(callback) callback(gitdir + _T("/") + path, *status, false, pData, false, false); return 0; } //Check ignore always. { if (g_IgnoreList.CheckIgnoreChanged(gitdir, path, true)) g_IgnoreList.LoadAllIgnoreFile(gitdir, path, true); if (g_IgnoreList.IsIgnore(path, gitdir, true)) *status = git_wc_status_ignored; else *status = git_wc_status_unversioned; g_HeadFileMap.CheckHeadAndUpdate(gitdir, false); SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir); //Check init repository if (treeptr->HeadIsEmpty() && path.IsEmpty()) *status = git_wc_status_normal; } } else // In version control { *status = git_wc_status_normal; int start=0; int end=0; if(path.IsEmpty()) { start=0; end = (int)indexptr->size() - 1; } GetRangeInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos); CGitIndexList::iterator it; it = indexptr->begin()+start; // Check Conflict; for (int i = start; i <= end; ++i) { if (((*it).m_Flags & GIT_IDXENTRY_STAGEMASK) !=0) { *status = git_wc_status_conflicted; if(callback) { int dirpos = (*it).m_FileName.Find(_T('/'), path.GetLength()); if(dirpos<0 || IsRecursive) callback(gitdir + _T("\\") + it->m_FileName, git_wc_status_conflicted, false, pData, false, false); } else break; } ++it; } if( IsFul && (*status != git_wc_status_conflicted)) { *status = git_wc_status_normal; g_HeadFileMap.CheckHeadAndUpdate(gitdir); //Check Add it = indexptr->begin()+start; { //Check if new init repository SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir); if (!treeptr->empty() || treeptr->HeadIsEmpty()) { for (int i = start; i<= end; ++i) { pos = SearchInSortVector(*treeptr, (*it).m_FileName, -1); if(pos < 0) { *status = max(git_wc_status_added, *status); // added file found if(callback) { int dirpos = (*it).m_FileName.Find(_T('/'), path.GetLength()); if(dirpos<0 || IsRecursive) callback(gitdir + _T("\\") + it->m_FileName, git_wc_status_added, false, pData, false, false); } else break; } if( pos>=0 && treeptr->at(pos).m_Hash != (*it).m_IndexHash) { *status = max(git_wc_status_modified, *status); // modified file found if(callback) { int dirpos = (*it).m_FileName.Find(_T('/'), path.GetLength()); if(dirpos<0 || IsRecursive) callback(gitdir + _T("\\") + it->m_FileName, git_wc_status_modified, false, pData, ((*it).m_Flags & GIT_IDXENTRY_VALID) && !((*it).m_Flags & GIT_IDXENTRY_SKIP_WORKTREE), ((*it).m_Flags & GIT_IDXENTRY_SKIP_WORKTREE) != 0); } else break; } ++it; } //Check Delete if( *status == git_wc_status_normal ) { pos = SearchInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength()); if(pos <0) { *status = max(git_wc_status_added, *status); // added file found } else { int hstart,hend; GetRangeInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength(), &hstart, &hend, pos); CGitHeadFileList::iterator hit; hit = treeptr->begin() + hstart; CGitHeadFileList::iterator lastElement = treeptr->end(); for (int i = hstart; i <= hend && hit != lastElement; ++i) { if (SearchInSortVector(*indexptr, (*hit).m_FileName, -1) < 0) { *status = max(git_wc_status_deleted, *status); // deleted file found break; } ++hit; } } } } }/* End lock*/ } // If define callback, it need update each file status. // If not define callback, status == git_wc_status_conflicted, needn't check each file status // because git_wc_status_conflicted is highest.s if(callback || (*status != git_wc_status_conflicted)) { //Check File Time; //if(IsRecursive) { CString sub, currentPath; it = indexptr->begin()+start; for (int i = start; i <= end; ++i, ++it) { if( !IsRecursive ) { //skip child directory int pos = (*it).m_FileName.Find(_T('/'), path.GetLength()); if( pos > 0) { currentPath = (*it).m_FileName.Left(pos); if( callback && (sub != currentPath) ) { sub = currentPath; CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": index subdir %s\n"),sub); if(callback) callback(gitdir + _T("\\") + sub, git_wc_status_normal, true, pData, false, false); } continue; } } git_wc_status_kind filestatus = git_wc_status_none; bool assumeValid = false; bool skipWorktree = false; GetFileStatus(gitdir, (*it).m_FileName, &filestatus, IsFul, IsRecursive, IsIgnore, callback, pData, &assumeValid, &skipWorktree); } } } } if(callback) callback(gitdir + _T("/") + subpath, *status, true, pData, false, false); } }catch(...) { if(status) *status = git_wc_status_none; return -1; } return 0; }
int GitStatus::GetDirStatus(const CString& gitdir, const CString& subpath, git_wc_status_kind* status, BOOL IsFul, BOOL IsRecursive, BOOL IsIgnore) { if (!status) return 0; CString path = subpath; path.Replace(_T('\\'), _T('/')); if (!path.IsEmpty() && path[path.GetLength() - 1] != _T('/')) path += _T('/'); //Add trail / to show it is directory, not file name. g_IndexFileMap.CheckAndUpdate(gitdir, true); SHARED_INDEX_PTR indexptr = g_IndexFileMap.SafeGet(gitdir); if (!indexptr) { *status = git_wc_status_unversioned; return 0; } CString lowcasepath = path; lowcasepath.MakeLower(); int pos = SearchInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength()); // Not In Version Contorl if (pos < 0) { if (!IsIgnore) { *status = git_wc_status_unversioned; return 0; } // Check ignore always. if (g_IgnoreList.CheckIgnoreChanged(gitdir, path, true)) g_IgnoreList.LoadAllIgnoreFile(gitdir, path, true); if (g_IgnoreList.IsIgnore(path, gitdir, true)) *status = git_wc_status_ignored; else *status = git_wc_status_unversioned; g_HeadFileMap.CheckHeadAndUpdate(gitdir); SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir); // Check init repository if (treeptr->HeadIsEmpty() && path.IsEmpty()) *status = git_wc_status_normal; // check if only one file in repository is deleted in index else if (path.IsEmpty() && !treeptr->empty()) *status = git_wc_status_deleted; return 0; } // In version control *status = git_wc_status_normal; int start = 0; int end = 0; GetRangeInSortVector(*indexptr, lowcasepath, lowcasepath.GetLength(), &start, &end, pos); // Check Conflict; for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; indexptr->m_bHasConflicts && it <= itlast; ++it) { if (((*it).m_Flags & GIT_IDXENTRY_STAGEMASK) != 0) { *status = git_wc_status_conflicted; break; } } if (IsFul && (*status != git_wc_status_conflicted)) { *status = git_wc_status_normal; g_HeadFileMap.CheckHeadAndUpdate(gitdir); // Check Add { // Check if new init repository SHARED_TREE_PTR treeptr = g_HeadFileMap.SafeGet(gitdir); if (!treeptr->empty() || treeptr->HeadIsEmpty()) { for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; it <= itlast; ++it) { pos = SearchInSortVector(*treeptr, (*it).m_FileName, -1); if (pos < 0) { *status = max(git_wc_status_added, *status); // added file found break; } if (pos >= 0 && treeptr->at(pos).m_Hash != (*it).m_IndexHash) { *status = max(git_wc_status_modified, *status); // modified file found break; } } // Check Delete if (*status == git_wc_status_normal) { pos = SearchInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength()); if (pos < 0) *status = max(git_wc_status_added, *status); // added file found else { int hstart, hend; GetRangeInSortVector(*treeptr, lowcasepath, lowcasepath.GetLength(), &hstart, &hend, pos); for (auto hit = treeptr->cbegin() + hstart, lastElement = treeptr->cbegin() + hend; hit <= lastElement; ++hit) { if (SearchInSortVector(*indexptr, (*hit).m_FileName, -1) < 0) { *status = max(git_wc_status_deleted, *status); // deleted file found break; } } } } } } /* End lock*/ } // When status == git_wc_status_conflicted, needn't check each file status // because git_wc_status_conflicted is highest.s if (*status == git_wc_status_conflicted) return 0; for (auto it = indexptr->cbegin() + start, itlast = indexptr->cbegin() + end; it <= itlast; ++it) { //skip child directory if (!IsRecursive && (*it).m_FileName.Find(_T('/'), path.GetLength()) > 0) continue; git_wc_status_kind filestatus = git_wc_status_none; bool assumeValid = false; bool skipWorktree = false; GetFileStatus(gitdir, (*it).m_FileName, &filestatus, IsFul, IsRecursive, IsIgnore, nullptr, nullptr, &assumeValid, &skipWorktree); switch (filestatus) { case git_wc_status_added: case git_wc_status_modified: case git_wc_status_deleted: case git_wc_status_conflicted: *status = GetMoreImportant(filestatus, *status); } } return 0; }