|
|
|
@@ -12,15 +12,15 @@
|
|
|
|
|
RefreshInfo RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(
|
|
|
|
|
const std::vector<std::shared_ptr<SourceGroup>>& sourceGroups, std::shared_ptr<const PersistentStorage> storage)
|
|
|
|
|
{
|
|
|
|
|
const std::set<FilePath> allSourceFilePathsFromSourcegroups = getAllSourceFilePaths(sourceGroups);
|
|
|
|
|
|
|
|
|
|
std::set<FilePath> unchangedFilePaths;
|
|
|
|
|
// 1) Divide filepaths that are already known by the storage to "unchanged and indexed", "unchanged and non-indexed" and "changed"
|
|
|
|
|
std::set<FilePath> unchangedIndexedFilePaths;
|
|
|
|
|
std::set<FilePath> unchangedNonindexedFilePaths;
|
|
|
|
|
std::set<FilePath> changedFilePaths;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const std::vector<FileInfo> fileInfosFromStorage = storage->getFileInfoForAllIndexedFiles();
|
|
|
|
|
const std::vector<FileInfo> fileInfosFromStorage = storage->getFileInfoForAllFiles();
|
|
|
|
|
|
|
|
|
|
std::set<FilePath> alreadyIndexedPaths;
|
|
|
|
|
std::set<FilePath> alreadyKnownPaths;
|
|
|
|
|
{
|
|
|
|
|
const std::set<FilePath> filePathsFromStorage = utility::toSet(utility::convert<FileInfo, FilePath>(
|
|
|
|
|
fileInfosFromStorage, [](const FileInfo& info) { return info.path; }
|
|
|
|
@@ -28,24 +28,35 @@ RefreshInfo RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(
|
|
|
|
|
|
|
|
|
|
for (std::shared_ptr<SourceGroup> sourceGroup : sourceGroups)
|
|
|
|
|
{
|
|
|
|
|
utility::append(alreadyIndexedPaths, sourceGroup->filterToContainedFilePaths(filePathsFromStorage));
|
|
|
|
|
utility::append(alreadyKnownPaths, sourceGroup->filterToContainedFilePaths(filePathsFromStorage));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checking source and header files
|
|
|
|
|
for (const FileInfo& info : fileInfosFromStorage)
|
|
|
|
|
{
|
|
|
|
|
if (alreadyIndexedPaths.find(info.path) != alreadyIndexedPaths.end() && info.path.exists())
|
|
|
|
|
if (alreadyKnownPaths.find(info.path) != alreadyKnownPaths.end() && info.path.exists())
|
|
|
|
|
{
|
|
|
|
|
if (didFileChange(info, storage))
|
|
|
|
|
if (storage->getFilePathIndexed(info.path))
|
|
|
|
|
{
|
|
|
|
|
changedFilePaths.insert(info.path);
|
|
|
|
|
if (didFileChange(info, storage))
|
|
|
|
|
{
|
|
|
|
|
changedFilePaths.insert(info.path);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unchangedIndexedFilePaths.insert(info.path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unchangedFilePaths.insert(info.path);
|
|
|
|
|
changedFilePaths.insert(info.path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (!storage->getFilePathIndexed(info.path) && !didFileChange(info, storage))
|
|
|
|
|
{
|
|
|
|
|
unchangedNonindexedFilePaths.insert(info.path);
|
|
|
|
|
}
|
|
|
|
|
else // file has been removed
|
|
|
|
|
{
|
|
|
|
|
changedFilePaths.insert(info.path);
|
|
|
|
@@ -53,56 +64,68 @@ RefreshInfo RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::set<FilePath> allSourceFilePathsFromSourcegroups = getAllSourceFilePaths(sourceGroups);
|
|
|
|
|
|
|
|
|
|
// 2) Figure out which files need to be cleared
|
|
|
|
|
// 2.1) Add all changed files
|
|
|
|
|
std::set<FilePath> filesToClear = changedFilePaths;
|
|
|
|
|
|
|
|
|
|
// handle referencing paths
|
|
|
|
|
// 2.2) Add files that are reference the changed files
|
|
|
|
|
utility::append(filesToClear, storage->getReferencing(changedFilePaths));
|
|
|
|
|
|
|
|
|
|
// handle referenced paths
|
|
|
|
|
// 2.3) Handle files that are referenced by the files that will be cleared. These will be re-indexed on the fly. However, we do not
|
|
|
|
|
// need to clear files that are also referenced by unchanged source files, because otherwise we will lose these connections.
|
|
|
|
|
// 2.3.1) Get all source file paths that will not be cleared.
|
|
|
|
|
// - Initially this list contains all source file paths the project would index right now.
|
|
|
|
|
// - Then we remove all source files that will be cleared
|
|
|
|
|
// - NOTE: Source files that are new to the project will part of this list, but won't result in any referenced
|
|
|
|
|
// paths because they are not part of the DB. Source files that are new to the project but are already in the
|
|
|
|
|
// DB will be removed from this list if they have changed or reference changed files.
|
|
|
|
|
std::set<FilePath> staticSourceFiles = allSourceFilePathsFromSourcegroups;
|
|
|
|
|
for (const FilePath& path : changedFilePaths)
|
|
|
|
|
for (const FilePath& path : filesToClear)
|
|
|
|
|
{
|
|
|
|
|
staticSourceFiles.erase(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2.3.2) Get sets of referenced files
|
|
|
|
|
const std::set<FilePath> staticReferencedFilePaths = storage->getReferenced(staticSourceFiles);
|
|
|
|
|
const std::set<FilePath> dynamicReferencedFilePaths = storage->getReferenced(changedFilePaths);
|
|
|
|
|
const std::set<FilePath> dynamicReferencedFilePaths = storage->getReferenced(filesToClear);
|
|
|
|
|
|
|
|
|
|
// 2.3.3) Add "dynamicReferencedFilePaths" to "filesToClear" that are not refenced by static paths, because these files may not be
|
|
|
|
|
// referenced anymore. If they still are, they will be re-added when encountered during re-indexing.
|
|
|
|
|
for (const FilePath& path : dynamicReferencedFilePaths)
|
|
|
|
|
{
|
|
|
|
|
if (staticReferencedFilePaths.find(path) == staticReferencedFilePaths.end() &&
|
|
|
|
|
staticSourceFiles.find(path) == staticSourceFiles.end())
|
|
|
|
|
{
|
|
|
|
|
// file may not be referenced anymore and will be reindexed if still needed
|
|
|
|
|
filesToClear.insert(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const FilePath& path : unchangedFilePaths)
|
|
|
|
|
{
|
|
|
|
|
staticSourceFiles.erase(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::set<FilePath> filesToAdd = staticSourceFiles;
|
|
|
|
|
|
|
|
|
|
std::set<FilePath> staticSourceFilePaths;
|
|
|
|
|
// 3) Figure out which files need to be indexed
|
|
|
|
|
std::set<FilePath> filesToIndex;
|
|
|
|
|
for (const FilePath& path : allSourceFilePathsFromSourcegroups)
|
|
|
|
|
{
|
|
|
|
|
if (filesToClear.find(path) == filesToClear.end() && filesToAdd.find(path) == filesToAdd.end())
|
|
|
|
|
if (filesToClear.find(path) != filesToClear.end() || // file will be cleared
|
|
|
|
|
unchangedIndexedFilePaths.find(path) == unchangedIndexedFilePaths.end()) // file has been changed or added
|
|
|
|
|
{
|
|
|
|
|
staticSourceFilePaths.insert(path);
|
|
|
|
|
filesToIndex.insert(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4) Store and return this information
|
|
|
|
|
RefreshInfo info;
|
|
|
|
|
info.mode = REFRESH_UPDATED_FILES;
|
|
|
|
|
info.filesToClear = filesToClear;
|
|
|
|
|
|
|
|
|
|
for (const std::shared_ptr<SourceGroup>& sourceGroup : sourceGroups)
|
|
|
|
|
info.filesToIndex = filesToIndex;
|
|
|
|
|
for (const FilePath fileToClear : filesToClear)
|
|
|
|
|
{
|
|
|
|
|
if (sourceGroup->getStatus() == SOURCE_GROUP_STATUS_ENABLED)
|
|
|
|
|
if (storage->getFilePathIndexed(fileToClear))
|
|
|
|
|
{
|
|
|
|
|
utility::append(info.filesToIndex, sourceGroup->filterToContainedSourceFilePath(staticSourceFilePaths));
|
|
|
|
|
info.filesToClear.insert(fileToClear);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info.nonIndexedFilesToClear.insert(fileToClear);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -115,11 +138,14 @@ RefreshInfo RefreshInfoGenerator::getRefreshInfoForIncompleteFiles(const std::ve
|
|
|
|
|
info.mode = REFRESH_UPDATED_AND_INCOMPLETE_FILES;
|
|
|
|
|
|
|
|
|
|
std::set<FilePath> incompleteFiles;
|
|
|
|
|
for (const FilePath& path : storage->getIncompleteFiles())
|
|
|
|
|
{
|
|
|
|
|
if (info.filesToClear.find(path) == info.filesToClear.end())
|
|
|
|
|
const std::set<FilePath> filesToClear = utility::concat(info.filesToClear, info.nonIndexedFilesToClear);
|
|
|
|
|
for (const FilePath& path : storage->getIncompleteFiles())
|
|
|
|
|
{
|
|
|
|
|
incompleteFiles.insert(path);
|
|
|
|
|
if (filesToClear.find(path) == filesToClear.end())
|
|
|
|
|
{
|
|
|
|
|
incompleteFiles.insert(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -188,24 +214,30 @@ bool RefreshInfoGenerator::didFileChange(const FileInfo& info, std::shared_ptr<c
|
|
|
|
|
FileInfo diskFileInfo = FileSystem::getFileInfoForPath(info.path);
|
|
|
|
|
if (diskFileInfo.lastWriteTime > info.lastWriteTime)
|
|
|
|
|
{
|
|
|
|
|
if (!storage->hasContentForFile(info.path))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<TextAccess> storedFileContent = storage->getFileContent(info.path);
|
|
|
|
|
std::shared_ptr<TextAccess> diskFileContent = TextAccess::createFromFile(diskFileInfo.path);
|
|
|
|
|
|
|
|
|
|
const std::vector<std::string>& diskFileLines = diskFileContent->getAllLines();
|
|
|
|
|
const std::vector<std::string>& storedFileLines = storedFileContent->getAllLines();
|
|
|
|
|
|
|
|
|
|
if (diskFileLines.size() == storedFileLines.size())
|
|
|
|
|
if (diskFileLines.size() != storedFileLines.size())
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < diskFileLines.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (diskFileLines[i] != storedFileLines[i])
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < diskFileLines.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (diskFileLines[i] != storedFileLines[i])
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|