[x-download] Implement `--header` argument
MODIFY
include/vcpkg-test/util.h
include/vcpkg-test/util.h
@@ -107,6 +107,20 @@ namespace vcpkg::Test
return std::move(*opt.get());
}
+ template<class R1, class R2>
+ void check_ranges(const R1& r1, const R2& r2)
+ {
+ CHECK(r1.size() == r2.size());
+ auto it1 = r1.begin();
+ auto e1 = r1.end();
+ auto it2 = r2.begin();
+ auto e2 = r2.end();
+ for (; it1 != e1 && it2 != e2; ++it1, ++it2)
+ {
+ CHECK(*it1 == *it2);
+ }
+ }
+
struct AllowSymlinks
{
enum Tag : bool

MODIFY
include/vcpkg/base/downloads.h
include/vcpkg/base/downloads.h
@@ -27,46 +27,67 @@ namespace vcpkg::Downloads
// Returns url that was successfully downloaded from
std::string download_file(Files::Filesystem& fs,
View<std::string> urls,
+ View<std::string> headers,
const fs::path& download_path,
const std::string& sha512);
void download_file(Files::Filesystem& fs,
const std::string& url,
+ View<std::string> headers,
const fs::path& download_path,
const std::string& sha512);
+ View<std::string> azure_blob_headers();
+
std::vector<int> download_files(Files::Filesystem& fs, View<std::pair<std::string, fs::path>> url_pairs);
- int put_file(const Files::Filesystem&, StringView url, const fs::path& file);
- std::vector<int> url_heads(View<std::string> urls);
+ ExpectedS<int> put_file(const Files::Filesystem&, StringView url, View<std::string> headers, const fs::path& file);
+ std::vector<int> url_heads(View<std::string> urls, View<std::string> headers);
+
+ struct DownloadManagerConfig
+ {
+ Optional<std::string> m_read_url_template;
+ std::vector<std::string> m_read_headers;
+ Optional<std::string> m_write_url_template;
+ std::vector<std::string> m_write_headers;
+ bool m_block_origin = false;
+ };
// Handles downloading and uploading to a content addressable mirror
- struct DownloadManager
+ struct DownloadManager : private DownloadManagerConfig
{
DownloadManager() = default;
explicit DownloadManager(Optional<std::string> read_url_template,
+ std::vector<std::string> read_headers,
Optional<std::string> write_url_template,
+ std::vector<std::string> write_headers,
bool block_origin);
void download_file(Files::Filesystem& fs,
const std::string& url,
const fs::path& download_path,
+ const std::string& sha512) const
+ {
+ this->download_file(fs, url, {}, download_path, sha512);
+ }
+
+ void download_file(Files::Filesystem& fs,
+ const std::string& url,
+ View<std::string> headers,
+ const fs::path& download_path,
const std::string& sha512) const;
std::string download_file(Files::Filesystem& fs,
View<std::string> urls,
+ View<std::string> headers,
const fs::path& download_path,
const std::string& sha512) const;
- int put_file_to_mirror(const Files::Filesystem& fs, const fs::path& path, const std::string& sha512) const;
+ ExpectedS<int> put_file_to_mirror(const Files::Filesystem& fs,
+ const fs::path& path,
+ const std::string& sha512) const;
- const Optional<std::string>& internal_get_read_url_template() const { return m_read_url_template; }
- const Optional<std::string>& internal_get_write_url_template() const { return m_write_url_template; }
+ const DownloadManagerConfig& internal_get_config() const { return *this; }
bool block_origin() const { return m_block_origin; }
-
- private:
- bool m_block_origin = false;
- Optional<std::string> m_read_url_template;
- Optional<std::string> m_write_url_template;
};
}

MODIFY
src/vcpkg-test/configparser.cpp
src/vcpkg-test/configparser.cpp
#include <vcpkg/binarycaching.h>
+#include <vcpkg-test/util.h>
+
using namespace vcpkg;
#if defined(_WIN32)
@@ -383,23 +385,50 @@ TEST_CASE ("AssetConfigParser azurl provider", "[assetconfigparser]")
CHECK(create_download_manager("x-azurl,https://abc/123,foo"));
CHECK(create_download_manager("x-azurl,ftp://magic,none"));
CHECK(create_download_manager("x-azurl,ftp://magic,none"));
- auto value_or = [](auto o, auto v) {
- if (o)
- return std::move(*o.get());
- else
- return std::move(v);
- };
+ {
Downloads::DownloadManager empty;
-
- CHECK(value_or(create_download_manager("x-azurl,https://abc/123,foo"), empty).internal_get_read_url_template() ==
- "https://abc/123/<SHA>?foo");
- CHECK(value_or(create_download_manager("x-azurl,https://abc/123/,foo"), empty).internal_get_read_url_template() ==
- "https://abc/123/<SHA>?foo");
- CHECK(value_or(create_download_manager("x-azurl,https://abc/123,?foo"), empty).internal_get_read_url_template() ==
- "https://abc/123/<SHA>?foo");
- CHECK(value_or(create_download_manager("x-azurl,https://abc/123"), empty).internal_get_read_url_template() ==
- "https://abc/123/<SHA>");
+ CHECK(empty.internal_get_config().m_write_headers.empty());
+ CHECK(empty.internal_get_config().m_read_headers.empty());
+ }
+ {
+ Downloads::DownloadManager dm = Test::unwrap(create_download_manager("x-azurl,https://abc/123,foo"));
+ CHECK(dm.internal_get_config().m_read_url_template == "https://abc/123/<SHA>?foo");
+ CHECK(dm.internal_get_config().m_read_headers.empty());
+ CHECK(dm.internal_get_config().m_write_url_template == nullopt);
+ }
+ {
+ Downloads::DownloadManager dm = Test::unwrap(create_download_manager("x-azurl,https://abc/123/,foo"));
+ CHECK(dm.internal_get_config().m_read_url_template == "https://abc/123/<SHA>?foo");
+ CHECK(dm.internal_get_config().m_read_headers.empty());
+ CHECK(dm.internal_get_config().m_write_url_template == nullopt);
+ }
+ {
+ Downloads::DownloadManager dm = Test::unwrap(create_download_manager("x-azurl,https://abc/123,?foo"));
+ CHECK(dm.internal_get_config().m_read_url_template == "https://abc/123/<SHA>?foo");
+ CHECK(dm.internal_get_config().m_read_headers.empty());
+ CHECK(dm.internal_get_config().m_write_url_template == nullopt);
+ }
+ {
+ Downloads::DownloadManager dm = Test::unwrap(create_download_manager("x-azurl,https://abc/123"));
+ CHECK(dm.internal_get_config().m_read_url_template == "https://abc/123/<SHA>");
+ CHECK(dm.internal_get_config().m_read_headers.empty());
+ CHECK(dm.internal_get_config().m_write_url_template == nullopt);
+ }
+ {
+ Downloads::DownloadManager dm = Test::unwrap(create_download_manager("x-azurl,https://abc/123,,readwrite"));
+ CHECK(dm.internal_get_config().m_read_url_template == "https://abc/123/<SHA>");
+ CHECK(dm.internal_get_config().m_read_headers.empty());
+ CHECK(dm.internal_get_config().m_write_url_template == "https://abc/123/<SHA>");
+ Test::check_ranges(dm.internal_get_config().m_write_headers, Downloads::azure_blob_headers());
+ }
+ {
+ Downloads::DownloadManager dm = Test::unwrap(create_download_manager("x-azurl,https://abc/123,foo,readwrite"));
+ CHECK(dm.internal_get_config().m_read_url_template == "https://abc/123/<SHA>?foo");
+ CHECK(dm.internal_get_config().m_read_headers.empty());
+ CHECK(dm.internal_get_config().m_write_url_template == "https://abc/123/<SHA>?foo");
+ Test::check_ranges(dm.internal_get_config().m_write_headers, Downloads::azure_blob_headers());
+ }
}
TEST_CASE ("AssetConfigParser clear provider", "[assetconfigparser]")
@@ -417,9 +446,11 @@ TEST_CASE ("AssetConfigParser clear provider", "[assetconfigparser]")
Downloads::DownloadManager empty;
CHECK(value_or(create_download_manager("x-azurl,https://abc/123,foo;clear"), empty)
- .internal_get_read_url_template() == nullopt);
+ .internal_get_config()
+ .m_read_url_template == nullopt);
CHECK(value_or(create_download_manager("clear;x-azurl,https://abc/123/,foo"), empty)
- .internal_get_read_url_template() == "https://abc/123/<SHA>?foo");
+ .internal_get_config()
+ .m_read_url_template == "https://abc/123/<SHA>?foo");
}
TEST_CASE ("AssetConfigParser x-block-origin provider", "[assetconfigparser]")

MODIFY
src/vcpkg/base/checks.cpp
src/vcpkg/base/checks.cpp
@@ -71,6 +71,10 @@ namespace vcpkg
{
if (!expression)
{
+ System::print2(System::Color::error,
+ "Error: vcpkg has crashed; no additional details are available.\nThe source line is ",
+ Strings::format("%s(%d)\n", line_info.file_name, line_info.line_number),
+ '\n');
exit_fail(line_info);
}
}

MODIFY
src/vcpkg/base/downloads.cpp
src/vcpkg/base/downloads.cpp
@@ -231,7 +231,7 @@ namespace vcpkg::Downloads
}
}
- static void url_heads_inner(View<std::string> urls, std::vector<int>* out)
+ static void url_heads_inner(View<std::string> urls, View<std::string> headers, std::vector<int>* out)
{
static constexpr StringLiteral guid_marker = "8a1db05f-a65d-419b-aa72-037fb4d0672e";
@@ -241,6 +241,10 @@ namespace vcpkg::Downloads
.string_arg("--location")
.string_arg("-w")
.string_arg(Strings::concat(guid_marker, " %{http_code}\\n"));
+ for (auto&& header : headers)
+ {
+ cmd.string_arg("-H").string_arg(header);
+ }
for (auto&& url : urls)
{
cmd.string_arg(url);
@@ -253,7 +257,7 @@ namespace vcpkg::Downloads
});
Checks::check_exit(VCPKG_LINE_INFO, res == 0, "curl failed to execute with exit code: %d", res);
}
- std::vector<int> url_heads(View<std::string> urls)
+ std::vector<int> url_heads(View<std::string> urls, View<std::string> headers)
{
static constexpr size_t batch_size = 100;
@@ -262,9 +266,9 @@ namespace vcpkg::Downloads
size_t i = 0;
for (; i + batch_size <= urls.size(); i += batch_size)
{
- url_heads_inner({urls.data() + i, batch_size}, &ret);
+ url_heads_inner({urls.data() + i, batch_size}, headers, &ret);
}
- if (i != urls.size()) url_heads_inner({urls.begin() + i, urls.end()}, &ret);
+ if (i != urls.size()) url_heads_inner({urls.begin() + i, urls.end()}, headers, &ret);
return ret;
}
@@ -273,6 +277,9 @@ namespace vcpkg::Downloads
View<std::pair<std::string, fs::path>> url_pairs,
std::vector<int>* out)
{
+ for (auto i : {100, 1000, 10000, 0})
+ {
+ size_t start_size = out->size();
static constexpr StringLiteral guid_marker = "8a1db05f-a65d-419b-aa72-037fb4d0672e";
System::Command cmd;
@@ -290,7 +297,21 @@ namespace vcpkg::Downloads
out->push_back(std::strtol(line.data() + guid_marker.size(), nullptr, 10));
}
});
- Checks::check_exit(VCPKG_LINE_INFO, res == 0, "curl failed to execute with exit code: %d", res);
+ 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())
+ {
+ // curl stopped before finishing all downloads; retry after some time
+ System::print2(System::Color::warning, "Warning: an unexpected error occurred during bulk download.\n");
+ std::this_thread::sleep_for(std::chrono::milliseconds(i));
+ url_pairs = View<std::pair<std::string, fs::path>>{url_pairs.begin() + out->size() - start_size,
+ url_pairs.end()};
+ }
+ else
+ {
+ break;
+ }
+ }
}
std::vector<int> download_files(Files::Filesystem& fs, View<std::pair<std::string, fs::path>> url_pairs)
{
@@ -305,16 +326,24 @@ namespace vcpkg::Downloads
}
if (i != url_pairs.size()) download_files_inner(fs, {url_pairs.begin() + i, url_pairs.end()}, &ret);
- Checks::check_exit(VCPKG_LINE_INFO, ret.size() == url_pairs.size());
+ Checks::check_exit(
+ VCPKG_LINE_INFO,
+ ret.size() == url_pairs.size(),
+ "Error: curl returned a different number of response codes than were expected for the request (",
+ ret.size(),
+ " vs expected ",
+ url_pairs.size(),
+ ")");
return ret;
}
- int put_file(const Files::Filesystem&, StringView url, const fs::path& file)
+ ExpectedS<int> put_file(const Files::Filesystem&, StringView url, View<std::string> headers, const fs::path& file)
{
static constexpr StringLiteral guid_marker = "9a1db05f-a65d-419b-aa72-037fb4d0672e";
if (Strings::starts_with(url, "ftp://"))
{
+ // HTTP headers are ignored for FTP clients
System::Command cmd;
cmd.string_arg("curl");
cmd.string_arg(url);
@@ -323,17 +352,20 @@ namespace vcpkg::Downloads
if (res.exit_code != 0)
{
Debug::print(res.output, '\n');
- System::print2(System::Color::warning, "curl failed to execute with exit code: ", res.exit_code, '\n');
+ return Strings::concat(
+ "Error: curl failed to put file to ", url, " with exit code: ", res.exit_code, '\n');
}
- return res.exit_code;
+ return 0;
}
System::Command cmd;
cmd.string_arg("curl").string_arg("-X").string_arg("PUT");
+ for (auto&& header : headers)
+ {
+ cmd.string_arg("-H").string_arg(header);
+ }
cmd.string_arg("-w").string_arg(Strings::concat("\\n", guid_marker, "%{http_code}"));
cmd.string_arg(url);
cmd.string_arg("-T").path_arg(file);
- cmd.string_arg("-H").string_arg("x-ms-version: 2020-04-08");
- cmd.string_arg("-H").string_arg("x-ms-blob-type: BlockBlob");
int code = 0;
auto res = System::cmd_execute_and_stream_lines(cmd, [&code](StringView line) {
if (Strings::starts_with(line, guid_marker))
@@ -341,19 +373,21 @@ namespace vcpkg::Downloads
code = std::strtol(line.data() + guid_marker.size(), nullptr, 10);
}
});
- if (res != 0)
+ if (res != 0 || code < 200 || code >= 300)
{
- System::print2(System::Color::warning, "curl failed to execute with exit code: ", res, '\n');
+ return Strings::concat(
+ "Error: curl failed to put file to ", url, " with exit code '", res, "' and http code '", code, "'\n");
}
return code;
}
void download_file(Files::Filesystem& fs,
const std::string& url,
+ View<std::string> headers,
const fs::path& download_path,
const std::string& sha512)
{
- download_file(fs, {&url, 1}, download_path, sha512);
+ download_file(fs, {&url, 1}, headers, download_path, sha512);
}
#if defined(_WIN32)
@@ -440,13 +474,13 @@ namespace vcpkg::Downloads
}
#endif
- std::string download_file(vcpkg::Files::Filesystem& fs,
- View<std::string> urls,
+ static bool try_download_file(vcpkg::Files::Filesystem& fs,
+ const std::string& url,
+ View<std::string> headers,
const fs::path& download_path,
- const std::string& sha512)
+ const std::string& sha512,
+ std::string& errors)
{
- Checks::check_exit(VCPKG_LINE_INFO, urls.size() > 0);
-
auto download_path_part_path = download_path;
#if defined(_WIN32)
download_path_part_path += fs::u8path(Strings::concat(".", _getpid(), ".part"));
@@ -454,10 +488,9 @@ namespace vcpkg::Downloads
download_path_part_path += fs::u8path(Strings::concat(".", getpid(), ".part"));
#endif
- std::string errors;
- for (const std::string& url : urls)
- {
#if defined(_WIN32)
+ if (headers.size() == 0)
+ {
auto split_uri = details::split_uri_view(url).value_or_exit(VCPKG_LINE_INFO);
auto authority = split_uri.authority.value_or_exit(VCPKG_LINE_INFO).substr(2);
if (split_uri.scheme == "https" || split_uri.scheme == "http")
@@ -471,14 +504,19 @@ namespace vcpkg::Downloads
if (auto err = maybe_error.get())
{
Strings::append(errors, *err);
+ return false;
}
else
{
fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
- return url;
+ return true;
+ }
+ }
+ else
+ {
+ return false;
}
}
- continue;
}
}
#endif
@@ -490,83 +528,139 @@ namespace vcpkg::Downloads
.string_arg("--create-dirs")
.string_arg("--output")
.path_arg(download_path_part_path);
+ for (auto&& header : headers)
+ {
+ cmd.string_arg("-H").string_arg(header);
+ }
const auto out = System::cmd_execute_and_capture_output(cmd);
if (out.exit_code != 0)
{
Strings::append(errors, url, ": ", out.output, '\n');
- continue;
+ return false;
}
auto maybe_error = try_verify_downloaded_file_hash(fs, url, download_path_part_path, sha512);
if (auto err = maybe_error.get())
{
Strings::append(errors, *err);
+ return false;
}
else
{
fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
- return url;
+ return true;
}
}
- Checks::exit_with_message(VCPKG_LINE_INFO, Strings::concat("Failed to download from mirror set:\n", errors));
+
+ static Optional<const std::string&> try_download_files(vcpkg::Files::Filesystem& fs,
+ View<std::string> urls,
+ View<std::string> headers,
+ const fs::path& download_path,
+ const std::string& sha512,
+ std::string& errors)
+ {
+ for (auto&& url : urls)
+ {
+ if (try_download_file(fs, url, headers, download_path, sha512, errors)) return url;
+ }
+ return nullopt;
+ }
+
+ std::string download_file(vcpkg::Files::Filesystem& fs,
+ View<std::string> urls,
+ View<std::string> headers,
+ const fs::path& download_path,
+ const std::string& sha512)
+ {
+ Checks::check_exit(VCPKG_LINE_INFO, urls.size(), "Error: No urls specified to download SHA: %s", sha512);
+
+ std::string errors;
+ auto maybe_url = try_download_files(fs, urls, headers, download_path, sha512, errors);
+ if (auto url = maybe_url.get())
+ {
+ return *url;
+ }
+ else
+ {
+ Checks::exit_with_message(VCPKG_LINE_INFO, "Failed to download from mirror set:\n%s", errors);
+ }
+ }
+
+ View<std::string> azure_blob_headers()
+ {
+ static std::string s_headers[2] = {"x-ms-version: 2020-04-08", "x-ms-blob-type: BlockBlob"};
+ return s_headers;
}
DownloadManager::DownloadManager(Optional<std::string> read_url_template,
+ std::vector<std::string> read_headers,
Optional<std::string> write_url_template,
+ std::vector<std::string> write_headers,
bool block_origin)
- : m_block_origin(block_origin)
- , m_read_url_template(std::move(read_url_template))
- , m_write_url_template(std::move(write_url_template))
+ : DownloadManagerConfig{std::move(read_url_template),
+ std::move(read_headers),
+ std::move(write_url_template),
+ std::move(write_headers),
+ block_origin}
{
}
void DownloadManager::download_file(Files::Filesystem& fs,
const std::string& url,
+ View<std::string> headers,
const fs::path& download_path,
const std::string& sha512) const
{
- this->download_file(fs, View<std::string>(&url, 1), download_path, sha512);
+ this->download_file(fs, View<std::string>(&url, 1), headers, download_path, sha512);
}
std::string DownloadManager::download_file(Files::Filesystem& fs,
View<std::string> urls,
+ View<std::string> headers,
const fs::path& download_path,
const std::string& sha512) const
{
- auto maybe_mirror_url = Strings::replace_all(m_read_url_template.value_or(""), "<SHA>", sha512);
-
- std::vector<std::string> all_urls;
- if (!maybe_mirror_url.empty()) all_urls.push_back(maybe_mirror_url);
-
- if (!m_block_origin)
+ std::string errors;
+ if (auto read_template = m_read_url_template.get())
{
- Util::Vectors::append(&all_urls, urls);
+ auto read_url = Strings::replace_all(std::string(*read_template), "<SHA>", sha512);
+ if (Downloads::try_download_file(fs, read_url, m_read_headers, download_path, sha512, errors))
+ return read_url;
}
- if (all_urls.empty())
+ if (!m_block_origin)
+ {
+ if (urls.size() == 0)
{
- Checks::exit_with_message(VCPKG_LINE_INFO, "Error: No urls specified to download SHA: %s", sha512);
+ Strings::append(errors, "Error: No urls specified to download SHA: ", sha512);
}
-
- auto fetched_url = Downloads::download_file(fs, all_urls, download_path, sha512);
- if (fetched_url != maybe_mirror_url)
+ else
+ {
+ auto maybe_url = try_download_files(fs, urls, headers, download_path, sha512, errors);
+ if (auto url = maybe_url.get())
{
- put_file_to_mirror(fs, download_path, sha512);
+ auto maybe_push = put_file_to_mirror(fs, download_path, sha512);
+ if (!maybe_push.has_value())
+ {
+ System::print2(
+ System::Color::warning, "Warning: failed to store back to mirror:\n", maybe_push.error());
+ }
+ return *url;
}
- return fetched_url;
+ }
+ }
+ Checks::exit_with_message(VCPKG_LINE_INFO, "Error: Failed to download from mirror set:\n%s", errors);
}
- int DownloadManager::put_file_to_mirror(const Files::Filesystem& fs,
+ ExpectedS<int> DownloadManager::put_file_to_mirror(const Files::Filesystem& fs,
const fs::path& path,
const std::string& sha512) const
{
- int code = 0;
auto maybe_mirror_url = Strings::replace_all(m_write_url_template.value_or(""), "<SHA>", sha512);
if (!maybe_mirror_url.empty())
{
- code = Downloads::put_file(fs, maybe_mirror_url, path);
- Debug::print("Putting to cache: ", maybe_mirror_url, ": ", code, "\n");
+ return Downloads::put_file(fs, maybe_mirror_url, m_write_headers, path);
}
- return code;
+ return 0;
}
}

MODIFY
src/vcpkg/binarycaching.cpp
src/vcpkg/binarycaching.cpp
@@ -326,23 +326,24 @@ namespace
for (auto&& put_url_template : m_put_url_templates)
{
auto url = Strings::replace_all(std::string(put_url_template), "<SHA>", abi_tag);
- auto code = Downloads::put_file(fs, url, tmp_archive_path);
- if (code >= 200 && code < 300)
+ auto maybe_success = Downloads::put_file(fs, url, Downloads::azure_blob_headers(), tmp_archive_path);
+ if (maybe_success.has_value())
{
http_remotes_pushed++;
continue;
}
- auto safe_url = url;
+ auto errors = std::move(maybe_success).error();
+
if (!Debug::g_debugging.load(std::memory_order_relaxed))
{
for (const auto& secret : m_secrets)
{
- Strings::inplace_replace_all(safe_url, secret, "*** SECRET ***");
+ Strings::inplace_replace_all(errors, secret, "*** SECRET ***");
}
}
- System::print2(System::Color::warning, "Failed to upload to ", safe_url, ": ", code, '\n');
+ System::print2(System::Color::warning, errors);
}
if (!m_put_url_templates.empty())
@@ -516,7 +517,7 @@ namespace
break;
}
- auto codes = Downloads::url_heads(urls);
+ auto codes = Downloads::url_heads(urls, {});
Checks::check_exit(VCPKG_LINE_INFO, codes.size() == url_actions.size());
for (size_t i = 0; i < codes.size(); ++i)
{
@@ -1538,12 +1539,16 @@ ExpectedS<Downloads::DownloadManager> vcpkg::create_download_manager(const Optio
get_url = std::move(s.url_templates_to_get.back());
}
Optional<std::string> put_url;
+ std::vector<std::string> put_headers;
if (!s.azblob_templates_to_put.empty())
{
put_url = std::move(s.azblob_templates_to_put.back());
+ auto v = Downloads::azure_blob_headers();
+ put_headers.assign(v.begin(), v.end());
}
- return Downloads::DownloadManager{std::move(get_url), std::move(put_url), s.block_origin};
+ return Downloads::DownloadManager{
+ std::move(get_url), std::vector<std::string>{}, std::move(put_url), std::move(put_headers), s.block_origin};
}
ExpectedS<std::unique_ptr<IBinaryProvider>> vcpkg::create_binary_provider_from_configs(View<std::string> args)

MODIFY
src/vcpkg/commands.xdownload.cpp
src/vcpkg/commands.xdownload.cpp
@@ -19,7 +19,7 @@ namespace vcpkg::Commands::X_Download
};
static constexpr CommandMultiSetting FETCH_MULTISETTINGS[] = {
{OPTION_URL, "URL to download and store if missing from cache"},
- {OPTION_HEADER, "(Not Implemented) Additional header to use when fetching from URLs"},
+ {OPTION_HEADER, "Additional header to use when fetching from URLs"},
};
const CommandStructure COMMAND_STRUCTURE = {
@@ -65,20 +65,27 @@ namespace vcpkg::Commands::X_Download
auto hash =
Strings::ascii_to_lowercase(Hash::get_file_hash(VCPKG_LINE_INFO, fs, file, Hash::Algorithm::Sha512));
if (hash != sha) Checks::exit_with_message(VCPKG_LINE_INFO, "Error: file to store does not match hash");
- paths.get_download_manager().put_file_to_mirror(fs, file, sha);
+ paths.get_download_manager().put_file_to_mirror(fs, file, sha).value_or_exit(VCPKG_LINE_INFO);
Checks::exit_success(VCPKG_LINE_INFO);
}
else
{
// Try to fetch from urls
+ auto it_headers = parsed.multisettings.find(OPTION_HEADER);
+ View<std::string> headers;
+ if (it_headers != parsed.multisettings.end())
+ {
+ headers = it_headers->second;
+ }
+
auto it_urls = parsed.multisettings.find(OPTION_URL);
if (it_urls == parsed.multisettings.end())
{
- paths.get_download_manager().download_file(fs, View<std::string>{}, file, sha);
+ paths.get_download_manager().download_file(fs, View<std::string>{}, headers, file, sha);
}
else
{
- paths.get_download_manager().download_file(fs, it_urls->second, file, sha);
+ paths.get_download_manager().download_file(fs, it_urls->second, headers, file, sha);
}
Checks::exit_success(VCPKG_LINE_INFO);
}

[x-download] Implement `--header` argument (#91)