Make sure file exists before importing it.

This commit is contained in:
Jacob Dufault 2017-08-15 22:39:50 -07:00
parent 49aca3038b
commit 7901653698
6 changed files with 58 additions and 24 deletions

View File

@ -818,6 +818,12 @@ struct IndexManager {
//} // namespace
enum class FileParseState {
NeedsParse,
DoesNotNeedParse,
BadFile
};
std::vector<Index_DoIdMap> DoParseFile(
Config* config,
clang::Index* index,
@ -832,22 +838,31 @@ std::vector<Index_DoIdMap> DoParseFile(
if (previous_index) {
// If none of the dependencies have changed, skip parsing and just load from cache.
auto file_needs_parse = [&](const std::string& path) {
int64_t modification_timestamp = GetLastModificationTime(path);
optional<int64_t> modification_timestamp = GetLastModificationTime(path);
if (!modification_timestamp)
return FileParseState::BadFile;
optional<int64_t> last_cached_modification = timestamp_manager->GetLastCachedModificationTime(cache_loader, path);
if (!last_cached_modification || modification_timestamp != *last_cached_modification) {
file_consumer_shared->Reset(path);
return true;
return FileParseState::NeedsParse;
}
return false;
return FileParseState::DoesNotNeedParse;
};
// Check timestamps and update |file_consumer_shared|.
bool needs_reparse = file_needs_parse(path);
bool needs_reparse = false;
FileParseState path_state = file_needs_parse(path);
if (path_state == FileParseState::BadFile)
return result;
if (path_state == FileParseState::NeedsParse)
needs_reparse = true;
for (const std::string& dependency : previous_index->dependencies) {
assert(!dependency.empty());
if (file_needs_parse(dependency)) {
if (file_needs_parse(dependency) == FileParseState::NeedsParse) {
LOG_S(INFO) << "Timestamp has changed for " << dependency;
needs_reparse = true;
// SUBTLE: Do not break here, as |file_consumer_shared| is updated
@ -890,6 +905,7 @@ std::vector<Index_DoIdMap> DoParseFile(
// TODO: We might be able to optimize perf by only copying for files in
// working_files. We can pass that same set of files to the indexer as
// well. We then default to a fast file-copy if not in working set.
bool loaded_primary = false;
std::vector<FileContents> file_contents;
for (const auto& it : cache_loader->caches) {
const std::unique_ptr<IndexFile>& index = it.second;
@ -900,6 +916,16 @@ std::vector<Index_DoIdMap> DoParseFile(
continue;
}
file_contents.push_back(FileContents(index->path, *index_content));
loaded_primary = loaded_primary || index->path == path;
}
if (!loaded_primary) {
optional<std::string> content = ReadContent(path);
if (!content) {
LOG_S(ERROR) << "Skipping index (file cannot be found): " << path;
return result;
}
file_contents.push_back(FileContents(path, *content));
}
PerformanceImportFile perf;

View File

@ -128,7 +128,10 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
param->seen_files.push_back(file_name);
// Set modification time.
param->file_modification_times[file_name] = GetLastModificationTime(file_name);
optional<int64_t> modification_time = GetLastModificationTime(file_name);
LOG_IF_S(ERROR, !modification_time) << "Failed fetching modification time for " << file_name;
if (modification_time)
param->file_modification_times[file_name] = *modification_time;
// Capture file contents in |param->file_contents| if it was not specified
// at the start of indexing.

View File

@ -1,9 +1,14 @@
#pragma once
#include <optional.h>
#include <memory>
#include <string>
#include <vector>
using std::experimental::optional;
using std::experimental::nullopt;
struct PlatformMutex {
virtual ~PlatformMutex();
};
@ -37,7 +42,7 @@ bool TryMakeDirectory(const std::string& absolute_path);
void SetCurrentThreadName(const std::string& thread_name);
int64_t GetLastModificationTime(const std::string& absolute_path);
optional<int64_t> GetLastModificationTime(const std::string& absolute_path);
void MoveFileTo(const std::string& destination, const std::string& source);
void CopyFileTo(const std::string& destination, const std::string& source);

View File

@ -166,20 +166,20 @@ void SetCurrentThreadName(const std::string& thread_name) {
#endif
}
int64_t GetLastModificationTime(const std::string& absolute_path) {
optional<int64_t> GetLastModificationTime(const std::string& absolute_path) {
struct stat buf;
if (stat(absolute_path.c_str(), &buf) != 0) {
switch (errno) {
case ENOENT:
std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl;
break;
//std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl;
return nullopt;
case EINVAL:
std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl;
break;
//std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl;
return nullopt;
default:
std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl;
exit(1);
break;
//std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl;
//exit(1);
return nullopt;
}
}

View File

@ -184,20 +184,20 @@ void SetCurrentThreadName(const std::string& thread_name) {
__except (EXCEPTION_EXECUTE_HANDLER) {}
}
int64_t GetLastModificationTime(const std::string& absolute_path) {
optional<int64_t> GetLastModificationTime(const std::string& absolute_path) {
struct _stat buf;
if (_stat(absolute_path.c_str(), &buf) != 0) {
switch (errno) {
case ENOENT:
std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl;
break;
//std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl;
return nullopt;
case EINVAL:
std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl;
break;
//std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl;
return nullopt;
default:
std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl;
exit(1);
break;
//std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl;
//exit(1);
return nullopt;
}
}

View File

@ -305,7 +305,7 @@ QueryVarId GetQueryVarIdFromUsr(QueryDatabase* query_db, const Usr& usr) {
IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
: local_ids(local_ids) {
LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file;
//LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file;
primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file);
cached_type_ids_.resize(local_ids.type_id_to_usr.size());