diff options
-rwxr-xr-x | bin/just-mr.py | 4 | ||||
-rw-r--r-- | src/buildtool/common/TARGETS | 3 | ||||
-rw-r--r-- | src/buildtool/common/cli.hpp | 10 | ||||
-rw-r--r-- | src/buildtool/compatibility/TARGETS | 8 | ||||
-rw-r--r-- | src/buildtool/compatibility/compatibility.hpp | 68 | ||||
-rw-r--r-- | src/buildtool/crypto/hash_generator.hpp | 16 | ||||
-rw-r--r-- | src/buildtool/execution_api/common/execution_common.hpp | 2 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/TARGETS | 3 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/config.hpp | 80 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/local_ac.hpp | 8 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/local_action.cpp | 2 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/local_cas.hpp | 11 | ||||
-rw-r--r-- | src/buildtool/execution_api/local/local_storage.hpp | 8 | ||||
-rw-r--r-- | src/buildtool/execution_engine/executor/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/execution_engine/executor/executor.hpp | 40 | ||||
-rw-r--r-- | src/buildtool/file_system/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/file_system/file_root.hpp | 8 | ||||
-rw-r--r-- | src/buildtool/main/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/main/main.cpp | 26 |
19 files changed, 228 insertions, 72 deletions
diff --git a/bin/just-mr.py b/bin/just-mr.py index 2c2a08b3..7b68eb19 100755 --- a/bin/just-mr.py +++ b/bin/just-mr.py @@ -188,7 +188,7 @@ def git_hash(content): def add_to_cas(data): if isinstance(data, str): data = data.encode('utf-8') - cas_root = os.path.join(ROOT,"casf") + cas_root = os.path.join(ROOT,"protocol-dependent/git-sha1/casf") basename = git_hash(data) target = os.path.join(cas_root, basename) tempname = os.path.join(cas_root, "%s.%d" % (basename, os.getpid())) @@ -205,7 +205,7 @@ def add_to_cas(data): return target def cas_path(h): - return os.path.join(ROOT, "casf", h) + return os.path.join(ROOT, "protocol-dependent/git-sha1/casf", h) def is_in_cas(h): return os.path.exists(cas_path(h)) diff --git a/src/buildtool/common/TARGETS b/src/buildtool/common/TARGETS index eec2b011..a9c1547f 100644 --- a/src/buildtool/common/TARGETS +++ b/src/buildtool/common/TARGETS @@ -3,7 +3,8 @@ , "name": ["cli"] , "hdrs": ["cli.hpp"] , "deps": - [ ["src/buildtool/logging", "log_level"] + [ ["src/buildtool/compatibility", "compatibility"] + , ["src/buildtool/logging", "log_level"] , ["@", "cli11", "", "cli11"] , ["@", "json", "", "json"] , ["@", "fmt", "", "fmt"] diff --git a/src/buildtool/common/cli.hpp b/src/buildtool/common/cli.hpp index 8bb0ec89..c00b7b1b 100644 --- a/src/buildtool/common/cli.hpp +++ b/src/buildtool/common/cli.hpp @@ -12,6 +12,7 @@ #include "fmt/core.h" #include "gsl-lite/gsl-lite.hpp" #include "nlohmann/json.hpp" +#include "src/buildtool/compatibility/compatibility.hpp" #include "src/buildtool/logging/log_level.hpp" constexpr auto kDefaultLogLevel = LogLevel::Progress; @@ -374,4 +375,13 @@ static inline auto SetupGraphArguments( "missing KNOWN artifacts."); } +static inline auto SetupCompatibilityArguments( + gsl::not_null<CLI::App*> const& app) { + app->add_flag_function( + "--compatible", + [](auto /*unused*/) { Compatibility::SetCompatible(); }, + "At increased computational effort, be compatible with the original " + "remote build execution protocol. As the change affects identifiers, " + "the flag must be used consistently for all related invocations."); +} #endif // INCLUDED_SRC_BUILDTOOL_COMMON_CLI_HPP diff --git a/src/buildtool/compatibility/TARGETS b/src/buildtool/compatibility/TARGETS new file mode 100644 index 00000000..277ca22b --- /dev/null +++ b/src/buildtool/compatibility/TARGETS @@ -0,0 +1,8 @@ +{ "compatibility": + { "type": ["@", "rules", "CC", "library"] + , "name": ["compatibility"] + , "hdrs": ["compatibility.hpp"] + , "deps": [["src/buildtool/crypto", "hash_generator"]] + , "stage": ["src", "buildtool", "compatibility"] + } +} diff --git a/src/buildtool/compatibility/compatibility.hpp b/src/buildtool/compatibility/compatibility.hpp new file mode 100644 index 00000000..271d590e --- /dev/null +++ b/src/buildtool/compatibility/compatibility.hpp @@ -0,0 +1,68 @@ +#ifndef INCLUDED_SRC_BUILDTOOL_COMPATIBILITY_COMPATIBILITY_HPP +#define INCLUDED_SRC_BUILDTOOL_COMPATIBILITY_COMPATIBILITY_HPP +#include <shared_mutex> +#include <unordered_map> +#include <utility> + +#include "src/buildtool/crypto/hash_generator.hpp" +#include "src/buildtool/logging/logger.hpp" +class Compatibility { + using git_hash = std::string; + using sha256_hash = std::string; + using git_repo = std::string; + using GitToComaptibleMap = std::unordered_map<git_hash, sha256_hash>; + using CompatibleToGitMap = + std::unordered_map<sha256_hash, std::pair<git_hash, git_repo>>; + + public: + [[nodiscard]] static auto Instance() noexcept -> Compatibility& { + static Compatibility instance{}; + return instance; + } + [[nodiscard]] static auto IsCompatible() noexcept -> bool { + return Instance().compatible_; + } + static void SetCompatible() noexcept { Instance().compatible_ = true; } + + static auto RegisterGitEntry(std::string const& git_hash, + std::string const& data, + std::string const& repo) -> sha256_hash { + + { + auto& git_to_compatible = Instance().git_to_compatible_; + std::shared_lock lock_{Instance().mutex_}; + auto it = git_to_compatible.find(git_hash); + if (it != git_to_compatible.end()) { + return it->second; + } + } + auto compatible_hash = ComputeHash(data); + std::unique_lock lock_{Instance().mutex_}; + Instance().git_to_compatible_[git_hash] = compatible_hash; + Instance().compatible_to_git_[compatible_hash] = {git_hash, repo}; + return compatible_hash; + } + + static auto GetGitEntry(std::string const& compatible_hash) + -> std::optional<std::pair<git_hash const&, git_repo const&>> { + auto const& compatible_to_git = Instance().compatible_to_git_; + std::shared_lock lock_{Instance().mutex_}; + auto it = compatible_to_git.find(compatible_hash); + if (it != compatible_to_git.end()) { + return it->second; + } + Logger::Log( + LogLevel::Warning, + fmt::format("Unable to get the git-sha1 code associated to {}", + compatible_hash)); + return std::nullopt; + } + + private: + GitToComaptibleMap git_to_compatible_{}; + + CompatibleToGitMap compatible_to_git_{}; + bool compatible_{false}; + std::shared_mutex mutex_; +}; +#endif // INCLUDED_SRC_BUILDTOOL_COMPATIBILITY_COMPATIBILITY_HPP diff --git a/src/buildtool/crypto/hash_generator.hpp b/src/buildtool/crypto/hash_generator.hpp index 7ff9e004..79d744fc 100644 --- a/src/buildtool/crypto/hash_generator.hpp +++ b/src/buildtool/crypto/hash_generator.hpp @@ -20,6 +20,19 @@ class HashGenerator { /// \brief Types of hash implementations supported by generator. enum class HashType { MD5, SHA1, SHA256, GIT }; + // this function is called for the first time from the main to initialize + // the HashGenerator according to the command line flag --compatible + // note that, once the HashGenerator is initialized, it cannot be changed + [[maybe_unused]] static auto SetHashGenerator( + std::optional<HashType> const x = std::nullopt) -> HashGenerator& { + static HashGenerator gen{x.value_or(HashType::GIT)}; + return gen; + } + [[nodiscard]] static auto Instance() -> HashGenerator& { + return SetHashGenerator(); // return the already initialized + // HashGenerator + } + /// \brief The universal hash digest. /// The type of hash and the digest length depends on the hash /// implementation used to generated this digest. @@ -123,8 +136,7 @@ class HashGenerator { /// \brief Hash function used for the entire buildtool [[maybe_unused]] [[nodiscard]] static inline auto ComputeHash( std::string const& data) noexcept -> std::string { - static HashGenerator gen{HashGenerator::HashType::GIT}; - return gen.Run(data).HexString(); + return HashGenerator::Instance().Run(data).HexString(); } #endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_GENERATOR_HPP diff --git a/src/buildtool/execution_api/common/execution_common.hpp b/src/buildtool/execution_api/common/execution_common.hpp index 1cf198fe..1208fc99 100644 --- a/src/buildtool/execution_api/common/execution_common.hpp +++ b/src/buildtool/execution_api/common/execution_common.hpp @@ -89,7 +89,7 @@ static void EncodeUUIDVariant1(std::string* uuid) { constexpr auto kHexDashPos = std::array{8UL, 12UL, 16UL, 20UL}; auto value = fmt::format("{}-{}", std::to_string(kRandomConstant), seed); - auto uuid = HashGenerator{HashGenerator::HashType::SHA1}.Run(value).Bytes(); + auto uuid = HashGenerator::Instance().Run(value).Bytes(); EncodeUUIDVersion4(&uuid); EncodeUUIDVariant1(&uuid); gsl_Expects(uuid.size() >= kRawLength); diff --git a/src/buildtool/execution_api/local/TARGETS b/src/buildtool/execution_api/local/TARGETS index b6d265a6..e395f7d2 100644 --- a/src/buildtool/execution_api/local/TARGETS +++ b/src/buildtool/execution_api/local/TARGETS @@ -3,7 +3,8 @@ , "name": ["config"] , "hdrs": ["config.hpp"] , "deps": - [ ["src/buildtool/logging", "logging"] + [ ["src/buildtool/compatibility", "compatibility"] + , ["src/buildtool/logging", "logging"] , ["src/buildtool/file_system", "file_system_manager"] ] , "stage": ["src", "buildtool", "execution_api", "local"] diff --git a/src/buildtool/execution_api/local/config.hpp b/src/buildtool/execution_api/local/config.hpp index 3f293b95..c65f7d17 100644 --- a/src/buildtool/execution_api/local/config.hpp +++ b/src/buildtool/execution_api/local/config.hpp @@ -14,20 +14,25 @@ #include <string> #include <vector> +#include "src/buildtool/compatibility/compatibility.hpp" #include "src/buildtool/file_system/file_system_manager.hpp" #include "src/buildtool/logging/logger.hpp" /// \brief Store global build system configuration. class LocalExecutionConfig { struct ConfigData { - // User root directory (Unix default: /home/${USER}) - std::filesystem::path user_root{}; - // Build root directory (default: empty) + // Build root directory. All the cache dirs are subdirs of build_root. + // By default, build_root is set to $HOME/.cache/just. + // If the user uses --local_build_root PATH, + // then build_root will be set to PATH. std::filesystem::path build_root{}; - // Disk cache directory (default: empty) - std::filesystem::path disk_cache{}; + // cache_root points to one of the following + // build_root/protocol-dependent/{git-sha1,compatible-sha256} + // git-sha1 is the current default. If the user passes the flag + // --compatible, then the subfolder compatible_sha256 is used + std::filesystem::path cache_root{}; // Launcher to be prepended to action's command before executed. // Default: ["env", "--"] @@ -37,6 +42,13 @@ class LocalExecutionConfig { bool keep_build_dir{false}; }; + // different folder for different caching protocol + [[nodiscard]] static auto UpdatePathForCompatibility( + std::filesystem::path const& dir) -> std::filesystem::path { + return dir / (Compatibility::IsCompatible() ? "compatible-sha256" + : "git-sha1"); + } + public: [[nodiscard]] static auto SetBuildRoot( std::filesystem::path const& dir) noexcept -> bool { @@ -47,18 +59,8 @@ class LocalExecutionConfig { return false; } Data().build_root = dir; - return true; - } - - [[nodiscard]] static auto SetDiskCache( - std::filesystem::path const& dir) noexcept -> bool { - if (FileSystemManager::IsRelativePath(dir)) { - Logger::Log(LogLevel::Error, - "Disk cache must be absolute path but got '{}'.", - dir.string()); - return false; - } - Data().disk_cache = dir; + Data().cache_root = ""; // in case we re-set build_root, we are sure + // that the cache path is recomputed as well return true; } @@ -83,29 +85,42 @@ class LocalExecutionConfig { /// \brief User directory. [[nodiscard]] static auto GetUserDir() noexcept -> std::filesystem::path { - auto& user_root = Data().user_root; - if (user_root.empty()) { - user_root = GetUserRoot() / ".cache" / "just"; - } - return user_root; + return GetUserHome() / ".cache" / "just"; } /// \brief Build directory, defaults to user directory if not set - [[nodiscard]] static auto GetBuildDir() noexcept -> std::filesystem::path { + [[nodiscard]] static auto BuildRoot() noexcept -> std::filesystem::path { auto& build_root = Data().build_root; if (build_root.empty()) { - return GetUserDir(); + build_root = GetUserDir(); } return build_root; } - /// \brief Cache directory, defaults to user directory if not set - [[nodiscard]] static auto GetCacheDir() noexcept -> std::filesystem::path { - auto& disk_cache = Data().disk_cache; - if (disk_cache.empty()) { - return GetBuildDir(); + [[nodiscard]] static auto CacheRoot() noexcept -> std::filesystem::path { + auto& cache_root = Data().cache_root; + if (cache_root.empty()) { + cache_root = + UpdatePathForCompatibility(BuildRoot() / "protocol-dependent"); } - return disk_cache; + return cache_root; + } + + // CAS directory based on the type of the file. + // Specialized just for regular File or Exectuable + template <ObjectType kType, + typename = std::enable_if<kType == ObjectType::File or + kType == ObjectType::Executable>> + [[nodiscard]] static inline auto CASDir() noexcept + -> std::filesystem::path { + static const std::string kSuffix = std::string{"cas"} + ToChar(kType); + return CacheRoot() / kSuffix; + } + + /// \brief Action cache directory + [[nodiscard]] static auto ActionCacheDir() noexcept + -> std::filesystem::path { + return CacheRoot() / "ac"; } [[nodiscard]] static auto GetLauncher() noexcept @@ -124,7 +139,7 @@ class LocalExecutionConfig { } /// \brief Determine user root directory - [[nodiscard]] static auto GetUserRoot() noexcept -> std::filesystem::path { + [[nodiscard]] static auto GetUserHome() noexcept -> std::filesystem::path { char const* root{nullptr}; #ifdef __unix__ @@ -135,7 +150,8 @@ class LocalExecutionConfig { #endif if (root == nullptr) { - Logger::Log(LogLevel::Error, "Cannot determine user directory."); + Logger::Log(LogLevel::Error, + "Cannot determine user home directory."); std::exit(EXIT_FAILURE); } diff --git a/src/buildtool/execution_api/local/local_ac.hpp b/src/buildtool/execution_api/local/local_ac.hpp index 0378a74d..08f384d8 100644 --- a/src/buildtool/execution_api/local/local_ac.hpp +++ b/src/buildtool/execution_api/local/local_ac.hpp @@ -15,10 +15,6 @@ class LocalAC { explicit LocalAC(gsl::not_null<LocalCAS<ObjectType::File>*> cas) noexcept : cas_{std::move(cas)} {}; - LocalAC(gsl::not_null<LocalCAS<ObjectType::File>*> cas, - std::filesystem::path cache_root) noexcept - : cas_{std::move(cas)}, cache_root_{std::move(cache_root)} {} - LocalAC(LocalAC const&) = delete; LocalAC(LocalAC&&) = delete; auto operator=(LocalAC const&) -> LocalAC& = delete; @@ -74,10 +70,8 @@ class LocalAC { Logger logger_{"LocalAC"}; gsl::not_null<LocalCAS<ObjectType::File>*> cas_; - std::filesystem::path const cache_root_{ - LocalExecutionConfig::GetCacheDir()}; FileStorage<ObjectType::File, kStoreMode, /*kSetEpochTime=*/false> - file_store_{cache_root_ / "ac"}; + file_store_{LocalExecutionConfig::ActionCacheDir()}; }; #endif // INCLUDED_SRC_BUILDTOOL_EXECUTION_API_LOCAL_LOCAL_AC_HPP diff --git a/src/buildtool/execution_api/local/local_action.cpp b/src/buildtool/execution_api/local/local_action.cpp index d8ec8be3..93a00c0d 100644 --- a/src/buildtool/execution_api/local/local_action.cpp +++ b/src/buildtool/execution_api/local/local_action.cpp @@ -80,7 +80,7 @@ auto LocalAction::Execute(Logger const* logger) noexcept auto LocalAction::Run(bazel_re::Digest const& action_id) const noexcept -> std::optional<Output> { - auto exec_path = CreateUniquePath(LocalExecutionConfig::GetBuildDir() / + auto exec_path = CreateUniquePath(LocalExecutionConfig::CacheRoot() / "exec_root" / action_id.hash()); if (not exec_path) { diff --git a/src/buildtool/execution_api/local/local_cas.hpp b/src/buildtool/execution_api/local/local_cas.hpp index 1b76b72f..ea10b638 100644 --- a/src/buildtool/execution_api/local/local_cas.hpp +++ b/src/buildtool/execution_api/local/local_cas.hpp @@ -17,9 +17,6 @@ class LocalCAS { public: LocalCAS() noexcept = default; - explicit LocalCAS(std::filesystem::path cache_root) noexcept - : cache_root_{std::move(cache_root)} {} - LocalCAS(LocalCAS const&) = delete; LocalCAS(LocalCAS&&) = delete; auto operator=(LocalCAS const&) -> LocalCAS& = delete; @@ -48,12 +45,10 @@ class LocalCAS { } private: - static constexpr char kSuffix = ToChar(kType); - Logger logger_{std::string{"LocalCAS"} + kSuffix}; - std::filesystem::path const cache_root_{ - LocalExecutionConfig::GetCacheDir()}; + Logger logger_{std::string{"LocalCAS"} + ToChar(kType)}; + FileStorage<kType, StoreMode::FirstWins, /*kSetEpochTime=*/true> - file_store_{cache_root_ / (std::string{"cas"} + kSuffix)}; + file_store_{LocalExecutionConfig::CASDir<kType>()}; [[nodiscard]] static auto CreateDigest(std::string const& bytes) noexcept -> std::optional<bazel_re::Digest> { diff --git a/src/buildtool/execution_api/local/local_storage.hpp b/src/buildtool/execution_api/local/local_storage.hpp index 568d412d..4560a859 100644 --- a/src/buildtool/execution_api/local/local_storage.hpp +++ b/src/buildtool/execution_api/local/local_storage.hpp @@ -16,14 +16,6 @@ class LocalStorage { std::shared_ptr<LocalTreeMap> tree_map = nullptr) noexcept : tree_map_{std::move(tree_map)} {} - explicit LocalStorage( - std::filesystem::path const& cache_root, - std::shared_ptr<LocalTreeMap> tree_map = nullptr) noexcept - : cas_file_{cache_root}, - cas_exec_{cache_root}, - ac_{&cas_file_, cache_root}, - tree_map_{std::move(tree_map)} {} - /// \brief Store blob from file path with x-bit determined from file system. template <bool kOwner = false> [[nodiscard]] auto StoreBlob(std::filesystem::path const& file_path) diff --git a/src/buildtool/execution_engine/executor/TARGETS b/src/buildtool/execution_engine/executor/TARGETS index 6354665a..fa1e3e9f 100644 --- a/src/buildtool/execution_engine/executor/TARGETS +++ b/src/buildtool/execution_engine/executor/TARGETS @@ -6,6 +6,7 @@ [ ["src/buildtool/logging", "logging"] , ["src/buildtool/common", "config"] , ["src/buildtool/common", "tree"] + , ["src/buildtool/compatibility", "compatibility"] , ["src/buildtool/file_system", "file_system_manager"] , ["src/buildtool/execution_engine/dag", "dag"] , ["src/buildtool/execution_api/common", "common"] diff --git a/src/buildtool/execution_engine/executor/executor.hpp b/src/buildtool/execution_engine/executor/executor.hpp index 9caa7bee..c08a6a2c 100644 --- a/src/buildtool/execution_engine/executor/executor.hpp +++ b/src/buildtool/execution_engine/executor/executor.hpp @@ -14,6 +14,7 @@ #include "src/buildtool/common/repository_config.hpp" #include "src/buildtool/common/statistics.hpp" #include "src/buildtool/common/tree.hpp" +#include "src/buildtool/compatibility/compatibility.hpp" #include "src/buildtool/execution_api/common/execution_api.hpp" #include "src/buildtool/execution_engine/dag/dag.hpp" #include "src/buildtool/file_system/file_system_manager.hpp" @@ -112,10 +113,10 @@ class ExecutorImpl { // is available to the execution API if (object_info_opt) { if (not api->IsAvailable(object_info_opt->digest) and - not UploadGitBlob(api, - artifact->Content().Repository(), - object_info_opt->digest, - /*skip_check=*/true)) { + not UploadKnownArtifact(api, + artifact->Content().Repository(), + object_info_opt->digest, + /*skip_check=*/true)) { Logger::Log( LogLevel::Error, "artifact {} should be present in CAS but is missing.", @@ -149,27 +150,52 @@ class ExecutorImpl { /// \param repo The global repository name, the artifact belongs to /// \param digest The digest of the object /// \param skip_check Skip check for existence before upload + /// \param hash The git-sha1 hash of the object /// \returns true on success [[nodiscard]] static auto UploadGitBlob( gsl::not_null<IExecutionApi*> const& api, std::string const& repo, ArtifactDigest const& digest, - bool skip_check) noexcept -> bool { + bool skip_check, + std::string const& hash) noexcept -> bool { auto const& repo_config = RepositoryConfig::Instance(); std::optional<std::string> blob{}; if (auto const* ws_root = repo_config.WorkspaceRoot(repo)) { // try to obtain blob from local workspace's Git CAS, if any - blob = ws_root->ReadBlob(digest.hash()); + blob = ws_root->ReadBlob(hash); } if (not blob) { // try to obtain blob from global Git CAS, if any - blob = repo_config.ReadBlobFromGitCAS(digest.hash()); + blob = repo_config.ReadBlobFromGitCAS(hash); } return blob and api->Upload(BlobContainer{{BazelBlob{digest, std::move(*blob)}}}, skip_check); } + /// \brief Lookup blob via digest in local git repositories and upload. + /// \param api The endpoint used for uploading + /// \param repo The global repository name, the artifact belongs to + /// \param digest The digest of the object + /// \param skip_check Skip check for existence before upload + /// \returns true on success + [[nodiscard]] static auto UploadKnownArtifact( + gsl::not_null<IExecutionApi*> const& api, + std::string const& repo, + ArtifactDigest const& digest, + bool skip_check) noexcept -> bool { + if (Compatibility::IsCompatible()) { + auto opt = Compatibility::GetGitEntry(digest.hash()); + if (opt) { + auto const& [git_sha1_hash, comp_repo] = *opt; + return UploadGitBlob( + api, comp_repo, digest, skip_check, git_sha1_hash); + } + return false; + } + return UploadGitBlob(api, repo, digest, skip_check, digest.hash()); + } + /// \brief Lookup file via path in local workspace root and upload. /// \param api The endpoint used for uploading /// \param repo The global repository name, the artifact belongs to diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS index 929c372f..32dd96db 100644 --- a/src/buildtool/file_system/TARGETS +++ b/src/buildtool/file_system/TARGETS @@ -62,6 +62,7 @@ [ "git_tree" , "file_system_manager" , ["src/buildtool/common", "artifact_description"] + , ["src/buildtool/compatibility", "compatibility"] , ["@", "gsl-lite", "", "gsl-lite"] ] , "stage": ["src", "buildtool", "file_system"] diff --git a/src/buildtool/file_system/file_root.hpp b/src/buildtool/file_system/file_root.hpp index 58f521cd..c374e937 100644 --- a/src/buildtool/file_system/file_root.hpp +++ b/src/buildtool/file_system/file_root.hpp @@ -12,6 +12,7 @@ #include "gsl-lite/gsl-lite.hpp" #include "src/buildtool/common/artifact_description.hpp" +#include "src/buildtool/compatibility/compatibility.hpp" #include "src/buildtool/file_system/file_system_manager.hpp" #include "src/buildtool/file_system/git_tree.hpp" #include "src/utils/cpp/concepts.hpp" @@ -387,6 +388,13 @@ class FileRoot { std::get<git_root_t>(root_).tree->LookupEntryByPath( file_path)) { if (entry->IsBlob()) { + if (Compatibility::IsCompatible()) { + auto compatible_hash = Compatibility::RegisterGitEntry( + entry->Hash(), *entry->Blob(), repository); + return ArtifactDescription{ + ArtifactDigest{compatible_hash, *entry->Size()}, + entry->Type()}; + } return ArtifactDescription{ ArtifactDigest{entry->Hash(), *entry->Size()}, entry->Type(), diff --git a/src/buildtool/main/TARGETS b/src/buildtool/main/TARGETS index 3151d9ae..d8d1f8f9 100644 --- a/src/buildtool/main/TARGETS +++ b/src/buildtool/main/TARGETS @@ -7,6 +7,7 @@ , "deps": [ ["src/buildtool/common", "cli"] , ["src/buildtool/common", "config"] + , ["src/buildtool/compatibility", "compatibility"] , ["src/buildtool/graph_traverser", "graph_traverser"] , ["src/buildtool/logging", "logging"] , ["src/buildtool/progress_reporting", "base_progress_reporter"] diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp index a608fb07..7cb26e45 100644 --- a/src/buildtool/main/main.cpp +++ b/src/buildtool/main/main.cpp @@ -18,6 +18,7 @@ #include "src/buildtool/common/artifact_description.hpp" #include "src/buildtool/common/cli.hpp" #include "src/buildtool/common/repository_config.hpp" +#include "src/buildtool/compatibility/compatibility.hpp" #ifndef BOOTSTRAP_BUILD_TOOL #include "src/buildtool/graph_traverser/graph_traverser.hpp" #include "src/buildtool/progress_reporting/base_progress_reporter.hpp" @@ -84,6 +85,7 @@ auto SetupBuildCommandArguments( SetupAnalysisArguments(app, &clargs->analysis); SetupEndpointArguments(app, &clargs->endpoint); SetupBuildArguments(app, &clargs->build); + SetupCompatibilityArguments(app); } /// \brief Setup arguments for sub command "just install". @@ -106,6 +108,7 @@ auto SetupRebuildCommandArguments( auto SetupInstallCasCommandArguments( gsl::not_null<CLI::App*> const& app, gsl::not_null<CommandLineArguments*> const& clargs) { + SetupCompatibilityArguments(app); SetupEndpointArguments(app, &clargs->endpoint); SetupFetchArguments(app, &clargs->fetch); } @@ -119,6 +122,7 @@ auto SetupTraverseCommandArguments( SetupGraphArguments(app, &clargs->graph); // instead of analysis SetupBuildArguments(app, &clargs->build); SetupStageArguments(app, &clargs->stage); + SetupCompatibilityArguments(app); } auto ParseCommandLineArguments(int argc, char const* const* argv) @@ -198,13 +202,22 @@ void SetupLocalExecution(EndpointArguments const& eargs, using LocalConfig = LocalExecutionConfig; if (not LocalConfig::SetKeepBuildDir(bargs.persistent_build_dir) or not(not eargs.local_root or - (LocalConfig::SetBuildRoot(*eargs.local_root) and - LocalConfig::SetDiskCache(*eargs.local_root))) or + (LocalConfig::SetBuildRoot(*eargs.local_root))) or not(not bargs.local_launcher or LocalConfig::SetLauncher(*bargs.local_launcher))) { Logger::Log(LogLevel::Error, "failed to configure local execution."); } } + +void SetupHashGenerator() { + if (Compatibility::IsCompatible()) { + HashGenerator::SetHashGenerator(HashGenerator::HashType::SHA256); + } + else { + HashGenerator::SetHashGenerator(HashGenerator::HashType::GIT); + } +} + #endif // returns path relative to `root`. @@ -1185,6 +1198,7 @@ auto main(int argc, char* argv[]) -> int { SetupLogging(arguments.common); #ifndef BOOTSTRAP_BUILD_TOOL + SetupHashGenerator(); SetupLocalExecution(arguments.endpoint, arguments.build); #endif @@ -1224,6 +1238,14 @@ auto main(int argc, char* argv[]) -> int { #ifndef BOOTSTRAP_BUILD_TOOL if (arguments.cmd == SubCommand::kTraverse) { if (arguments.graph.git_cas) { + if (Compatibility::IsCompatible()) { + Logger::Log(LogLevel::Error, + "Command line options {} and {} cannot be used " + "together.", + "--git_cas", + "--compatible"); + std::exit(EXIT_FAILURE); + } if (not RepositoryConfig::Instance().SetGitCAS( *arguments.graph.git_cas)) { Logger::Log(LogLevel::Warning, |