Add command line parser for simulator

Add a command line parser. Also add the support to parse the oem
property file and skip certain functions.

Bug: 131911365
Test: run simulator for wear builds
Change-Id: Ide306b53d3f42b29c02279969aeb18bec4045d6f
This commit is contained in:
Tianjie Xu 2019-07-15 16:13:49 -07:00
parent fc2ad88770
commit 7efd23338a
3 changed files with 97 additions and 10 deletions

View file

@ -51,9 +51,18 @@ class BuildInfo {
// Parses the given target-file, initializes the build properties and extracts the images.
bool ParseTargetFile(const std::string_view target_file_path, bool extracted_input);
std::string GetOemSettings() const {
return oem_settings_;
}
void SetOemSettings(const std::string_view oem_settings) {
oem_settings_ = oem_settings;
}
private:
// A map to store the system properties during simulation.
std::map<std::string, std::string, std::less<>> build_props_;
// A file that contains the oem properties.
std::string oem_settings_;
// A map from the blockdev_name to the FakeBlockDevice object, which contains the path to the
// temporary file.
std::map<std::string, FakeBlockDevice, std::less<>> blockdev_map_;

View file

@ -87,7 +87,11 @@ int SimulatorRuntime::WipeBlockDevice(const std::string_view filename, size_t /*
}
bool SimulatorRuntime::ReadFileToString(const std::string_view filename,
std::string* /* content */) const {
std::string* content) const {
if (android::base::EndsWith(filename, "oem.prop")) {
return android::base::ReadFileToString(source_->GetOemSettings(), content);
}
LOG(INFO) << "SKip reading filename " << filename;
return true;
}

View file

@ -14,11 +14,18 @@
* limitations under the License.
*/
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <string_view>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include "edify/expr.h"
#include "otautil/error_code.h"
#include "otautil/paths.h"
#include "updater/blockimg.h"
@ -28,21 +35,67 @@
#include "updater/simulator_runtime.h"
#include "updater/updater.h"
using namespace std::string_literals;
void Usage(std::string_view name) {
LOG(INFO) << "Usage: " << name << "[--oem_settings <oem_property_file>]"
<< "[--skip_functions <skip_function_file>]"
<< " --source <source_target_file>"
<< " --ota_package <ota_package>";
}
Value* SimulatorPlaceHolderFn(const char* name, State* /* state */,
const std::vector<std::unique_ptr<Expr>>& /* argv */) {
LOG(INFO) << "Skip function " << name << " in host simulation";
return StringValue("t");
}
int main(int argc, char** argv) {
// Write the logs to stdout.
android::base::InitLogging(argv, &android::base::StderrLogger);
if (argc != 3 && argc != 4) {
LOG(ERROR) << "unexpected number of arguments: " << argc << std::endl
<< "Usage: " << argv[0] << " <source_target-file> <ota_package>";
return EXIT_FAILURE;
std::string oem_settings;
std::string skip_function_file;
std::string source_target_file;
std::string package_name;
constexpr struct option OPTIONS[] = {
{ "oem_settings", required_argument, nullptr, 0 },
{ "ota_package", required_argument, nullptr, 0 },
{ "skip_functions", required_argument, nullptr, 0 },
{ "source", required_argument, nullptr, 0 },
{ nullptr, 0, nullptr, 0 },
};
int arg;
int option_index;
while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) {
if (arg != 0) {
LOG(ERROR) << "Invalid command argument";
Usage(argv[0]);
return EXIT_FAILURE;
}
auto option_name = OPTIONS[option_index].name;
// The same oem property file used during OTA generation. It's needed for file_getprop() to
// return the correct value for the source build.
if (option_name == "oem_settings"s) {
oem_settings = optarg;
} else if (option_name == "skip_functions"s) {
skip_function_file = optarg;
} else if (option_name == "source"s) {
source_target_file = optarg;
} else if (option_name == "ota_package"s) {
package_name = optarg;
} else {
Usage(argv[0]);
return EXIT_FAILURE;
}
}
// TODO(xunchang) implement a commandline parser, e.g. it can take an oem property so that the
// file_getprop() will return correct value.
std::string source_target_file = argv[1];
std::string package_name = argv[2];
if (source_target_file.empty() || package_name.empty()) {
Usage(argv[0]);
return EXIT_FAILURE;
}
// Configure edify's functions.
RegisterBuiltins();
@ -50,6 +103,22 @@ int main(int argc, char** argv) {
RegisterBlockImageFunctions();
RegisterDynamicPartitionsFunctions();
if (!skip_function_file.empty()) {
std::string content;
if (!android::base::ReadFileToString(skip_function_file, &content)) {
PLOG(ERROR) << "Failed to read " << skip_function_file;
return EXIT_FAILURE;
}
auto lines = android::base::Split(content, "\n");
for (const auto& line : lines) {
if (line.empty() || android::base::StartsWith(line, "#")) {
continue;
}
RegisterFunction(line, SimulatorPlaceHolderFn);
}
}
TemporaryFile temp_saved_source;
TemporaryFile temp_last_command;
TemporaryDir temp_stash_base;
@ -67,6 +136,11 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
if (!oem_settings.empty()) {
CHECK_EQ(0, access(oem_settings.c_str(), R_OK));
source_build_info.SetOemSettings(oem_settings);
}
Updater updater(std::make_unique<SimulatorRuntime>(&source_build_info));
if (!updater.Init(cmd_pipe.release(), package_name, false)) {
return EXIT_FAILURE;