From ca6efc1d4560f1811fbef48668ee8bd51e9118cb Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 7 Aug 2020 16:38:48 +0200 Subject: [PATCH] Add --trust_install_base option This will allow Bazel client to run individually without the appended zip archive, which is a requirement for Debian installation. The following changes are made: - Add --trust_install_base option. When this is enabled. Bazel client trusts the install base provided by --install_base option and skip the step of verifying the install directory. We need it because the Bazel client alone doesn't contain information to verify the install directory. - Reimplement --version as a actual Bazel startup flag. The version info is read from the zip archive, but when --trust_install_base is enabled it should be read from the given install base. Related: https://github.com/bazelbuild/bazel/issues/9408 Fixes: https://github.com/bazelbuild/bazel/issues/11842 --- src/main/cpp/blaze.cc | 66 ++++++++++++++++++++++++++++----- src/main/cpp/startup_options.cc | 8 +++- src/main/cpp/startup_options.h | 9 +++++ 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc index 19a399520e9243..4050cb8776537f 100644 --- a/src/main/cpp/blaze.cc +++ b/src/main/cpp/blaze.cc @@ -1007,6 +1007,10 @@ static DurationMillis ExtractData(const string &self_path, << "install base directory '" << install_base << "' could not be created. It exists but is not a directory."; } + // If --trust_install_base is true, we skip the following checks. + if (startup_options.trust_install_base) { + return DurationMillis(); + } blaze_util::Path install_dir(install_base); // Check that all files are present and have timestamps from BlessFiles(). std::unique_ptr mtime( @@ -1198,7 +1202,10 @@ static void EnsureCorrectRunningVersion(const StartupOptions &startup_options, // find install bases that haven't been used for a long time std::unique_ptr mtime( blaze_util::CreateFileMtime()); - if (!mtime->SetToNow(blaze_util::Path(startup_options.install_base))) { + // We skip touching the install base if --trust_install_base is enabled, + // because the provided install base might not be writable. + if (!startup_options.trust_install_base && + !mtime->SetToNow(blaze_util::Path(startup_options.install_base))) { string err = GetLastErrorString(); BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR) << "failed to set timestamp on '" << startup_options.install_base @@ -1486,9 +1493,20 @@ static int GetExitCodeForAbruptExit(const blaze_util::Path &output_base) { return custom_exit_code; } -void PrintVersionInfo(const string &self_path, const string &product_name) { +void PrintVersionInfo(const string &self_path, + const string &product_name, + const StartupOptions &startup_options) { string build_label; - ExtractBuildLabel(self_path, &build_label); + if (startup_options.trust_install_base) { + blaze_util::Path install_base(startup_options.install_base); + if (!blaze_util::ReadFile(install_base.GetRelative("build-label.txt"), &build_label)) { + BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR) + << "Cannot read build-label.txt file from install base: " + << install_base.AsPrintablePath(); + } + } else { + ExtractBuildLabel(self_path, &build_label); + } printf("%s %s\n", product_name.c_str(), build_label.c_str()); } @@ -1582,11 +1600,6 @@ int Main(int argc, const char *const *argv, WorkspaceLayout *workspace_layout, const string self_path = GetSelfPath(argv[0]); - if (argc == 2 && strcmp(argv[1], "--version") == 0) { - PrintVersionInfo(self_path, option_processor->GetLowercaseProductName()); - return blaze_exit_code::SUCCESS; - } - string cwd = GetCanonicalCwd(); LoggingInfo logging_info(CheckAndGetBinaryPath(cwd, argv[0]), start_time); @@ -1617,11 +1630,22 @@ int Main(int argc, const char *const *argv, WorkspaceLayout *workspace_layout, StartupOptions *startup_options = option_processor->GetParsedStartupOptions(); startup_options->MaybeLogStartupOptionWarnings(); + // Check --install_base is provided when --trust_install_base is enabled + if (startup_options->trust_install_base && startup_options->install_base.empty()) { + BAZEL_DIE(blaze_exit_code::BAD_ARGV) + << "--trust_install_base requires --install_base to be provided"; + } + SetDebugLog(startup_options->client_debug); // If client_debug was false, this is ignored, so it's accurate. BAZEL_LOG(INFO) << "Debug logging requested, sending all client log " "statements to stderr"; + if (startup_options->version) { + PrintVersionInfo(self_path, option_processor->GetLowercaseProductName(), *startup_options); + return blaze_exit_code::SUCCESS; + } + if (startup_options->unlimit_coredumps) { UnlimitCoredumps(); } @@ -1637,7 +1661,31 @@ int Main(int argc, const char *const *argv, WorkspaceLayout *workspace_layout, vector archive_contents; string install_md5; - DetermineArchiveContents(self_path, &archive_contents, &install_md5); + if (startup_options->trust_install_base) { + blaze_util::Path install_base(startup_options->install_base); + + // Read install_md5 value from /install_base_key + if (!blaze_util::ReadFile(install_base.GetRelative("install_base_key"), &install_md5)) { + BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR) + << "Cannot read install_base_key file from install base: " + << install_base.AsPrintablePath(); + } + + // Read all archive content entries and calculate the relative paths to install base. + blaze_util::GetAllFilesUnder(startup_options->install_base, &archive_contents); + std::size_t pos = install_base.AsNativePath().length() + 1; + for (int i = 0; i < archive_contents.size(); i++) { + blaze_util::Path entry(archive_contents[i]); + #if defined(_WIN32) || defined(__CYGWIN__) + archive_contents[i] = blaze_util::WstringToCstring(entry.AsNativePath().substr(pos)); + #else + archive_contents[i] = entry.AsNativePath().substr(pos); + #endif + } + std::sort(archive_contents.begin(), archive_contents.end()); + } else { + DetermineArchiveContents(self_path, &archive_contents, &install_md5); + } UpdateConfiguration(install_md5, workspace, IsServerMode(option_processor->GetCommand()), diff --git a/src/main/cpp/startup_options.cc b/src/main/cpp/startup_options.cc index f9b2fda40180ea..8f23c38093284e 100644 --- a/src/main/cpp/startup_options.cc +++ b/src/main/cpp/startup_options.cc @@ -96,7 +96,9 @@ StartupOptions::StartupOptions(const string &product_name, #endif unlimit_coredumps(false), incompatible_enable_execution_transition(false), - windows_enable_symlinks(false) { + windows_enable_symlinks(false), + version(false), + trust_install_base(false) { if (blaze::IsRunningWithinTest()) { output_root = blaze_util::MakeAbsolute(blaze::GetPathEnv("TEST_TMPDIR")); max_idle_secs = 15; @@ -147,6 +149,10 @@ StartupOptions::StartupOptions(const string &product_name, RegisterNullaryStartupFlag("write_command_log", &write_command_log); RegisterNullaryStartupFlag("windows_enable_symlinks", &windows_enable_symlinks); + RegisterNullaryStartupFlag("version", + &version); + RegisterNullaryStartupFlag("trust_install_base", + &trust_install_base); RegisterUnaryStartupFlag("command_port"); RegisterUnaryStartupFlag("connect_timeout_secs"); RegisterUnaryStartupFlag("digest_function"); diff --git a/src/main/cpp/startup_options.h b/src/main/cpp/startup_options.h index cc9ca667811b72..3a7efc7561fb4e 100644 --- a/src/main/cpp/startup_options.h +++ b/src/main/cpp/startup_options.h @@ -277,6 +277,15 @@ class StartupOptions { // developer mode to be enabled. bool windows_enable_symlinks; + // Whether to print version info and exit. + bool version; + + // Whether to trust the install base directory provided by --install_base + // and skip all the checks. This will allow running the Bazel client without + // appending the zip archive when a install base is available, eg. for Debian + // installation. + bool trust_install_base; + protected: // Constructor for subclasses only so that site-specific extensions of this // class can override the product name. The product_name must be the