|
39 | 39 | #include "common/libs/utils/environment.h"
|
40 | 40 | #include "common/libs/utils/files.h"
|
41 | 41 | #include "common/libs/utils/result.h"
|
| 42 | +#include "cuttlefish/host/commands/cvd/fetch/host_pkg_migration.pb.h" |
42 | 43 | #include "host/commands/cvd/fetch/fetch_cvd_parser.h"
|
43 | 44 | #include "host/commands/cvd/fetch/fetch_tracer.h"
|
44 | 45 | #include "host/commands/cvd/utils/common.h"
|
|
55 | 56 | #include "host/libs/web/luci_build_api.h"
|
56 | 57 | #include "host/libs/web/oauth2_consent.h"
|
57 | 58 |
|
| 59 | +#include <google/protobuf/text_format.h> |
| 60 | + |
58 | 61 | #ifndef BAZEL_CURRENT_REPOSITORY
|
59 | 62 | #define BAZEL_CURRENT_REPOSITORY ""
|
60 | 63 | #endif
|
@@ -303,40 +306,10 @@ Result<void> EnsureDirectoriesExist(const std::string& host_tools_directory,
|
303 | 306 |
|
304 | 307 | static constexpr std::string_view kInstallDir = "/usr/lib/cuttlefish-common/bin";
|
305 | 308 |
|
306 |
| -Result<void> FetchHostPackage( |
307 |
| - BuildApi& build_api, const Build& build, const std::string& target_dir, |
308 |
| - const bool keep_archives, |
309 |
| - std::vector<std::string> debian_package_executables, |
310 |
| - FetchTracer::Trace trace) { |
311 |
| - LOG(INFO) << "Preparing host package for " << build; |
312 |
| - // This function is called asynchronously, so it may take a while to start. |
313 |
| - // Complete a phase here to ensure that delay is not counted in the download |
314 |
| - // time. |
315 |
| - // The download time will still include time spent waiting for the mutex in |
316 |
| - // the build_api though. |
317 |
| - trace.CompletePhase("Async start delay"); |
318 |
| - auto host_tools_name = GetFilepath(build).value_or("cvd-host_package.tar.gz"); |
319 |
| - std::string host_tools_filepath = |
320 |
| - CF_EXPECT(build_api.DownloadFile(build, target_dir, host_tools_name)); |
321 |
| - trace.CompletePhase("Download", FileSize(host_tools_filepath)); |
322 |
| - |
323 |
| - CF_EXPECT( |
324 |
| - ExtractArchiveContents(host_tools_filepath, target_dir, keep_archives)); |
325 |
| - trace.CompletePhase("Extract"); |
326 |
| - |
| 309 | +Result<void> SubstituteWithFlag(const std::string& target_dir, const std::vector<std::string>& debian_package_executables) { |
327 | 310 | std::string self_path;
|
328 | 311 | CF_EXPECT(android::base::Readlink("/proc/self/exe", &self_path));
|
329 | 312 | bool is_installed_cvd = self_path == fmt::format("{}/cvd", kInstallDir);
|
330 |
| - |
331 |
| - std::string sub_file = target_dir + "/etc/debian_substitution_marker"; |
332 |
| - if (debian_package_executables.empty() && FileExists(sub_file)) { |
333 |
| - std::string sub_file_contents; |
334 |
| - CF_EXPECTF(android::base::ReadFileToString(sub_file, &sub_file_contents), |
335 |
| - "failed to read '{}'", sub_file); |
336 |
| - sub_file_contents = android::base::Trim(sub_file_contents); |
337 |
| - debian_package_executables = android::base::Tokenize(sub_file_contents, "\n"); |
338 |
| - } |
339 |
| - |
340 | 313 | std::string runfiles_error;
|
341 | 314 | std::unique_ptr<Runfiles> runfiles;
|
342 | 315 | if (!debian_package_executables.empty() && !is_installed_cvd) {
|
@@ -375,6 +348,63 @@ Result<void> FetchHostPackage(
|
375 | 348 | CF_EXPECTF(unlink(to_substitute.c_str()) == 0, "{}", strerror(errno));
|
376 | 349 | CF_EXPECT(CreateSymLink(source, to_substitute));
|
377 | 350 | }
|
| 351 | + return {}; |
| 352 | +} |
| 353 | + |
| 354 | +Result<void> SubstituteWithMarker(const std::string& target_dir, const std::string& marker_file) { |
| 355 | + std::string content; |
| 356 | + CF_EXPECTF(android::base::ReadFileToString(marker_file, &content), |
| 357 | + "failed to read '{}'", marker_file); |
| 358 | + fetch::HostPkgMigrationConfig config; |
| 359 | + CF_EXPECT(google::protobuf::TextFormat::ParseFromString(content, &config), "failed parsing debian_substitution_marker file"); |
| 360 | + for (int j = 0; j < config.symlinks_size(); j++) { |
| 361 | + const fetch::Symlink& symlink = config.symlinks(j); |
| 362 | + std::string full_link_name = |
| 363 | + fmt::format("{}/{}", target_dir, symlink.link_name()); |
| 364 | + // TODO: schuffelen - relax this check after migration completes |
| 365 | + CF_EXPECTF(FileExists(full_link_name), |
| 366 | + "Cannot substitute '{}', does not exist", full_link_name); |
| 367 | + CF_EXPECTF(unlink(full_link_name.c_str()) == 0, "{}", strerror(errno)); |
| 368 | + CF_EXPECT(CreateSymLink(symlink.target(), full_link_name)); |
| 369 | + } |
| 370 | + return {}; |
| 371 | +} |
| 372 | + |
| 373 | +Result<void> FetchHostPackage( |
| 374 | + BuildApi& build_api, const Build& build, const std::string& target_dir, |
| 375 | + const bool keep_archives, |
| 376 | + std::vector<std::string> debian_package_executables, |
| 377 | + FetchTracer::Trace trace) { |
| 378 | + LOG(INFO) << "Preparing host package for " << build; |
| 379 | + // This function is called asynchronously, so it may take a while to start. |
| 380 | + // Complete a phase here to ensure that delay is not counted in the download |
| 381 | + // time. |
| 382 | + // The download time will still include time spent waiting for the mutex in |
| 383 | + // the build_api though. |
| 384 | + trace.CompletePhase("Async start delay"); |
| 385 | + auto host_tools_name = GetFilepath(build).value_or("cvd-host_package.tar.gz"); |
| 386 | + std::string host_tools_filepath = |
| 387 | + CF_EXPECT(build_api.DownloadFile(build, target_dir, host_tools_name)); |
| 388 | + trace.CompletePhase("Download", FileSize(host_tools_filepath)); |
| 389 | + |
| 390 | + CF_EXPECT( |
| 391 | + ExtractArchiveContents(host_tools_filepath, target_dir, keep_archives)); |
| 392 | + trace.CompletePhase("Extract"); |
| 393 | + |
| 394 | + std::string marker_file = target_dir + "/etc/debian_substitution_marker"; |
| 395 | + // Use a local debian_substitution_marker file for development purposes. |
| 396 | + std::optional<std::string> local_marker_file = StringFromEnv("LOCAL_DEBIAN_SUBSTITUTION_MARKER_FILE"); |
| 397 | + if (local_marker_file.has_value()) { |
| 398 | + marker_file = local_marker_file.value(); |
| 399 | + CF_EXPECTF(FileExists(marker_file), "local debian substitution marker file does not exist: {}", marker_file); |
| 400 | + LOG(INFO) << "using local debian substitution marker file: " << marker_file; |
| 401 | + } |
| 402 | + |
| 403 | + if (debian_package_executables.empty() && FileExists(marker_file)) { |
| 404 | + CF_EXPECT(SubstituteWithMarker(target_dir, marker_file)); |
| 405 | + } else { |
| 406 | + CF_EXPECT(SubstituteWithFlag(target_dir, debian_package_executables)); |
| 407 | + } |
378 | 408 | trace.CompletePhase("Substitute");
|
379 | 409 | return {};
|
380 | 410 | }
|
@@ -1034,6 +1064,7 @@ std::string GetFetchLogsFileName(const std::string& target_directory) {
|
1034 | 1064 | }
|
1035 | 1065 |
|
1036 | 1066 | Result<void> FetchCvdMain(const FetchFlags& flags) {
|
| 1067 | + GOOGLE_PROTOBUF_VERIFY_VERSION; |
1037 | 1068 | const bool append_subdirectory = ShouldAppendSubdirectory(flags);
|
1038 | 1069 | std::vector<Target> targets = GetFetchTargets(flags, append_subdirectory);
|
1039 | 1070 | HostToolsTarget host_target = GetHostToolsTarget(flags, append_subdirectory);
|
|
0 commit comments