You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.3 KiB
217 lines
6.3 KiB
/*
|
|
* Copyright (C) 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "host/libs/config/fetcher_config.h"
|
|
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "android-base/logging.h"
|
|
#include "android-base/strings.h"
|
|
#include "gflags/gflags.h"
|
|
#include "json/json.h"
|
|
|
|
#include "common/libs/utils/files.h"
|
|
|
|
namespace cuttlefish {
|
|
|
|
namespace {
|
|
|
|
const char* kFlags = "flags";
|
|
const char* kCvdFiles = "cvd_files";
|
|
const char* kCvdFileSource = "source";
|
|
const char* kCvdFileBuildId = "build_id";
|
|
const char* kCvdFileBuildTarget = "build_target";
|
|
|
|
FileSource SourceStringToEnum(std::string source) {
|
|
for (auto& c : source) {
|
|
c = std::tolower(c);
|
|
}
|
|
if (source == "default_build") {
|
|
return FileSource::DEFAULT_BUILD;
|
|
} else if (source == "system_build") {
|
|
return FileSource::SYSTEM_BUILD;
|
|
} else if (source == "kernel_build") {
|
|
return FileSource::KERNEL_BUILD;
|
|
} else if (source == "local_file") {
|
|
return FileSource::LOCAL_FILE;
|
|
} else if (source == "generated") {
|
|
return FileSource::GENERATED;
|
|
} else {
|
|
return FileSource::UNKNOWN_PURPOSE;
|
|
}
|
|
}
|
|
|
|
std::string SourceEnumToString(const FileSource& source) {
|
|
if (source == FileSource::DEFAULT_BUILD) {
|
|
return "default_build";
|
|
} else if (source == FileSource::SYSTEM_BUILD) {
|
|
return "system_build";
|
|
} else if (source == FileSource::KERNEL_BUILD) {
|
|
return "kernel_build";
|
|
} else if (source == FileSource::LOCAL_FILE) {
|
|
return "local_file";
|
|
} else if (source == FileSource::GENERATED) {
|
|
return "generated";
|
|
} else {
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
CvdFile::CvdFile() {
|
|
}
|
|
|
|
CvdFile::CvdFile(const FileSource& source, const std::string& build_id,
|
|
const std::string& build_target, const std::string& file_path)
|
|
: source(source), build_id(build_id), build_target(build_target), file_path(file_path) {
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const CvdFile& cvd_file) {
|
|
os << "CvdFile(";
|
|
os << "source = " << SourceEnumToString(cvd_file.source) << ", ";
|
|
os << "build_id = " << cvd_file.build_id << ", ";
|
|
os << "build_target = " << cvd_file.build_target << ", ";
|
|
os << "file_path = " << cvd_file.file_path << ")";
|
|
return os;
|
|
}
|
|
|
|
FetcherConfig::FetcherConfig() : dictionary_(new Json::Value()) {
|
|
}
|
|
|
|
FetcherConfig::FetcherConfig(FetcherConfig&&) = default;
|
|
|
|
FetcherConfig::~FetcherConfig() {
|
|
}
|
|
|
|
bool FetcherConfig::SaveToFile(const std::string& file) const {
|
|
std::ofstream ofs(file);
|
|
if (!ofs.is_open()) {
|
|
LOG(ERROR) << "Unable to write to file " << file;
|
|
return false;
|
|
}
|
|
ofs << *dictionary_;
|
|
return !ofs.fail();
|
|
}
|
|
|
|
bool FetcherConfig::LoadFromFile(const std::string& file) {
|
|
auto real_file_path = AbsolutePath(file);
|
|
if (real_file_path.empty()) {
|
|
LOG(ERROR) << "Could not get real path for file " << file;
|
|
return false;
|
|
}
|
|
Json::CharReaderBuilder builder;
|
|
std::ifstream ifs(real_file_path);
|
|
std::string errorMessage;
|
|
if (!Json::parseFromStream(builder, ifs, dictionary_.get(), &errorMessage)) {
|
|
LOG(ERROR) << "Could not read config file " << file << ": " << errorMessage;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void FetcherConfig::RecordFlags() {
|
|
std::vector<gflags::CommandLineFlagInfo> all_flags;
|
|
GetAllFlags(&all_flags);
|
|
Json::Value flags_json(Json::arrayValue);
|
|
for (const auto& flag : all_flags) {
|
|
Json::Value flag_json;
|
|
flag_json["name"] = flag.name;
|
|
flag_json["type"] = flag.type;
|
|
flag_json["description"] = flag.description;
|
|
flag_json["current_value"] = flag.current_value;
|
|
flag_json["default_value"] = flag.default_value;
|
|
flag_json["filename"] = flag.filename;
|
|
flag_json["has_validator_fn"] = flag.has_validator_fn;
|
|
flag_json["is_default"] = flag.is_default;
|
|
flags_json.append(flag_json);
|
|
}
|
|
(*dictionary_)[kFlags] = flags_json;
|
|
}
|
|
|
|
namespace {
|
|
|
|
CvdFile JsonToCvdFile(const std::string& file_path, const Json::Value& json) {
|
|
CvdFile cvd_file;
|
|
cvd_file.file_path = file_path;
|
|
if (json.isMember(kCvdFileSource)) {
|
|
cvd_file.source = SourceStringToEnum(json[kCvdFileSource].asString());
|
|
} else {
|
|
cvd_file.source = UNKNOWN_PURPOSE;
|
|
}
|
|
if (json.isMember(kCvdFileBuildId)) {
|
|
cvd_file.build_id = json[kCvdFileBuildId].asString();
|
|
}
|
|
if (json.isMember(kCvdFileBuildTarget)) {
|
|
cvd_file.build_target = json[kCvdFileBuildTarget].asString();
|
|
}
|
|
return cvd_file;
|
|
}
|
|
|
|
Json::Value CvdFileToJson(const CvdFile& cvd_file) {
|
|
Json::Value json;
|
|
json[kCvdFileSource] = SourceEnumToString(cvd_file.source);
|
|
json[kCvdFileBuildId] = cvd_file.build_id;
|
|
json[kCvdFileBuildTarget] = cvd_file.build_target;
|
|
return json;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool FetcherConfig::add_cvd_file(const CvdFile& file, bool override_entry) {
|
|
if (!dictionary_->isMember(kCvdFiles)) {
|
|
Json::Value files_json(Json::objectValue);
|
|
(*dictionary_)[kCvdFiles] = files_json;
|
|
}
|
|
if ((*dictionary_)[kCvdFiles].isMember(file.file_path) && !override_entry) {
|
|
return false;
|
|
}
|
|
(*dictionary_)[kCvdFiles][file.file_path] = CvdFileToJson(file);
|
|
return true;
|
|
}
|
|
|
|
std::map<std::string, CvdFile> FetcherConfig::get_cvd_files() const {
|
|
if (!dictionary_->isMember(kCvdFiles)) {
|
|
return {};
|
|
}
|
|
std::map<std::string, CvdFile> files;
|
|
const auto& json_files = (*dictionary_)[kCvdFiles];
|
|
for (auto it = json_files.begin(); it != json_files.end(); it++) {
|
|
files[it.key().asString()] = JsonToCvdFile(it.key().asString(), *it);
|
|
}
|
|
return files;
|
|
}
|
|
|
|
std::string FetcherConfig::FindCvdFileWithSuffix(const std::string& suffix) const {
|
|
if (!dictionary_->isMember(kCvdFiles)) {
|
|
return {};
|
|
}
|
|
const auto& json_files = (*dictionary_)[kCvdFiles];
|
|
for (auto it = json_files.begin(); it != json_files.end(); it++) {
|
|
const auto& file = it.key().asString();
|
|
if (android::base::EndsWith(file, suffix)) {
|
|
return file;
|
|
}
|
|
}
|
|
LOG(DEBUG) << "Could not find file ending in " << suffix;
|
|
return "";
|
|
}
|
|
|
|
} // namespace cuttlefish
|