void FileMonitor::ProcessChangeNotification( FileSystemUtils::Path& file ) { // Notify any listeners and add to change list if this is a watched file/dir // Again - this isn't correct, just a hack bool bPathIsDir = !file.HasExtension(); FileSystemUtils::Path pathDir = bPathIsDir ? file : file.ParentPath(); TDirList::iterator dirIt = GetWatchedDirEntry(pathDir); if (dirIt != m_DirWatchList.end()) { // Is directory itself being watched? // Unsure here - no need to notify as folder will get it's own notification come through? // Bit below feels redundant if (dirIt->bWatchDirItself) { if (dirIt->pListener != NULL) { dirIt->pListener->OnFileChange(pathDir); } else { m_FileChangedList.push_back(pathDir); m_bChangeFlag = true; } } #ifdef _MSC_VER auto pos = file.m_string.find("~"); if (pos != file.m_string.npos) { file.m_string = file.m_string.substr(0, pos); } #endif // Is this one of the files being watched in the directory? TFileList::iterator fileIt = GetWatchedFileEntry(file, dirIt->fileWatchList); if (fileIt != dirIt->fileWatchList.end()) { if (fileIt->pListener != NULL) { fileIt->pListener->OnFileChange(file); } else { m_FileChangedList.push_back(file); m_bChangeFlag = true; } } } }
void FileMonitor::Watch( const FileSystemUtils::Path& filename, IFileMonitorListener *pListener /*= NULL*/ ) { FileSystemUtils::Path filepath = filename.DelimitersToOSDefault(); // Is this a directory path or a file path? // Actually, we can't tell from a path, in general // foo/bar could be a filename with no extension // It seems reasonable to inspect the path using FileSystemUtils, check it actually exists // (it should, surely? otherwise error?) and determine whether it is a file or a folder // but for now - we cheat by assuming files have extensions bool bPathIsDir = !filepath.HasExtension(); FileSystemUtils::Path pathDir = bPathIsDir ? filepath : filepath.ParentPath(); TDirList::iterator dirIt = GetWatchedDirEntry(pathDir); if (dirIt == m_DirWatchList.end()) { // New directory entry m_DirWatchList.push_back( WatchedDir(pathDir) ); dirIt = --(m_DirWatchList.end()); StartWatchingDir(*dirIt); } assert(dirIt != m_DirWatchList.end()); if (bPathIsDir) { if (!dirIt->bWatchDirItself) { assert(!dirIt->pListener); dirIt->pListener = pListener; dirIt->bWatchDirItself = true; } } else { // Add file to directory's watch list (if it's not already there) TFileList::iterator fileIt = GetWatchedFileEntry(filepath, dirIt->fileWatchList); if (fileIt == dirIt->fileWatchList.end()) { dirIt->fileWatchList.push_back(WatchedFile(filepath, pListener)); } } }
FileSystemUtils::Path RuntimeObjectSystem::FindFile( const FileSystemUtils::Path& input ) { FileSystemUtils::Path requestedDirectory = input; FileSystemUtils::Path filename; FileSystemUtils::Path foundFile = input; bool bIsFile = input.HasExtension(); if( bIsFile ) { requestedDirectory = requestedDirectory.ParentPath(); filename = input.Filename(); } requestedDirectory.ToOSCanonicalCase(); filename.ToOSCanonicalCase(); foundFile.ToOSCanonicalCase(); // Step 1: Try input directory if( requestedDirectory.Exists() ) { m_FoundSourceDirectoryMappings[ requestedDirectory ] = requestedDirectory; } else { // Step 2: Attempt to find a pre-existing mapping bool bFoundMapping = false; if( m_FoundSourceDirectoryMappings.size() ) { FileSystemUtils::Path testDir = requestedDirectory; FileSystemUtils::Path foundDir; unsigned int depth = 0; bool bFound = false; while( testDir.HasParentPath() ) { TFileMapIterator itrFind = m_FoundSourceDirectoryMappings.find( testDir ); if( itrFind != m_FoundSourceDirectoryMappings.end() ) { foundDir = itrFind->second; bFound = true; break; } testDir = testDir.ParentPath(); ++depth; } if( bFound ) { if( depth ) { // not an exact match FileSystemUtils::Path directory = requestedDirectory; directory.m_string.replace( 0, testDir.m_string.length(), foundDir.m_string ); if( directory.Exists() ) { foundFile = directory / filename; if( foundFile.Exists() ) { m_FoundSourceDirectoryMappings[ requestedDirectory ] = directory; if( m_pCompilerLogger ) { m_pCompilerLogger->LogInfo( "Found Directory Mapping: %s to %s\n", requestedDirectory.c_str(), directory.c_str() ); } bFoundMapping = true; } } } else { // exact match foundFile = foundDir / filename; bFoundMapping = true; } } if( !bFoundMapping ) { // Step 3: Attempt to find a mapping from a known path TFileList requestedSubPaths; FileSystemUtils::Path requestedSubPath = requestedDirectory; while( requestedSubPath.HasParentPath() ) { requestedSubPaths.push_back( requestedSubPath ); requestedSubPath = requestedSubPath.ParentPath(); } TFileMapIterator itr = m_FoundSourceDirectoryMappings.begin(); while( ( itr != m_FoundSourceDirectoryMappings.end() ) && !bFoundMapping ) { FileSystemUtils::Path existingPath = itr->second; while( ( existingPath.HasParentPath() ) && !bFoundMapping ) { // check all potentials for( size_t i=0; i<requestedSubPaths.size(); ++i ) { FileSystemUtils::Path toCheck = existingPath / requestedSubPaths[i].Filename(); if( toCheck.Exists() ) { // potential mapping FileSystemUtils::Path directory = requestedDirectory; directory.m_string.replace( 0, requestedSubPaths[i].m_string.length(), toCheck.m_string ); if( directory.Exists() ) { foundFile = directory / filename; if( foundFile.Exists() ) { m_FoundSourceDirectoryMappings[ requestedDirectory ] = directory; if( m_pCompilerLogger ) { m_pCompilerLogger->LogInfo( "Found Directory Mapping: %s to %s\n", requestedDirectory.c_str(), directory.c_str() ); } bFoundMapping = true; break; } } } } existingPath = existingPath.ParentPath(); } ++itr; } } } } if( !foundFile.Exists() ) { if( m_pCompilerLogger ) { m_pCompilerLogger->LogWarning( "Could not find Directory Mapping for: %s\n", input.c_str() ); } ++m_NumNotFoundSourceFiles; } return foundFile; }
void RuntimeObjectSystem::SetupRuntimeFileTracking(const IAUDynArray<IObjectConstructor*>& constructors_) { #ifndef RCCPPOFF // for optimization purposes we skip some actions when running for the first time (i.e. no previous constructors) static bool bFirstTime = true; for (size_t i = 0, iMax = constructors_.Size(); i < iMax; ++i) { const char* pFilename = constructors_[i]->GetFileName(); // GetFileName returns full path including GetCompiledPath() if( !pFilename ) { continue; } Path filePath = pFilename; filePath = filePath.GetCleanPath(); filePath = FindFile( filePath ); unsigned short projectId = constructors_[ i ]->GetProjectId(); ProjectSettings& project = GetProject( projectId ); AddToRuntimeFileList( filePath.c_str( ), projectId ); if( !bFirstTime ) { //remove old include file mappings for this file TFileToFilesIterator itrCurr = project.m_RuntimeIncludeMap.begin( ); while( itrCurr != project.m_RuntimeIncludeMap.end( ) ) { if( itrCurr->second == filePath ) { TFileToFilesIterator itrErase = itrCurr; ++itrCurr; project.m_RuntimeIncludeMap.erase( itrErase ); } else { ++itrCurr; } } //remove previous link libraries for this file project.m_RuntimeLinkLibraryMap.erase( filePath ); //remove previous source dependencies project.m_RuntimeSourceDependencyMap.erase( filePath ); } //we need the compile path for some platforms where the __FILE__ path is relative to the compile path FileSystemUtils::Path compileDir = constructors_[i]->GetCompiledPath(); //add include file mappings for (size_t includeNum = 0; includeNum <= constructors_[i]->GetMaxNumIncludeFiles(); ++includeNum) { const char* pIncludeFile = constructors_[i]->GetIncludeFile(includeNum); if( pIncludeFile ) { FileSystemUtils::Path pathInc = compileDir / pIncludeFile; pathInc = FindFile( pathInc.GetCleanPath() ); TFileToFilePair includePathPair; includePathPair.first = pathInc; includePathPair.second = filePath; AddToRuntimeFileList( pathInc.c_str(), projectId ); project.m_RuntimeIncludeMap.insert( includePathPair ); } } //add link library file mappings for (size_t linklibraryNum = 0; linklibraryNum <= constructors_[i]->GetMaxNumLinkLibraries(); ++linklibraryNum) { const char* pLinkLibrary = constructors_[i]->GetLinkLibrary(linklibraryNum); if( pLinkLibrary ) { // We do not use FindFiles for Linked Libraries as these are searched for on // the library paths, which are themselves searched for. TFileToFilePair linklibraryPathPair; linklibraryPathPair.first = filePath; linklibraryPathPair.second = pLinkLibrary; project.m_RuntimeLinkLibraryMap.insert( linklibraryPathPair ); } } //add source dependency file mappings for (size_t num = 0; num <= constructors_[i]->GetMaxNumSourceDependencies(); ++num) { SourceDependencyInfo sourceDependency = constructors_[i]->GetSourceDependency(num); FileSystemUtils::Path pathInc[2]; // array of potential include files for later checks if( sourceDependency.filename ) { FileSystemUtils::Path pathSrc; if( sourceDependency.relativeToPath ) { pathSrc = sourceDependency.relativeToPath; if( pathSrc.HasExtension() ) { pathInc[1] = compileDir / pathSrc; pathSrc = compileDir / pathSrc.ParentPath() / sourceDependency.filename; } else { pathSrc = compileDir / pathSrc / sourceDependency.filename; } } else { pathSrc = compileDir / sourceDependency.filename; } pathSrc.ToOSCanonicalCase(); pathSrc = pathSrc.DelimitersToOSDefault(); pathSrc = pathSrc.GetCleanPath(); pathInc[0] = pathSrc; if( sourceDependency.extension ) { pathSrc.ReplaceExtension( sourceDependency.extension ); } pathSrc = FindFile( pathSrc.GetCleanPath() ); TFileToFilePair sourcePathPair; sourcePathPair.first = filePath; sourcePathPair.second = pathSrc; project.m_RuntimeSourceDependencyMap.insert( sourcePathPair ); // if the include file with a source dependancy is logged as an runtime include, then we mark this .cpp as compile dependencies on change for( int inc=0; inc<2; ++inc ) { TFileToFilesEqualRange range = project.m_RuntimeIncludeMap.equal_range( pathInc[inc] ); if( range.first != range.second ) { // add source file to runtime file list AddToRuntimeFileList( pathSrc.c_str(), projectId ); // also add this as a source dependency, so it gets force compiled on change of header (and not just compiled) TFileToFilePair includePathPair; includePathPair.first = pathInc[inc]; includePathPair.second = pathSrc; project.m_RuntimeIncludeMap.insert( includePathPair ); } } } } } bFirstTime = false; #endif }