| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/developer/debug/zxdb/client/source_file_provider_impl.h" | |
| #include <lib/syslog/cpp/macros.h> | |
| #include <limits> | |
| #include "src/developer/debug/zxdb/client/setting_schema_definition.h" | |
| #include "src/developer/debug/zxdb/client/target.h" | |
| #include "src/developer/debug/zxdb/common/file_util.h" | |
| #include "src/lib/files/file.h" | |
| namespace zxdb { | |
| SourceFileProviderImpl::SourceFileProviderImpl(std::vector<std::string> build_dirs) | |
| : build_dir_prefs_(std::move(build_dirs)) {} | |
| SourceFileProviderImpl::SourceFileProviderImpl(const SettingStore& settings) | |
| : build_dir_prefs_(settings.GetList(ClientSettings::Target::kBuildDirs)) {} | |
| ErrOr<SourceFileProvider::FileData> SourceFileProviderImpl::GetFileData( | |
| const std::string& file_name, const std::string& file_build_dir) const { | |
| std::string contents; | |
| // Search for the source file. If it's relative, try to find it relative to the build dir, and if | |
| // that doesn't exist, try relative to the current directory). | |
| if (IsPathAbsolute(file_name)) { | |
| // Absolute path, expect it to be readable or fail. | |
| if (files::ReadFileToString(file_name, &contents)) | |
| return FileData(std::move(contents), file_name, GetFileModificationTime(file_name)); | |
| return Err("Source file not found: " + file_name); | |
| } | |
| // Search the build directory preferences in order. | |
| for (const auto& cur : build_dir_prefs_) { | |
| std::string cur_path = CatPathComponents(cur, file_name); | |
| if (files::ReadFileToString(cur_path, &contents)) | |
| return FileData(std::move(contents), cur_path, GetFileModificationTime(cur_path)); | |
| } | |
| // Try to find relative to the build directory given in the symbols. | |
| if (!file_build_dir.empty()) { | |
| if (!IsPathAbsolute(file_build_dir)) { | |
| // Relative build directory. | |
| // | |
| // Try to apply the prefs combined with the file build directory. As of this writing the | |
| // Fuchsia build produces relative build directories from the symbols. This normally maps back | |
| // to the same place as the preference but will be different when shelling out to the separate | |
| // Zircon build). Even when we fix the multiple build mess in Fuchsia, this relative directory | |
| // feature can be useful for projects building in different parts. | |
| for (const auto& cur : build_dir_prefs_) { | |
| std::string cur_path = CatPathComponents(cur, CatPathComponents(file_build_dir, file_name)); | |
| if (files::ReadFileToString(cur_path, &contents)) | |
| return FileData(std::move(contents), cur_path, GetFileModificationTime(cur_path)); | |
| } | |
| } | |
| // Try to find relative to the file build dir. Even do this if the file build dir is relative to | |
| // search relative to the current working directory. | |
| std::string cur_path = CatPathComponents(file_build_dir, file_name); | |
| if (files::ReadFileToString(cur_path, &contents)) | |
| return FileData(std::move(contents), cur_path, GetFileModificationTime(cur_path)); | |
| } | |
| // Fall back on reading relative to the working directory. | |
| if (files::ReadFileToString(file_name, &contents)) | |
| return FileData(std::move(contents), file_name, GetFileModificationTime(file_name)); | |
| return Err("Source file not found: " + file_name); | |
| } | |
| } // namespace zxdb |