-
Notifications
You must be signed in to change notification settings - Fork 287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unified object provider backend #911
base: main
Are you sure you want to change the base?
Changes from 9 commits
95f0438
42ec787
0b1d87f
2d04507
7e1e57e
e4ed60e
2e71ca8
a4200ec
4bbc46a
9d999d8
e0ba623
163d9cd
2a54205
0912655
5d7288c
10189ac
2567607
ecdd000
8e7ae61
850d7c9
548be38
6dbbf06
74b86fd
5171d3e
d69ed8f
2df42d5
5f1786e
6f5a7ba
93303c3
8a26c8b
aa7e52f
d46a4d6
b045c64
104758f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -249,10 +249,22 @@ namespace vcpkg | |
{ | ||
constexpr OptionalStorage() noexcept : m_t(nullptr) { } | ||
constexpr OptionalStorage(const T& t) : m_t(&t) { } | ||
constexpr OptionalStorage(const Optional<T>& t) : m_t(t.get()) { } | ||
constexpr OptionalStorage(const Optional<const T>& t) : m_t(t.get()) { } | ||
constexpr OptionalStorage(Optional<T>&& t) = delete; | ||
constexpr OptionalStorage(Optional<const T>&& t) = delete; | ||
template<typename U, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain why this change was necessary? Optional stores T, not T*, so whether T is abstract should not matter. ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From Discord: the problem is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also don't see how you would use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the question is if the following is a valid expressions: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I see, the problem is that given
I believe the correct fix is just to put the
should be
and in
should just be
|
||
std::enable_if_t<std::is_same_v<T, std::decay_t<U>> && !std::is_abstract_v<T>, int*> = nullptr> | ||
constexpr OptionalStorage(const Optional<U>& t) : m_t(t.get()) | ||
{ | ||
} | ||
template<typename U, | ||
std::enable_if_t<std::is_same_v<T, std::decay_t<U>> && !std::is_abstract_v<T>, int*> = nullptr> | ||
constexpr OptionalStorage(const Optional<const U>& t) : m_t(t.get()) | ||
{ | ||
} | ||
template<typename U, | ||
std::enable_if_t<std::is_same_v<T, std::decay_t<U>> && !std::is_abstract_v<T>, int*> = nullptr> | ||
constexpr OptionalStorage(Optional<U>&& t) = delete; | ||
template<typename U, | ||
std::enable_if_t<std::is_same_v<T, std::decay_t<U>> && !std::is_abstract_v<T>, int*> = nullptr> | ||
constexpr OptionalStorage(Optional<const U>&& t) = delete; | ||
|
||
constexpr bool has_value() const { return m_t != nullptr; } | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,24 @@ | ||
#pragma once | ||
|
||
// #include <vcpkg/base/fwd/optional.h> | ||
|
||
#include <vcpkg/fwd/binarycaching.h> | ||
#include <vcpkg/fwd/dependencies.h> | ||
#include <vcpkg/fwd/tools.h> | ||
#include <vcpkg/fwd/vcpkgpaths.h> | ||
|
||
#include <vcpkg/base/downloads.h> | ||
#include <vcpkg/base/expected.h> | ||
#include <vcpkg/base/files.h> | ||
|
||
#include <vcpkg/packagespec.h> | ||
#include <vcpkg/sourceparagraph.h> | ||
|
||
#include <condition_variable> | ||
#include <iterator> | ||
#include <queue> | ||
#include <set> | ||
#include <string> | ||
#include <thread> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
|
@@ -42,6 +48,51 @@ namespace vcpkg | |
const IBinaryProvider* m_available_provider = nullptr; // meaningful iff m_status == available | ||
}; | ||
|
||
struct BinaryPackageInformation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm I wonder if this scheme makes it easier to pass around shared cache information, like the zip, between config providers so we can get out of the business of multiple destinations trying to share the same provider? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this is the idea behind this PR and implemented. The |
||
{ | ||
explicit BinaryPackageInformation(const InstallPlanAction& action); | ||
std::string package_abi; | ||
// The following fields are only needed for the nuget binary cache | ||
PackageSpec spec; | ||
SourceControlFile& source_control_file; | ||
std::string& raw_version; | ||
std::string compiler_id; | ||
std::string compiler_version; | ||
std::string triplet_abi; | ||
InternalFeatureSet feature_list; | ||
std::vector<PackageSpec> package_dependencies; | ||
}; | ||
|
||
struct IObjectProvider | ||
{ | ||
enum class Access : uint8_t | ||
{ | ||
Read = 0b01, | ||
Write = 0b10, | ||
ReadWrite = 0b11, | ||
}; | ||
Access access; | ||
|
||
bool supports_write() const { return static_cast<uint8_t>(access) & static_cast<uint8_t>(Access::Write); } | ||
bool supports_read() const { return static_cast<uint8_t>(access) & static_cast<uint8_t>(Access::Read); } | ||
|
||
IObjectProvider(Access access) : access(access) { } | ||
virtual ~IObjectProvider() = default; | ||
|
||
virtual void download(Optional<const ToolCache&> tool_cache, | ||
View<StringView> objects, | ||
const Path& target_dir) const = 0; | ||
|
||
virtual void upload(Optional<const ToolCache&> tool_cache, | ||
StringView object_id, | ||
const Path& object_file, | ||
MessageSink& msg_sink) = 0; | ||
|
||
virtual void check_availability(Optional<const ToolCache&> tool_cache, | ||
View<StringView> objects, | ||
Span<bool> cache_status) const = 0; | ||
}; | ||
|
||
struct IBinaryProvider | ||
{ | ||
virtual ~IBinaryProvider() = default; | ||
|
@@ -52,7 +103,9 @@ namespace vcpkg | |
|
||
/// Called upon a successful build of `action` to store those contents in the binary cache. | ||
/// Prerequisite: action has a package_abi() | ||
virtual void push_success(const InstallPlanAction& action) const = 0; | ||
virtual void push_success(const BinaryPackageInformation& info, | ||
const Path& packages_dir, | ||
MessageSink& msg_sink) = 0; | ||
|
||
/// Gives the IBinaryProvider an opportunity to batch any downloading or server communication for | ||
/// executing `actions`. | ||
|
@@ -77,61 +130,82 @@ namespace vcpkg | |
std::vector<std::string> headers_for_get; | ||
|
||
LocalizedString valid() const; | ||
std::string instantiate_variables(const InstallPlanAction& action) const; | ||
std::string instantiate_variable(StringView sha) const; | ||
|
||
protected: | ||
LocalizedString valid(View<StringLiteral> valid_keys) const; | ||
}; | ||
|
||
struct BinaryConfigParserState | ||
struct ExtendedUrlTemplate : private UrlTemplate | ||
{ | ||
bool nuget_interactive = false; | ||
std::set<StringLiteral> binary_cache_providers; | ||
|
||
std::string nugettimeout = "100"; | ||
|
||
std::vector<Path> archives_to_read; | ||
std::vector<Path> archives_to_write; | ||
|
||
std::vector<UrlTemplate> url_templates_to_get; | ||
std::vector<UrlTemplate> url_templates_to_put; | ||
using UrlTemplate::headers_for_get; | ||
using UrlTemplate::headers_for_put; | ||
using UrlTemplate::url_template; | ||
ExtendedUrlTemplate(UrlTemplate&& t) : UrlTemplate(std::move(t)) { } | ||
LocalizedString valid() const; | ||
std::string instantiate_variables(const BinaryPackageInformation& info) const; | ||
}; | ||
|
||
std::vector<std::string> gcs_read_prefixes; | ||
std::vector<std::string> gcs_write_prefixes; | ||
struct ObjectCacheConfig | ||
{ | ||
ObjectCacheConfig() = default; | ||
ObjectCacheConfig(const ObjectCacheConfig&) = delete; | ||
ObjectCacheConfig& operator=(const ObjectCacheConfig&) = delete; | ||
ObjectCacheConfig(ObjectCacheConfig&&) = default; | ||
ObjectCacheConfig& operator=(ObjectCacheConfig&&) = default; | ||
virtual ~ObjectCacheConfig() = default; | ||
std::vector<std::unique_ptr<IObjectProvider>> object_providers; | ||
std::vector<std::string> secrets; | ||
virtual void clear(); | ||
}; | ||
|
||
std::vector<std::string> aws_read_prefixes; | ||
std::vector<std::string> aws_write_prefixes; | ||
bool aws_no_sign_request = false; | ||
struct BinaryConfigParserState : ObjectCacheConfig | ||
{ | ||
bool nuget_interactive = false; | ||
std::string nugettimeout = "100"; | ||
|
||
std::vector<std::string> cos_read_prefixes; | ||
std::vector<std::string> cos_write_prefixes; | ||
std::vector<ExtendedUrlTemplate> url_templates_to_get; | ||
std::vector<ExtendedUrlTemplate> url_templates_to_put; | ||
|
||
std::vector<std::string> sources_to_read; | ||
std::vector<std::string> sources_to_write; | ||
|
||
std::vector<Path> configs_to_read; | ||
std::vector<Path> configs_to_write; | ||
|
||
std::vector<std::string> secrets; | ||
void clear() override; | ||
}; | ||
|
||
void clear(); | ||
struct DownloadManagerConfig : public ObjectCacheConfig | ||
{ | ||
bool block_origin = false; | ||
Optional<std::string> script; | ||
void clear() override; | ||
}; | ||
|
||
ExpectedL<BinaryConfigParserState> create_binary_providers_from_configs_pure(const std::string& env_string, | ||
ExpectedL<BinaryConfigParserState> create_binary_providers_from_configs_pure(Filesystem& fs, | ||
const std::string& env_string, | ||
View<std::string> args); | ||
ExpectedL<std::vector<std::unique_ptr<IBinaryProvider>>> create_binary_providers_from_configs( | ||
const VcpkgPaths& paths, View<std::string> args); | ||
|
||
struct BinaryCache | ||
{ | ||
BinaryCache() = default; | ||
static BinaryCache* current_instance; | ||
static void wait_for_async_complete(); | ||
BinaryCache(Filesystem& filesystem); | ||
explicit BinaryCache(const VcpkgCmdArguments& args, const VcpkgPaths& paths); | ||
|
||
~BinaryCache(); | ||
|
||
void install_providers(std::vector<std::unique_ptr<IBinaryProvider>>&& providers); | ||
void install_providers_for(const VcpkgCmdArguments& args, const VcpkgPaths& paths); | ||
|
||
/// Attempts to restore the package referenced by `action` into the packages directory. | ||
RestoreResult try_restore(const InstallPlanAction& action); | ||
|
||
/// Called upon a successful build of `action` to store those contents in the binary cache. | ||
void push_success(const InstallPlanAction& action); | ||
void push_success(const InstallPlanAction& action, Path package_dir); | ||
|
||
/// Gives the IBinaryProvider an opportunity to batch any downloading or server communication for | ||
/// executing `actions`. | ||
|
@@ -143,11 +217,25 @@ namespace vcpkg | |
std::vector<CacheAvailability> precheck(View<InstallPlanAction> actions); | ||
|
||
private: | ||
struct ActionToPush | ||
{ | ||
BinaryPackageInformation info; | ||
bool clean_after_push; | ||
Path packages_dir; | ||
}; | ||
void push_thread_main(); | ||
|
||
std::unordered_map<std::string, CacheStatus> m_status; | ||
std::vector<std::unique_ptr<IBinaryProvider>> m_providers; | ||
std::condition_variable actions_to_push_notifier; | ||
std::mutex actions_to_push_mutex; | ||
std::queue<ActionToPush> actions_to_push; | ||
std::thread push_thread; | ||
std::atomic_bool end_push_thread; | ||
Filesystem& filesystem; | ||
}; | ||
|
||
ExpectedL<DownloadManagerConfig> parse_download_configuration(const Optional<std::string>& arg); | ||
ExpectedL<DownloadManagerConfig> parse_download_configuration(Filesystem& fs, const Optional<std::string>& arg); | ||
|
||
std::string generate_nuget_packages_config(const ActionPlan& action); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think you meant to do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests do not build currently (expected) but I want to run the e2e tests in the ci, so I have to disable the unit tests temporarily.