-
Notifications
You must be signed in to change notification settings - Fork 7.4k
[vcpkg] Add feature option 'withMirror' ⚡ #12532
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
Changes from all commits
a4cc356
2b3e855
d7cd136
881fbe0
d17ae85
874a6bd
6b92077
d108534
849377c
f04daea
83fe7f9
f4e3e42
e34006a
1481205
fc78256
ec07566
7650258
ee17142
067e40b
4711530
1f403ba
248ebb8
c74d73d
b6eafe0
66a6485
1e0e45c
acf8198
8a03f8b
d54eb30
bf18e5f
de5c3e5
d840763
5d2b39b
3be7d69
a3f7c26
afe4d52
b716b5b
5c23abb
d26bcde
f5843c4
942b8dd
1ca45af
9edf845
d9313de
940f46c
e190ce6
cf59c08
a306414
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 |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| #pragma once | ||
JackBoosY marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| #include <vcpkg/build.h> | ||
|
|
||
| namespace vcpkg::Commands::Mirror | ||
| { | ||
| void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); | ||
|
|
||
| struct MirrorCommand : Commands::TripletCommand | ||
| { | ||
| virtual void perform_and_exit(const VcpkgCmdArguments& inArgs, | ||
| const VcpkgPaths& paths, | ||
| Triplet default_triplet) const override; | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -154,6 +154,10 @@ namespace vcpkg | |||||
| constexpr static StringLiteral WAIT_FOR_LOCK_SWITCH = "x-wait-for-lock"; | ||||||
| Optional<bool> wait_for_lock = nullopt; | ||||||
|
|
||||||
| constexpr static StringLiteral VCPKG_EXPERIMENTAL_MIRROR_URL = "VCPKG_EXPERIMENTAL_MIRROR_URL"; | ||||||
|
Member
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 don't think we should name the variable EXPERIMENTAL because someday it won't be and there's no reason to force everyone to edit their scripts then?
Contributor
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. OTOH we can continue respecting the experimental form for backwards compatibility and this makes it clear for users that they are using an unsupported feature. Alternatively, the tool could emit a big yelllow warning at the top every time it's run with this env var set.
Contributor
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. We conventionally use lowercase here
Suggested change
Contributor
Author
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. The environment variable name is set here. Is this correct? |
||||||
| std::unique_ptr<std::string> download_mirror_url; | ||||||
| Optional<bool> use_mirror = nullopt; | ||||||
|
|
||||||
| constexpr static StringLiteral JSON_SWITCH = "x-json"; | ||||||
| Optional<bool> json = nullopt; | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,134 +10,6 @@ | |
|
|
||
| namespace vcpkg::Downloads | ||
| { | ||
| #if defined(_WIN32) | ||
| static void winhttp_download_file(Files::Filesystem& fs, | ||
|
Contributor
Author
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. Since |
||
| ZStringView target_file_path, | ||
| StringView hostname, | ||
| StringView url_path) | ||
| { | ||
| // Make sure the directories are present, otherwise fopen_s fails | ||
| const auto dir = fs::path(target_file_path.c_str()).parent_path(); | ||
| std::error_code ec; | ||
| fs.create_directories(dir, ec); | ||
| Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", fs::u8string(dir)); | ||
|
|
||
| FILE* f = nullptr; | ||
| const errno_t err = fopen_s(&f, target_file_path.c_str(), "wb"); | ||
| Checks::check_exit(VCPKG_LINE_INFO, | ||
| !err, | ||
| "Could not download https://%s%s. Failed to open file %s. Error code was %s", | ||
| hostname, | ||
| url_path, | ||
| target_file_path, | ||
| std::to_string(err)); | ||
| ASSUME(f != nullptr); | ||
|
|
||
| auto hSession = WinHttpOpen(L"vcpkg/1.0", | ||
| IsWindows8Point1OrGreater() ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY | ||
| : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | ||
| WINHTTP_NO_PROXY_NAME, | ||
| WINHTTP_NO_PROXY_BYPASS, | ||
| 0); | ||
| Checks::check_exit(VCPKG_LINE_INFO, hSession, "WinHttpOpen() failed: %d", GetLastError()); | ||
|
|
||
| // If the environment variable HTTPS_PROXY is set | ||
| // use that variable as proxy. This situation might exist when user is in a company network | ||
| // with restricted network/proxy settings | ||
| auto maybe_https_proxy_env = System::get_environment_variable("HTTPS_PROXY"); | ||
| if (auto p_https_proxy = maybe_https_proxy_env.get()) | ||
| { | ||
| std::wstring env_proxy_settings = Strings::to_utf16(*p_https_proxy); | ||
| WINHTTP_PROXY_INFO proxy; | ||
| proxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; | ||
| proxy.lpszProxy = env_proxy_settings.data(); | ||
| proxy.lpszProxyBypass = nullptr; | ||
|
|
||
| WinHttpSetOption(hSession, WINHTTP_OPTION_PROXY, &proxy, sizeof(proxy)); | ||
| } | ||
| // Win7 IE Proxy fallback | ||
| else if (IsWindows7OrGreater() && !IsWindows8Point1OrGreater()) | ||
| { | ||
| // First check if any proxy has been found automatically | ||
| WINHTTP_PROXY_INFO proxyInfo; | ||
| DWORD proxyInfoSize = sizeof(WINHTTP_PROXY_INFO); | ||
| auto noProxyFound = !WinHttpQueryOption(hSession, WINHTTP_OPTION_PROXY, &proxyInfo, &proxyInfoSize) || | ||
| proxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY; | ||
|
|
||
| // If no proxy was found automatically, use IE's proxy settings, if any | ||
| if (noProxyFound) | ||
| { | ||
| WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxy; | ||
| if (WinHttpGetIEProxyConfigForCurrentUser(&ieProxy) && ieProxy.lpszProxy != nullptr) | ||
| { | ||
| WINHTTP_PROXY_INFO proxy; | ||
| proxy.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; | ||
| proxy.lpszProxy = ieProxy.lpszProxy; | ||
| proxy.lpszProxyBypass = ieProxy.lpszProxyBypass; | ||
| WinHttpSetOption(hSession, WINHTTP_OPTION_PROXY, &proxy, sizeof(proxy)); | ||
| GlobalFree(ieProxy.lpszProxy); | ||
| GlobalFree(ieProxy.lpszProxyBypass); | ||
| GlobalFree(ieProxy.lpszAutoConfigUrl); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Use Windows 10 defaults on Windows 7 | ||
| DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | | ||
| WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2); | ||
| WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols)); | ||
|
|
||
| // Specify an HTTP server. | ||
| auto hConnect = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0); | ||
| Checks::check_exit(VCPKG_LINE_INFO, hConnect, "WinHttpConnect() failed: %d", GetLastError()); | ||
|
|
||
| // Create an HTTP request handle. | ||
| auto hRequest = WinHttpOpenRequest(hConnect, | ||
| L"GET", | ||
| Strings::to_utf16(url_path).c_str(), | ||
| nullptr, | ||
| WINHTTP_NO_REFERER, | ||
| WINHTTP_DEFAULT_ACCEPT_TYPES, | ||
| WINHTTP_FLAG_SECURE); | ||
| Checks::check_exit(VCPKG_LINE_INFO, hRequest, "WinHttpOpenRequest() failed: %d", GetLastError()); | ||
|
|
||
| // Send a request. | ||
| auto bResults = | ||
| WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); | ||
|
|
||
| Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpSendRequest() failed: %d", GetLastError()); | ||
|
|
||
| // End the request. | ||
| bResults = WinHttpReceiveResponse(hRequest, NULL); | ||
| Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReceiveResponse() failed: %d", GetLastError()); | ||
|
|
||
| std::vector<char> buf; | ||
|
|
||
| size_t total_downloaded_size = 0; | ||
| DWORD dwSize = 0; | ||
| do | ||
| { | ||
| DWORD downloaded_size = 0; | ||
| bResults = WinHttpQueryDataAvailable(hRequest, &dwSize); | ||
| Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpQueryDataAvailable() failed: %d", GetLastError()); | ||
|
|
||
| if (buf.size() < dwSize) buf.resize(static_cast<size_t>(dwSize) * 2); | ||
|
|
||
| bResults = WinHttpReadData(hRequest, (LPVOID)buf.data(), dwSize, &downloaded_size); | ||
| Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReadData() failed: %d", GetLastError()); | ||
| fwrite(buf.data(), 1, downloaded_size, f); | ||
|
|
||
| total_downloaded_size += downloaded_size; | ||
| } while (dwSize > 0); | ||
|
|
||
| WinHttpCloseHandle(hSession); | ||
| WinHttpCloseHandle(hConnect); | ||
| WinHttpCloseHandle(hRequest); | ||
| fflush(f); | ||
| fclose(f); | ||
| } | ||
| #endif | ||
|
|
||
| void verify_downloaded_file_hash(const Files::Filesystem& fs, | ||
| const std::string& url, | ||
| const fs::path& path, | ||
|
|
@@ -178,12 +50,15 @@ namespace vcpkg::Downloads | |
| fs.remove(download_path, ec); | ||
| fs.remove(download_path_part_path, ec); | ||
| #if defined(_WIN32) | ||
| auto url_no_proto = url.substr(8); // drop https:// | ||
| auto url_no_proto = url.substr(Strings::starts_with(url, "ftp") ? 6 : 8); // drop ftp:// or https:// | ||
| auto path_begin = Util::find(url_no_proto, '/'); | ||
| std::string hostname(url_no_proto.begin(), path_begin); | ||
| std::string path(path_begin, url_no_proto.end()); | ||
|
|
||
| winhttp_download_file(fs, download_path_part, hostname, path); | ||
| if (Strings::starts_with(url, "ftp")) | ||
| ftp_download_file(fs, download_path_part, hostname, path); | ||
| else | ||
| winhttp_download_file(fs, download_path_part, hostname, path); | ||
| #else | ||
| const auto code = System::cmd_execute( | ||
| Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #include "pch.h" | ||
|
|
||
| #include <vcpkg/base/downloads.h> | ||
| #include <vcpkg/base/hash.h> | ||
| #include <vcpkg/base/system.h> | ||
| #include <vcpkg/base/system.process.h> | ||
| #include <vcpkg/base/util.h> | ||
|
|
||
| #if defined(_WIN32) | ||
| #include <VersionHelpers.h> | ||
| #include <wininet.h> | ||
| #pragma comment(lib, "Wininet") | ||
| #endif | ||
|
|
||
| namespace vcpkg::Downloads | ||
| { | ||
| #if defined(_WIN32) | ||
| void ftp_download_file(Files::Filesystem& fs, | ||
| ZStringView target_file_path, | ||
| StringView hostname, | ||
| StringView url_path) | ||
| { | ||
| // Make sure the directories are present, otherwise fopen_s fails | ||
| const auto dir = fs::path(target_file_path.c_str()).parent_path(); | ||
| std::error_code ec; | ||
| fs.create_directories(dir, ec); | ||
| Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", fs::u8string(dir)); | ||
|
|
||
| HINTERNET hConnect; | ||
| HINTERNET hFtpSession; | ||
| hConnect = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); | ||
| Checks::check_exit(VCPKG_LINE_INFO, hConnect, "InternetOpen() failed: %d", GetLastError()); | ||
|
|
||
| hFtpSession = InternetConnect( | ||
| hConnect, hostname.to_string().c_str(), INTERNET_DEFAULT_FTP_PORT, "", "", INTERNET_SERVICE_FTP, 0, 0); | ||
| Checks::check_exit(VCPKG_LINE_INFO, hFtpSession, "InternetConnect() failed: %d", GetLastError()); | ||
| BOOL bSuc = FtpGetFile(hFtpSession, | ||
| url_path.to_string().c_str(), | ||
| target_file_path.to_string().c_str(), | ||
| FALSE, | ||
| FTP_TRANSFER_TYPE_BINARY, | ||
| 0, | ||
| 0); | ||
| Checks::check_exit(VCPKG_LINE_INFO, bSuc == TRUE, "InternetConnect() failed: %d", GetLastError()); | ||
| InternetCloseHandle(hFtpSession); | ||
| InternetCloseHandle(hConnect); | ||
| } | ||
| #endif | ||
| } |
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.
This should do something reasonable in the
vcpkg_download_distfile_SKIP_SHA512caseThere 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.
Without SHA512,
vcpkg_download_distfilecannot splice the download URL.