diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-05-30 17:58:38 +0200 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-06-26 17:57:29 +0200 |
commit | 39fc14811a67cc4381de726840e7b852f7d126c9 (patch) | |
tree | 296b8e1394ec3a09042db71b48b0d3b8a05d0f15 | |
parent | 0b924c5c23a89760ddecf8d8f6baa19333f9b667 (diff) | |
download | justbuild-39fc14811a67cc4381de726840e7b852f7d126c9.tar.gz |
ObjectType: Add non-upwards symlinks as a known object type...
...but make sure it is still considered a special type.
The only non-special entry types remain file, executable, and tree.
-rw-r--r-- | src/buildtool/file_system/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/file_system/file_root.hpp | 16 | ||||
-rw-r--r-- | src/buildtool/file_system/file_system_manager.hpp | 22 | ||||
-rw-r--r-- | src/buildtool/file_system/git_repo.cpp | 16 | ||||
-rw-r--r-- | src/buildtool/file_system/git_tree.hpp | 4 | ||||
-rw-r--r-- | src/buildtool/file_system/object_type.hpp | 16 |
6 files changed, 63 insertions, 12 deletions
diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS index 53be1bae..81455fe6 100644 --- a/src/buildtool/file_system/TARGETS +++ b/src/buildtool/file_system/TARGETS @@ -106,6 +106,7 @@ , ["src/utils/cpp", "path"] , ["src/utils/cpp", "hex_string"] , ["src/utils/cpp", "gsl"] + , ["src/buildtool/file_system", "file_system_manager"] ] , "cflags": ["-pthread"] } diff --git a/src/buildtool/file_system/file_root.hpp b/src/buildtool/file_system/file_root.hpp index ed03f55d..1d4b6f1c 100644 --- a/src/buildtool/file_system/file_root.hpp +++ b/src/buildtool/file_system/file_root.hpp @@ -182,7 +182,7 @@ class FileRoot { auto const& data = std::get<tree_t>(data_); auto ptr = data->LookupEntryByName(name); if (static_cast<bool>(ptr)) { - return ptr->IsBlob(); + return IsFileObject(ptr->Type()); } return false; } @@ -250,7 +250,7 @@ class FileRoot { auto const& data = std::get<tree_t>(data_); return Iterator{FilteredIterator{ data->begin(), data->end(), [](auto const& x) noexcept -> bool { - return x.second->IsBlob(); + return IsFileObject(x.second->Type()); }}}; } @@ -343,8 +343,8 @@ class FileRoot { // std::holds_alternative<fs_root_t>(root_) == true auto root_path = std::get<fs_root_t>(root_) / path; auto exists = FileSystemManager::Exists(root_path); - return (ignore_special_ ? exists and FileSystemManager::Type( - root_path) != std::nullopt + auto type = FileSystemManager::Type(root_path); + return (ignore_special_ ? exists and type and IsNonSpecialObject(*type) : exists); } @@ -354,7 +354,7 @@ class FileRoot { if (auto entry = std::get<git_root_t>(root_).tree->LookupEntryByPath( file_path)) { - return entry->IsBlob(); + return IsFileObject(entry->Type()); } return false; } @@ -385,7 +385,9 @@ class FileRoot { if (auto entry = std::get<git_root_t>(root_).tree->LookupEntryByPath( file_path)) { - return entry->Blob(); + if (IsFileObject(entry->Type())) { + return entry->Blob(); + } } return std::nullopt; } @@ -434,7 +436,7 @@ class FileRoot { if (auto entry = std::get<git_root_t>(root_).tree->LookupEntryByPath( file_path)) { - if (entry->IsBlob()) { + if (IsFileObject(entry->Type())) { return entry->Type(); } } diff --git a/src/buildtool/file_system/file_system_manager.hpp b/src/buildtool/file_system/file_system_manager.hpp index 49357130..8555e8dc 100644 --- a/src/buildtool/file_system/file_system_manager.hpp +++ b/src/buildtool/file_system/file_system_manager.hpp @@ -225,6 +225,7 @@ class FileSystemManager { kSetEpochTime>(file_path, link_path); case ObjectType::Tree: + case ObjectType::Symlink: return false; } } @@ -336,6 +337,7 @@ class FileSystemManager { return CopyFileAs<ObjectType::Executable, kSetEpochTime, kSetWritable>(src, dst, fd_less, opt); + case ObjectType::Symlink: case ObjectType::Tree: break; } @@ -539,6 +541,10 @@ class FileSystemManager { if (std::filesystem::is_directory(status)) { return ObjectType::Tree; } + if (std::filesystem::is_symlink(status) and + IsNonUpwardsSymlink(path)) { + return ObjectType::Symlink; + } if (std::filesystem::exists(status)) { Logger::Log(LogLevel::Debug, "object type for {} is not supported yet.", @@ -633,9 +639,24 @@ class FileSystemManager { else if (std::filesystem::is_directory(status)) { type = ObjectType::Tree; } + // if not file, executable, or tree, ignore every other entry + // type if asked to do so else if (ignore_special) { continue; } + // if not already ignored, check symlinks and only add the + // non-upwards ones + else if (std::filesystem::is_symlink(status)) { + if (IsNonUpwardsSymlink(entry)) { + type = ObjectType::Symlink; + } + else { + Logger::Log(LogLevel::Error, + "unsupported upwards symlink dir entry {}", + entry.path().string()); + return false; + } + } else { Logger::Log(LogLevel::Error, "unsupported type for dir entry {}", @@ -736,6 +757,7 @@ class FileSystemManager { return WriteFileAs<ObjectType::Executable, kSetEpochTime, kSetWritable>(content, file, fd_less); + case ObjectType::Symlink: case ObjectType::Tree: return false; } diff --git a/src/buildtool/file_system/git_repo.cpp b/src/buildtool/file_system/git_repo.cpp index 01db8269..e10da57e 100644 --- a/src/buildtool/file_system/git_repo.cpp +++ b/src/buildtool/file_system/git_repo.cpp @@ -17,6 +17,7 @@ #include <thread> #include <unordered_set> +#include "src/buildtool/file_system/file_system_manager.hpp" #include "src/buildtool/logging/logger.hpp" #include "src/utils/cpp/gsl.hpp" #include "src/utils/cpp/hex_string.hpp" @@ -30,7 +31,8 @@ extern "C" { #ifndef BOOTSTRAP_BUILD_TOOL namespace { -std::unordered_set<git_filemode_t> const kSupportedGitFileModes{ +/// \brief libgit2 file modes corresponding to non-special entries. +std::unordered_set<git_filemode_t> const kNonSpecialGitFileModes{ GIT_FILEMODE_BLOB, GIT_FILEMODE_BLOB_EXECUTABLE, GIT_FILEMODE_TREE}; @@ -53,9 +55,9 @@ std::unordered_set<git_filemode_t> const kSupportedGitFileModes{ } /// \brief Returns true if mode corresponds to a supported object type. -[[nodiscard]] auto GitFileModeIsSupported(git_filemode_t const& mode) noexcept +[[nodiscard]] auto GitFileModeIsNonSpecial(git_filemode_t const& mode) noexcept -> bool { - return kSupportedGitFileModes.contains(mode); + return kNonSpecialGitFileModes.contains(mode); } [[nodiscard]] auto GitFileModeToObjectType(git_filemode_t const& mode) noexcept @@ -67,6 +69,8 @@ std::unordered_set<git_filemode_t> const kSupportedGitFileModes{ return ObjectType::Executable; case GIT_FILEMODE_TREE: return ObjectType::Tree; + case GIT_FILEMODE_LINK: + return ObjectType::Symlink; // condition not tested here default: { std::ostringstream str; str << std::oct << static_cast<int>(mode); @@ -86,6 +90,8 @@ std::unordered_set<git_filemode_t> const kSupportedGitFileModes{ return GIT_FILEMODE_BLOB_EXECUTABLE; case ObjectType::Tree: return GIT_FILEMODE_TREE; + case ObjectType::Symlink: + return GIT_FILEMODE_LINK; } return GIT_FILEMODE_UNREADABLE; // make gcc happy } @@ -132,11 +138,12 @@ std::unordered_set<git_filemode_t> const kSupportedGitFileModes{ std::string name = git_tree_entry_name(entry); auto const* oid = git_tree_entry_id(entry); if (auto raw_id = ToRawString(*oid)) { - if (not GitFileModeIsSupported(git_tree_entry_filemode(entry))) { + if (not GitFileModeIsNonSpecial(git_tree_entry_filemode(entry))) { return 0; // allow, but not store } if (auto type = GitFileModeToObjectType(git_tree_entry_filemode(entry))) { + // no need to test for symlinks, as no symlink entry will reach this (*entries)[*raw_id].emplace_back(std::move(name), *type); return 1; // return >=0 on success, 1 == skip subtrees (flat) } @@ -156,6 +163,7 @@ std::unordered_set<git_filemode_t> const kSupportedGitFileModes{ if (auto raw_id = ToRawString(*oid)) { if (auto type = GitFileModeToObjectType(git_tree_entry_filemode(entry))) { + // symlinks need to be checked in caller for non-upwardness (*entries)[*raw_id].emplace_back(std::move(name), *type); return 1; // return >=0 on success, 1 == skip subtrees (flat) } diff --git a/src/buildtool/file_system/git_tree.hpp b/src/buildtool/file_system/git_tree.hpp index b634ffb2..8dbfb4ed 100644 --- a/src/buildtool/file_system/git_tree.hpp +++ b/src/buildtool/file_system/git_tree.hpp @@ -114,7 +114,9 @@ class GitTreeEntry { ObjectType type) noexcept : cas_{cas}, raw_id_{std::move(raw_id)}, type_{type} {} - [[nodiscard]] auto IsBlob() const noexcept { return IsFileObject(type_); } + [[nodiscard]] auto IsBlob() const noexcept { + return IsFileObject(type_) or IsSymlinkObject(type_); + } [[nodiscard]] auto IsTree() const noexcept { return IsTreeObject(type_); } [[nodiscard]] auto Blob() const noexcept -> std::optional<std::string>; diff --git a/src/buildtool/file_system/object_type.hpp b/src/buildtool/file_system/object_type.hpp index 36a451e8..28e34236 100644 --- a/src/buildtool/file_system/object_type.hpp +++ b/src/buildtool/file_system/object_type.hpp @@ -22,6 +22,7 @@ enum class ObjectType : std::int8_t { File, Executable, Tree, + Symlink // non-upwards symbolic link }; [[nodiscard]] constexpr auto FromChar(char c) -> ObjectType { @@ -30,6 +31,8 @@ enum class ObjectType : std::int8_t { return ObjectType::Executable; case 't': return ObjectType::Tree; + case 'l': + return ObjectType::Symlink; default: return ObjectType::File; } @@ -44,6 +47,8 @@ enum class ObjectType : std::int8_t { return 'x'; case ObjectType::Tree: return 't'; + case ObjectType::Symlink: + return 'l'; } Ensures(false); // unreachable } @@ -60,4 +65,15 @@ enum class ObjectType : std::int8_t { return type == ObjectType::Tree; } +/// \brief Non-upwards symlinks are designated as first-class citizens. +[[nodiscard]] constexpr auto IsSymlinkObject(ObjectType type) -> bool { + return type == ObjectType::Symlink; +} + +/// \brief Only regular files, executables, and trees are non-special entries. +[[nodiscard]] constexpr auto IsNonSpecialObject(ObjectType type) -> bool { + return type == ObjectType::File or type == ObjectType::Executable or + type == ObjectType::Tree; +} + #endif // INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_OBJECT_TYPE_HPP |