Add test to ensure the blaze archive is not extracted if the `install_base` already exists.

Move `ExtractData` and associated data structures to `archive_utils`.

PiperOrigin-RevId: 535333531
Change-Id: Ia2b7112b86cda1126948121b89b09718ec689142
diff --git a/src/main/cpp/archive_utils.h b/src/main/cpp/archive_utils.h
index e74ae67..18856ab 100644
--- a/src/main/cpp/archive_utils.h
+++ b/src/main/cpp/archive_utils.h
@@ -18,6 +18,9 @@
 #include <string>
 #include <vector>
 
+#include "src/main/cpp/startup_options.h"
+#include "src/main/cpp/util/logging.h"
+
 namespace blaze {
 
 // Determines the contents of the archive, storing the names of the contained
@@ -26,6 +29,77 @@
                               std::vector<std::string> *files,
                               std::string *install_md5);
 
+struct DurationMillis {
+ public:
+  const uint64_t millis;
+
+  DurationMillis() : millis(kUnknownDuration) {}
+  DurationMillis(const uint64_t ms) : millis(ms) {}
+
+  bool IsUnknown() const { return millis == kUnknownDuration; }
+
+ private:
+  // Value representing that a timing event never occurred or is unknown.
+  static constexpr uint64_t kUnknownDuration = 0;
+};
+
+// DurationMillis that tracks if an archive was extracted.
+struct ExtractionDurationMillis : DurationMillis {
+  const bool archive_extracted;
+  ExtractionDurationMillis() : DurationMillis(), archive_extracted(false) {}
+  ExtractionDurationMillis(const uint64_t ms, const bool archive_extracted)
+      : DurationMillis(ms), archive_extracted(archive_extracted) {}
+};
+
+// The reason for a blaze server restart.
+// Keep in sync with logging.proto.
+enum RestartReason {
+  NO_RESTART = 0,
+  NO_DAEMON,
+  NEW_VERSION,
+  NEW_OPTIONS,
+  PID_FILE_BUT_NO_SERVER,
+  SERVER_VANISHED,
+  SERVER_UNRESPONSIVE
+};
+
+// Encapsulates miscellaneous information reported to the server for logging and
+// profiling purposes.
+struct LoggingInfo {
+ public:
+  explicit LoggingInfo(const std::string &binary_path_,
+                       const uint64_t start_time_ms_)
+      : binary_path(binary_path_),
+        start_time_ms(start_time_ms_),
+        restart_reason(NO_RESTART) {}
+
+  void SetRestartReasonIfNotSet(const RestartReason restart_reason_) {
+    if (restart_reason == NO_RESTART) {
+      restart_reason = restart_reason_;
+    }
+  }
+
+  // Path of this binary.
+  const std::string binary_path;
+
+  // The time in ms the binary started up, measured from approximately the time
+  // that "main" was called.
+  const uint64_t start_time_ms;
+
+  // The reason the server was restarted.
+  RestartReason restart_reason;
+};
+
+// Extracts the archive and ensures success via calls to ExtractArchiveOrDie and
+// BlessFiles. If the install base, the location the archive is unpacked,
+// already exists, extraction is skipped. Kills the client if an error is
+// encountered.
+ExtractionDurationMillis ExtractData(
+    const std::string &self_path,
+    const std::vector<std::string> &archive_contents,
+    const std::string &expected_install_md5,
+    const StartupOptions &startup_options, LoggingInfo *logging_info);
+
 // Extracts the embedded data files in `archive_path` into `output_dir`.
 // It's expected that `output_dir` already exists and that it's a directory.
 // Fails if `expected_install_md5` doesn't match that contained in the archive,