Skip to content
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

Add https binary cache #558

Merged
merged 4 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions include/vcpkg/base/api_stable_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ namespace vcpkg
(*(F*)(f))(s, sv);
}

ExpectedS<std::string> api_stable_format_impl(StringView fmtstr,
ExpectedL<std::string> api_stable_format_impl(StringView fmtstr,
void (*cb)(void*, std::string&, StringView),
void* data);

}

// This function exists in order to provide an API-stable formatting function similar to `std::format()` that does
// not depend on the feature set of fmt or the C++ standard library and thus can be contractual for user interfaces.
template<class F>
ExpectedS<std::string> api_stable_format(StringView fmtstr, F&& handler)
ExpectedL<std::string> api_stable_format(StringView fmtstr, F&& handler)
{
return details::api_stable_format_impl(fmtstr, &details::api_stable_format_cb<F>, &handler);
}
Expand Down
3 changes: 2 additions & 1 deletion include/vcpkg/base/downloads.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ namespace vcpkg

View<std::string> azure_blob_headers();

std::vector<int> download_files(Filesystem& fs, View<std::pair<std::string, Path>> url_pairs);
std::vector<int> download_files(Filesystem& fs,
View<std::tuple<std::string, View<std::string>, Path>> url_header_path_tuples);
ExpectedS<int> put_file(const Filesystem&, StringView url, View<std::string> headers, const Path& file);
std::vector<int> url_heads(View<std::string> urls, View<std::string> headers, View<std::string> secrets);
std::string replace_secrets(std::string input, View<std::string> secrets);
Expand Down
13 changes: 11 additions & 2 deletions include/vcpkg/binarycaching.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ namespace vcpkg
virtual void precheck(View<Dependencies::InstallPlanAction> actions, View<CacheStatus*> cache_status) const = 0;
};

struct UrlTemplate
{
std::string url_template;
std::vector<std::string> headers;

LocalizedString valid();
std::string instantiate_variables(const Dependencies::InstallPlanAction& action) const;
};

struct BinaryConfigParserState
{
bool m_cleared = false;
Expand All @@ -78,8 +87,8 @@ namespace vcpkg
std::vector<Path> archives_to_read;
std::vector<Path> archives_to_write;

std::vector<std::string> url_templates_to_get;
std::vector<std::string> azblob_templates_to_put;
std::vector<UrlTemplate> url_templates_to_get;
std::vector<UrlTemplate> url_templates_to_put;

std::vector<std::string> gcs_read_prefixes;
std::vector<std::string> gcs_write_prefixes;
Expand Down
2 changes: 2 additions & 0 deletions locales/messages.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
"InvalidArgumentRequiresSourceArgument": "invalid argument: binary config '{binary_source}' requires at least a source argument",
"InvalidArgumentRequiresTwoOrThreeArguments": "invalid argument: binary config '{binary_source}' requires 2 or 3 arguments",
"InvalidArgumentRequiresValidToken": "invalid argument: binary config '{binary_source}' requires a SAS token without a preceeding '?' as the second argument",
"InvalidFormatString": "invalid format string: {actual}",
"JsonErrorFailedToParse": "failed to parse {path}:",
"JsonErrorFailedToRead": "failed to read {path}: {error_msg}",
"LaunchingProgramFailed": "Launching {tool_name}:",
Expand Down Expand Up @@ -197,6 +198,7 @@
"UnknownBaselineFileContent": "unrecognizable baseline entry; expected 'port:triplet=(fail|skip)'",
"UnknownBinaryProviderType": "unknown binary provider type: valid providers are 'clear', 'default', 'nuget', 'nugetconfig', 'interactive', and 'files'",
"UnknownTool": "vcpkg does not have a definition of this tool for this platform.",
"UnknownVariablesInTemplate": "invalid argument: url template '{value}' contains unknown variables: {list}",
"UnsupportedSystemName": "Could not map VCPKG_CMAKE_SYSTEM_NAME '{system_name}' to a vcvarsall platform. Supported system names are '', 'Windows' and 'WindowsStore'.",
"UnsupportedToolchain": "in triplet {triplet}: Unable to find a valid toolchain for requested target architecture {arch}.\nThe selected Visual Studio instance is at: {path}\nThe available toolchain combinations are: {list}",
"UpdateBaselineAddBaselineNoManifest": "the --{option} switch was passed, but there is no manifest file to add a `builtin-baseline` field to.",
Expand Down
4 changes: 4 additions & 0 deletions locales/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@
"_InvalidArgumentRequiresTwoOrThreeArguments.comment": "An example of {binary_source} is azblob.",
"InvalidArgumentRequiresValidToken": "invalid argument: binary config '{binary_source}' requires a SAS token without a preceeding '?' as the second argument",
"_InvalidArgumentRequiresValidToken.comment": "An example of {binary_source} is azblob.",
"InvalidFormatString": "invalid format string: {actual}",
"_InvalidFormatString.comment": "{actual} is the provided format string",
"JsonErrorFailedToParse": "failed to parse {path}:",
"_JsonErrorFailedToParse.comment": "An example of {path} is /foo/bar.",
"JsonErrorFailedToRead": "failed to read {path}: {error_msg}",
Expand Down Expand Up @@ -339,6 +341,8 @@
"UnknownBaselineFileContent": "unrecognizable baseline entry; expected 'port:triplet=(fail|skip)'",
"UnknownBinaryProviderType": "unknown binary provider type: valid providers are 'clear', 'default', 'nuget', 'nugetconfig', 'interactive', and 'files'",
"UnknownTool": "vcpkg does not have a definition of this tool for this platform.",
"UnknownVariablesInTemplate": "invalid argument: url template '{value}' contains unknown variables: {list}",
"_UnknownVariablesInTemplate.comment": "{value} is the value provided by the user and {list} a list of unknown variables seperated by comma",
"UnsupportedSystemName": "Could not map VCPKG_CMAKE_SYSTEM_NAME '{system_name}' to a vcvarsall platform. Supported system names are '', 'Windows' and 'WindowsStore'.",
"_UnsupportedSystemName.comment": "An example of {system_name} is Darwin.",
"UnsupportedToolchain": "in triplet {triplet}: Unable to find a valid toolchain for requested target architecture {arch}.\nThe selected Visual Studio instance is at: {path}\nThe available toolchain combinations are: {list}",
Expand Down
32 changes: 20 additions & 12 deletions src/vcpkg/base/downloads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,9 @@ namespace vcpkg
return input;
}

static void download_files_inner(Filesystem&, View<std::pair<std::string, Path>> url_pairs, std::vector<int>* out)
static void download_files_inner(Filesystem&,
View<std::tuple<std::string, View<std::string>, Path>> url_header_path_tuples,
std::vector<int>* out)
{
for (auto i : {100, 1000, 10000, 0})
{
Expand All @@ -366,9 +368,13 @@ namespace vcpkg
.string_arg("--location")
.string_arg("-w")
.string_arg(Strings::concat(guid_marker, " %{http_code}\\n"));
for (auto&& url : url_pairs)
for (auto&& url : url_header_path_tuples)
{
cmd.string_arg(url.first).string_arg("-o").string_arg(url.second);
cmd.string_arg(std::get<0>(url)).string_arg("-o").string_arg(std::get<2>(url));
for (StringView header : std::get<1>(url))
{
cmd.string_arg("-H").string_arg(header);
}
}
auto res = cmd_execute_and_stream_lines(cmd, [out](StringView line) {
if (Strings::starts_with(line, guid_marker))
Expand All @@ -378,40 +384,42 @@ namespace vcpkg
}).value_or_exit(VCPKG_LINE_INFO);
Checks::check_exit(VCPKG_LINE_INFO, res == 0, "Error: curl failed to execute with exit code: %d", res);

if (start_size + url_pairs.size() > out->size())
if (start_size + url_header_path_tuples.size() > out->size())
{
// curl stopped before finishing all downloads; retry after some time
msg::println_warning(msgUnexpectedErrorDuringBulkDownload);
std::this_thread::sleep_for(std::chrono::milliseconds(i));
url_pairs =
View<std::pair<std::string, Path>>{url_pairs.begin() + out->size() - start_size, url_pairs.end()};
url_header_path_tuples = View<std::tuple<std::string, View<std::string>, Path>>{
url_header_path_tuples.begin() + out->size() - start_size, url_header_path_tuples.end()};
}
else
{
break;
}
}
}
std::vector<int> download_files(Filesystem& fs, View<std::pair<std::string, Path>> url_pairs)
std::vector<int> download_files(Filesystem& fs,
View<std::tuple<std::string, View<std::string>, Path>> url_header_path_tuples)
{
static constexpr size_t batch_size = 50;

std::vector<int> ret;

size_t i = 0;
for (; i + batch_size <= url_pairs.size(); i += batch_size)
for (; i + batch_size <= url_header_path_tuples.size(); i += batch_size)
{
download_files_inner(fs, {url_pairs.data() + i, batch_size}, &ret);
download_files_inner(fs, {url_header_path_tuples.data() + i, batch_size}, &ret);
}
if (i != url_pairs.size()) download_files_inner(fs, {url_pairs.begin() + i, url_pairs.end()}, &ret);
if (i != url_header_path_tuples.size())
download_files_inner(fs, {url_header_path_tuples.begin() + i, url_header_path_tuples.end()}, &ret);

Checks::check_exit(
VCPKG_LINE_INFO,
ret.size() == url_pairs.size(),
ret.size() == url_header_path_tuples.size(),
"Error: curl returned a different number of response codes than were expected for the request (",
ret.size(),
" vs expected ",
url_pairs.size(),
url_header_path_tuples.size(),
")");
return ret;
}
Expand Down
20 changes: 16 additions & 4 deletions src/vcpkg/base/strings.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <vcpkg/base/api_stable_format.h>
#include <vcpkg/base/checks.h>
#include <vcpkg/base/expected.h>
#include <vcpkg/base/messages.h>
#include <vcpkg/base/parse.h>
#include <vcpkg/base/strings.h>
#include <vcpkg/base/unicode.h>
Expand All @@ -15,7 +16,18 @@
#include <string>
#include <vector>

vcpkg::ExpectedS<std::string> vcpkg::details::api_stable_format_impl(StringView sv,
using namespace vcpkg;

namespace
{

DECLARE_AND_REGISTER_MESSAGE(InvalidFormatString,
(msg::actual),
"{actual} is the provided format string",
"invalid format string: {actual}");
}

vcpkg::ExpectedL<std::string> vcpkg::details::api_stable_format_impl(StringView sv,
void (*cb)(void*, std::string&, StringView),
void* user)
{
Expand All @@ -37,7 +49,7 @@ vcpkg::ExpectedS<std::string> vcpkg::details::api_stable_format_impl(StringView
{
if (p == last)
{
return {Strings::concat("Error: invalid format string: ", sv), expected_right_tag};
return msg::format(msgInvalidFormatString, msg::actual = sv);
}
else if (*p == '{')
{
Expand All @@ -51,7 +63,7 @@ vcpkg::ExpectedS<std::string> vcpkg::details::api_stable_format_impl(StringView
p = std::find_first_of(p, last, s_brackets, s_brackets + 2);
if (p == last || p[0] != '}')
{
return {Strings::concat("Error: invalid format string: ", sv), expected_right_tag};
return msg::format(msgInvalidFormatString, msg::actual = sv);
}
// p[0] == '}'
cb(user, out, {seq_start, p});
Expand All @@ -62,7 +74,7 @@ vcpkg::ExpectedS<std::string> vcpkg::details::api_stable_format_impl(StringView
{
if (p == last || p[0] != '}')
{
return {Strings::concat("Error: invalid format string: ", sv), expected_right_tag};
return msg::format(msgInvalidFormatString, msg::actual = sv);
}
out.push_back('}');
prev = ++p;
Expand Down
Loading