aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorBilly O'Neal <bion@microsoft.com>2021-02-04 10:15:44 -0800
committerGitHub <noreply@github.com>2021-02-04 10:15:44 -0800
commitaa60b7efa56a83ead743718941d8b320ef4a05af (patch)
treedb9f9ebd6fa37598b2f5f2ad564eb858cdeddcb0 /toolsrc/src
parentf226416d2eafc495dd03572cb61542fb1670ffdc (diff)
downloadvcpkg-aa60b7efa56a83ead743718941d8b320ef4a05af.tar.gz
vcpkg-aa60b7efa56a83ead743718941d8b320ef4a05af.zip
[vcpkg] Download vcpkg.exe rather than building it in bootstrap on Windows. (#15474)
This reduces bootstrap cost for Windows customers, resolving the issue initially submitted as #12502 . The `toolsrc` tree was extracted to https://github.com/microsoft/vcpkg-tool. `bootstrap.sh` was changed to download the right source tarball, extract, and build it. This was chosen over the previous attempt, a submodule, over concerns of accidentally destroying people's local modifications.
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/pch.cpp2
-rw-r--r--toolsrc/src/tls12-download.c311
-rw-r--r--toolsrc/src/vcpkg-fuzz/main.cpp194
-rw-r--r--toolsrc/src/vcpkg-test/arguments.cpp135
-rw-r--r--toolsrc/src/vcpkg-test/binarycaching.cpp290
-rw-r--r--toolsrc/src/vcpkg-test/binaryconfigparser.cpp336
-rw-r--r--toolsrc/src/vcpkg-test/catch.cpp12
-rw-r--r--toolsrc/src/vcpkg-test/chrono.cpp34
-rw-r--r--toolsrc/src/vcpkg-test/commands.cpp83
-rw-r--r--toolsrc/src/vcpkg-test/dependencies.cpp1713
-rw-r--r--toolsrc/src/vcpkg-test/downloads.cpp59
-rw-r--r--toolsrc/src/vcpkg-test/files.cpp406
-rw-r--r--toolsrc/src/vcpkg-test/hash.cpp276
-rw-r--r--toolsrc/src/vcpkg-test/json.cpp241
-rw-r--r--toolsrc/src/vcpkg-test/large-json-document.json.inc516
-rw-r--r--toolsrc/src/vcpkg-test/manifests.cpp733
-rw-r--r--toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp28
-rw-r--r--toolsrc/src/vcpkg-test/optional.cpp121
-rw-r--r--toolsrc/src/vcpkg-test/paragraph.cpp516
-rw-r--r--toolsrc/src/vcpkg-test/plan.cpp1297
-rw-r--r--toolsrc/src/vcpkg-test/platform-expression.cpp80
-rw-r--r--toolsrc/src/vcpkg-test/registries.cpp132
-rw-r--r--toolsrc/src/vcpkg-test/specifier.cpp130
-rw-r--r--toolsrc/src/vcpkg-test/statusparagraphs.cpp116
-rw-r--r--toolsrc/src/vcpkg-test/strings.cpp114
-rw-r--r--toolsrc/src/vcpkg-test/stringview.cpp19
-rw-r--r--toolsrc/src/vcpkg-test/system.cpp149
-rw-r--r--toolsrc/src/vcpkg-test/uint128.cpp68
-rw-r--r--toolsrc/src/vcpkg-test/update.cpp105
-rw-r--r--toolsrc/src/vcpkg-test/util.cpp230
-rw-r--r--toolsrc/src/vcpkg-test/versionplan.cpp152
-rw-r--r--toolsrc/src/vcpkg.cpp313
-rw-r--r--toolsrc/src/vcpkg/archives.cpp130
-rw-r--r--toolsrc/src/vcpkg/base/checks.cpp120
-rw-r--r--toolsrc/src/vcpkg/base/chrono.cpp180
-rw-r--r--toolsrc/src/vcpkg/base/cofffilereader.cpp311
-rw-r--r--toolsrc/src/vcpkg/base/downloads.cpp467
-rw-r--r--toolsrc/src/vcpkg/base/enums.cpp12
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp1595
-rw-r--r--toolsrc/src/vcpkg/base/hash.cpp703
-rw-r--r--toolsrc/src/vcpkg/base/json.cpp1411
-rw-r--r--toolsrc/src/vcpkg/base/machinetype.cpp39
-rw-r--r--toolsrc/src/vcpkg/base/parse.cpp110
-rw-r--r--toolsrc/src/vcpkg/base/strings.cpp381
-rw-r--r--toolsrc/src/vcpkg/base/stringview.cpp45
-rw-r--r--toolsrc/src/vcpkg/base/system.cpp343
-rw-r--r--toolsrc/src/vcpkg/base/system.print.cpp30
-rw-r--r--toolsrc/src/vcpkg/base/system.process.cpp793
-rw-r--r--toolsrc/src/vcpkg/base/uint128.cpp66
-rw-r--r--toolsrc/src/vcpkg/base/unicode.cpp282
-rw-r--r--toolsrc/src/vcpkg/base/xmlserializer.cpp113
-rw-r--r--toolsrc/src/vcpkg/binarycaching.cpp1477
-rw-r--r--toolsrc/src/vcpkg/binaryparagraph.cpp312
-rw-r--r--toolsrc/src/vcpkg/build.cpp1491
-rw-r--r--toolsrc/src/vcpkg/buildenvironment.cpp20
-rw-r--r--toolsrc/src/vcpkg/cmakevars.cpp323
-rw-r--r--toolsrc/src/vcpkg/commands.add-version.cpp416
-rw-r--r--toolsrc/src/vcpkg/commands.autocomplete.cpp185
-rw-r--r--toolsrc/src/vcpkg/commands.buildexternal.cpp54
-rw-r--r--toolsrc/src/vcpkg/commands.cache.cpp79
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp606
-rw-r--r--toolsrc/src/vcpkg/commands.ciclean.cpp46
-rw-r--r--toolsrc/src/vcpkg/commands.civerifyversions.cpp418
-rw-r--r--toolsrc/src/vcpkg/commands.contact.cpp66
-rw-r--r--toolsrc/src/vcpkg/commands.cpp134
-rw-r--r--toolsrc/src/vcpkg/commands.create.cpp70
-rw-r--r--toolsrc/src/vcpkg/commands.dependinfo.cpp339
-rw-r--r--toolsrc/src/vcpkg/commands.edit.cpp278
-rw-r--r--toolsrc/src/vcpkg/commands.env.cpp122
-rw-r--r--toolsrc/src/vcpkg/commands.fetch.cpp30
-rw-r--r--toolsrc/src/vcpkg/commands.format-manifest.cpp291
-rw-r--r--toolsrc/src/vcpkg/commands.hash.cpp41
-rw-r--r--toolsrc/src/vcpkg/commands.info.cpp147
-rw-r--r--toolsrc/src/vcpkg/commands.integrate.cpp607
-rw-r--r--toolsrc/src/vcpkg/commands.list.cpp147
-rw-r--r--toolsrc/src/vcpkg/commands.owns.cpp47
-rw-r--r--toolsrc/src/vcpkg/commands.porthistory.cpp240
-rw-r--r--toolsrc/src/vcpkg/commands.portsdiff.cpp200
-rw-r--r--toolsrc/src/vcpkg/commands.search.cpp184
-rw-r--r--toolsrc/src/vcpkg/commands.setinstalled.cpp176
-rw-r--r--toolsrc/src/vcpkg/commands.upgrade.cpp210
-rw-r--r--toolsrc/src/vcpkg/commands.upload-metrics.cpp29
-rw-r--r--toolsrc/src/vcpkg/commands.version.cpp60
-rw-r--r--toolsrc/src/vcpkg/commands.xvsinstances.cpp41
-rw-r--r--toolsrc/src/vcpkg/configuration.cpp84
-rw-r--r--toolsrc/src/vcpkg/dependencies.cpp1896
-rw-r--r--toolsrc/src/vcpkg/export.chocolatey.cpp233
-rw-r--r--toolsrc/src/vcpkg/export.cpp707
-rw-r--r--toolsrc/src/vcpkg/export.ifw.cpp517
-rw-r--r--toolsrc/src/vcpkg/export.prefab.cpp719
-rw-r--r--toolsrc/src/vcpkg/globalstate.cpp13
-rw-r--r--toolsrc/src/vcpkg/help.cpp205
-rw-r--r--toolsrc/src/vcpkg/input.cpp56
-rw-r--r--toolsrc/src/vcpkg/install.cpp1105
-rw-r--r--toolsrc/src/vcpkg/metrics.cpp501
-rw-r--r--toolsrc/src/vcpkg/packagespec.cpp291
-rw-r--r--toolsrc/src/vcpkg/paragraphs.cpp531
-rw-r--r--toolsrc/src/vcpkg/platform-expression.cpp577
-rw-r--r--toolsrc/src/vcpkg/portfileprovider.cpp390
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.buildtype.cpp71
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.cpp981
-rw-r--r--toolsrc/src/vcpkg/registries.cpp1204
-rw-r--r--toolsrc/src/vcpkg/remove.cpp337
-rw-r--r--toolsrc/src/vcpkg/sourceparagraph.cpp1389
-rw-r--r--toolsrc/src/vcpkg/spdx-exceptions.inc45
-rw-r--r--toolsrc/src/vcpkg/spdx-licenses.inc426
-rw-r--r--toolsrc/src/vcpkg/statusparagraph.cpp121
-rw-r--r--toolsrc/src/vcpkg/statusparagraphs.cpp186
-rw-r--r--toolsrc/src/vcpkg/tools.cpp615
-rw-r--r--toolsrc/src/vcpkg/triplet.cpp110
-rw-r--r--toolsrc/src/vcpkg/update.cpp103
-rw-r--r--toolsrc/src/vcpkg/userconfig.cpp77
-rw-r--r--toolsrc/src/vcpkg/vcpkgcmdarguments.cpp960
-rw-r--r--toolsrc/src/vcpkg/vcpkglib.cpp239
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp1086
-rw-r--r--toolsrc/src/vcpkg/versiondeserializers.cpp202
-rw-r--r--toolsrc/src/vcpkg/versions.cpp247
-rw-r--r--toolsrc/src/vcpkg/versiont.cpp48
-rw-r--r--toolsrc/src/vcpkg/visualstudio.cpp381
119 files changed, 0 insertions, 41581 deletions
diff --git a/toolsrc/src/pch.cpp b/toolsrc/src/pch.cpp
deleted file mode 100644
index ebc3d8904..000000000
--- a/toolsrc/src/pch.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-// This file intentionally left blank. It exists to be a target for pch compilation,
-// but `#include "pch.h"` is already injected by the compiler. \ No newline at end of file
diff --git a/toolsrc/src/tls12-download.c b/toolsrc/src/tls12-download.c
deleted file mode 100644
index 16edc5448..000000000
--- a/toolsrc/src/tls12-download.c
+++ /dev/null
@@ -1,311 +0,0 @@
-#include <Windows.h>
-#include <process.h>
-#include <winhttp.h>
-/*
- * This program must be as small as possible, because it is committed in binary form to the
- * vcpkg github repo to enable downloading the main vcpkg program on Windows 7, where TLS 1.2 is
- * unavailable to PowerShell.
- * To that end it avoids using C runtime functions (beyond the vcruntime ones the compiler
- * injects itself).
- * (In testing as of 2021-01-07, this version that doesn't link with the CRT is ~8kb, whereas a
- * hello world program that does link with the CRT is ~300kb)
- */
-
-static void __declspec(noreturn) win32_abort()
-{
- /*
- * Note that TerminateProcess does not return when called from the terminated process, see
- * https://github.com/MicrosoftDocs/sdk-api/pull/626
- */
- TerminateProcess(GetCurrentProcess(), 3);
-}
-
-static size_t wide_length(const wchar_t* str)
-{
- size_t answer = 0;
- while (*str)
- {
- ++answer;
- ++str;
- }
- return answer;
-}
-
-static void write_message(const HANDLE std_out, const wchar_t* msg)
-{
- size_t wchars_to_write = wide_length(msg);
- if (wchars_to_write == 0)
- {
- return;
- }
-
- if (wchars_to_write > 65535)
- {
- win32_abort();
- }
-
- if (WriteConsoleW(std_out, msg, wchars_to_write, 0, 0))
- {
- return;
- }
-
- // this happens if output has been redirected
- int narrow_chars = WideCharToMultiByte(CP_ACP, 0, msg, (int)wchars_to_write, 0, 0, 0, 0);
- if (narrow_chars == 0)
- {
- win32_abort();
- }
-
- char* narrow_buffer = HeapAlloc(GetProcessHeap(), 0, (size_t)narrow_chars);
- if (WideCharToMultiByte(CP_ACP, 0, msg, (int)wchars_to_write, narrow_buffer, narrow_chars, 0, 0) == 0)
- {
- win32_abort();
- }
-
- while (narrow_chars != 0)
- {
- DWORD chars_written;
- if (!WriteFile(std_out, narrow_buffer, (DWORD)narrow_chars, &chars_written, 0))
- {
- win32_abort();
- }
-
- narrow_chars -= (int)chars_written;
- }
-
- if (!HeapFree(GetProcessHeap(), 0, narrow_buffer))
- {
- win32_abort();
- }
-}
-
-static void write_number(const HANDLE std_out, DWORD number)
-{
- wchar_t buffer[11]; // 4294967295\0
- wchar_t* first_digit = buffer + 11;
- *--first_digit = L'\0';
- if (number == 0)
- {
- *--first_digit = L'0';
- }
- else
- {
- do
- {
- *--first_digit = L'0' + number % 10;
- number /= 10;
- } while (number != 0);
- }
-
- write_message(std_out, first_digit);
-}
-
-static void write_hex(const HANDLE std_out, DWORD number)
-{
- wchar_t buffer[] = L"0x00000000";
- wchar_t* first_digit = buffer + (sizeof(buffer) / sizeof(wchar_t)) - 1;
- while (number != 0)
- {
- *--first_digit = L"0123456789ABCDEF"[number % 16];
- number /= 16;
- }
-
- write_message(std_out, buffer);
-}
-
-static void __declspec(noreturn) abort_api_failure(const HANDLE std_out, const wchar_t* api_name)
-{
- DWORD last_error = GetLastError();
- write_message(std_out, L"While calling Windows API function ");
- write_message(std_out, api_name);
- write_message(std_out, L" got error ");
- write_hex(std_out, last_error);
- write_message(std_out, L":\r\n");
- wchar_t* message;
- if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- GetModuleHandleW(L"winhttp.dll"),
- last_error,
- 0,
- (LPWSTR)&message,
- 0,
- 0))
- {
- write_message(std_out, message);
- // intentionally leaks the message buffer
- }
- else
- {
- last_error = GetLastError();
- write_message(std_out, L"(unknown error, FormatMessageW failed with ");
- write_hex(std_out, last_error);
- write_message(std_out, L")");
- }
-
- write_message(std_out, L"\r\n");
- FlushFileBuffers(std_out);
- win32_abort();
-}
-
-#ifndef NDEBUG
-int main()
-#else // ^^^ debug // !debug vvv
-int __stdcall entry()
-#endif // ^^^ !debug
-{
-#ifdef NDEBUG
- __security_init_cookie();
-#endif // ^^^ release
-
- const HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
- if (std_out == INVALID_HANDLE_VALUE)
- {
- win32_abort();
- }
-
- int argc;
- wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc); // intentionally leaks argv
- if (argv == 0)
- {
- win32_abort();
- }
-
- if (argc != 4)
- {
- write_message(std_out, L"Usage: tls12-download.exe DOMAIN RELATIVE-PATH OUT-FILE\r\n");
- return 1;
- }
-
- const wchar_t* const domain = argv[1];
- const wchar_t* const relative_path = argv[2];
- const wchar_t* const out_file_path = argv[3];
- write_message(std_out, L"Downloading https://");
- write_message(std_out, domain);
- write_message(std_out, relative_path);
- write_message(std_out, L" -> ");
- write_message(std_out, out_file_path);
-
- wchar_t https_proxy_env[32767];
- DWORD access_type;
- const wchar_t* proxy_setting;
- const wchar_t* proxy_bypass_setting;
- if (GetEnvironmentVariableW(L"HTTPS_PROXY", https_proxy_env, sizeof(https_proxy_env) / sizeof(wchar_t)))
- {
- access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
- proxy_setting = https_proxy_env;
- proxy_bypass_setting = L"<local>";
- write_message(std_out, L" (using proxy: ");
- write_message(std_out, proxy_setting);
- write_message(std_out, L")");
- }
- else if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
- {
- access_type = WINHTTP_ACCESS_TYPE_NO_PROXY;
- proxy_setting = WINHTTP_NO_PROXY_NAME;
- proxy_bypass_setting = WINHTTP_NO_PROXY_BYPASS;
- }
- else
- {
- abort_api_failure(std_out, L"GetEnvironmentVariableW");
- }
-
- write_message(std_out, L"\r\n");
-
- const HANDLE out_file = CreateFileW(out_file_path, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if (out_file == INVALID_HANDLE_VALUE)
- {
- abort_api_failure(std_out, L"CreateFileW");
- }
-
- BOOL results = FALSE;
- const HINTERNET session = WinHttpOpen(L"tls12-download/1.0", access_type, proxy_setting, proxy_bypass_setting, 0);
- if (!session)
- {
- abort_api_failure(std_out, L"WinHttpOpen");
- }
-
- unsigned long secure_protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
- if (!WinHttpSetOption(session, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(DWORD)))
- {
- abort_api_failure(std_out, L"WinHttpSetOption");
- }
-
- const HINTERNET connect = WinHttpConnect(session, domain, INTERNET_DEFAULT_HTTPS_PORT, 0);
- if (!connect)
- {
- abort_api_failure(std_out, L"WinHttpConnect");
- }
-
- const HINTERNET request = WinHttpOpenRequest(
- connect, L"GET", relative_path, 0, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
- if (!request)
- {
- abort_api_failure(std_out, L"WinHttpOpenRequest");
- }
-
- if (!WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
- {
- abort_api_failure(std_out, L"WinHttpSendRequest");
- }
-
- if (!WinHttpReceiveResponse(request, 0))
- {
- abort_api_failure(std_out, L"WinHttpReceiveResponse");
- }
-
- DWORD http_code = 0;
- DWORD query_headers_buffer_size = sizeof(http_code);
- if (!WinHttpQueryHeaders(request,
- WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
- WINHTTP_HEADER_NAME_BY_INDEX,
- &http_code,
- &query_headers_buffer_size,
- WINHTTP_NO_HEADER_INDEX))
- {
- abort_api_failure(std_out, L"WinHttpQueryHeaders");
- }
-
- if (http_code != 200)
- {
- write_message(std_out, L"Download failed, server returned HTTP status: ");
- write_number(std_out, http_code);
- write_message(std_out, L"\r\n");
- FlushFileBuffers(std_out);
- TerminateProcess(GetCurrentProcess(), 2);
- }
-
- char buffer[32768];
- for (;;)
- {
- DWORD received_bytes;
- if (!WinHttpReadData(request, buffer, sizeof(buffer), &received_bytes))
- {
- abort_api_failure(std_out, L"WinHttpReadData");
- }
-
- if (received_bytes == 0)
- {
- break; // end of response
- }
-
- do
- {
- DWORD written_bytes;
- if (!WriteFile(out_file, buffer, received_bytes, &written_bytes, 0))
- {
- abort_api_failure(std_out, L"WriteFile");
- }
-
- received_bytes -= written_bytes;
- } while (received_bytes != 0);
- }
-
- WinHttpCloseHandle(request);
- WinHttpCloseHandle(connect);
- WinHttpCloseHandle(session);
- CloseHandle(out_file);
-
- write_message(std_out, L"Done.\r\n");
- FlushFileBuffers(std_out);
- TerminateProcess(GetCurrentProcess(), 0);
- return 0;
-}
diff --git a/toolsrc/src/vcpkg-fuzz/main.cpp b/toolsrc/src/vcpkg-fuzz/main.cpp
deleted file mode 100644
index bbbf71708..000000000
--- a/toolsrc/src/vcpkg-fuzz/main.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/stringview.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/unicode.h>
-
-#include <vcpkg/platform-expression.h>
-
-#include <string.h>
-
-#include <iostream>
-#include <sstream>
-#include <utility>
-
-using namespace vcpkg;
-
-namespace
-{
- enum class FuzzKind
- {
- None,
- Utf8Decoder,
- JsonParser,
- PlatformExpr,
- };
-
- struct FuzzArgs
- {
- FuzzArgs(int argc, char** argv)
- {
- if (argc <= 1)
- {
- print_help_and_exit();
- }
-
- char** it = argv + 1; // skip the name of the program
- char** last = argv + argc;
-
- for (; it != last; ++it)
- {
- auto arg = StringView(*it, strlen(*it));
- if (arg == "/?")
- {
- print_help_and_exit();
- }
-
- auto pr = split_arg(arg);
- auto key = pr.first;
- auto value = pr.second;
- if (key == "h" || key == "help")
- {
- print_help_and_exit();
- }
-
- if (key == "kind")
- {
- if (value == "json")
- {
- kind = FuzzKind::JsonParser;
- }
- else if (value == "utf-8")
- {
- kind = FuzzKind::Utf8Decoder;
- }
- else if (value == "platform-expr")
- {
- kind = FuzzKind::PlatformExpr;
- }
- else
- {
- System::print2(System::Color::error, "Invalid kind: ", value, "\n");
- System::print2(System::Color::error, " Expected one of: utf-8, json, platform-expr\n\n");
- print_help_and_exit(true);
- }
- }
- else
- {
- System::print2("Unknown option: ", key, "\n\n");
- print_help_and_exit(true);
- }
- }
- }
-
- // returns {arg, ""} when there isn't an `=`
- // skips preceding `-`s
- std::pair<StringView, StringView> split_arg(StringView arg)
- {
- auto first = std::find_if(arg.begin(), arg.end(), [](char c) { return c != '-'; });
- auto division = std::find(first, arg.end(), '=');
- if (division == arg.end())
- {
- return {StringView(first, arg.end()), StringView(arg.end(), arg.end())};
- }
- else
- {
- return {StringView(first, division), StringView(division + 1, arg.end())};
- }
- }
-
- [[noreturn]] void print_help_and_exit(bool invalid = false)
- {
- constexpr auto help =
- R"(
-Usage: vcpkg-fuzz <options>
-
-Accepts input on stdin.
-
-Options:
- --kind=... One of {utf-8, json}
-)";
-
- auto color = invalid ? System::Color::error : System::Color::success;
-
- System::print2(color, help);
- if (invalid)
- {
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- else
- {
- Checks::exit_success(VCPKG_LINE_INFO);
- }
- }
-
- FuzzKind kind;
- };
-
- std::string read_all_of_stdin()
- {
- std::stringstream ss;
- ss << std::cin.rdbuf();
- return std::move(ss).str();
- }
-
- [[noreturn]] void fuzz_json_and_exit(StringView text)
- {
- auto res = Json::parse(text);
- if (!res)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, res.error()->format());
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- [[noreturn]] void fuzz_utf8_and_exit(StringView text)
- {
- auto res = Unicode::Utf8Decoder(text.begin(), text.end());
- for (auto ch : res)
- {
- (void)ch;
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- [[noreturn]] void fuzz_platform_expr_and_exit(StringView text)
- {
- auto res1 =
- PlatformExpression::parse_platform_expression(text, PlatformExpression::MultipleBinaryOperators::Deny);
- auto res2 =
- PlatformExpression::parse_platform_expression(text, PlatformExpression::MultipleBinaryOperators::Allow);
-
- if (!res1)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, res1.error());
- }
- if (!res2)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, res2.error());
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-}
-
-int main(int argc, char** argv)
-{
- auto args = FuzzArgs(argc, argv);
-
- if (args.kind == FuzzKind::None)
- {
- args.print_help_and_exit(true);
- }
-
- auto text = read_all_of_stdin();
- switch (args.kind)
- {
- case FuzzKind::JsonParser: fuzz_json_and_exit(text);
- case FuzzKind::Utf8Decoder: fuzz_utf8_and_exit(text);
- case FuzzKind::PlatformExpr: fuzz_platform_expr_and_exit(text);
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-}
diff --git a/toolsrc/src/vcpkg-test/arguments.cpp b/toolsrc/src/vcpkg-test/arguments.cpp
deleted file mode 100644
index 7a7c70151..000000000
--- a/toolsrc/src/vcpkg-test/arguments.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/vcpkgcmdarguments.h>
-
-#include <vector>
-
-using vcpkg::CommandSetting;
-using vcpkg::CommandStructure;
-using vcpkg::CommandSwitch;
-using vcpkg::VcpkgCmdArguments;
-
-TEST_CASE ("VcpkgCmdArguments from lowercase argument sequence", "[arguments]")
-{
- std::vector<std::string> t = {"--vcpkg-root",
- "C:\\vcpkg",
- "--x-scripts-root=C:\\scripts",
- "--x-builtin-ports-root=C:\\ports",
- "--x-builtin-registry-versions-dir=C:\\versions",
- "--debug",
- "--sendmetrics",
- "--printmetrics",
- "--overlay-ports=C:\\ports1",
- "--overlay-ports=C:\\ports2",
- "--overlay-triplets=C:\\tripletsA",
- "--overlay-triplets=C:\\tripletsB"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
-
- REQUIRE(*v.vcpkg_root_dir == "C:\\vcpkg");
- REQUIRE(*v.scripts_root_dir == "C:\\scripts");
- REQUIRE(*v.builtin_ports_root_dir == "C:\\ports");
- REQUIRE(*v.builtin_registry_versions_dir == "C:\\versions");
- REQUIRE(v.debug);
- REQUIRE(*v.debug.get());
- REQUIRE(v.send_metrics);
- REQUIRE(*v.send_metrics.get());
- REQUIRE(v.print_metrics);
- REQUIRE(*v.print_metrics.get());
-
- REQUIRE(v.overlay_ports.size() == 2);
- REQUIRE(v.overlay_ports.at(0) == "C:\\ports1");
- REQUIRE(v.overlay_ports.at(1) == "C:\\ports2");
-
- REQUIRE(v.overlay_triplets.size() == 2);
- REQUIRE(v.overlay_triplets.at(0) == "C:\\tripletsA");
- REQUIRE(v.overlay_triplets.at(1) == "C:\\tripletsB");
-}
-
-TEST_CASE ("VcpkgCmdArguments from uppercase argument sequence", "[arguments]")
-{
- std::vector<std::string> t = {"--VCPKG-ROOT",
- "C:\\vcpkg",
- "--X-SCRIPTS-ROOT=C:\\scripts",
- "--X-BUILTIN-PORTS-ROOT=C:\\ports",
- "--X-BUILTIN-REGISTRY-VERSIONS-DIR=C:\\versions",
- "--DEBUG",
- "--SENDMETRICS",
- "--PRINTMETRICS",
- "--OVERLAY-PORTS=C:\\ports1",
- "--OVERLAY-PORTS=C:\\ports2",
- "--OVERLAY-TRIPLETS=C:\\tripletsA",
- "--OVERLAY-TRIPLETS=C:\\tripletsB"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
-
- REQUIRE(*v.vcpkg_root_dir == "C:\\vcpkg");
- REQUIRE(*v.scripts_root_dir == "C:\\scripts");
- REQUIRE(*v.builtin_ports_root_dir == "C:\\ports");
- REQUIRE(*v.builtin_registry_versions_dir == "C:\\versions");
- REQUIRE(v.debug);
- REQUIRE(*v.debug.get());
- REQUIRE(v.send_metrics);
- REQUIRE(*v.send_metrics.get());
- REQUIRE(v.print_metrics);
- REQUIRE(*v.print_metrics.get());
-
- REQUIRE(v.overlay_ports.size() == 2);
- REQUIRE(v.overlay_ports.at(0) == "C:\\ports1");
- REQUIRE(v.overlay_ports.at(1) == "C:\\ports2");
-
- REQUIRE(v.overlay_triplets.size() == 2);
- REQUIRE(v.overlay_triplets.at(0) == "C:\\tripletsA");
- REQUIRE(v.overlay_triplets.at(1) == "C:\\tripletsB");
-}
-
-TEST_CASE ("VcpkgCmdArguments from argument sequence with valued options", "[arguments]")
-{
- SECTION ("case 1")
- {
- std::array<CommandSetting, 1> settings = {{{"a", ""}}};
- CommandStructure cmdstruct = {"", 0, SIZE_MAX, {{}, settings}, nullptr};
-
- std::vector<std::string> t = {"--a=b", "command", "argument"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto opts = v.parse_arguments(cmdstruct);
-
- REQUIRE(opts.settings["a"] == "b");
- REQUIRE(v.command_arguments.size() == 1);
- REQUIRE(v.command_arguments[0] == "argument");
- REQUIRE(v.command == "command");
- }
-
- SECTION ("case 2")
- {
- std::array<CommandSwitch, 2> switches = {{{"a", ""}, {"c", ""}}};
- std::array<CommandSetting, 2> settings = {{{"b", ""}, {"d", ""}}};
- CommandStructure cmdstruct = {"", 0, SIZE_MAX, {switches, settings}, nullptr};
-
- std::vector<std::string> t = {"--a", "--b=c"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto opts = v.parse_arguments(cmdstruct);
-
- REQUIRE(opts.settings["b"] == "c");
- REQUIRE(opts.settings.find("d") == opts.settings.end());
- REQUIRE(opts.switches.find("a") != opts.switches.end());
- REQUIRE(opts.settings.find("c") == opts.settings.end());
- REQUIRE(v.command_arguments.size() == 0);
- }
-}
-
-TEST_CASE ("vcpkg_root parse with arg separator", "[arguments]")
-{
- std::vector<std::string> t = {"--vcpkg-root", "C:\\vcpkg"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto& vcpkg_root_dir = v.vcpkg_root_dir;
- REQUIRE(vcpkg_root_dir);
- REQUIRE(*vcpkg_root_dir == "C:\\vcpkg");
-}
-
-TEST_CASE ("vcpkg_root parse with equal separator", "[arguments]")
-{
- std::vector<std::string> t = {"--vcpkg-root=C:\\vcpkg"};
- auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto& vcpkg_root_dir = v.vcpkg_root_dir;
- REQUIRE(vcpkg_root_dir);
- REQUIRE(*vcpkg_root_dir == "C:\\vcpkg");
-}
diff --git a/toolsrc/src/vcpkg-test/binarycaching.cpp b/toolsrc/src/vcpkg-test/binarycaching.cpp
deleted file mode 100644
index 8a1a28d23..000000000
--- a/toolsrc/src/vcpkg-test/binarycaching.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/xmlserializer.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/binarycaching.private.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-#include <string>
-
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-
-#define REQUIRE_EQUAL_TEXT(lhs, rhs) \
- { \
- auto lhs_lines = Strings::split((lhs), '\n'); \
- auto rhs_lines = Strings::split((rhs), '\n'); \
- for (size_t i = 0; i < lhs_lines.size() && i < rhs_lines.size(); ++i) \
- { \
- INFO("on line: " << i); \
- REQUIRE(lhs_lines[i] == rhs_lines[i]); \
- } \
- REQUIRE(lhs_lines.size() == rhs_lines.size()); \
- }
-
-TEST_CASE ("reformat_version semver-ish", "[reformat_version]")
-{
- REQUIRE(reformat_version("0.0.0", "abitag") == "0.0.0-vcpkgabitag");
- REQUIRE(reformat_version("1.0.1", "abitag") == "1.0.1-vcpkgabitag");
- REQUIRE(reformat_version("1.01.000", "abitag") == "1.1.0-vcpkgabitag");
- REQUIRE(reformat_version("1.2", "abitag") == "1.2.0-vcpkgabitag");
- REQUIRE(reformat_version("v52", "abitag") == "52.0.0-vcpkgabitag");
- REQUIRE(reformat_version("v09.01.02", "abitag") == "9.1.2-vcpkgabitag");
- REQUIRE(reformat_version("1.1.1q", "abitag") == "1.1.1-vcpkgabitag");
- REQUIRE(reformat_version("1", "abitag") == "1.0.0-vcpkgabitag");
-}
-
-TEST_CASE ("reformat_version date", "[reformat_version]")
-{
- REQUIRE(reformat_version("2020-06-26", "abitag") == "2020.6.26-vcpkgabitag");
- REQUIRE(reformat_version("20-06-26", "abitag") == "0.0.0-vcpkgabitag");
- REQUIRE(reformat_version("2020-06-26-release", "abitag") == "2020.6.26-vcpkgabitag");
- REQUIRE(reformat_version("2020-06-26000", "abitag") == "2020.6.26-vcpkgabitag");
-}
-
-TEST_CASE ("reformat_version generic", "[reformat_version]")
-{
- REQUIRE(reformat_version("apr", "abitag") == "0.0.0-vcpkgabitag");
- REQUIRE(reformat_version("", "abitag") == "0.0.0-vcpkgabitag");
-}
-
-TEST_CASE ("generate_nuspec", "[generate_nuspec]")
-{
- auto& fsWrapper = Files::get_real_filesystem();
- VcpkgCmdArguments args = VcpkgCmdArguments::create_from_arg_sequence(nullptr, nullptr);
- args.imbue_from_environment();
- args.packages_root_dir = std::make_unique<std::string>("/");
- auto pkgPath = fsWrapper.absolute(VCPKG_LINE_INFO, fs::u8path("/zlib2_x64-windows")) / fs::u8path("**");
- pkgPath.make_preferred();
- const auto pkgPathStr = fs::u8string(pkgPath);
- VcpkgPaths paths(fsWrapper, args);
-
- auto pghs = Paragraphs::parse_paragraphs(R"(
-Source: zlib2
-Version: 1.5
-Build-Depends: zlib
-Description: a spiffy compression library wrapper
-
-Feature: a
-Description: a feature
-
-Feature: b
-Description: enable bzip capabilities
-Build-Depends: bzip
-)",
- "<testdata>");
- REQUIRE(pghs.has_value());
- auto maybe_scf = SourceControlFile::parse_control_file(fs::u8string(fs::path()), std::move(*pghs.get()));
- REQUIRE(maybe_scf.has_value());
- SourceControlFileLocation scfl{std::move(*maybe_scf.get()), fs::path()};
-
- Dependencies::InstallPlanAction ipa(PackageSpec{"zlib2", Test::X64_WINDOWS},
- scfl,
- Dependencies::RequestType::USER_REQUESTED,
- {{"a", {}}, {"b", {}}});
-
- ipa.abi_info = Build::AbiInfo{};
- ipa.abi_info.get()->package_abi = "packageabi";
- std::string tripletabi("tripletabi");
- ipa.abi_info.get()->triplet_abi = tripletabi;
- Build::CompilerInfo compiler_info;
- compiler_info.hash = "compilerhash";
- compiler_info.id = "compilerid";
- compiler_info.version = "compilerversion";
- ipa.abi_info.get()->compiler_info = compiler_info;
-
- NugetReference ref(ipa);
-
- REQUIRE(ref.nupkg_filename() == "zlib2_x64-windows.1.5.0-vcpkgpackageabi.nupkg");
-
- {
- auto nuspec = generate_nuspec(paths, ipa, ref, {});
- std::string expected = R"(<package>
- <metadata>
- <id>zlib2_x64-windows</id>
- <version>1.5.0-vcpkgpackageabi</version>
- <authors>vcpkg</authors>
- <description>NOT FOR DIRECT USE. Automatically generated cache package.
-
-a spiffy compression library wrapper
-
-Version: 1.5
-Triplet: x64-windows
-CXX Compiler id: compilerid
-CXX Compiler version: compilerversion
-Triplet/Compiler hash: tripletabi
-Features: a, b
-Dependencies:
-</description>
- <packageTypes><packageType name="vcpkg"/></packageTypes>
- </metadata>
- <files><file src=")" + pkgPathStr +
- R"(" target=""/></files>
-</package>
-)";
- REQUIRE_EQUAL_TEXT(nuspec, expected);
- }
-
- {
- auto nuspec = generate_nuspec(paths, ipa, ref, {"urlvalue"});
- std::string expected = R"(<package>
- <metadata>
- <id>zlib2_x64-windows</id>
- <version>1.5.0-vcpkgpackageabi</version>
- <authors>vcpkg</authors>
- <description>NOT FOR DIRECT USE. Automatically generated cache package.
-
-a spiffy compression library wrapper
-
-Version: 1.5
-Triplet: x64-windows
-CXX Compiler id: compilerid
-CXX Compiler version: compilerversion
-Triplet/Compiler hash: tripletabi
-Features: a, b
-Dependencies:
-</description>
- <packageTypes><packageType name="vcpkg"/></packageTypes>
- <repository type="git" url="urlvalue"/>
- </metadata>
- <files><file src=")" + pkgPathStr +
- R"(" target=""/></files>
-</package>
-)";
- REQUIRE_EQUAL_TEXT(nuspec, expected);
- }
- {
- auto nuspec = generate_nuspec(paths, ipa, ref, {"urlvalue", "branchvalue", "commitvalue"});
- std::string expected = R"(<package>
- <metadata>
- <id>zlib2_x64-windows</id>
- <version>1.5.0-vcpkgpackageabi</version>
- <authors>vcpkg</authors>
- <description>NOT FOR DIRECT USE. Automatically generated cache package.
-
-a spiffy compression library wrapper
-
-Version: 1.5
-Triplet: x64-windows
-CXX Compiler id: compilerid
-CXX Compiler version: compilerversion
-Triplet/Compiler hash: tripletabi
-Features: a, b
-Dependencies:
-</description>
- <packageTypes><packageType name="vcpkg"/></packageTypes>
- <repository type="git" url="urlvalue" branch="branchvalue" commit="commitvalue"/>
- </metadata>
- <files><file src=")" + pkgPathStr +
- R"(" target=""/></files>
-</package>
-)";
- REQUIRE_EQUAL_TEXT(nuspec, expected);
- }
-}
-
-TEST_CASE ("XmlSerializer", "[XmlSerializer]")
-{
- XmlSerializer xml;
- xml.open_tag("a");
- xml.open_tag("b");
- xml.simple_tag("c", "d");
- xml.close_tag("b");
- xml.text("escaping: & < > \" '");
-
- REQUIRE(xml.buf == R"(<a><b><c>d</c></b>escaping: &amp; &lt; &gt; &quot; &apos;)");
-
- xml = XmlSerializer();
- xml.emit_declaration();
- xml.start_complex_open_tag("a")
- .text_attr("b", "<")
- .text_attr("c", " ")
- .finish_self_closing_complex_tag()
- .line_break();
- xml.simple_tag("d", "e");
- REQUIRE(xml.buf == R"(<?xml version="1.0" encoding="utf-8"?><a b="&lt;" c=" "/>)"
- "\n<d>e</d>");
-
- xml = XmlSerializer();
- xml.start_complex_open_tag("a").finish_complex_open_tag();
- REQUIRE(xml.buf == R"(<a>)");
-
- xml = XmlSerializer();
- xml.line_break();
- xml.open_tag("a").line_break().line_break();
- xml.close_tag("a").line_break().line_break();
- REQUIRE(xml.buf == "\n<a>\n\n</a>\n\n");
-
- xml = XmlSerializer();
- xml.start_complex_open_tag("a")
- .text_attr("b", "<")
- .line_break()
- .text_attr("c", " ")
- .finish_complex_open_tag()
- .line_break();
- xml.simple_tag("d", "e").line_break();
- REQUIRE(xml.buf == "<a b=\"&lt;\"\n c=\" \">\n <d>e</d>\n");
-}
-
-TEST_CASE ("generate_nuget_packages_config", "[generate_nuget_packages_config]")
-{
- Dependencies::ActionPlan plan;
- auto packageconfig = generate_nuget_packages_config(plan);
- REQUIRE(packageconfig == R"(<?xml version="1.0" encoding="utf-8"?>
-<packages>
-</packages>
-)");
-
- auto pghs = Paragraphs::parse_paragraphs(R"(
-Source: zlib
-Version: 1.5
-Description: a spiffy compression library wrapper
-)",
- "<testdata>");
- REQUIRE(pghs.has_value());
- auto maybe_scf = SourceControlFile::parse_control_file(fs::u8string(fs::path()), std::move(*pghs.get()));
- REQUIRE(maybe_scf.has_value());
- SourceControlFileLocation scfl{std::move(*maybe_scf.get()), fs::path()};
- plan.install_actions.push_back(Dependencies::InstallPlanAction());
- plan.install_actions[0].spec = PackageSpec("zlib", Test::X64_ANDROID);
- plan.install_actions[0].source_control_file_location = scfl;
- plan.install_actions[0].abi_info = Build::AbiInfo{};
- plan.install_actions[0].abi_info.get()->package_abi = "packageabi";
-
- packageconfig = generate_nuget_packages_config(plan);
- REQUIRE(packageconfig == R"(<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="zlib_x64-android" version="1.5.0-vcpkgpackageabi"/>
-</packages>
-)");
-
- auto pghs2 = Paragraphs::parse_paragraphs(R"(
-Source: zlib2
-Version: 1.52
-Description: a spiffy compression library wrapper
-)",
- "<testdata>");
- REQUIRE(pghs2.has_value());
- auto maybe_scf2 = SourceControlFile::parse_control_file(fs::u8string(fs::path()), std::move(*pghs2.get()));
- REQUIRE(maybe_scf2.has_value());
- SourceControlFileLocation scfl2{std::move(*maybe_scf2.get()), fs::path()};
- plan.install_actions.push_back(Dependencies::InstallPlanAction());
- plan.install_actions[1].spec = PackageSpec("zlib2", Test::X64_ANDROID);
- plan.install_actions[1].source_control_file_location = scfl2;
- plan.install_actions[1].abi_info = Build::AbiInfo{};
- plan.install_actions[1].abi_info.get()->package_abi = "packageabi2";
-
- packageconfig = generate_nuget_packages_config(plan);
- REQUIRE(packageconfig == R"(<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="zlib_x64-android" version="1.5.0-vcpkgpackageabi"/>
- <package id="zlib2_x64-android" version="1.52.0-vcpkgpackageabi2"/>
-</packages>
-)");
-}
diff --git a/toolsrc/src/vcpkg-test/binaryconfigparser.cpp b/toolsrc/src/vcpkg-test/binaryconfigparser.cpp
deleted file mode 100644
index 1c46790bf..000000000
--- a/toolsrc/src/vcpkg-test/binaryconfigparser.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/binarycaching.h>
-
-using namespace vcpkg;
-
-#if defined(_WIN32)
-#define ABSOLUTE_PATH "C:\\foo"
-#else
-#define ABSOLUTE_PATH "/foo"
-#endif
-
-TEST_CASE ("BinaryConfigParser empty", "[binaryconfigparser]")
-{
- auto parsed = create_binary_provider_from_configs_pure("", {});
- REQUIRE(parsed.has_value());
-}
-
-TEST_CASE ("BinaryConfigParser unacceptable provider", "[binaryconfigparser]")
-{
- auto parsed = create_binary_provider_from_configs_pure("unacceptable", {});
- REQUIRE(!parsed.has_value());
-}
-
-TEST_CASE ("BinaryConfigParser files provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("files", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files,relative-path", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files,C:foo", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH, {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH ",nonsense", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH ",read", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH ",write", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH ",readwrite", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH ",readwrite,extra", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files,,upload", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser nuget source provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget,relative-path", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget,http://example.org/", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget," ABSOLUTE_PATH, {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget," ABSOLUTE_PATH ",nonsense", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget," ABSOLUTE_PATH ",readwrite", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget," ABSOLUTE_PATH ",readwrite,extra", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nuget,,readwrite", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser nuget config provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig,relative-path", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig,http://example.org/", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig," ABSOLUTE_PATH, {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig," ABSOLUTE_PATH ",nonsense", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig," ABSOLUTE_PATH ",read", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig," ABSOLUTE_PATH ",write", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig," ABSOLUTE_PATH ",readwrite", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig," ABSOLUTE_PATH ",readwrite,extra", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("nugetconfig,,readwrite", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser default provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("default", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("default,nonsense", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("default,read", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("default,readwrite", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("default,write", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("default,read,extra", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser clear provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("clear", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("clear,upload", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser interactive provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("interactive", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("interactive,read", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser multiple providers", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("clear;default", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("clear;default,read", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("clear;default,write", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("clear;default,readwrite", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("clear;default,readwrite;clear;clear", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("clear;files,relative;default", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure(";;;clear;;;;", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure(";;;,;;;;", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser escaping", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure(";;;;;;;`", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure(";;;;;;;`defaul`t", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH "`", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH "`,", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH "``", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH "```", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH "````", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH ",", {});
- REQUIRE(!parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser args", "[binaryconfigparser]")
-{
- {
- auto parsed =
- create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH, std::vector<std::string>{"clear"});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed =
- create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH, std::vector<std::string>{"clear;default"});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH,
- std::vector<std::string>{"clear;default,"});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH,
- std::vector<std::string>{"clear", "clear;default,"});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("files," ABSOLUTE_PATH,
- std::vector<std::string>{"clear", "clear"});
- REQUIRE(parsed.has_value());
- }
-}
-
-TEST_CASE ("BinaryConfigParser azblob provider", "[binaryconfigparser]")
-{
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container,sas", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container,?sas", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,,sas", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container,sas,invalid", {});
- REQUIRE(!parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container,sas,read", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container,sas,write", {});
- REQUIRE(parsed.has_value());
- }
- {
- auto parsed = create_binary_provider_from_configs_pure("x-azblob,https://azure/container,sas,readwrite", {});
- REQUIRE(parsed.has_value());
- }
-}
diff --git a/toolsrc/src/vcpkg-test/catch.cpp b/toolsrc/src/vcpkg-test/catch.cpp
deleted file mode 100644
index fb62c5d06..000000000
--- a/toolsrc/src/vcpkg-test/catch.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#define CATCH_CONFIG_RUNNER
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.h>
-
-int main(int argc, char** argv)
-{
- if (vcpkg::System::get_environment_variable("VCPKG_DEBUG").value_or("") == "1") vcpkg::Debug::g_debugging = true;
-
- return Catch::Session().run(argc, argv);
-}
diff --git a/toolsrc/src/vcpkg-test/chrono.cpp b/toolsrc/src/vcpkg-test/chrono.cpp
deleted file mode 100644
index fb8a0dee9..000000000
--- a/toolsrc/src/vcpkg-test/chrono.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/chrono.h>
-
-namespace Chrono = vcpkg::Chrono;
-
-TEST_CASE ("parse time", "[chrono]")
-{
- auto timestring = "1990-02-03T04:05:06.0Z";
- auto maybe_time = Chrono::CTime::parse(timestring);
-
- REQUIRE(maybe_time.has_value());
- REQUIRE(maybe_time.get()->to_string() == timestring);
-}
-
-TEST_CASE ("parse blank time", "[chrono]")
-{
- auto maybe_time = Chrono::CTime::parse("");
-
- REQUIRE_FALSE(maybe_time.has_value());
-}
-
-TEST_CASE ("difference of times", "[chrono]")
-{
- auto maybe_time1 = Chrono::CTime::parse("1990-02-03T04:05:06.0Z");
- auto maybe_time2 = Chrono::CTime::parse("1990-02-10T04:05:06.0Z");
-
- REQUIRE(maybe_time1.has_value());
- REQUIRE(maybe_time2.has_value());
-
- auto delta = maybe_time2.get()->to_time_point() - maybe_time1.get()->to_time_point();
-
- REQUIRE(std::chrono::duration_cast<std::chrono::hours>(delta).count() == 24 * 7);
-}
diff --git a/toolsrc/src/vcpkg-test/commands.cpp b/toolsrc/src/vcpkg-test/commands.cpp
deleted file mode 100644
index 1a582beb3..000000000
--- a/toolsrc/src/vcpkg-test/commands.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/commands.contact.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/commands.upload-metrics.h>
-#include <vcpkg/commands.version.h>
-
-#include <stddef.h>
-
-using namespace vcpkg;
-
-namespace
-{
- template<class CommandListT, size_t ExpectedCount>
- void check_all_commands(const CommandListT& actual_commands, const char* const (&expected_commands)[ExpectedCount])
- {
- CHECK(actual_commands.size() == ExpectedCount); // makes sure this test is updated if we add a command
- for (const char* expected_command : expected_commands)
- {
- CHECK(Commands::find(StringView{expected_command, strlen(expected_command)}, actual_commands) != nullptr);
- }
-
- CHECK(Commands::find("x-never-will-exist", actual_commands) == nullptr);
- }
-} // unnamed namespace
-
-// clang-format tries to wrap the following lists inappropriately
-
-// clang-format off
-TEST_CASE ("get_available_basic_commands works", "[commands]")
-{
- check_all_commands(Commands::get_available_basic_commands(), {
- "contact",
- "version",
-#if defined(_WIN32)
- "x-upload-metrics",
-#endif // defined(_WIN32)
- });
-}
-
-TEST_CASE ("get_available_paths_commands works", "[commands]")
-{
- check_all_commands(Commands::get_available_paths_commands(), {
- "/?",
- "help",
- "search",
- "list",
- "integrate",
- "owns",
- "update",
- "edit",
- "create",
- "cache",
- "portsdiff",
- "autocomplete",
- "hash",
- "fetch",
- "format-manifest",
- "x-ci-clean",
- "x-history",
- "x-package-info",
- "x-vsinstances",
- "x-ci-verify-versions",
- "x-add-version",
- });
-}
-
-TEST_CASE ("get_available_commands_type_a works", "[commands]")
-{
- check_all_commands(Commands::get_available_triplet_commands(), {
- "install",
- "x-set-installed",
- "ci",
- "remove",
- "upgrade",
- "build",
- "env",
- "build-external",
- "export",
- "depend-info",
- });
-}
-// clang-format on
diff --git a/toolsrc/src/vcpkg-test/dependencies.cpp b/toolsrc/src/vcpkg-test/dependencies.cpp
deleted file mode 100644
index c6241ebe0..000000000
--- a/toolsrc/src/vcpkg-test/dependencies.cpp
+++ /dev/null
@@ -1,1713 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/graphs.h>
-
-#include <vcpkg/dependencies.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/triplet.h>
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include <vcpkg-test/mockcmakevarprovider.h>
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-
-using Test::make_control_file;
-using Test::make_status_feature_pgh;
-using Test::make_status_pgh;
-using Test::MockCMakeVarProvider;
-using Test::PackageSpecMap;
-
-struct MockBaselineProvider : PortFileProvider::IBaselineProvider
-{
- mutable std::map<std::string, Versions::Version, std::less<>> v;
-
- Optional<Versions::Version> get_baseline_version(StringView name) const override
- {
- auto it = v.find(name);
- if (it == v.end()) return nullopt;
- return it->second;
- }
-};
-
-struct MockVersionedPortfileProvider : PortFileProvider::IVersionedPortfileProvider
-{
- mutable std::map<std::string, std::map<Versions::Version, SourceControlFileLocation, VersionTMapLess>> v;
-
- ExpectedS<const SourceControlFileLocation&> get_control_file(
- const vcpkg::Versions::VersionSpec& versionspec) const override
- {
- return get_control_file(versionspec.port_name, versionspec.version);
- }
-
- ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& name,
- const vcpkg::Versions::Version& version) const
- {
- auto it = v.find(name);
- if (it == v.end()) return std::string("Unknown port name");
- auto it2 = it->second.find(version);
- if (it2 == it->second.end()) return std::string("Unknown port version");
- return it2->second;
- }
-
- virtual View<vcpkg::VersionT> get_port_versions(StringView) const override { Checks::unreachable(VCPKG_LINE_INFO); }
-
- SourceControlFileLocation& emplace(std::string&& name,
- Versions::Version&& version,
- Versions::Scheme scheme = Versions::Scheme::String)
- {
- auto it = v.find(name);
- if (it == v.end())
- it = v.emplace(name, std::map<Versions::Version, SourceControlFileLocation, VersionTMapLess>{}).first;
-
- auto it2 = it->second.find(version);
- if (it2 == it->second.end())
- {
- auto scf = std::make_unique<SourceControlFile>();
- auto core = std::make_unique<SourceParagraph>();
- core->name = name;
- core->version = version.text();
- core->port_version = version.port_version();
- core->version_scheme = scheme;
- scf->core_paragraph = std::move(core);
- it2 = it->second.emplace(version, SourceControlFileLocation{std::move(scf), fs::u8path(name)}).first;
- }
- return it2->second;
- }
-
- virtual void load_all_control_files(std::map<std::string, const SourceControlFileLocation*>&) const override
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-};
-
-using Versions::Constraint;
-using Versions::Scheme;
-
-template<class T>
-T unwrap(ExpectedS<T> e)
-{
- if (!e.has_value())
- {
- INFO(e.error());
- REQUIRE(false);
- }
- return std::move(*e.get());
-}
-
-static void check_name_and_version(const Dependencies::InstallPlanAction& ipa,
- StringLiteral name,
- Versions::Version v,
- std::initializer_list<StringLiteral> features = {})
-{
- CHECK(ipa.spec.name() == name);
- CHECK(ipa.source_control_file_location.has_value());
- CHECK(ipa.feature_list.size() == features.size() + 1);
- {
- INFO("ipa.feature_list = [" << Strings::join(", ", ipa.feature_list) << "]");
- for (auto&& f : features)
- {
- INFO("f = \"" << f.c_str() << "\"");
- CHECK(Util::find(ipa.feature_list, f) != ipa.feature_list.end());
- }
- CHECK(Util::find(ipa.feature_list, "core") != ipa.feature_list.end());
- }
- if (auto scfl = ipa.source_control_file_location.get())
- {
- CHECK(scfl->source_control_file->core_paragraph->version == v.text());
- CHECK(scfl->source_control_file->core_paragraph->port_version == v.port_version());
- }
-}
-
-static void check_semver_version(const ExpectedS<Versions::SemanticVersion>& maybe_version,
- const std::string& version_string,
- const std::string& prerelease_string,
- uint64_t major,
- uint64_t minor,
- uint64_t patch,
- const std::vector<std::string>& identifiers)
-{
- auto actual_version = unwrap(maybe_version);
- CHECK(actual_version.version_string == version_string);
- CHECK(actual_version.prerelease_string == prerelease_string);
- REQUIRE(actual_version.version.size() == 3);
- CHECK(actual_version.version[0] == major);
- CHECK(actual_version.version[1] == minor);
- CHECK(actual_version.version[2] == patch);
- CHECK(actual_version.identifiers == identifiers);
-}
-
-static void check_relaxed_version(const ExpectedS<Versions::RelaxedVersion>& maybe_version,
- const std::vector<uint64_t>& version)
-{
- auto actual_version = unwrap(maybe_version);
- CHECK(actual_version.version == version);
-}
-
-static void check_date_version(const ExpectedS<Versions::DateVersion>& maybe_version,
- const std::string& version_string,
- const std::string& identifiers_string,
- const std::vector<uint64_t>& identifiers)
-{
- auto actual_version = unwrap(maybe_version);
- CHECK(actual_version.version_string == version_string);
- CHECK(actual_version.identifiers_string == identifiers_string);
- CHECK(actual_version.identifiers == identifiers);
-}
-
-static const PackageSpec& toplevel_spec()
-{
- static const PackageSpec ret("toplevel-spec", Test::X86_WINDOWS);
- return ret;
-}
-
-struct MockOverlayProvider : PortFileProvider::IOverlayProvider, Util::ResourceBase
-{
- virtual Optional<const SourceControlFileLocation&> get_control_file(StringView name) const override
- {
- auto it = mappings.find(name);
- if (it != mappings.end())
- return it->second;
- else
- return nullopt;
- }
-
- SourceControlFileLocation& emplace(const std::string& name,
- Versions::Version&& version,
- Versions::Scheme scheme = Versions::Scheme::String)
- {
- auto it = mappings.find(name);
- if (it == mappings.end())
- {
- auto scf = std::make_unique<SourceControlFile>();
- auto core = std::make_unique<SourceParagraph>();
- core->name = name;
- core->version = version.text();
- core->port_version = version.port_version();
- core->version_scheme = scheme;
- scf->core_paragraph = std::move(core);
- it = mappings.emplace(name, SourceControlFileLocation{std::move(scf), fs::u8path(name)}).first;
- }
- return it->second;
- }
-
- virtual void load_all_control_files(std::map<std::string, const SourceControlFileLocation*>&) const override
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
-private:
- std::map<std::string, SourceControlFileLocation, std::less<>> mappings;
-};
-
-static const MockOverlayProvider s_empty_mock_overlay;
-
-static ExpectedS<Dependencies::ActionPlan> create_versioned_install_plan(
- const PortFileProvider::IVersionedPortfileProvider& provider,
- const PortFileProvider::IBaselineProvider& bprovider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const std::vector<Dependency>& deps,
- const std::vector<DependencyOverride>& overrides,
- const PackageSpec& toplevel)
-{
- return Dependencies::create_versioned_install_plan(
- provider, bprovider, s_empty_mock_overlay, var_provider, deps, overrides, toplevel);
-}
-
-TEST_CASE ("basic version install single", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"a"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- REQUIRE(install_plan.install_actions.at(0).spec.name() == "a");
-}
-
-TEST_CASE ("basic version install detect cycle", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{}},
- };
- vp.emplace("b", {"1", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"a", {}, {}, DependencyConstraint{}},
- };
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = create_versioned_install_plan(vp, bp, var_provider, {{"a"}}, {}, toplevel_spec());
-
- REQUIRE(!install_plan.has_value());
-}
-
-TEST_CASE ("basic version install scheme", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{}},
- };
- vp.emplace("b", {"1", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"a"}}, {}, toplevel_spec()));
-
- CHECK(install_plan.size() == 2);
-
- StringLiteral names[] = {"b", "a"};
- for (size_t i = 0; i < install_plan.install_actions.size() && i < 2; ++i)
- {
- CHECK(install_plan.install_actions[i].spec.name() == names[i]);
- }
-}
-
-TEST_CASE ("basic version install scheme diamond", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
- bp.v["d"] = {"1", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{}},
- Dependency{"c", {}, {}, DependencyConstraint{}},
- };
- vp.emplace("b", {"1", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, DependencyConstraint{}},
- Dependency{"d", {}, {}, DependencyConstraint{}},
- };
- vp.emplace("c", {"1", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"d", {}, {}, DependencyConstraint{}},
- };
- vp.emplace("d", {"1", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"a"}}, {}, toplevel_spec()));
-
- CHECK(install_plan.size() == 4);
-
- StringLiteral names[] = {"d", "c", "b", "a"};
- for (size_t i = 0; i < install_plan.install_actions.size() && i < 4; ++i)
- {
- CHECK(install_plan.install_actions[i].spec.name() == names[i]);
- }
-}
-
-TEST_CASE ("basic version install scheme baseline missing", "[versionplan]")
-{
- MockBaselineProvider bp;
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = create_versioned_install_plan(vp, bp, var_provider, {{"a"}}, {}, toplevel_spec());
-
- REQUIRE(!install_plan.has_value());
-}
-
-TEST_CASE ("basic version install scheme baseline missing success", "[versionplan]")
-{
- MockBaselineProvider bp;
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
- vp.emplace("a", {"2", 0});
- vp.emplace("a", {"3", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2"}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"2", 0});
-}
-
-TEST_CASE ("basic version install scheme baseline", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
- vp.emplace("a", {"2", 0});
- vp.emplace("a", {"3", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"a"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"2", 0});
-}
-
-TEST_CASE ("version string baseline agree", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
- vp.emplace("a", {"2", 0});
- vp.emplace("a", {"3", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = create_versioned_install_plan(
- vp, bp, var_provider, {Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2"}}}, {}, toplevel_spec());
-
- REQUIRE(install_plan.has_value());
-}
-
-TEST_CASE ("version install scheme baseline conflict", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
- vp.emplace("a", {"2", 0});
- vp.emplace("a", {"3", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3"}},
- },
- {},
- toplevel_spec());
-
- REQUIRE(!install_plan.has_value());
-}
-
-TEST_CASE ("version install string port version", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0});
- vp.emplace("a", {"2", 1});
- vp.emplace("a", {"2", 2});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"2", 1});
-}
-
-TEST_CASE ("version install string port version 2", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 1};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0});
- vp.emplace("a", {"2", 1});
- vp.emplace("a", {"2", 2});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"2", 1});
-}
-
-TEST_CASE ("version install transitive string", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "1"}},
- };
- vp.emplace("a", {"2", 1}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2"}},
- };
- vp.emplace("b", {"1", 0});
- vp.emplace("b", {"2", 0});
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"2", 0});
- check_name_and_version(install_plan.install_actions[1], "a", {"2", 1});
-}
-
-TEST_CASE ("version install simple relaxed", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0}, Scheme::Relaxed);
- vp.emplace("a", {"3", 0}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"3", 0});
-}
-
-TEST_CASE ("version install transitive relaxed", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
- bp.v["b"] = {"2", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0}, Scheme::Relaxed);
- vp.emplace("a", {"3", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "3"}},
- };
- vp.emplace("b", {"2", 0}, Scheme::Relaxed);
- vp.emplace("b", {"3", 0}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"3", 0});
- check_name_and_version(install_plan.install_actions[1], "a", {"3", 0});
-}
-
-TEST_CASE ("version install diamond relaxed", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
- bp.v["b"] = {"3", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0}, Scheme::Relaxed);
- vp.emplace("a", {"3", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2", 1}},
- Dependency{"c", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "5", 1}},
- };
- vp.emplace("b", {"2", 1}, Scheme::Relaxed);
- vp.emplace("b", {"3", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "9", 2}},
- };
- vp.emplace("c", {"5", 1}, Scheme::Relaxed);
- vp.emplace("c", {"9", 2}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3", 0}},
- Dependency{"b", {}, {}, {Constraint::Type::Minimum, "2", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 3);
- check_name_and_version(install_plan.install_actions[0], "c", {"9", 2});
- check_name_and_version(install_plan.install_actions[1], "b", {"3", 0});
- check_name_and_version(install_plan.install_actions[2], "a", {"3", 0});
-}
-
-TEST_CASE ("version parse semver", "[versionplan]")
-{
- auto version_basic = Versions::SemanticVersion::from_string("1.2.3");
- check_semver_version(version_basic, "1.2.3", "", 1, 2, 3, {});
-
- auto version_simple_tag = Versions::SemanticVersion::from_string("1.0.0-alpha");
- check_semver_version(version_simple_tag, "1.0.0", "alpha", 1, 0, 0, {"alpha"});
-
- auto version_alphanumeric_tag = Versions::SemanticVersion::from_string("1.0.0-0alpha0");
- check_semver_version(version_alphanumeric_tag, "1.0.0", "0alpha0", 1, 0, 0, {"0alpha0"});
-
- auto version_complex_tag = Versions::SemanticVersion::from_string("1.0.0-alpha.1.0.0");
- check_semver_version(version_complex_tag, "1.0.0", "alpha.1.0.0", 1, 0, 0, {"alpha", "1", "0", "0"});
-
- auto version_complexer_tag = Versions::SemanticVersion::from_string("1.0.0-alpha.1.x.y.z.0-alpha.0-beta.l-a-s-t");
- check_semver_version(version_complexer_tag,
- "1.0.0",
- "alpha.1.x.y.z.0-alpha.0-beta.l-a-s-t",
- 1,
- 0,
- 0,
- {"alpha", "1", "x", "y", "z", "0-alpha", "0-beta", "l-a-s-t"});
-
- auto version_ridiculous_tag = Versions::SemanticVersion::from_string("1.0.0----------------------------------");
- check_semver_version(version_ridiculous_tag,
- "1.0.0",
- "---------------------------------",
- 1,
- 0,
- 0,
- {"---------------------------------"});
-
- auto version_build_tag = Versions::SemanticVersion::from_string("1.0.0+build");
- check_semver_version(version_build_tag, "1.0.0", "", 1, 0, 0, {});
-
- auto version_prerelease_build_tag = Versions::SemanticVersion::from_string("1.0.0-alpha+build");
- check_semver_version(version_prerelease_build_tag, "1.0.0", "alpha", 1, 0, 0, {"alpha"});
-
- auto version_invalid_incomplete = Versions::SemanticVersion::from_string("1.0-alpha");
- CHECK(!version_invalid_incomplete.has_value());
-
- auto version_invalid_leading_zeroes = Versions::SemanticVersion::from_string("1.02.03-alpha+build");
- CHECK(!version_invalid_leading_zeroes.has_value());
-
- auto version_invalid_leading_zeroes_in_tag = Versions::SemanticVersion::from_string("1.0.0-01");
- CHECK(!version_invalid_leading_zeroes_in_tag.has_value());
-
- auto version_invalid_characters = Versions::SemanticVersion::from_string("1.0.0-alpha#2");
- CHECK(!version_invalid_characters.has_value());
-}
-
-TEST_CASE ("version parse relaxed", "[versionplan]")
-{
- auto version_basic = Versions::RelaxedVersion::from_string("1.2.3");
- check_relaxed_version(version_basic, {1, 2, 3});
-
- auto version_short = Versions::RelaxedVersion::from_string("1");
- check_relaxed_version(version_short, {1});
-
- auto version_long =
- Versions::RelaxedVersion::from_string("1.20.300.4000.50000.6000000.70000000.80000000.18446744073709551610");
- check_relaxed_version(version_long, {1, 20, 300, 4000, 50000, 6000000, 70000000, 80000000, 18446744073709551610u});
-
- auto version_invalid_characters = Versions::RelaxedVersion::from_string("1.a.0");
- CHECK(!version_invalid_characters.has_value());
-
- auto version_invalid_identifiers_2 = Versions::RelaxedVersion::from_string("1.1a.2");
- CHECK(!version_invalid_identifiers_2.has_value());
-
- auto version_invalid_leading_zeroes = Versions::RelaxedVersion::from_string("01.002.003");
- CHECK(!version_invalid_leading_zeroes.has_value());
-}
-
-TEST_CASE ("version parse date", "[versionplan]")
-{
- auto version_basic = Versions::DateVersion::from_string("2020-12-25");
- check_date_version(version_basic, "2020-12-25", "", {});
-
- auto version_identifiers = Versions::DateVersion::from_string("2020-12-25.1.2.3");
- check_date_version(version_identifiers, "2020-12-25", "1.2.3", {1, 2, 3});
-
- auto version_invalid_date = Versions::DateVersion::from_string("2020-1-1");
- CHECK(!version_invalid_date.has_value());
-
- auto version_invalid_identifiers = Versions::DateVersion::from_string("2020-01-01.alpha");
- CHECK(!version_invalid_identifiers.has_value());
-
- auto version_invalid_identifiers_2 = Versions::DateVersion::from_string("2020-01-01.2a");
- CHECK(!version_invalid_identifiers_2.has_value());
-
- auto version_invalid_leading_zeroes = Versions::DateVersion::from_string("2020-01-01.01");
- CHECK(!version_invalid_leading_zeroes.has_value());
-}
-
-TEST_CASE ("version sort semver", "[versionplan]")
-{
- std::vector<Versions::SemanticVersion> versions{unwrap(Versions::SemanticVersion::from_string("1.0.0")),
- unwrap(Versions::SemanticVersion::from_string("0.0.0")),
- unwrap(Versions::SemanticVersion::from_string("1.1.0")),
- unwrap(Versions::SemanticVersion::from_string("2.0.0")),
- unwrap(Versions::SemanticVersion::from_string("1.1.1")),
- unwrap(Versions::SemanticVersion::from_string("1.0.1")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-alpha.1")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-beta")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-alpha")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-alpha.beta")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-rc")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-beta.2")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-beta.20")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-beta.3")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-1")),
- unwrap(Versions::SemanticVersion::from_string("1.0.0-0alpha"))};
-
- std::sort(std::begin(versions), std::end(versions), [](const auto& lhs, const auto& rhs) -> bool {
- return Versions::compare(lhs, rhs) == Versions::VerComp::lt;
- });
-
- CHECK(versions[0].original_string == "0.0.0");
- CHECK(versions[1].original_string == "1.0.0-1");
- CHECK(versions[2].original_string == "1.0.0-0alpha");
- CHECK(versions[3].original_string == "1.0.0-alpha");
- CHECK(versions[4].original_string == "1.0.0-alpha.1");
- CHECK(versions[5].original_string == "1.0.0-alpha.beta");
- CHECK(versions[6].original_string == "1.0.0-beta");
- CHECK(versions[7].original_string == "1.0.0-beta.2");
- CHECK(versions[8].original_string == "1.0.0-beta.3");
- CHECK(versions[9].original_string == "1.0.0-beta.20");
- CHECK(versions[10].original_string == "1.0.0-rc");
- CHECK(versions[11].original_string == "1.0.0");
- CHECK(versions[12].original_string == "1.0.1");
- CHECK(versions[13].original_string == "1.1.0");
- CHECK(versions[14].original_string == "1.1.1");
- CHECK(versions[15].original_string == "2.0.0");
-}
-
-TEST_CASE ("version sort relaxed", "[versionplan]")
-{
- std::vector<Versions::RelaxedVersion> versions{unwrap(Versions::RelaxedVersion::from_string("1.0.0")),
- unwrap(Versions::RelaxedVersion::from_string("1.0")),
- unwrap(Versions::RelaxedVersion::from_string("1")),
- unwrap(Versions::RelaxedVersion::from_string("2")),
- unwrap(Versions::RelaxedVersion::from_string("1.1")),
- unwrap(Versions::RelaxedVersion::from_string("1.10.1")),
- unwrap(Versions::RelaxedVersion::from_string("1.0.1")),
- unwrap(Versions::RelaxedVersion::from_string("1.0.0.1")),
- unwrap(Versions::RelaxedVersion::from_string("1.0.0.2"))};
-
- std::sort(std::begin(versions), std::end(versions), [](const auto& lhs, const auto& rhs) -> bool {
- return Versions::compare(lhs, rhs) == Versions::VerComp::lt;
- });
-
- CHECK(versions[0].original_string == "1");
- CHECK(versions[1].original_string == "1.0");
- CHECK(versions[2].original_string == "1.0.0");
- CHECK(versions[3].original_string == "1.0.0.1");
- CHECK(versions[4].original_string == "1.0.0.2");
- CHECK(versions[5].original_string == "1.0.1");
- CHECK(versions[6].original_string == "1.1");
- CHECK(versions[7].original_string == "1.10.1");
- CHECK(versions[8].original_string == "2");
-}
-
-TEST_CASE ("version sort date", "[versionplan]")
-{
- std::vector<Versions::DateVersion> versions{unwrap(Versions::DateVersion::from_string("2021-01-01.2")),
- unwrap(Versions::DateVersion::from_string("2021-01-01.1")),
- unwrap(Versions::DateVersion::from_string("2021-01-01.1.1")),
- unwrap(Versions::DateVersion::from_string("2021-01-01.1.0")),
- unwrap(Versions::DateVersion::from_string("2021-01-01")),
- unwrap(Versions::DateVersion::from_string("2021-01-01")),
- unwrap(Versions::DateVersion::from_string("2020-12-25")),
- unwrap(Versions::DateVersion::from_string("2020-12-31")),
- unwrap(Versions::DateVersion::from_string("2021-01-01.10"))};
-
- std::sort(std::begin(versions), std::end(versions), [](const auto& lhs, const auto& rhs) -> bool {
- return Versions::compare(lhs, rhs) == Versions::VerComp::lt;
- });
-
- CHECK(versions[0].original_string == "2020-12-25");
- CHECK(versions[1].original_string == "2020-12-31");
- CHECK(versions[2].original_string == "2021-01-01");
- CHECK(versions[3].original_string == "2021-01-01");
- CHECK(versions[4].original_string == "2021-01-01.1");
- CHECK(versions[5].original_string == "2021-01-01.1.0");
- CHECK(versions[6].original_string == "2021-01-01.1.1");
- CHECK(versions[7].original_string == "2021-01-01.2");
- CHECK(versions[8].original_string == "2021-01-01.10");
-}
-
-TEST_CASE ("version install simple semver", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2.0.0", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2.0.0", 0}, Scheme::Semver);
- vp.emplace("a", {"3.0.0", 0}, Scheme::Semver);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3.0.0", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"3.0.0", 0});
-}
-
-TEST_CASE ("version install transitive semver", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2.0.0", 0};
- bp.v["b"] = {"2.0.0", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2.0.0", 0}, Scheme::Semver);
- vp.emplace("a", {"3.0.0", 0}, Scheme::Semver).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "3.0.0"}},
- };
- vp.emplace("b", {"2.0.0", 0}, Scheme::Semver);
- vp.emplace("b", {"3.0.0", 0}, Scheme::Semver);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3.0.0", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"3.0.0", 0});
- check_name_and_version(install_plan.install_actions[1], "a", {"3.0.0", 0});
-}
-
-TEST_CASE ("version install diamond semver", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2.0.0", 0};
- bp.v["b"] = {"3.0.0", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2.0.0", 0}, Scheme::Semver);
- vp.emplace("a", {"3.0.0", 0}, Scheme::Semver).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2.0.0", 1}},
- Dependency{"c", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "5.0.0", 1}},
- };
- vp.emplace("b", {"2.0.0", 1}, Scheme::Semver);
- vp.emplace("b", {"3.0.0", 0}, Scheme::Semver).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "9.0.0", 2}},
- };
- vp.emplace("c", {"5.0.0", 1}, Scheme::Semver);
- vp.emplace("c", {"9.0.0", 2}, Scheme::Semver);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "3.0.0", 0}},
- Dependency{"b", {}, {}, {Constraint::Type::Minimum, "2.0.0", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 3);
- check_name_and_version(install_plan.install_actions[0], "c", {"9.0.0", 2});
- check_name_and_version(install_plan.install_actions[1], "b", {"3.0.0", 0});
- check_name_and_version(install_plan.install_actions[2], "a", {"3.0.0", 0});
-}
-
-TEST_CASE ("version install simple date", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2020-02-01", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2020-02-01", 0}, Scheme::Date);
- vp.emplace("a", {"2020-03-01", 0}, Scheme::Date);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2020-03-01", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"2020-03-01", 0});
-}
-
-TEST_CASE ("version install transitive date", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2020-01-01.2", 0};
- bp.v["b"] = {"2020-01-01.3", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2020-01-01.2", 0}, Scheme::Date);
- vp.emplace("a", {"2020-01-01.3", 0}, Scheme::Date).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2020-01-01.3"}},
- };
- vp.emplace("b", {"2020-01-01.2", 0}, Scheme::Date);
- vp.emplace("b", {"2020-01-01.3", 0}, Scheme::Date);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan = unwrap(
- create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2020-01-01.3", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"2020-01-01.3", 0});
- check_name_and_version(install_plan.install_actions[1], "a", {"2020-01-01.3", 0});
-}
-
-TEST_CASE ("version install diamond date", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"2020-01-02", 0};
- bp.v["b"] = {"2020-01-03", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2020-01-02", 0}, Scheme::Date);
- vp.emplace("a", {"2020-01-03", 0}, Scheme::Date).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2020-01-02", 1}},
- Dependency{"c", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2020-01-05", 1}},
- };
- vp.emplace("b", {"2020-01-02", 1}, Scheme::Date);
- vp.emplace("b", {"2020-01-03", 0}, Scheme::Date).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "2020-01-09", 2}},
- };
- vp.emplace("c", {"2020-01-05", 1}, Scheme::Date);
- vp.emplace("c", {"2020-01-09", 2}, Scheme::Date);
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2020-01-03", 0}},
- Dependency{"b", {}, {}, {Constraint::Type::Minimum, "2020-01-02", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 3);
- check_name_and_version(install_plan.install_actions[0], "c", {"2020-01-09", 2});
- check_name_and_version(install_plan.install_actions[1], "b", {"2020-01-03", 0});
- check_name_and_version(install_plan.install_actions[2], "a", {"2020-01-03", 0});
-}
-
-TEST_CASE ("version install scheme failure", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1.0.0", 0}, Scheme::Semver);
- vp.emplace("a", {"1.0.1", 0}, Scheme::Relaxed);
- vp.emplace("a", {"1.0.2", 0}, Scheme::Semver);
-
- MockCMakeVarProvider var_provider;
-
- SECTION ("lower baseline")
- {
- MockBaselineProvider bp;
- bp.v["a"] = {"1.0.0", 0};
-
- auto install_plan =
- create_versioned_install_plan(vp,
- bp,
- var_provider,
- {Dependency{"a", {}, {}, {Constraint::Type::Minimum, "1.0.1", 0}}},
- {},
- toplevel_spec());
-
- REQUIRE(!install_plan.error().empty());
- CHECK(install_plan.error() == "Version conflict on a@1.0.1: baseline required 1.0.0");
- }
- SECTION ("higher baseline")
- {
- MockBaselineProvider bp;
- bp.v["a"] = {"1.0.2", 0};
-
- auto install_plan =
- create_versioned_install_plan(vp,
- bp,
- var_provider,
- {Dependency{"a", {}, {}, {Constraint::Type::Minimum, "1.0.1", 0}}},
- {},
- toplevel_spec());
-
- REQUIRE(!install_plan.error().empty());
- CHECK(install_plan.error() == "Version conflict on a@1.0.1: baseline required 1.0.2");
- }
-}
-
-TEST_CASE ("version install scheme change in port version", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"2", 0}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "1"}},
- };
- vp.emplace("a", {"2", 1}).source_control_file->core_paragraph->dependencies = {
- Dependency{"b", {}, {}, DependencyConstraint{Constraint::Type::Minimum, "1", 1}},
- };
- vp.emplace("b", {"1", 0}, Scheme::String);
- vp.emplace("b", {"1", 1}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
-
- SECTION ("lower baseline")
- {
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 0};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"1", 1});
- check_name_and_version(install_plan.install_actions[1], "a", {"2", 1});
- }
- SECTION ("higher baseline")
- {
- MockBaselineProvider bp;
- bp.v["a"] = {"2", 1};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "2", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"1", 1});
- check_name_and_version(install_plan.install_actions[1], "a", {"2", 1});
- }
-}
-
-TEST_CASE ("version install simple feature", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
- auto a_x = std::make_unique<FeatureParagraph>();
- a_x->name = "x";
- vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file->feature_paragraphs.push_back(std::move(a_x));
-
- MockCMakeVarProvider var_provider;
-
- SECTION ("with baseline")
- {
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
-
- auto install_plan = unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {"x"}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
- }
-
- SECTION ("without baseline")
- {
- MockBaselineProvider bp;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {"x"}, {}, {Constraint::Type::Minimum, "1", 0}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
- }
-}
-
-static std::unique_ptr<FeatureParagraph> make_fpgh(std::string name)
-{
- auto f = std::make_unique<FeatureParagraph>();
- f->name = std::move(name);
- return f;
-}
-
-TEST_CASE ("version install transitive features", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto a_x = make_fpgh("x");
- a_x->dependencies.push_back(Dependency{"b", {"y"}});
- vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file->feature_paragraphs.push_back(std::move(a_x));
-
- auto b_y = make_fpgh("y");
- vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file->feature_paragraphs.push_back(std::move(b_y));
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
-
- auto install_plan = unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {"x"}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "b", {"1", 0}, {"y"});
- check_name_and_version(install_plan.install_actions[1], "a", {"1", 0}, {"x"});
-}
-
-TEST_CASE ("version install transitive feature versioned", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto a_x = make_fpgh("x");
- a_x->dependencies.push_back(Dependency{"b", {"y"}, {}, {Constraint::Type::Minimum, "2", 0}});
- vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file->feature_paragraphs.push_back(std::move(a_x));
-
- {
- auto b_y = make_fpgh("y");
- vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file->feature_paragraphs.push_back(std::move(b_y));
- }
- {
- auto b_y = make_fpgh("y");
- b_y->dependencies.push_back(Dependency{"c"});
- vp.emplace("b", {"2", 0}, Scheme::Relaxed).source_control_file->feature_paragraphs.push_back(std::move(b_y));
- }
-
- vp.emplace("c", {"1", 0}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["c"] = {"1", 0};
-
- auto install_plan = unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"a", {"x"}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 3);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- check_name_and_version(install_plan.install_actions[1], "b", {"2", 0}, {"y"});
- check_name_and_version(install_plan.install_actions[2], "a", {"1", 0}, {"x"});
-}
-
-TEST_CASE ("version install constraint-reduction", "[versionplan]")
-{
- MockCMakeVarProvider var_provider;
-
- SECTION ("higher baseline")
- {
- MockVersionedPortfileProvider vp;
-
- vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, {Constraint::Type::Minimum, "2"}},
- };
- vp.emplace("b", {"2", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, {Constraint::Type::Minimum, "1"}},
- };
-
- vp.emplace("c", {"1", 0}, Scheme::Relaxed);
- // c@2 is used to detect if certain constraints were evaluated
- vp.emplace("c", {"2", 0}, Scheme::Relaxed);
-
- MockBaselineProvider bp;
- bp.v["b"] = {"2", 0};
- bp.v["c"] = {"1", 0};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"b", {}, {}, {Constraint::Type::Minimum, "1"}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- check_name_and_version(install_plan.install_actions[1], "b", {"2", 0});
- }
-
- SECTION ("higher toplevel")
- {
- MockVersionedPortfileProvider vp;
-
- vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, {Constraint::Type::Minimum, "2"}},
- };
- vp.emplace("b", {"2", 0}, Scheme::Relaxed).source_control_file->core_paragraph->dependencies = {
- Dependency{"c", {}, {}, {Constraint::Type::Minimum, "1"}},
- };
-
- vp.emplace("c", {"1", 0}, Scheme::Relaxed);
- // c@2 is used to detect if certain constraints were evaluated
- vp.emplace("c", {"2", 0}, Scheme::Relaxed);
-
- MockBaselineProvider bp;
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {
- Dependency{"b", {}, {}, {Constraint::Type::Minimum, "2"}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- check_name_and_version(install_plan.install_actions[1], "b", {"2", 0});
- }
-}
-
-TEST_CASE ("version install overrides", "[versionplan]")
-{
- MockCMakeVarProvider var_provider;
-
- MockVersionedPortfileProvider vp;
-
- vp.emplace("b", {"1", 0}, Scheme::Relaxed);
- vp.emplace("b", {"2", 0}, Scheme::Relaxed);
- vp.emplace("c", {"1", 0}, Scheme::String);
- vp.emplace("c", {"2", 0}, Scheme::String);
-
- MockBaselineProvider bp;
- bp.v["b"] = {"2", 0};
- bp.v["c"] = {"2", 0};
-
- SECTION ("string")
- {
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {Dependency{"c"}},
- {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- }
-
- SECTION ("relaxed")
- {
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {Dependency{"b"}},
- {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "b", {"1", 0});
- }
-}
-
-TEST_CASE ("version install transitive overrides", "[versionplan]")
-{
- MockCMakeVarProvider var_provider;
-
- MockVersionedPortfileProvider vp;
-
- vp.emplace("b", {"1", 0}, Scheme::Relaxed)
- .source_control_file->core_paragraph->dependencies.push_back(
- {"c", {}, {}, {Constraint::Type::Minimum, "2", 1}});
- vp.emplace("b", {"2", 0}, Scheme::Relaxed);
- vp.emplace("c", {"1", 0}, Scheme::String);
- vp.emplace("c", {"2", 1}, Scheme::String);
-
- MockBaselineProvider bp;
- bp.v["b"] = {"2", 0};
- bp.v["c"] = {"2", 1};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp,
- bp,
- var_provider,
- {Dependency{"b"}},
- {DependencyOverride{"b", "1"}, DependencyOverride{"c", "1"}},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- check_name_and_version(install_plan.install_actions[1], "b", {"1", 0});
-}
-
-TEST_CASE ("version install default features", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto a_x = make_fpgh("x");
- auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
- a_scf->core_paragraph->default_features.push_back("x");
- a_scf->feature_paragraphs.push_back(std::move(a_x));
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp, bp, var_provider, {Dependency{"a"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
-}
-
-TEST_CASE ("version dont install default features", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto a_x = make_fpgh("x");
- auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
- a_scf->core_paragraph->default_features.push_back("x");
- a_scf->feature_paragraphs.push_back(std::move(a_x));
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp, bp, var_provider, {Dependency{"a", {"core"}}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0});
-}
-
-TEST_CASE ("version install transitive default features", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto a_x = make_fpgh("x");
- auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
- a_scf->core_paragraph->default_features.push_back("x");
- a_scf->feature_paragraphs.push_back(std::move(a_x));
-
- auto& b_scf = vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file;
- b_scf->core_paragraph->dependencies.push_back({"a", {"core"}});
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp, bp, var_provider, {Dependency{"b"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
- check_name_and_version(install_plan.install_actions[1], "b", {"1", 0});
-}
-
-static PlatformExpression::Expr parse_platform(StringView l)
-{
- return unwrap(PlatformExpression::parse_platform_expression(l, PlatformExpression::MultipleBinaryOperators::Deny));
-}
-
-TEST_CASE ("version install qualified dependencies", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- vp.emplace("b", {"1", 0}, Scheme::Relaxed);
- vp.emplace("c", {"1", 0}, Scheme::Relaxed);
-
- MockBaselineProvider bp;
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
-
- SECTION ("windows")
- {
- MockCMakeVarProvider var_provider;
- var_provider.dep_info_vars[toplevel_spec()] = {{"VCPKG_CMAKE_SYSTEM_NAME", "Windows"}};
-
- auto install_plan = unwrap(
- create_versioned_install_plan(vp,
- bp,
- var_provider,
- {{"b", {}, parse_platform("!linux")}, {"c", {}, parse_platform("linux")}},
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "b", {"1", 0});
- }
-
- SECTION ("linux")
- {
- MockCMakeVarProvider var_provider;
- var_provider.dep_info_vars[toplevel_spec()] = {{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}};
-
- auto install_plan = unwrap(
- create_versioned_install_plan(vp,
- bp,
- var_provider,
- {{"b", {}, parse_platform("!linux")}, {"c", {}, parse_platform("linux")}},
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- }
-}
-
-TEST_CASE ("version install qualified default suppression", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
- a_scf->core_paragraph->default_features.push_back("x");
- a_scf->feature_paragraphs.push_back(make_fpgh("x"));
-
- vp.emplace("b", {"1", 0}, Scheme::Relaxed)
- .source_control_file->core_paragraph->dependencies.push_back({"a", {"core"}});
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
-
- auto install_plan = unwrap(
- create_versioned_install_plan(vp,
- bp,
- var_provider,
- {{"b", {}, parse_platform("!linux")}, {"a", {"core"}, parse_platform("linux")}},
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x"});
- check_name_and_version(install_plan.install_actions[1], "b", {"1", 0});
-}
-
-TEST_CASE ("version install qualified transitive", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- vp.emplace("a", {"1", 0}, Scheme::Relaxed);
- vp.emplace("c", {"1", 0}, Scheme::Relaxed);
-
- auto& b_scf = vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file;
- b_scf->core_paragraph->dependencies.push_back({"a", {}, parse_platform("!linux")});
- b_scf->core_paragraph->dependencies.push_back({"c", {}, parse_platform("linux")});
-
- MockCMakeVarProvider var_provider;
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"b"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0});
- check_name_and_version(install_plan.install_actions[1], "b", {"1", 0});
-}
-
-TEST_CASE ("version install different vars", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto& b_scf = vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file;
- b_scf->core_paragraph->dependencies.push_back({"a", {}, parse_platform("!linux")});
-
- auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
- a_scf->core_paragraph->dependencies.push_back({"c", {}, parse_platform("linux")});
-
- vp.emplace("c", {"1", 0}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
- var_provider.dep_info_vars[PackageSpec{"a", Test::X86_WINDOWS}] = {{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}};
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"b"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 3);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0});
- check_name_and_version(install_plan.install_actions[1], "a", {"1", 0});
- check_name_and_version(install_plan.install_actions[2], "b", {"1", 0});
-}
-
-TEST_CASE ("version install qualified features", "[versionplan]")
-{
- MockVersionedPortfileProvider vp;
-
- auto& b_scf = vp.emplace("b", {"1", 0}, Scheme::Relaxed).source_control_file;
- b_scf->core_paragraph->default_features.push_back("x");
- b_scf->feature_paragraphs.push_back(make_fpgh("x"));
- b_scf->feature_paragraphs.back()->dependencies.push_back({"a", {}, parse_platform("!linux")});
-
- auto& a_scf = vp.emplace("a", {"1", 0}, Scheme::Relaxed).source_control_file;
- a_scf->core_paragraph->default_features.push_back("y");
- a_scf->feature_paragraphs.push_back(make_fpgh("y"));
- a_scf->feature_paragraphs.back()->dependencies.push_back({"c", {}, parse_platform("linux")});
-
- auto& c_scf = vp.emplace("c", {"1", 0}, Scheme::Relaxed).source_control_file;
- c_scf->core_paragraph->default_features.push_back("z");
- c_scf->feature_paragraphs.push_back(make_fpgh("z"));
- c_scf->feature_paragraphs.back()->dependencies.push_back({"d", {}, parse_platform("linux")});
-
- vp.emplace("d", {"1", 0}, Scheme::Relaxed);
-
- MockCMakeVarProvider var_provider;
- var_provider.dep_info_vars[PackageSpec{"a", Test::X86_WINDOWS}] = {{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}};
-
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
- bp.v["d"] = {"1", 0};
-
- auto install_plan = unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"b"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 3);
- check_name_and_version(install_plan.install_actions[0], "c", {"1", 0}, {"z"});
- check_name_and_version(install_plan.install_actions[1], "a", {"1", 0}, {"y"});
- check_name_and_version(install_plan.install_actions[2], "b", {"1", 0}, {"x"});
-}
-
-TEST_CASE ("version install self features", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
-
- MockVersionedPortfileProvider vp;
- auto& a_scf = vp.emplace("a", {"1", 0}).source_control_file;
- a_scf->feature_paragraphs.push_back(make_fpgh("x"));
- a_scf->feature_paragraphs.back()->dependencies.push_back({"a", {"core", "y"}});
- a_scf->feature_paragraphs.push_back(make_fpgh("y"));
- a_scf->feature_paragraphs.push_back(make_fpgh("z"));
-
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- unwrap(create_versioned_install_plan(vp, bp, var_provider, {{"a", {"x"}}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x", "y"});
-}
-
-TEST_CASE ("version overlay ports", "[versionplan]")
-{
- MockBaselineProvider bp;
- bp.v["a"] = {"1", 0};
- bp.v["b"] = {"1", 0};
- bp.v["c"] = {"1", 0};
-
- MockVersionedPortfileProvider vp;
- vp.emplace("a", {"1", 0});
- vp.emplace("a", {"1", 1});
- vp.emplace("a", {"2", 0});
- vp.emplace("b", {"1", 0}).source_control_file->core_paragraph->dependencies.emplace_back(Dependency{"a"});
- vp.emplace("c", {"1", 0})
- .source_control_file->core_paragraph->dependencies.emplace_back(
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "1", 1}});
-
- MockCMakeVarProvider var_provider;
-
- MockOverlayProvider oprovider;
- oprovider.emplace("a", {"overlay", 0});
-
- SECTION ("no baseline")
- {
- const MockBaselineProvider empty_bp;
-
- auto install_plan = unwrap(Dependencies::create_versioned_install_plan(
- vp, empty_bp, oprovider, var_provider, {{"a"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- }
-
- SECTION ("transitive")
- {
- auto install_plan = unwrap(
- Dependencies::create_versioned_install_plan(vp, bp, oprovider, var_provider, {{"b"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- check_name_and_version(install_plan.install_actions[1], "b", {"1", 0});
- }
-
- SECTION ("transitive constraint")
- {
- auto install_plan = unwrap(
- Dependencies::create_versioned_install_plan(vp, bp, oprovider, var_provider, {{"c"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 2);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- check_name_and_version(install_plan.install_actions[1], "c", {"1", 0});
- }
-
- SECTION ("none")
- {
- auto install_plan = unwrap(
- Dependencies::create_versioned_install_plan(vp, bp, oprovider, var_provider, {{"a"}}, {}, toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- }
- SECTION ("constraint")
- {
- auto install_plan = unwrap(Dependencies::create_versioned_install_plan(
- vp,
- bp,
- oprovider,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "1", 1}},
- },
- {},
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- }
- SECTION ("constraint+override")
- {
- auto install_plan = unwrap(Dependencies::create_versioned_install_plan(
- vp,
- bp,
- oprovider,
- var_provider,
- {
- Dependency{"a", {}, {}, {Constraint::Type::Minimum, "1", 1}},
- },
- {
- DependencyOverride{"a", {"2", 0}},
- },
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- }
- SECTION ("override")
- {
- auto install_plan = unwrap(Dependencies::create_versioned_install_plan(vp,
- bp,
- oprovider,
- var_provider,
- {
- Dependency{"a"},
- },
- {
- DependencyOverride{"a", {"2", 0}},
- },
- toplevel_spec()));
-
- REQUIRE(install_plan.size() == 1);
- check_name_and_version(install_plan.install_actions[0], "a", {"overlay", 0});
- }
-}
diff --git a/toolsrc/src/vcpkg-test/downloads.cpp b/toolsrc/src/vcpkg-test/downloads.cpp
deleted file mode 100644
index b182e46d6..000000000
--- a/toolsrc/src/vcpkg-test/downloads.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/downloads.h>
-
-using namespace vcpkg;
-
-TEST_CASE ("Downloads::details::split_uri_view", "[downloads]")
-{
- {
- auto x = Downloads::details::split_uri_view("https://github.com/Microsoft/vcpkg");
- REQUIRE(x.has_value());
- REQUIRE(x.get()->scheme == "https");
- REQUIRE(x.get()->authority.value_or("") == "//github.com");
- REQUIRE(x.get()->path_query_fragment == "/Microsoft/vcpkg");
- }
- {
- auto x = Downloads::details::split_uri_view("");
- REQUIRE(!x.has_value());
- }
- {
- auto x = Downloads::details::split_uri_view("hello");
- REQUIRE(!x.has_value());
- }
- {
- auto x = Downloads::details::split_uri_view("file:");
- REQUIRE(x.has_value());
- REQUIRE(x.get()->scheme == "file");
- REQUIRE(!x.get()->authority.has_value());
- REQUIRE(x.get()->path_query_fragment == "");
- }
- {
- auto x = Downloads::details::split_uri_view("file:path");
- REQUIRE(x.has_value());
- REQUIRE(x.get()->scheme == "file");
- REQUIRE(!x.get()->authority.has_value());
- REQUIRE(x.get()->path_query_fragment == "path");
- }
- {
- auto x = Downloads::details::split_uri_view("file:/path");
- REQUIRE(x.has_value());
- REQUIRE(x.get()->scheme == "file");
- REQUIRE(!x.get()->authority.has_value());
- REQUIRE(x.get()->path_query_fragment == "/path");
- }
- {
- auto x = Downloads::details::split_uri_view("file://user:pw@host");
- REQUIRE(x.has_value());
- REQUIRE(x.get()->scheme == "file");
- REQUIRE(x.get()->authority.value_or({}) == "//user:pw@host");
- REQUIRE(x.get()->path_query_fragment == "");
- }
- {
- auto x = Downloads::details::split_uri_view("ftp://host:port/");
- REQUIRE(x.has_value());
- REQUIRE(x.get()->scheme == "ftp");
- REQUIRE(x.get()->authority.value_or({}) == "//host:port");
- REQUIRE(x.get()->path_query_fragment == "/");
- }
-}
diff --git a/toolsrc/src/vcpkg-test/files.cpp b/toolsrc/src/vcpkg-test/files.cpp
deleted file mode 100644
index ffa72d0fb..000000000
--- a/toolsrc/src/vcpkg-test/files.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/strings.h>
-
-#include <iostream>
-#include <random>
-#include <vector>
-
-#include <vcpkg-test/util.h>
-
-using vcpkg::Test::AllowSymlinks;
-using vcpkg::Test::base_temporary_directory;
-using vcpkg::Test::can_create_symlinks;
-
-#define CHECK_EC_ON_FILE(file, ec) \
- do \
- { \
- if (ec) \
- { \
- FAIL(file << ": " << ec.message()); \
- } \
- } while (0)
-
-namespace
-{
- using uid_t = std::uniform_int_distribution<std::uint64_t>;
- using urbg_t = std::mt19937_64;
-
- urbg_t get_urbg(std::uint64_t index)
- {
- // smallest prime > 2**63 - 1
- return urbg_t{index + 9223372036854775837ULL};
- }
-
- std::string get_random_filename(urbg_t& urbg) { return vcpkg::Strings::b32_encode(uid_t{}(urbg)); }
-
- struct MaxDepth
- {
- std::uint64_t i;
- explicit MaxDepth(std::uint64_t i) : i(i) { }
- operator uint64_t() const { return i; }
- };
-
- struct Width
- {
- std::uint64_t i;
- explicit Width(std::uint64_t i) : i(i) { }
- operator uint64_t() const { return i; }
- };
-
- struct CurrentDepth
- {
- std::uint64_t i;
- explicit CurrentDepth(std::uint64_t i) : i(i) { }
- operator uint64_t() const { return i; }
- CurrentDepth incremented() const { return CurrentDepth{i + 1}; }
- };
-
- void create_directory_tree(urbg_t& urbg,
- vcpkg::Files::Filesystem& fs,
- const fs::path& base,
- MaxDepth max_depth,
- AllowSymlinks allow_symlinks = AllowSymlinks::Yes,
- Width width = Width{5},
- CurrentDepth current_depth = CurrentDepth{0})
- {
- // we want ~70% of our "files" to be directories, and then a third
- // each of the remaining ~30% to be regular files, directory symlinks,
- // and regular symlinks
- constexpr std::uint64_t directory_min_tag = 0;
- constexpr std::uint64_t directory_max_tag = 6;
- constexpr std::uint64_t regular_file_tag = 7;
- constexpr std::uint64_t regular_symlink_tag = 8;
- constexpr std::uint64_t directory_symlink_tag = 9;
-
- allow_symlinks = AllowSymlinks{allow_symlinks && can_create_symlinks()};
-
- // if we're at the max depth, we only want to build non-directories
- std::uint64_t file_type;
- if (current_depth >= max_depth)
- {
- file_type = uid_t{regular_file_tag, directory_symlink_tag}(urbg);
- }
- else if (current_depth < 2)
- {
- file_type = directory_min_tag;
- }
- else
- {
- file_type = uid_t{directory_min_tag, regular_symlink_tag}(urbg);
- }
-
- if (!allow_symlinks && file_type > regular_file_tag)
- {
- file_type = regular_file_tag;
- }
-
- std::error_code ec;
- if (file_type <= directory_max_tag)
- {
- fs.create_directory(base, ec);
- if (ec)
- {
- CHECK_EC_ON_FILE(base, ec);
- }
-
- for (std::uint64_t i = 0; i < width; ++i)
- {
- create_directory_tree(urbg,
- fs,
- base / get_random_filename(urbg),
- max_depth,
- allow_symlinks,
- width,
- current_depth.incremented());
- }
- }
- else if (file_type == regular_file_tag)
- {
- // regular file
- fs.write_contents(base, "", ec);
- }
- else if (file_type == regular_symlink_tag)
- {
- // regular symlink
- auto base_link = base;
- base_link.replace_filename(fs::u8string(base.filename()) + "-orig");
- fs.write_contents(base_link, "", ec);
- CHECK_EC_ON_FILE(base_link, ec);
- vcpkg::Test::create_symlink(base_link, base, ec);
- }
- else // file_type == directory_symlink_tag
- {
- // directory symlink
- auto parent = base;
- parent.remove_filename();
- vcpkg::Test::create_directory_symlink(parent, base, ec);
- }
-
- CHECK_EC_ON_FILE(base, ec);
- REQUIRE(fs::exists(fs.symlink_status(base, ec)));
- CHECK_EC_ON_FILE(base, ec);
- }
-
- vcpkg::Files::Filesystem& setup()
- {
- auto& fs = vcpkg::Files::get_real_filesystem();
-
- std::error_code ec;
- fs.create_directory(base_temporary_directory(), ec);
- CHECK_EC_ON_FILE(base_temporary_directory(), ec);
-
- return fs;
- }
-}
-
-TEST_CASE ("fs::combine works correctly", "[filesystem][files]")
-{
- using namespace fs;
- using namespace vcpkg::Files;
- CHECK(combine(u8path("/a/b"), u8path("c/d")) == u8path("/a/b/c/d"));
- CHECK(combine(u8path("a/b"), u8path("c/d")) == u8path("a/b/c/d"));
- CHECK(combine(u8path("/a/b"), u8path("/c/d")) == u8path("/c/d"));
-
-#if defined(_WIN32)
- CHECK(combine(u8path("C:/a/b"), u8path("c/d")) == u8path("C:/a/b/c/d"));
- CHECK(combine(u8path("C:a/b"), u8path("c/d")) == u8path("C:a/b/c/d"));
- CHECK(combine(u8path("C:a/b"), u8path("/c/d")) == u8path("C:/c/d"));
- CHECK(combine(u8path("C:/a/b"), u8path("/c/d")) == u8path("C:/c/d"));
- CHECK(combine(u8path("C:/a/b"), u8path("D:/c/d")) == u8path("D:/c/d"));
- CHECK(combine(u8path("C:/a/b"), u8path("D:c/d")) == u8path("D:c/d"));
- CHECK(combine(u8path("C:/a/b"), u8path("C:c/d")) == u8path("C:/a/b/c/d"));
-#endif
-}
-
-TEST_CASE ("remove all", "[files]")
-{
- auto urbg = get_urbg(0);
-
- auto& fs = setup();
-
- fs::path temp_dir = base_temporary_directory() / get_random_filename(urbg);
- INFO("temp dir is: " << temp_dir);
-
- create_directory_tree(urbg, fs, temp_dir, MaxDepth{5});
-
- std::error_code ec;
- fs::path fp;
- fs.remove_all(temp_dir, ec, fp);
- CHECK_EC_ON_FILE(fp, ec);
-
- REQUIRE_FALSE(fs.exists(temp_dir, ec));
- CHECK_EC_ON_FILE(temp_dir, ec);
-}
-
-TEST_CASE ("lexically_normal", "[files]")
-{
- const auto lexically_normal = [](const char* s) { return fs::lexically_normal(fs::u8path(s)); };
- const auto native = [](const char* s) { return std::move(fs::u8path(s).make_preferred()); };
- CHECK(fs::lexically_normal(fs::path()).native() == fs::path().native());
-
- // these test cases are taken from the MS STL tests
- CHECK(lexically_normal("cat/./dog/..").native() == native("cat/").native());
- CHECK(lexically_normal("cat/.///dog/../").native() == native("cat/").native());
-
- CHECK(lexically_normal("cat/./dog/..").native() == native("cat/").native());
- CHECK(lexically_normal("cat/.///dog/../").native() == native("cat/").native());
-
- CHECK(lexically_normal(".").native() == native(".").native());
- CHECK(lexically_normal("./").native() == native(".").native());
- CHECK(lexically_normal("./.").native() == native(".").native());
- CHECK(lexically_normal("././").native() == native(".").native());
-
- CHECK(lexically_normal("../../..").native() == native("../../..").native());
- CHECK(lexically_normal("../../../").native() == native("../../..").native());
-
- CHECK(lexically_normal("../../../a/b/c").native() == native("../../../a/b/c").native());
-
- CHECK(lexically_normal("/../../..").native() == native("/").native());
- CHECK(lexically_normal("/../../../").native() == native("/").native());
-
- CHECK(lexically_normal("/../../../a/b/c").native() == native("/a/b/c").native());
-
- CHECK(lexically_normal("a/..").native() == native(".").native());
- CHECK(lexically_normal("a/../").native() == native(".").native());
-
-#if defined(_WIN32)
- CHECK(lexically_normal(R"(X:)").native() == LR"(X:)");
-
- CHECK(lexically_normal(R"(X:DriveRelative)").native() == LR"(X:DriveRelative)");
-
- CHECK(lexically_normal(R"(X:\)").native() == LR"(X:\)");
- CHECK(lexically_normal(R"(X:/)").native() == LR"(X:\)");
- CHECK(lexically_normal(R"(X:\\\)").native() == LR"(X:\)");
- CHECK(lexically_normal(R"(X:///)").native() == LR"(X:\)");
-
- CHECK(lexically_normal(R"(X:\DosAbsolute)").native() == LR"(X:\DosAbsolute)");
- CHECK(lexically_normal(R"(X:/DosAbsolute)").native() == LR"(X:\DosAbsolute)");
- CHECK(lexically_normal(R"(X:\\\DosAbsolute)").native() == LR"(X:\DosAbsolute)");
- CHECK(lexically_normal(R"(X:///DosAbsolute)").native() == LR"(X:\DosAbsolute)");
-
- CHECK(lexically_normal(R"(\RootRelative)").native() == LR"(\RootRelative)");
- CHECK(lexically_normal(R"(/RootRelative)").native() == LR"(\RootRelative)");
- CHECK(lexically_normal(R"(\\\RootRelative)").native() == LR"(\RootRelative)");
- CHECK(lexically_normal(R"(///RootRelative)").native() == LR"(\RootRelative)");
-
- CHECK(lexically_normal(R"(\\server\share)").native() == LR"(\\server\share)");
- CHECK(lexically_normal(R"(//server/share)").native() == LR"(\\server\share)");
- CHECK(lexically_normal(R"(\\server\\\share)").native() == LR"(\\server\share)");
- CHECK(lexically_normal(R"(//server///share)").native() == LR"(\\server\share)");
-
- CHECK(lexically_normal(R"(\\?\device)").native() == LR"(\\?\device)");
- CHECK(lexically_normal(R"(//?/device)").native() == LR"(\\?\device)");
-
- CHECK(lexically_normal(R"(\??\device)").native() == LR"(\??\device)");
- CHECK(lexically_normal(R"(/??/device)").native() == LR"(\??\device)");
-
- CHECK(lexically_normal(R"(\\.\device)").native() == LR"(\\.\device)");
- CHECK(lexically_normal(R"(//./device)").native() == LR"(\\.\device)");
-
- CHECK(lexically_normal(R"(\\?\UNC\server\share)").native() == LR"(\\?\UNC\server\share)");
- CHECK(lexically_normal(R"(//?/UNC/server/share)").native() == LR"(\\?\UNC\server\share)");
-
- CHECK(lexically_normal(R"(C:\a/b\\c\/d/\e//f)").native() == LR"(C:\a\b\c\d\e\f)");
-
- CHECK(lexically_normal(R"(C:\meow\)").native() == LR"(C:\meow\)");
- CHECK(lexically_normal(R"(C:\meow/)").native() == LR"(C:\meow\)");
- CHECK(lexically_normal(R"(C:\meow\\)").native() == LR"(C:\meow\)");
- CHECK(lexically_normal(R"(C:\meow\/)").native() == LR"(C:\meow\)");
- CHECK(lexically_normal(R"(C:\meow/\)").native() == LR"(C:\meow\)");
- CHECK(lexically_normal(R"(C:\meow//)").native() == LR"(C:\meow\)");
-
- CHECK(lexically_normal(R"(C:\a\.\b\.\.\c\.\.\.)").native() == LR"(C:\a\b\c\)");
- CHECK(lexically_normal(R"(C:\a\.\b\.\.\c\.\.\.\)").native() == LR"(C:\a\b\c\)");
-
- CHECK(lexically_normal(R"(C:\a\b\c\d\e\..\f\..\..\..\g\h)").native() == LR"(C:\a\b\g\h)");
-
- CHECK(lexically_normal(R"(C:\a\b\c\d\e\..\f\..\..\..\g\h\..)").native() == LR"(C:\a\b\g\)");
- CHECK(lexically_normal(R"(C:\a\b\c\d\e\..\f\..\..\..\g\h\..\)").native() == LR"(C:\a\b\g\)");
- CHECK(lexically_normal(
- R"(/\server/\share/\a/\b/\c/\./\./\d/\../\../\../\../\../\../\../\other/x/y/z/.././..\meow.txt)")
- .native() == LR"(\\server\other\x\meow.txt)");
-#endif
-}
-
-#if defined(_WIN32)
-TEST_CASE ("win32_fix_path_case", "[files]")
-{
- using vcpkg::Files::win32_fix_path_case;
-
- // This test assumes that the Windows directory is C:\Windows
-
- CHECK(win32_fix_path_case(L"") == L"");
-
- CHECK(win32_fix_path_case(L"C:") == L"C:");
- CHECK(win32_fix_path_case(L"c:") == L"C:");
- CHECK(win32_fix_path_case(L"C:/") == L"C:\\");
- CHECK(win32_fix_path_case(L"C:\\") == L"C:\\");
- CHECK(win32_fix_path_case(L"c:\\") == L"C:\\");
- CHECK(win32_fix_path_case(L"C:\\WiNdOws") == L"C:\\Windows");
- CHECK(win32_fix_path_case(L"c:\\WiNdOws\\") == L"C:\\Windows\\");
- CHECK(win32_fix_path_case(L"C://///////WiNdOws") == L"C:\\Windows");
- CHECK(win32_fix_path_case(L"c:\\/\\/WiNdOws\\/") == L"C:\\Windows\\");
-
- auto& fs = vcpkg::Files::get_real_filesystem();
- auto original_cwd = fs.current_path(VCPKG_LINE_INFO);
- fs.current_path(L"C:\\", VCPKG_LINE_INFO);
- CHECK(win32_fix_path_case(L"\\") == L"\\");
- CHECK(win32_fix_path_case(L"\\/\\WiNdOws") == L"\\Windows");
- CHECK(win32_fix_path_case(L"\\WiNdOws") == L"\\Windows");
- CHECK(win32_fix_path_case(L"\\WiNdOws") == L"\\Windows");
- CHECK(win32_fix_path_case(L"c:WiNdOws") == L"C:Windows");
- CHECK(win32_fix_path_case(L"c:WiNdOws/system32") == L"C:Windows\\System32");
- fs.current_path(original_cwd, VCPKG_LINE_INFO);
-
- fs.create_directories("SuB/Dir/Ectory", VCPKG_LINE_INFO);
- CHECK(win32_fix_path_case(L"sub") == L"SuB");
- CHECK(win32_fix_path_case(L"SUB") == L"SuB");
- CHECK(win32_fix_path_case(L"sub/") == L"SuB\\");
- CHECK(win32_fix_path_case(L"sub/dir") == L"SuB\\Dir");
- CHECK(win32_fix_path_case(L"sub/dir/") == L"SuB\\Dir\\");
- CHECK(win32_fix_path_case(L"sub/dir/ectory") == L"SuB\\Dir\\Ectory");
- CHECK(win32_fix_path_case(L"sub/dir/ectory/") == L"SuB\\Dir\\Ectory\\");
- fs.remove_all("SuB", VCPKG_LINE_INFO);
-
- CHECK(win32_fix_path_case(L"//nonexistent_server\\nonexistent_share\\") ==
- L"\\\\nonexistent_server\\nonexistent_share\\");
- CHECK(win32_fix_path_case(L"\\\\nonexistent_server\\nonexistent_share\\") ==
- L"\\\\nonexistent_server\\nonexistent_share\\");
- CHECK(win32_fix_path_case(L"\\\\nonexistent_server\\nonexistent_share") ==
- L"\\\\nonexistent_server\\nonexistent_share");
-
- CHECK(win32_fix_path_case(L"///three_slashes_not_a_server\\subdir\\") == L"\\three_slashes_not_a_server\\subdir\\");
-
- CHECK(win32_fix_path_case(L"\\??\\c:\\WiNdOws") == L"\\??\\c:\\WiNdOws");
- CHECK(win32_fix_path_case(L"\\\\?\\c:\\WiNdOws") == L"\\\\?\\c:\\WiNdOws");
- CHECK(win32_fix_path_case(L"\\\\.\\c:\\WiNdOws") == L"\\\\.\\c:\\WiNdOws");
- CHECK(win32_fix_path_case(L"c:\\/\\/Nonexistent\\/path/here") == L"C:\\Nonexistent\\path\\here");
-}
-#endif // _WIN32
-
-#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-TEST_CASE ("remove all -- benchmarks", "[files][!benchmark]")
-{
- auto urbg = get_urbg(1);
- auto& fs = setup();
-
- struct
- {
- urbg_t& urbg;
- vcpkg::Files::Filesystem& fs;
-
- void operator()(Catch::Benchmark::Chronometer& meter, MaxDepth max_depth, AllowSymlinks allow_symlinks) const
- {
- std::vector<fs::path> temp_dirs;
- temp_dirs.resize(meter.runs());
-
- std::generate(begin(temp_dirs), end(temp_dirs), [&] {
- fs::path temp_dir = base_temporary_directory() / get_random_filename(urbg);
- create_directory_tree(urbg, fs, temp_dir, max_depth, allow_symlinks);
- return temp_dir;
- });
-
- meter.measure([&](int run) {
- std::error_code ec;
- fs::path fp;
- const auto& temp_dir = temp_dirs[run];
-
- fs.remove_all(temp_dir, ec, fp);
- CHECK_EC_ON_FILE(fp, ec);
- });
-
- for (const auto& dir : temp_dirs)
- {
- std::error_code ec;
- REQUIRE_FALSE(fs.exists(dir, ec));
- CHECK_EC_ON_FILE(dir, ec);
- }
- }
- } do_benchmark = {urbg, fs};
-
- BENCHMARK_ADVANCED("small directory, no symlinks")(Catch::Benchmark::Chronometer meter)
- {
- do_benchmark(meter, MaxDepth{2}, AllowSymlinks::No);
- };
-
- BENCHMARK_ADVANCED("large directory, no symlinks")(Catch::Benchmark::Chronometer meter)
- {
- do_benchmark(meter, MaxDepth{5}, AllowSymlinks::No);
- };
-
- if (can_create_symlinks())
- {
- BENCHMARK_ADVANCED("small directory, symlinks")(Catch::Benchmark::Chronometer meter)
- {
- do_benchmark(meter, MaxDepth{2}, AllowSymlinks::Yes);
- };
-
- BENCHMARK_ADVANCED("large directory, symlinks")(Catch::Benchmark::Chronometer meter)
- {
- do_benchmark(meter, MaxDepth{5}, AllowSymlinks::Yes);
- };
- }
-}
-#endif
diff --git a/toolsrc/src/vcpkg-test/hash.cpp b/toolsrc/src/vcpkg-test/hash.cpp
deleted file mode 100644
index 9f3ccc25e..000000000
--- a/toolsrc/src/vcpkg-test/hash.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/hash.h>
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-#include <map>
-
-namespace Hash = vcpkg::Hash;
-using vcpkg::StringView;
-
-// Require algorithm: Hash::Algorithm::Tag to be in scope
-#define CHECK_HASH(size, value, real_hash) \
- do \
- { \
- unsigned char data[size]; \
- std::fill(std::begin(data), std::end(data), static_cast<unsigned char>(value)); \
- const auto hash = Hash::get_bytes_hash(data, data + size, algorithm); \
- REQUIRE(hash == real_hash); \
- } while (0)
-
-#define CHECK_HASH_OF(data, real_hash) \
- do \
- { \
- const auto hash = Hash::get_bytes_hash(std::begin(data), std::end(data), algorithm); \
- REQUIRE(hash == real_hash); \
- } while (0)
-
-#define CHECK_HASH_STRING(data, real_hash) \
- do \
- { \
- const auto hash = Hash::get_string_hash(data, algorithm); \
- REQUIRE(hash == real_hash); \
- } while (0)
-
-// Requires hasher: std::unique_ptr<Hash::Hasher> to be in scope
-#define CHECK_HASH_LARGE(size, value, real_hash) \
- do \
- { \
- hasher->clear(); \
- std::uint64_t remaining = size; \
- unsigned char buffer[512]; \
- std::fill(std::begin(buffer), std::end(buffer), static_cast<unsigned char>(value)); \
- while (remaining) \
- { \
- if (remaining < 512) \
- { \
- hasher->add_bytes(std::begin(buffer), std::begin(buffer) + remaining); \
- remaining = 0; \
- } \
- else \
- { \
- hasher->add_bytes(std::begin(buffer), std::end(buffer)); \
- remaining -= 512; \
- } \
- } \
- REQUIRE(hasher->get_hash() == real_hash); \
- } while (0)
-
-TEST_CASE ("SHA1: basic tests", "[hash][sha1]")
-{
- const auto algorithm = Hash::Algorithm::Sha1;
-
- CHECK_HASH_STRING("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
- CHECK_HASH_STRING(";", "2d14ab97cc3dc294c51c0d6814f4ea45f4b4e312");
- CHECK_HASH_STRING("asdifasdfnas", "b77eb8a1b4c2ef6716d7d302647e4511b1a638a6");
- CHECK_HASH_STRING("asdfanvoinaoifawenflawenfiwnofvnasfjvnaslkdfjlkasjdfanm,"
- "werflawoienfowanevoinwai32910u2740918741o;j;wejfqwioaher9283hrpf;asd",
- "c69bcd30c196c7050906d212722dd7a7659aad04");
-}
-
-TEST_CASE ("SHA1: NIST test cases (small)", "[hash][sha1]")
-{
- const auto algorithm = Hash::Algorithm::Sha1;
-
- CHECK_HASH_STRING("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
- CHECK_HASH_STRING("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
-}
-
-TEST_CASE ("SHA256: basic tests", "[hash][sha256]")
-{
- const auto algorithm = Hash::Algorithm::Sha256;
-
- CHECK_HASH_STRING("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
- CHECK_HASH_STRING(";", "41b805ea7ac014e23556e98bb374702a08344268f92489a02f0880849394a1e4");
- CHECK_HASH_STRING("asdifasdfnas", "2bb1fb910831fdc11d5a3996425a84ace27aeb81c9c20ace9f60ac1b3218b291");
- CHECK_HASH_STRING("asdfanvoinaoifawenflawenfiwnofvnasfjvnaslkdfjlkasjdfanm,"
- "werflawoienfowanevoinwai32910u2740918741o;j;wejfqwioaher9283hrpf;asd",
- "10c98034b424d4e40ca933bc524ea38b4e53290d76e8b38edc4ea2fec7f529aa");
-}
-
-TEST_CASE ("SHA256: NIST test cases (small)", "[hash][sha256]")
-{
- const auto algorithm = Hash::Algorithm::Sha256;
-
- CHECK_HASH(1, 0xbd, "68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b");
- {
- const unsigned char data[] = {0xc9, 0x8c, 0x8e, 0x55};
- CHECK_HASH_OF(data, "7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504");
- }
- CHECK_HASH(55, 0, "02779466cdec163811d078815c633f21901413081449002f24aa3e80f0b88ef7");
- CHECK_HASH(56, 0, "d4817aa5497628e7c77e6b606107042bbba3130888c5f47a375e6179be789fbb");
- CHECK_HASH(57, 0, "65a16cb7861335d5ace3c60718b5052e44660726da4cd13bb745381b235a1785");
- CHECK_HASH(64, 0, "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b");
- CHECK_HASH(1000, 0, "541b3e9daa09b20bf85fa273e5cbd3e80185aa4ec298e765db87742b70138a53");
- CHECK_HASH(1000, 'A', "c2e686823489ced2017f6059b8b239318b6364f6dcd835d0a519105a1eadd6e4");
- CHECK_HASH(1005, 'U', "f4d62ddec0f3dd90ea1380fa16a5ff8dc4c54b21740650f24afc4120903552b0");
-}
-
-TEST_CASE ("SHA512: NIST test cases (small)", "[hash][sha512]")
-{
- const auto algorithm = Hash::Algorithm::Sha512;
-
- CHECK_HASH_STRING("",
- "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f"
- "63b931bd47417a81a538327af927da3e");
-
- CHECK_HASH(111,
- 0,
- "77ddd3a542e530fd047b8977c657ba6ce72f1492e360b2b2212cd264e75ec03882e4ff0525517ab4207d14c70c2259ba88d4d33"
- "5ee0e7e20543d22102ab1788c");
- CHECK_HASH(112,
- 0,
- "2be2e788c8a8adeaa9c89a7f78904cacea6e39297d75e0573a73c756234534d6627ab4156b48a6657b29ab8beb73334040ad39e"
- "ad81446bb09c70704ec707952");
- CHECK_HASH(113,
- 0,
- "0e67910bcf0f9ccde5464c63b9c850a12a759227d16b040d98986d54253f9f34322318e56b8feb86c5fb2270ed87f31252f7f68"
- "493ee759743909bd75e4bb544");
- CHECK_HASH(122,
- 0,
- "4f3f095d015be4a7a7cc0b8c04da4aa09e74351e3a97651f744c23716ebd9b3e822e5077a01baa5cc0ed45b9249e88ab343d433"
- "3539df21ed229da6f4a514e0f");
- CHECK_HASH(1000,
- 0,
- "ca3dff61bb23477aa6087b27508264a6f9126ee3a004f53cb8db942ed345f2f2d229b4b59c859220a1cf1913f34248e3803bab6"
- "50e849a3d9a709edc09ae4a76");
- CHECK_HASH(1000,
- 'A',
- "329c52ac62d1fe731151f2b895a00475445ef74f50b979c6f7bb7cae349328c1d4cb4f7261a0ab43f936a24b000651d4a824fcd"
- "d577f211aef8f806b16afe8af");
- CHECK_HASH(1005,
- 'U',
- "59f5e54fe299c6a8764c6b199e44924a37f59e2b56c3ebad939b7289210dc8e4c21b9720165b0f4d4374c90f1bf4fb4a5ace17a"
- "1161798015052893a48c3d161");
-}
-
-TEST_CASE ("SHA256: NIST test cases (large)", "[.][hash-expensive][sha256-expensive]")
-{
- auto hasher = Hash::get_hasher_for(Hash::Algorithm::Sha256);
- CHECK_HASH_LARGE(1'000'000, 0, "d29751f2649b32ff572b5e0a9f541ea660a50f94ff0beedfb0b692b924cc8025");
- CHECK_HASH_LARGE(0x2000'0000, 'Z', "15a1868c12cc53951e182344277447cd0979536badcc512ad24c67e9b2d4f3dd");
- CHECK_HASH_LARGE(0x4100'0000, 0, "461c19a93bd4344f9215f5ec64357090342bc66b15a148317d276e31cbc20b53");
- CHECK_HASH_LARGE(0x6000'003E, 'B', "c23ce8a7895f4b21ec0daf37920ac0a262a220045a03eb2dfed48ef9b05aabea");
-}
-
-TEST_CASE ("SHA512: NIST test cases (large)", "[.][hash-expensive][sha512-expensive]")
-{
- auto hasher = Hash::get_hasher_for(Hash::Algorithm::Sha512);
- CHECK_HASH_LARGE(1'000'000,
- 0,
- "ce044bc9fd43269d5bbc946cbebc3bb711341115cc4abdf2edbc3ff2c57ad4b15deb699bda257fea5aef9c6e55fcf4cf9"
- "dc25a8c3ce25f2efe90908379bff7ed");
- CHECK_HASH_LARGE(0x2000'0000,
- 'Z',
- "da172279f3ebbda95f6b6e1e5f0ebec682c25d3d93561a1624c2fa9009d64c7e9923f3b46bcaf11d39a531f43297992ba"
- "4155c7e827bd0f1e194ae7ed6de4cac");
- CHECK_HASH_LARGE(0x4100'0000,
- 0,
- "14b1be901cb43549b4d831e61e5f9df1c791c85b50e85f9d6bc64135804ad43ce8402750edbe4e5c0fc170b99cf78b9f4"
- "ecb9c7e02a157911d1bd1832d76784f");
- CHECK_HASH_LARGE(0x6000'003E,
- 'B',
- "fd05e13eb771f05190bd97d62647157ea8f1f6949a52bb6daaedbad5f578ec59b1b8d6c4a7ecb2feca6892b4dc1387716"
- "70a0f3bd577eea326aed40ab7dd58b1");
-}
-
-#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
-using Catch::Benchmark::Chronometer;
-void benchmark_hasher(Chronometer& meter, Hash::Hasher& hasher, std::uint64_t size, unsigned char byte) noexcept
-{
- unsigned char buffer[1024];
- std::fill(std::begin(buffer), std::end(buffer), byte);
-
- meter.measure([&] {
- hasher.clear();
- std::uint64_t remaining = size;
- while (remaining)
- {
- if (remaining < 512)
- {
- hasher.add_bytes(std::begin(buffer), std::begin(buffer) + remaining);
- remaining = 0;
- }
- else
- {
- hasher.add_bytes(std::begin(buffer), std::end(buffer));
- remaining -= 512;
- }
- }
- hasher.get_hash();
- });
-}
-
-TEST_CASE ("SHA1: benchmark", "[.][hash][sha256][!benchmark]")
-{
- using Catch::Benchmark::Chronometer;
-
- auto hasher = Hash::get_hasher_for(Hash::Algorithm::Sha1);
-
- BENCHMARK_ADVANCED("0 x 1'000'000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 1'000'000, 0);
- };
- BENCHMARK_ADVANCED("'Z' x 0x2000'0000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x2000'0000, 'Z');
- };
- BENCHMARK_ADVANCED("0 x 0x4100'0000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x4100'0000, 0);
- };
- BENCHMARK_ADVANCED("'B' x 0x6000'003E")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x6000'003E, 'B');
- };
-}
-
-TEST_CASE ("SHA256: benchmark", "[.][hash][sha256][!benchmark]")
-{
- using Catch::Benchmark::Chronometer;
-
- auto hasher = Hash::get_hasher_for(Hash::Algorithm::Sha256);
-
- BENCHMARK_ADVANCED("0 x 1'000'000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 1'000'000, 0);
- };
- BENCHMARK_ADVANCED("'Z' x 0x2000'0000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x2000'0000, 'Z');
- };
- BENCHMARK_ADVANCED("0 x 0x4100'0000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x4100'0000, 0);
- };
- BENCHMARK_ADVANCED("'B' x 0x6000'003E")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x6000'003E, 'B');
- };
-}
-
-TEST_CASE ("SHA512: large -- benchmark", "[.][hash][sha512][!benchmark]")
-{
- auto hasher = Hash::get_hasher_for(Hash::Algorithm::Sha512);
-
- BENCHMARK_ADVANCED("0 x 1'000'000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 1'000'000, 0);
- };
- BENCHMARK_ADVANCED("'Z' x 0x2000'0000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x2000'0000, 'Z');
- };
- BENCHMARK_ADVANCED("0 x 0x4100'0000")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x4100'0000, 0);
- };
- BENCHMARK_ADVANCED("'B' x 0x6000'003E")(Catch::Benchmark::Chronometer meter)
- {
- benchmark_hasher(meter, *hasher, 0x6000'003E, 'B');
- };
-}
-#endif
diff --git a/toolsrc/src/vcpkg-test/json.cpp b/toolsrc/src/vcpkg-test/json.cpp
deleted file mode 100644
index b03fe2aec..000000000
--- a/toolsrc/src/vcpkg-test/json.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/unicode.h>
-
-#include <iostream>
-
-#include "math.h"
-
-// TODO: remove this once we switch to C++20 completely
-// This is the worst, but we also can't really deal with it any other way.
-#if __cpp_char8_t
-template<size_t Sz>
-static auto _u8_string_to_char_string(const char8_t (&literal)[Sz]) -> const char (&)[Sz]
-{
- return reinterpret_cast<const char(&)[Sz]>(literal);
-}
-
-#define U8_STR(s) (::vcpkg::Unicode::_u8_string_to_char_string(u8"" s))
-#else
-#define U8_STR(s) (u8"" s)
-#endif
-
-namespace Json = vcpkg::Json;
-using Json::Value;
-
-static std::string mystringify(const Value& val) { return Json::stringify(val, Json::JsonStyle{}); }
-
-TEST_CASE ("JSON stringify weird strings", "[json]")
-{
- std::string str = U8_STR("😀 😁 😂 🤣 😃 😄 😅 😆 😉");
- REQUIRE(mystringify(Value::string(str)) == ('"' + str + "\"\n"));
- REQUIRE(mystringify(Value::string("\xED\xA0\x80")) == "\"\\ud800\"\n"); // unpaired surrogate
-}
-
-TEST_CASE ("JSON parse keywords", "[json]")
-{
- auto res = Json::parse("true");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_boolean());
- REQUIRE(res.get()->first.boolean());
- res = Json::parse(" false ");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_boolean());
- REQUIRE(!res.get()->first.boolean());
- res = Json::parse(" null\t ");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_null());
-}
-
-TEST_CASE ("JSON parse strings", "[json]")
-{
- auto res = Json::parse(R"("")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string().size() == 0);
-
- res = Json::parse(R"("\ud800")"); // unpaired surrogate
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\xED\xA0\x80");
-
- const auto make_json_string = [](vcpkg::StringView sv) { return '"' + sv.to_string() + '"'; };
- const vcpkg::StringView radical = U8_STR("⎷");
- const vcpkg::StringView grin = U8_STR("😁");
-
- res = Json::parse(R"("\uD83D\uDE01")"); // paired surrogates for grin
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == grin.to_string());
-
- res = Json::parse(make_json_string(radical)); // character in BMP
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == radical);
-
- res = Json::parse(make_json_string(grin)); // character above BMP
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == grin);
-}
-
-TEST_CASE ("JSON parse strings with escapes", "[json]")
-{
- auto res = Json::parse(R"("\t")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\t");
-
- res = Json::parse(R"("\\")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\\");
-
- res = Json::parse(R"("\/")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "/");
-
- res = Json::parse(R"("\b")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\b");
-
- res = Json::parse(R"("\f")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\f");
-
- res = Json::parse(R"("\n")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\n");
-
- res = Json::parse(R"("\r")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == "\r");
-
- res = Json::parse(R"("This is a \"test\", hopefully it worked")");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_string());
- REQUIRE(res.get()->first.string() == R"(This is a "test", hopefully it worked)");
-}
-
-TEST_CASE ("JSON parse integers", "[json]")
-{
- auto res = Json::parse("0");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_integer());
- REQUIRE(res.get()->first.integer() == 0);
- res = Json::parse("12345");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_integer());
- REQUIRE(res.get()->first.integer() == 12345);
- res = Json::parse("-12345");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_integer());
- REQUIRE(res.get()->first.integer() == -12345);
- res = Json::parse("9223372036854775807"); // INT64_MAX
- REQUIRE(res);
- REQUIRE(res.get()->first.is_integer());
- REQUIRE(res.get()->first.integer() == 9223372036854775807);
- res = Json::parse("-9223372036854775808");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_integer());
- REQUIRE(res.get()->first.integer() == (-9223372036854775807 - 1)); // INT64_MIN (C++'s parser is fun)
-}
-
-TEST_CASE ("JSON parse floats", "[json]")
-{
- auto res = Json::parse("0.0");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_number());
- REQUIRE(!res.get()->first.is_integer());
- REQUIRE(res.get()->first.number() == 0.0);
- REQUIRE(!signbit(res.get()->first.number()));
- res = Json::parse("-0.0");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_number());
- REQUIRE(res.get()->first.number() == 0.0);
- REQUIRE(signbit(res.get()->first.number()));
- res = Json::parse("12345.6789");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_number());
- REQUIRE_THAT(res.get()->first.number(), Catch::WithinULP(12345.6789, 3));
- res = Json::parse("-12345.6789");
- REQUIRE(res);
- REQUIRE(res.get()->first.is_number());
- REQUIRE_THAT(res.get()->first.number(), Catch::WithinULP(-12345.6789, 3));
-}
-
-TEST_CASE ("JSON parse arrays", "[json]")
-{
- auto res = Json::parse("[]");
- REQUIRE(res);
- auto val = std::move(res.get()->first);
- REQUIRE(val.is_array());
- REQUIRE(val.array().size() == 0);
-
- res = Json::parse("[123]");
- REQUIRE(res);
- val = std::move(res.get()->first);
- REQUIRE(val.is_array());
- REQUIRE(val.array().size() == 1);
- REQUIRE(val.array()[0].is_integer());
- REQUIRE(val.array()[0].integer() == 123);
-
- res = Json::parse("[123, 456]");
- REQUIRE(res);
- val = std::move(res.get()->first);
- REQUIRE(val.is_array());
- REQUIRE(val.array().size() == 2);
- REQUIRE(val.array()[0].is_integer());
- REQUIRE(val.array()[0].integer() == 123);
- REQUIRE(val.array()[1].is_integer());
- REQUIRE(val.array()[1].integer() == 456);
-
- res = Json::parse("[123, 456, [null]]");
- REQUIRE(res);
- val = std::move(res.get()->first);
- REQUIRE(val.is_array());
- REQUIRE(val.array().size() == 3);
- REQUIRE(val.array()[2].is_array());
- REQUIRE(val.array()[2].array().size() == 1);
- REQUIRE(val.array()[2].array()[0].is_null());
-}
-
-TEST_CASE ("JSON parse objects", "[json]")
-{
- auto res = Json::parse("{}");
- REQUIRE(res);
- auto val = std::move(res.get()->first);
- REQUIRE(val.is_object());
- REQUIRE(val.object().size() == 0);
-}
-
-TEST_CASE ("JSON parse full file", "[json]")
-{
- vcpkg::StringView json =
-#include "large-json-document.json.inc"
- ;
-
- auto res = Json::parse(json);
- if (!res)
- {
- std::cerr << res.error()->format() << '\n';
- }
- REQUIRE(res);
-}
-
-TEST_CASE ("JSON track newlines", "[json]")
-{
- auto res = Json::parse("{\n,", fs::u8path("filename"));
- REQUIRE(!res);
- REQUIRE(res.error()->format() ==
- R"(filename:2:1: error: Unexpected character; expected property name
- on expression: ,
- ^
-)");
-}
diff --git a/toolsrc/src/vcpkg-test/large-json-document.json.inc b/toolsrc/src/vcpkg-test/large-json-document.json.inc
deleted file mode 100644
index 6cab7cf21..000000000
--- a/toolsrc/src/vcpkg-test/large-json-document.json.inc
+++ /dev/null
@@ -1,516 +0,0 @@
-// randomly generated by json-generator.com
-R"json([
- {
- "_id": "5e7a86c71cf688019f4c4b9f",
- "index": 0,
- "guid": "0e3c8a89-9960-4d87-8634-f9d3fcdaf735",
- "isActive": false,
- "balance": "$2,473.46",
- "picture": "http://placehold.it/32x32",
- "age": 21,
- "eyeColor": "blue",
- "name": {
- "first": "Dana",
- "last": "Romero"
- },
- "company": "NETPLODE",
- "email": "dana.romero@netplode.info",
- "phone": "+1 (981) 479-2769",
- "address": "501 Cass Place, Strykersville, Missouri, 8329",
- "about": "Incididunt in fugiat ipsum proident aliqua voluptate Lorem nostrud laboris ut velit minim. Dolor culpa magna tempor cupidatat. Id esse quis ipsum incididunt. Aliqua deserunt aliquip esse minim cillum esse aliquip veniam non labore dolor incididunt. Sint ea consectetur exercitation aliqua proident reprehenderit tempor ea eu. Amet ipsum labore magna elit.",
- "registered": "Wednesday, September 4, 2019 8:29 AM",
- "latitude": "-49.844379",
- "longitude": "-5.565357",
- "tags": [
- "dolor",
- "fugiat",
- "ea",
- "nisi",
- "non"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Elena Suarez"
- },
- {
- "id": 1,
- "name": "Pruitt Leach"
- },
- {
- "id": 2,
- "name": "Pugh Robinson"
- }
- ],
- "greeting": "Hello, Dana! You have 8 unread messages.",
- "favoriteFruit": "apple"
- },
- {
- "_id": "5e7a86c70efbf62ab5579408",
- "index": 1,
- "guid": "2c64c2d3-a830-4598-a399-f68f798ba6dc",
- "isActive": true,
- "balance": "$1,838.58",
- "picture": "http://placehold.it/32x32",
- "age": 33,
- "eyeColor": "brown",
- "name": {
- "first": "Ladonna",
- "last": "Willis"
- },
- "company": "JOVIOLD",
- "email": "ladonna.willis@joviold.us",
- "phone": "+1 (921) 591-2296",
- "address": "441 Highland Place, Leyner, Pennsylvania, 1788",
- "about": "Consequat deserunt nisi sit ex occaecat. Magna pariatur irure nisi duis laborum proident ipsum duis. Tempor qui consectetur consequat sunt proident ex ad id sint cupidatat sint.",
- "registered": "Wednesday, January 13, 2016 6:03 PM",
- "latitude": "-62.130182",
- "longitude": "-102.884995",
- "tags": [
- "fugiat",
- "ipsum",
- "ut",
- "pariatur",
- "enim"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Gamble Rose"
- },
- {
- "id": 1,
- "name": "Olive Horn"
- },
- {
- "id": 2,
- "name": "Benita Ochoa"
- }
- ],
- "greeting": "Hello, Ladonna! You have 6 unread messages.",
- "favoriteFruit": "banana"
- },
- {
- "_id": "5e7a86c71e30c95bbb0ff386",
- "index": 2,
- "guid": "04e45222-d785-461b-99be-b330585eb1a1",
- "isActive": true,
- "balance": "$3,591.60",
- "picture": "http://placehold.it/32x32",
- "age": 32,
- "eyeColor": "brown",
- "name": {
- "first": "Lee",
- "last": "Buckley"
- },
- "company": "TELEQUIET",
- "email": "lee.buckley@telequiet.biz",
- "phone": "+1 (897) 511-2132",
- "address": "675 Argyle Road, Kempton, Ohio, 4411",
- "about": "Sunt aliquip excepteur veniam fugiat consequat commodo ex est nulla laboris cillum enim. Laboris cupidatat et ipsum anim reprehenderit officia officia aute aliqua tempor. Incididunt sunt cupidatat mollit deserunt id nisi esse elit nisi est eiusmod aliquip. Lorem cillum ipsum quis aliquip laboris ex minim eu quis. Dolore incididunt officia labore enim Lorem in occaecat aliquip. Mollit ad duis non non qui et Lorem cillum.",
- "registered": "Tuesday, January 16, 2018 3:14 PM",
- "latitude": "-51.283144",
- "longitude": "-112.569722",
- "tags": [
- "id",
- "veniam",
- "dolor",
- "nulla",
- "pariatur"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Dina Craft"
- },
- {
- "id": 1,
- "name": "Ashlee Ferrell"
- },
- {
- "id": 2,
- "name": "Mcbride Gill"
- }
- ],
- "greeting": "Hello, Lee! You have 7 unread messages.",
- "favoriteFruit": "banana"
- },
- {
- "_id": "5e7a86c70e08bf0c278749f9",
- "index": 3,
- "guid": "0928ccac-e028-405a-a614-76628ba131b4",
- "isActive": false,
- "balance": "$2,867.88",
- "picture": "http://placehold.it/32x32",
- "age": 26,
- "eyeColor": "green",
- "name": {
- "first": "Chen",
- "last": "Rosa"
- },
- "company": "EXPOSA",
- "email": "chen.rosa@exposa.me",
- "phone": "+1 (956) 519-3064",
- "address": "239 Amersfort Place, Fillmore, South Carolina, 2443",
- "about": "Est ipsum cillum proident veniam voluptate enim sit eu excepteur veniam sit. Sunt aliqua qui incididunt id irure nulla qui. Et consequat ad anim proident minim dolor quis aliquip Lorem qui fugiat voluptate ex.",
- "registered": "Wednesday, April 9, 2014 12:45 PM",
- "latitude": "-15.222992",
- "longitude": "76.730424",
- "tags": [
- "eiusmod",
- "sit",
- "do",
- "aute",
- "ea"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Huff Townsend"
- },
- {
- "id": 1,
- "name": "Stacie Downs"
- },
- {
- "id": 2,
- "name": "Liza Barron"
- }
- ],
- "greeting": "Hello, Chen! You have 8 unread messages.",
- "favoriteFruit": "banana"
- },
- {
- "_id": "5e7a86c7086fc15efc387abc",
- "index": 4,
- "guid": "c71e62aa-8428-44cd-a2a5-7c30aaf963fe",
- "isActive": true,
- "balance": "$3,022.64",
- "picture": "http://placehold.it/32x32",
- "age": 32,
- "eyeColor": "blue",
- "name": {
- "first": "Walton",
- "last": "Mendez"
- },
- "company": "BUZZNESS",
- "email": "walton.mendez@buzzness.tv",
- "phone": "+1 (849) 560-2058",
- "address": "507 Colonial Court, Collins, New York, 7941",
- "about": "Et nisi in excepteur velit non incididunt sit. Consectetur magna sunt dolor eu Lorem adipisicing incididunt laborum consequat proident. Laboris ut dolor laboris esse ut dolor adipisicing ad fugiat commodo fugiat incididunt pariatur anim. Amet reprehenderit aute fugiat incididunt irure eu duis sint amet aliquip excepteur tempor dolore. Anim reprehenderit commodo irure sint et tempor occaecat fugiat ex commodo consectetur. Id ex dolor et culpa mollit. Voluptate magna est ex proident deserunt ullamco enim quis nulla cupidatat voluptate culpa exercitation Lorem.",
- "registered": "Tuesday, May 9, 2017 2:38 PM",
- "latitude": "86.083203",
- "longitude": "57.386268",
- "tags": [
- "Lorem",
- "aute",
- "proident",
- "eu",
- "incididunt"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Byers Sims"
- },
- {
- "id": 1,
- "name": "Suzanne Gonzalez"
- },
- {
- "id": 2,
- "name": "Vicki Velasquez"
- }
- ],
- "greeting": "Hello, Walton! You have 5 unread messages.",
- "favoriteFruit": "banana"
- },
- {
- "_id": "5e7a86c7dc9b82ffcb2868a2",
- "index": 5,
- "guid": "76f1c1cc-9164-43df-8858-633ee696df1c",
- "isActive": true,
- "balance": "$2,625.28",
- "picture": "http://placehold.it/32x32",
- "age": 40,
- "eyeColor": "green",
- "name": {
- "first": "Wise",
- "last": "Head"
- },
- "company": "FARMEX",
- "email": "wise.head@farmex.com",
- "phone": "+1 (850) 478-3280",
- "address": "425 Kent Street, Witmer, New Jersey, 2411",
- "about": "Velit amet fugiat enim occaecat do. Nulla sint officia anim ullamco. Ea quis excepteur excepteur enim ullamco. Amet aliqua mollit ad excepteur minim voluptate in velit sunt elit duis quis consequat nulla. Est dolor quis culpa aute id occaecat adipisicing mollit do consectetur fugiat. Mollit elit ex nostrud pariatur. Deserunt proident et voluptate occaecat labore occaecat Lorem exercitation est minim magna.",
- "registered": "Monday, March 23, 2015 10:14 PM",
- "latitude": "29.880281",
- "longitude": "126.094567",
- "tags": [
- "enim",
- "sunt",
- "cupidatat",
- "officia",
- "aute"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Fuentes Tyler"
- },
- {
- "id": 1,
- "name": "Flora Massey"
- },
- {
- "id": 2,
- "name": "Manuela Parks"
- }
- ],
- "greeting": "Hello, Wise! You have 8 unread messages.",
- "favoriteFruit": "strawberry"
- },
- {
- "_id": "5e7a86c7b3605b4ab198b25f",
- "index": 6,
- "guid": "818a0d46-9595-4066-a819-c93979220983",
- "isActive": true,
- "balance": "$3,193.77",
- "picture": "http://placehold.it/32x32",
- "age": 30,
- "eyeColor": "brown",
- "name": {
- "first": "Baldwin",
- "last": "Mcguire"
- },
- "company": "ZILCH",
- "email": "baldwin.mcguire@zilch.io",
- "phone": "+1 (803) 562-3968",
- "address": "address replaced",
- "about": "Nostrud exercitation Lorem reprehenderit commodo aliquip. Exercitation exercitation proident aliquip et do cillum id ad ad reprehenderit ipsum elit nostrud. Occaecat velit sit commodo aliquip esse.",
- "registered": "Saturday, January 14, 2017 3:13 AM",
- "latitude": "-38.674801",
- "longitude": "78.160951",
- "tags": [
- "reprehenderit",
- "eu",
- "magna",
- "nulla",
- "non"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Austin Gonzales"
- },
- {
- "id": 1,
- "name": "Polly Mcknight"
- },
- {
- "id": 2,
- "name": "Lucy Wagner"
- }
- ],
- "greeting": "Hello, Baldwin! You have 7 unread messages.",
- "favoriteFruit": "banana"
- },
- {
- "_id": "5e7a86c700d93af1dcbe69f3",
- "index": 7,
- "guid": "09dc8fc1-207f-45f2-9d2c-f1e70e278e9a",
- "isActive": true,
- "balance": "$3,895.90",
- "picture": "http://placehold.it/32x32",
- "age": 21,
- "eyeColor": "brown",
- "name": {
- "first": "Key",
- "last": "Bolton"
- },
- "company": "MAGNINA",
- "email": "key.bolton@magnina.net",
- "phone": "+1 (918) 466-2785",
- "address": "139 Blake Court, Chautauqua, Georgia, 3570",
- "about": "Cupidatat excepteur reprehenderit eiusmod aute ea commodo ipsum pariatur dolore veniam adipisicing dolor. Excepteur ex in laborum cupidatat cillum cillum qui dolore consequat excepteur. Lorem deserunt eiusmod esse proident et ullamco reprehenderit ad ea. Cupidatat veniam deserunt magna eu labore ipsum et officia officia irure non eiusmod.",
- "registered": "Wednesday, October 5, 2016 8:28 AM",
- "latitude": "89.82294",
- "longitude": "45.807834",
- "tags": [
- "et",
- "excepteur",
- "sunt",
- "ea",
- "irure"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Farmer Adkins"
- },
- {
- "id": 1,
- "name": "Summers Huffman"
- },
- {
- "id": 2,
- "name": "Lessie Holden"
- }
- ],
- "greeting": "Hello, Key! You have 9 unread messages.",
- "favoriteFruit": "strawberry"
- },
- {
- "_id": "5e7a86c7a3fcbd25660a493d",
- "index": 8,
- "guid": "7d58a9c2-6940-499e-ba24-75227b1a09d9",
- "isActive": true,
- "balance": "$1,606.76",
- "picture": "http://placehold.it/32x32",
- "age": 31,
- "eyeColor": "green",
- "name": {
- "first": "Gonzales",
- "last": "Manning"
- },
- "company": "ORGANICA",
- "email": "gonzales.manning@organica.name",
- "phone": "+1 (993) 556-2745",
- "address": "690 Regent Place, Rodman, Marshall Islands, 7114",
- "about": "Magna ullamco voluptate nostrud et magna ea aute sint id quis proident ad excepteur ullamco. Aliquip nostrud qui quis duis occaecat commodo laborum labore aute. Mollit ullamco in qui eu voluptate dolore aute mollit sint do sit nulla aliqua. Occaecat laborum ex velit ea ex ad eiusmod enim fugiat.",
- "registered": "Monday, December 1, 2014 6:32 AM",
- "latitude": "48.780262",
- "longitude": "-75.333042",
- "tags": [
- "non",
- "laborum",
- "et",
- "Lorem",
- "id"
- ],
- "range": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9
- ],
- "friends": [
- {
- "id": 0,
- "name": "Hester Finch"
- },
- {
- "id": 1,
- "name": "Tia Cooley"
- },
- {
- "id": 2,
- "name": "Cathryn Howe"
- }
- ],
- "greeting": "Hello, Gonzales! You have 5 unread messages.",
- "favoriteFruit": "apple"
- }
-])json"
diff --git a/toolsrc/src/vcpkg-test/manifests.cpp b/toolsrc/src/vcpkg-test/manifests.cpp
deleted file mode 100644
index bbbe0c96c..000000000
--- a/toolsrc/src/vcpkg-test/manifests.cpp
+++ /dev/null
@@ -1,733 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-#include <vcpkg-test/util.h>
-
-#if defined(_MSC_VER)
-#pragma warning(disable : 6237)
-#endif
-
-using namespace vcpkg;
-using namespace vcpkg::Paragraphs;
-using namespace vcpkg::Test;
-
-static Json::Object parse_json_object(StringView sv)
-{
- auto json = Json::parse(sv);
- // we're not testing json parsing here, so just fail on errors
- if (auto r = json.get())
- {
- return std::move(r->first.object());
- }
- else
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, json.error()->format());
- }
-}
-
-static Parse::ParseExpected<SourceControlFile> test_parse_manifest(StringView sv, bool expect_fail = false)
-{
- auto object = parse_json_object(sv);
- auto res = SourceControlFile::parse_manifest_file(fs::u8path("<test manifest>"), object);
- if (!res.has_value() && !expect_fail)
- {
- print_error_message(res.error());
- }
- REQUIRE(res.has_value() == !expect_fail);
- return res;
-}
-
-static const FeatureFlagSettings feature_flags_with_versioning{false, false, false, true};
-static const FeatureFlagSettings feature_flags_without_versioning{false, false, false, false};
-
-TEST_CASE ("manifest construct minimum", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "1.2.8"
- })json");
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->name == "zlib");
- REQUIRE(pgh.core_paragraph->version == "1.2.8");
- REQUIRE(pgh.core_paragraph->maintainers.empty());
- REQUIRE(pgh.core_paragraph->description.empty());
- REQUIRE(pgh.core_paragraph->dependencies.empty());
- REQUIRE(!pgh.core_paragraph->builtin_baseline.has_value());
-
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning));
-}
-
-TEST_CASE ("manifest versioning", "[manifests]")
-{
- std::tuple<StringLiteral, Versions::Scheme, StringLiteral> data[] = {
- {R"json({
- "name": "zlib",
- "version-string": "abcd"
-}
-)json",
- Versions::Scheme::String,
- "abcd"},
- {R"json({
- "name": "zlib",
- "version-date": "2020-01-01"
-}
-)json",
- Versions::Scheme::Date,
- "2020-01-01"},
- {R"json({
- "name": "zlib",
- "version": "1.2.3.4.5"
-}
-)json",
- Versions::Scheme::Relaxed,
- "1.2.3.4.5"},
- {R"json({
- "name": "zlib",
- "version-semver": "1.2.3-rc3"
-}
-)json",
- Versions::Scheme::Semver,
- "1.2.3-rc3"},
- };
- for (auto v : data)
- {
- auto m_pgh = test_parse_manifest(std::get<0>(v));
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
- REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v));
- REQUIRE(pgh.core_paragraph->version_scheme == std::get<1>(v));
- REQUIRE(pgh.core_paragraph->version == std::get<2>(v));
- }
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "version-semver": "1.2.3-rc3"
- })json",
- true);
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd#1"
- })json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version": "abcd#1"
- })json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-date": "abcd#1"
- })json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-semver": "abcd#1"
- })json",
- true);
-
- SECTION ("version syntax")
- {
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-semver": "2020-01-01"
- })json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-date": "1.1.1"
- })json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version": "1.2.3-rc3"
- })json",
- true);
- }
-}
-
-TEST_CASE ("manifest constraints hash", "[manifests]")
-{
- auto p = unwrap(test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "dependencies": [
- {
- "name": "d",
- "version>=": "2018-09-01#1"
- }
- ]
-})json"));
- REQUIRE(p->core_paragraph->dependencies.at(0).constraint.value == "2018-09-01");
- REQUIRE(p->core_paragraph->dependencies.at(0).constraint.port_version == 1);
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "dependencies": [
- {
- "name": "d",
- "version>=": "2018-09-01#0"
- }
- ]
-})json",
- true);
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "dependencies": [
- {
- "name": "d",
- "version>=": "2018-09-01#-1"
- }
- ]
-})json",
- true);
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "dependencies": [
- {
- "name": "d",
- "version>=": "2018-09-01",
- "port-version": 1
- }
- ]
-})json",
- true);
-}
-
-TEST_CASE ("manifest overrides error hash", "[manifests]")
-{
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "d",
- "version-string": "abcd#1"
- }
- ]
-})json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "d",
- "version-date": "2018-01-01#1"
- }
- ]
-})json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "d",
- "version": "1.2#1"
- }
- ]
-})json",
- true);
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "d",
- "version-semver": "1.2#1"
- }
- ]
-})json",
- true);
-}
-
-TEST_CASE ("manifest constraints", "[manifests]")
-{
- std::string raw = R"json({
- "name": "zlib",
- "version-string": "abcd",
- "builtin-baseline": "089fa4de7dca22c67dcab631f618d5cd0697c8d4",
- "dependencies": [
- "a",
- {
- "$extra": null,
- "name": "c"
- },
- {
- "name": "d",
- "version>=": "2018-09-01"
- }
- ]
-}
-)json";
- auto m_pgh = test_parse_manifest(raw);
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
- REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
- REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw);
- REQUIRE(pgh.core_paragraph->dependencies.size() == 3);
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "a");
- REQUIRE(pgh.core_paragraph->dependencies[0].constraint ==
- DependencyConstraint{Versions::Constraint::Type::None, "", 0});
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "c");
- REQUIRE(pgh.core_paragraph->dependencies[1].constraint ==
- DependencyConstraint{Versions::Constraint::Type::None, "", 0});
- REQUIRE(pgh.core_paragraph->dependencies[2].name == "d");
- REQUIRE(pgh.core_paragraph->dependencies[2].constraint ==
- DependencyConstraint{Versions::Constraint::Type::Minimum, "2018-09-01", 0});
- REQUIRE(pgh.core_paragraph->builtin_baseline == "089fa4de7dca22c67dcab631f618d5cd0697c8d4");
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "dependencies": [
- {
- "name": "d",
- "port-version": 5
- }
- ]
- })json",
- true);
-}
-
-TEST_CASE ("manifest builtin-baseline", "[manifests]")
-{
- SECTION ("valid baseline")
- {
- std::string raw = R"json({
- "name": "zlib",
- "version-string": "abcd",
- "builtin-baseline": "089fa4de7dca22c67dcab631f618d5cd0697c8d4"
-}
-)json";
- auto m_pgh = test_parse_manifest(raw);
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
- REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
- REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") ==
- "089fa4de7dca22c67dcab631f618d5cd0697c8d4");
- }
-
- SECTION ("empty baseline")
- {
- std::string raw = R"json({
- "name": "zlib",
- "version-string": "abcd",
- "builtin-baseline": ""
-}
-)json";
-
- auto m_pgh = test_parse_manifest(raw);
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
- REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
- REQUIRE(pgh.core_paragraph->builtin_baseline.value_or("does not have a value") == "");
- }
-}
-
-TEST_CASE ("manifest overrides", "[manifests]")
-{
- std::tuple<StringLiteral, Versions::Scheme, StringLiteral> data[] = {
- {R"json({
- "name": "zlib",
- "version-date": "2020-01-01",
- "overrides": [
- {
- "name": "abc",
- "version-string": "abcd"
- }
- ]
-}
-)json",
- Versions::Scheme::String,
- "abcd"},
- {R"json({
- "name": "zlib",
- "version": "1.2.3.4.5",
- "overrides": [
- {
- "name": "abc",
- "version-date": "2020-01-01"
- }
- ]
-}
-)json",
- Versions::Scheme::Date,
- "2020-01-01"},
- {R"json({
- "name": "zlib",
- "version-date": "2020-01-01",
- "overrides": [
- {
- "name": "abc",
- "version": "1.2.3.4.5"
- }
- ]
-}
-)json",
- Versions::Scheme::Relaxed,
- "1.2.3.4.5"},
- {R"json({
- "name": "zlib",
- "version-date": "2020-01-01",
- "overrides": [
- {
- "name": "abc",
- "version-semver": "1.2.3-rc3"
- }
- ]
-}
-)json",
- Versions::Scheme::Semver,
- "1.2.3-rc3"},
- };
- for (auto v : data)
- {
- auto m_pgh = test_parse_manifest(std::get<0>(v));
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
- REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v));
- REQUIRE(pgh.core_paragraph->overrides.size() == 1);
- REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == std::get<1>(v));
- REQUIRE(pgh.core_paragraph->overrides[0].version == std::get<2>(v));
- REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
- }
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "abc",
- "version-semver": "1.2.3-rc3",
- "version-string": "1.2.3-rc3"
- }
- ]})json",
- true);
-
- test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "abc",
- "port-version": 5
- }
- ]})json",
- true);
-
- std::string raw = R"json({
- "name": "zlib",
- "version-string": "abcd",
- "overrides": [
- {
- "name": "abc",
- "version-string": "hello",
- "port-version": 5
- },
- {
- "name": "abcd",
- "version-string": "hello",
- "port-version": 7
- }
- ]
-}
-)json";
- auto m_pgh = test_parse_manifest(raw);
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
- REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw);
- REQUIRE(pgh.core_paragraph->overrides.size() == 2);
- REQUIRE(pgh.core_paragraph->overrides[0].name == "abc");
- REQUIRE(pgh.core_paragraph->overrides[0].port_version == 5);
- REQUIRE(pgh.core_paragraph->overrides[1].name == "abcd");
- REQUIRE(pgh.core_paragraph->overrides[1].port_version == 7);
-
- REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
-}
-
-TEST_CASE ("manifest construct maximum", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "s",
- "version-string": "v",
- "maintainers": ["m"],
- "description": "d",
- "dependencies": ["bd"],
- "default-features": ["df"],
- "features": [
- {
- "name": "iroh",
- "description": "zuko's uncle",
- "dependencies": [
- "firebending",
- {
- "name": "tea"
- },
- {
- "name": "order.white-lotus",
- "features": [ "the-ancient-ways" ],
- "platform": "!(windows & arm)"
- }
- ]
- },
- {
- "name": "zuko",
- "description": ["son of the fire lord", "firebending 師父"]
- }
- ]
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->name == "s");
- REQUIRE(pgh.core_paragraph->version == "v");
- REQUIRE(pgh.core_paragraph->maintainers.size() == 1);
- REQUIRE(pgh.core_paragraph->maintainers[0] == "m");
- REQUIRE(pgh.core_paragraph->description.size() == 1);
- REQUIRE(pgh.core_paragraph->description[0] == "d");
- REQUIRE(pgh.core_paragraph->dependencies.size() == 1);
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "bd");
- REQUIRE(pgh.core_paragraph->default_features.size() == 1);
- REQUIRE(pgh.core_paragraph->default_features[0] == "df");
-
- REQUIRE(pgh.feature_paragraphs.size() == 2);
-
- REQUIRE(pgh.feature_paragraphs[0]->name == "iroh");
- REQUIRE(pgh.feature_paragraphs[0]->description.size() == 1);
- REQUIRE(pgh.feature_paragraphs[0]->description[0] == "zuko's uncle");
- REQUIRE(pgh.feature_paragraphs[0]->dependencies.size() == 3);
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[0].name == "firebending");
-
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[1].name == "order.white-lotus");
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[1].features.size() == 1);
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[1].features[0] == "the-ancient-ways");
- REQUIRE_FALSE(pgh.feature_paragraphs[0]->dependencies[1].platform.evaluate(
- {{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "arm"}}));
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[1].platform.evaluate(
- {{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "x86"}}));
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[1].platform.evaluate(
- {{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}, {"VCPKG_TARGET_ARCHITECTURE", "x86"}}));
-
- REQUIRE(pgh.feature_paragraphs[0]->dependencies[2].name == "tea");
-
- REQUIRE(pgh.feature_paragraphs[1]->name == "zuko");
- REQUIRE(pgh.feature_paragraphs[1]->description.size() == 2);
- REQUIRE(pgh.feature_paragraphs[1]->description[0] == "son of the fire lord");
- REQUIRE(pgh.feature_paragraphs[1]->description[1] == "firebending 師父");
-
- REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning));
-}
-
-TEST_CASE ("SourceParagraph manifest two dependencies", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "1.2.8",
- "dependencies": ["z", "openssl"]
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->dependencies.size() == 2);
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "openssl");
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "z");
-}
-
-TEST_CASE ("SourceParagraph manifest three dependencies", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "1.2.8",
- "dependencies": ["z", "openssl", "xyz"]
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->dependencies.size() == 3);
- // should be ordered
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "openssl");
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "xyz");
- REQUIRE(pgh.core_paragraph->dependencies[2].name == "z");
-}
-
-TEST_CASE ("SourceParagraph manifest construct qualified dependencies", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "zlib",
- "version-string": "1.2.8",
- "dependencies": [
- {
- "name": "liba",
- "platform": "windows"
- },
- {
- "name": "libb",
- "platform": "uwp"
- }
- ]
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->name == "zlib");
- REQUIRE(pgh.core_paragraph->version == "1.2.8");
- REQUIRE(pgh.core_paragraph->maintainers.empty());
- REQUIRE(pgh.core_paragraph->description.empty());
- REQUIRE(pgh.core_paragraph->dependencies.size() == 2);
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "liba");
- REQUIRE(pgh.core_paragraph->dependencies[0].platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "libb");
- REQUIRE(pgh.core_paragraph->dependencies[1].platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
-}
-
-TEST_CASE ("SourceParagraph manifest default features", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "a",
- "version-string": "1.0",
- "default-features": ["a1"]
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->default_features.size() == 1);
- REQUIRE(pgh.core_paragraph->default_features[0] == "a1");
-}
-
-TEST_CASE ("SourceParagraph manifest description paragraph", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "a",
- "version-string": "1.0",
- "description": ["line 1", "line 2", "line 3"]
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->description.size() == 3);
- REQUIRE(pgh.core_paragraph->description[0] == "line 1");
- REQUIRE(pgh.core_paragraph->description[1] == "line 2");
- REQUIRE(pgh.core_paragraph->description[2] == "line 3");
-}
-
-TEST_CASE ("SourceParagraph manifest supports", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "a",
- "version-string": "1.0",
- "supports": "!(windows | osx)"
- })json");
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->supports_expression.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
- REQUIRE_FALSE(pgh.core_paragraph->supports_expression.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- REQUIRE_FALSE(pgh.core_paragraph->supports_expression.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
-}
-
-TEST_CASE ("SourceParagraph manifest empty supports", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "a",
- "version-string": "1.0",
- "supports": ""
- })json",
- true);
- REQUIRE_FALSE(m_pgh.has_value());
-}
-
-TEST_CASE ("SourceParagraph manifest non-string supports", "[manifests]")
-{
- auto m_pgh = test_parse_manifest(R"json({
- "name": "a",
- "version-string": "1.0",
- "supports": true
- })json",
- true);
- REQUIRE_FALSE(m_pgh.has_value());
-}
-
-TEST_CASE ("Serialize all the ports", "[manifests]")
-{
- std::vector<std::string> args_list = {"format-manifest"};
- auto& fs = Files::get_real_filesystem();
- auto args = VcpkgCmdArguments::create_from_arg_sequence(args_list.data(), args_list.data() + args_list.size());
- args.imbue_from_environment();
- VcpkgPaths paths{fs, args};
-
- std::vector<SourceControlFile> scfs;
-
- for (auto dir : fs::directory_iterator(paths.builtin_ports_directory()))
- {
- const auto control = dir / fs::u8path("CONTROL");
- const auto manifest = dir / fs::u8path("vcpkg.json");
- if (fs.exists(control))
- {
- INFO(fs::u8string(control));
- auto contents = fs.read_contents(control, VCPKG_LINE_INFO);
- auto pghs = Paragraphs::parse_paragraphs(contents, fs::u8string(control));
- REQUIRE(pghs);
-
- auto scf = SourceControlFile::parse_control_file(fs::u8string(control),
- std::move(pghs).value_or_exit(VCPKG_LINE_INFO));
- if (!scf)
- {
- INFO(scf.error()->name);
- INFO(scf.error()->error);
- REQUIRE(scf);
- }
-
- scfs.push_back(std::move(*scf.value_or_exit(VCPKG_LINE_INFO)));
- }
- else if (fs.exists(manifest))
- {
- std::error_code ec;
- auto contents = Json::parse_file(fs, manifest, ec);
- REQUIRE_FALSE(ec);
- REQUIRE(contents);
-
- auto scf = SourceControlFile::parse_manifest_file(manifest,
- contents.value_or_exit(VCPKG_LINE_INFO).first.object());
- REQUIRE(scf);
-
- scfs.push_back(std::move(*scf.value_or_exit(VCPKG_LINE_INFO)));
- }
- }
-
- for (auto& scf : scfs)
- {
- auto serialized = serialize_manifest(scf);
- auto serialized_scf = SourceControlFile::parse_manifest_file({}, serialized).value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(*serialized_scf == scf);
- }
-}
diff --git a/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp b/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp
deleted file mode 100644
index 77a796fad..000000000
--- a/toolsrc/src/vcpkg-test/mockcmakevarsprovider.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <vcpkg-test/mockcmakevarprovider.h>
-
-namespace vcpkg::Test
-{
- Optional<const std::unordered_map<std::string, std::string>&> MockCMakeVarProvider::get_generic_triplet_vars(
- Triplet triplet) const
- {
- auto it = generic_triplet_vars.find(triplet);
- if (it == generic_triplet_vars.end()) return nullopt;
- return it->second;
- }
-
- Optional<const std::unordered_map<std::string, std::string>&> MockCMakeVarProvider::get_dep_info_vars(
- const PackageSpec& spec) const
- {
- auto it = dep_info_vars.find(spec);
- if (it == dep_info_vars.end()) return nullopt;
- return it->second;
- }
-
- Optional<const std::unordered_map<std::string, std::string>&> MockCMakeVarProvider::get_tag_vars(
- const PackageSpec& spec) const
- {
- auto it = tag_vars.find(spec);
- if (it == tag_vars.end()) return nullopt;
- return it->second;
- }
-}
diff --git a/toolsrc/src/vcpkg-test/optional.cpp b/toolsrc/src/vcpkg-test/optional.cpp
deleted file mode 100644
index f18efb359..000000000
--- a/toolsrc/src/vcpkg-test/optional.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/lineinfo.h>
-#include <vcpkg/base/optional.h>
-#include <vcpkg/base/util.h>
-
-#include <vector>
-
-namespace
-{
- struct identity_projection
- {
- template<class T>
- const T& operator()(const T& val) noexcept
- {
- return val;
- }
- };
-}
-
-TEST_CASE ("equal", "[optional]")
-{
- using vcpkg::Optional;
-
- CHECK(Optional<int>{} == Optional<int>{});
- CHECK_FALSE(Optional<int>{} == Optional<int>{42});
- CHECK_FALSE(Optional<int>{42} == Optional<int>{});
- CHECK_FALSE(Optional<int>{1729} == Optional<int>{42});
- CHECK(Optional<int>{42} == Optional<int>{42});
-}
-
-TEST_CASE ("ref conversion", "[optional]")
-{
- using vcpkg::Optional;
-
- Optional<int> i_empty;
- Optional<int> i_1 = 1;
- const Optional<int> ci_1 = 1;
-
- Optional<int&> ref_empty = i_empty;
- Optional<const int&> cref_empty = i_empty;
-
- Optional<int&> ref_1 = i_1;
- Optional<const int&> cref_1 = ci_1;
-
- REQUIRE(ref_empty.has_value() == false);
- REQUIRE(cref_empty.has_value() == false);
-
- REQUIRE(ref_1.get() == i_1.get());
- REQUIRE(cref_1.get() == ci_1.get());
-
- ref_empty = i_1;
- cref_empty = ci_1;
- REQUIRE(ref_empty.get() == i_1.get());
- REQUIRE(cref_empty.get() == ci_1.get());
-
- const int x = 5;
- cref_1 = x;
- REQUIRE(cref_1.get() == &x);
-}
-
-TEST_CASE ("value conversion", "[optional]")
-{
- using vcpkg::Optional;
-
- Optional<long> j = 1;
- Optional<int> i = j;
- Optional<const char*> cstr = "hello, world!";
- Optional<std::string> cppstr = cstr;
-
- std::vector<int> v{1, 2, 3};
- Optional<std::vector<int>&> o_v(v);
- REQUIRE(o_v.has_value());
- REQUIRE(o_v.get()->size() == 3);
- Optional<std::vector<int>> o_w(std::move(o_v));
- REQUIRE(o_w.has_value());
- REQUIRE(o_w.get()->size() == 3);
- // Moving from Optional<&> should not move the underlying object
- REQUIRE(o_v.has_value());
- REQUIRE(o_v.get()->size() == 3);
-}
-
-TEST_CASE ("optional.map", "[optional]")
-{
- using vcpkg::NullOpt;
- using vcpkg::nullopt;
- using vcpkg::Optional;
-
- const Optional<std::unique_ptr<int>> move_only;
-
- Optional<int*> m = move_only.map([](auto&& p) { return p.get(); });
- Optional<Optional<int*>> n =
- move_only.map([](auto&& p) -> Optional<int*> { return p ? Optional<int*>{p.get()} : nullopt; });
- Optional<NullOpt> o = move_only.map([](auto&&) { return nullopt; });
-
- Optional<int> five = 5;
-
- struct MoveTest
- {
- int operator()(int&&) { return 1; }
- int operator()(const int&) { return -1; }
- } move_test;
-
- Optional<int> dst = std::move(five).map(move_test);
- REQUIRE(dst == 1);
- Optional<int> dst2 = five.map(move_test);
- REQUIRE(dst2 == -1);
-}
-
-TEST_CASE ("common_projection", "[optional]")
-{
- using vcpkg::Util::common_projection;
- std::vector<int> input;
- CHECK(!common_projection(input, identity_projection{}).has_value());
- input.push_back(42);
- CHECK(common_projection(input, identity_projection{}).value_or_exit(VCPKG_LINE_INFO) == 42);
- input.push_back(42);
- CHECK(common_projection(input, identity_projection{}).value_or_exit(VCPKG_LINE_INFO) == 42);
- input.push_back(1729);
- CHECK(!common_projection(input, identity_projection{}).has_value());
-}
diff --git a/toolsrc/src/vcpkg-test/paragraph.cpp b/toolsrc/src/vcpkg-test/paragraph.cpp
deleted file mode 100644
index cb3f8e620..000000000
--- a/toolsrc/src/vcpkg-test/paragraph.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/strings.h>
-
-#include <vcpkg/paragraphs.h>
-
-#include <vcpkg-test/util.h>
-
-namespace Strings = vcpkg::Strings;
-using vcpkg::Parse::Paragraph;
-
-namespace
-{
- auto test_parse_control_file(const std::vector<std::unordered_map<std::string, std::string>>& v)
- {
- std::vector<Paragraph> pghs;
- for (auto&& p : v)
- {
- pghs.emplace_back();
- for (auto&& kv : p)
- pghs.back().emplace(kv.first, std::make_pair(kv.second, vcpkg::Parse::TextRowCol{}));
- }
- return vcpkg::SourceControlFile::parse_control_file("", std::move(pghs));
- }
-
- auto test_make_binary_paragraph(const std::unordered_map<std::string, std::string>& v)
- {
- Paragraph pgh;
- for (auto&& kv : v)
- pgh.emplace(kv.first, std::make_pair(kv.second, vcpkg::Parse::TextRowCol{}));
-
- return vcpkg::BinaryParagraph(std::move(pgh));
- }
-
-}
-
-TEST_CASE ("SourceParagraph construct minimum", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- }});
-
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->name == "zlib");
- REQUIRE(pgh.core_paragraph->version == "1.2.8");
- REQUIRE(pgh.core_paragraph->maintainers.empty());
- REQUIRE(pgh.core_paragraph->description.empty());
- REQUIRE(pgh.core_paragraph->dependencies.size() == 0);
-}
-
-TEST_CASE ("SourceParagraph construct invalid", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- {"Build-Depends", "1.2.8"},
- }});
-
- REQUIRE(!m_pgh.has_value());
- REQUIRE(m_pgh.error()->has_error());
-
- m_pgh = test_parse_control_file({{
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- {"Default-Features", "1.2.8"},
- }});
-
- REQUIRE(!m_pgh.has_value());
- REQUIRE(m_pgh.error()->has_error());
-
- m_pgh = test_parse_control_file({
- {
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- },
- {
- {"Feature", "a"},
- {"Build-Depends", "1.2.8"},
- },
- });
-
- REQUIRE(!m_pgh.has_value());
- REQUIRE(m_pgh.error()->has_error());
-
- // invalid field`s name
- m_pgh = test_parse_control_file({{
- {"Surce", "zlib"},
- {"Vursion", "1.2.8"},
- }});
-
- REQUIRE(!m_pgh.has_value());
- REQUIRE(m_pgh.error()->has_error());
-}
-
-TEST_CASE ("SourceParagraph construct maximum", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "s"},
- {"Version", "v"},
- {"Maintainer", "m"},
- {"Description", "d"},
- {"Build-Depends", "bd"},
- {"Default-Features", "df"},
- }});
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->name == "s");
- REQUIRE(pgh.core_paragraph->version == "v");
- REQUIRE(pgh.core_paragraph->maintainers.size() == 1);
- REQUIRE(pgh.core_paragraph->maintainers[0] == "m");
- REQUIRE(pgh.core_paragraph->description.size() == 1);
- REQUIRE(pgh.core_paragraph->description[0] == "d");
- REQUIRE(pgh.core_paragraph->dependencies.size() == 1);
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "bd");
- REQUIRE(pgh.core_paragraph->default_features.size() == 1);
- REQUIRE(pgh.core_paragraph->default_features[0] == "df");
-}
-
-TEST_CASE ("SourceParagraph construct feature", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({
- {
- {"Source", "s"},
- {"Version", "v"},
- },
- {{"Feature", "f"}, {"Description", "d2"}, {"Build-Depends", "bd2"}},
- });
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.feature_paragraphs.size() == 1);
- REQUIRE(pgh.feature_paragraphs[0]->name == "f");
- REQUIRE(pgh.feature_paragraphs[0]->description == std::vector<std::string>{"d2"});
- REQUIRE(pgh.feature_paragraphs[0]->dependencies.size() == 1);
-}
-
-TEST_CASE ("SourceParagraph two dependencies", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- {"Build-Depends", "z, openssl"},
- }});
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->dependencies.size() == 2);
- // should be ordered
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "openssl");
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "z");
-}
-
-TEST_CASE ("SourceParagraph three dependencies", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- {"Build-Depends", "z, openssl, xyz"},
- }});
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->dependencies.size() == 3);
- // should be ordered
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "openssl");
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "xyz");
- REQUIRE(pgh.core_paragraph->dependencies[2].name == "z");
-}
-
-TEST_CASE ("SourceParagraph construct qualified dependencies", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "zlib"},
- {"Version", "1.2.8"},
- {"Build-Depends", "liba (windows), libb (uwp)"},
- }});
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->name == "zlib");
- REQUIRE(pgh.core_paragraph->version == "1.2.8");
- REQUIRE(pgh.core_paragraph->maintainers.empty());
- REQUIRE(pgh.core_paragraph->description.empty());
- REQUIRE(pgh.core_paragraph->dependencies.size() == 2);
- REQUIRE(pgh.core_paragraph->dependencies[0].name == "liba");
- REQUIRE(pgh.core_paragraph->dependencies[0].platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- REQUIRE(pgh.core_paragraph->dependencies[1].name == "libb");
- REQUIRE(pgh.core_paragraph->dependencies[1].platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
-}
-
-TEST_CASE ("SourceParagraph default features", "[paragraph]")
-{
- auto m_pgh = test_parse_control_file({{
- {"Source", "a"},
- {"Version", "1.0"},
- {"Default-Features", "a1"},
- }});
- REQUIRE(m_pgh.has_value());
- auto& pgh = **m_pgh.get();
-
- REQUIRE(pgh.core_paragraph->default_features.size() == 1);
- REQUIRE(pgh.core_paragraph->default_features[0] == "a1");
-}
-
-TEST_CASE ("BinaryParagraph construct minimum", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- });
-
- REQUIRE(pgh.spec.name() == "zlib");
- REQUIRE(pgh.version == "1.2.8");
- REQUIRE(pgh.maintainers.empty());
- REQUIRE(pgh.description.empty());
- REQUIRE(pgh.spec.triplet().canonical_name() == "x86-windows");
- REQUIRE(pgh.dependencies.size() == 0);
-}
-
-TEST_CASE ("BinaryParagraph construct maximum", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "s"},
- {"Version", "v"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Maintainer", "m"},
- {"Description", "d"},
- {"Depends", "bd"},
- });
-
- REQUIRE(pgh.spec.name() == "s");
- REQUIRE(pgh.version == "v");
- REQUIRE(pgh.maintainers.size() == 1);
- REQUIRE(pgh.maintainers[0] == "m");
- REQUIRE(pgh.description.size() == 1);
- REQUIRE(pgh.description[0] == "d");
- REQUIRE(pgh.dependencies.size() == 1);
- REQUIRE(pgh.dependencies[0] == "bd");
-}
-
-TEST_CASE ("BinaryParagraph three dependencies", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", "a, b, c"},
- });
-
- REQUIRE(pgh.dependencies.size() == 3);
- REQUIRE(pgh.dependencies[0] == "a");
- REQUIRE(pgh.dependencies[1] == "b");
- REQUIRE(pgh.dependencies[2] == "c");
-}
-
-TEST_CASE ("BinaryParagraph abi", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Abi", "abcd123"},
- });
-
- REQUIRE(pgh.dependencies.size() == 0);
- REQUIRE(pgh.abi == "abcd123");
-}
-
-TEST_CASE ("BinaryParagraph default features", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "a"},
- {"Version", "1.0"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Default-Features", "a1"},
- });
-
- REQUIRE(pgh.dependencies.size() == 0);
- REQUIRE(pgh.default_features.size() == 1);
- REQUIRE(pgh.default_features[0] == "a1");
-}
-
-TEST_CASE ("parse paragraphs empty", "[paragraph]")
-{
- const char* str = "";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
- REQUIRE(pghs.empty());
-}
-
-TEST_CASE ("parse paragraphs one field", "[paragraph]")
-{
- const char* str = "f1: v1";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0].size() == 1);
- REQUIRE(pghs[0]["f1"].first == "v1");
-}
-
-TEST_CASE ("parse paragraphs one pgh", "[paragraph]")
-{
- const char* str = "f1: v1\n"
- "f2: v2";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0].size() == 2);
- REQUIRE(pghs[0]["f1"].first == "v1");
- REQUIRE(pghs[0]["f2"].first == "v2");
-}
-
-TEST_CASE ("parse paragraphs two pgh", "[paragraph]")
-{
- const char* str = "f1: v1\n"
- "f2: v2\n"
- "\n"
- "f3: v3\n"
- "f4: v4";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 2);
- REQUIRE(pghs[0].size() == 2);
- REQUIRE(pghs[0]["f1"].first == "v1");
- REQUIRE(pghs[0]["f2"].first == "v2");
- REQUIRE(pghs[1].size() == 2);
- REQUIRE(pghs[1]["f3"].first == "v3");
- REQUIRE(pghs[1]["f4"].first == "v4");
-}
-
-TEST_CASE ("parse paragraphs field names", "[paragraph]")
-{
- const char* str = "1:\n"
- "f:\n"
- "F:\n"
- "0:\n"
- "F-2:\n";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0].size() == 5);
-}
-
-TEST_CASE ("parse paragraphs multiple blank lines", "[paragraph]")
-{
- const char* str = "f1: v1\n"
- "f2: v2\n"
- "\n"
- "\n"
- "f3: v3\n"
- "f4: v4";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 2);
-}
-
-TEST_CASE ("parse paragraphs empty fields", "[paragraph]")
-{
- const char* str = "f1:\n"
- "f2: ";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0].size() == 2);
- REQUIRE(pghs[0]["f1"].first.empty());
- REQUIRE(pghs[0]["f2"].first.empty());
- REQUIRE(pghs[0].size() == 2);
-}
-
-TEST_CASE ("parse paragraphs multiline fields", "[paragraph]")
-{
- const char* str = "f1: simple\n"
- " f1\r\n"
- "f2:\r\n"
- " f2\r\n"
- " continue\r\n";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0]["f1"].first == "simple\n f1");
- REQUIRE(pghs[0]["f2"].first == "\n f2\n continue");
-}
-
-TEST_CASE ("parse paragraphs crlfs", "[paragraph]")
-{
- const char* str = "f1: v1\r\n"
- "f2: v2\r\n"
- "\r\n"
- "f3: v3\r\n"
- "f4: v4";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 2);
- REQUIRE(pghs[0].size() == 2);
- REQUIRE(pghs[0]["f1"].first == "v1");
- REQUIRE(pghs[0]["f2"].first == "v2");
- REQUIRE(pghs[1].size() == 2);
- REQUIRE(pghs[1]["f3"].first == "v3");
- REQUIRE(pghs[1]["f4"].first == "v4");
-}
-
-TEST_CASE ("parse paragraphs comment", "[paragraph]")
-{
- const char* str = "f1: v1\r\n"
- "#comment\r\n"
- "f2: v2\r\n"
- "#comment\r\n"
- "\r\n"
- "#comment\r\n"
- "f3: v3\r\n"
- "#comment\r\n"
- "f4: v4";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 2);
- REQUIRE(pghs[0].size() == 2);
- REQUIRE(pghs[0]["f1"].first == "v1");
- REQUIRE(pghs[0]["f2"].first == "v2");
- REQUIRE(pghs[1].size());
- REQUIRE(pghs[1]["f3"].first == "v3");
- REQUIRE(pghs[1]["f4"].first == "v4");
-}
-
-TEST_CASE ("parse comment before single line feed", "[paragraph]")
-{
- const char* str = "f1: v1\r\n"
- "#comment\n";
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(str, "").value_or_exit(VCPKG_LINE_INFO);
- REQUIRE(pghs[0].size() == 1);
- REQUIRE(pghs[0]["f1"].first == "v1");
-}
-
-TEST_CASE ("BinaryParagraph serialize min", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- });
- std::string ss = Strings::serialize(pgh);
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0].size() == 5);
- REQUIRE(pghs[0]["Package"].first == "zlib");
- REQUIRE(pghs[0]["Version"].first == "1.2.8");
- REQUIRE(pghs[0]["Architecture"].first == "x86-windows");
- REQUIRE(pghs[0]["Multi-Arch"].first == "same");
- REQUIRE(pghs[0]["Type"].first == "Port");
-}
-
-TEST_CASE ("BinaryParagraph serialize max", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Description", "first line\n second line"},
- {"Maintainer", "abc <abc@abc.abc>"},
- {"Depends", "dep"},
- {"Multi-Arch", "same"},
- });
- std::string ss = Strings::serialize(pgh);
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0].size() == 8);
- REQUIRE(pghs[0]["Package"].first == "zlib");
- REQUIRE(pghs[0]["Version"].first == "1.2.8");
- REQUIRE(pghs[0]["Architecture"].first == "x86-windows");
- REQUIRE(pghs[0]["Multi-Arch"].first == "same");
- REQUIRE(pghs[0]["Description"].first == "first line\n second line");
- REQUIRE(pghs[0]["Depends"].first == "dep");
- REQUIRE(pghs[0]["Type"].first == "Port");
-}
-
-TEST_CASE ("BinaryParagraph serialize multiple deps", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", "a, b, c"},
- });
- std::string ss = Strings::serialize(pgh);
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0]["Depends"].first == "a, b, c");
-}
-
-TEST_CASE ("BinaryParagraph serialize abi", "[paragraph]")
-{
- auto pgh = test_make_binary_paragraph({
- {"Package", "zlib"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", "a, b, c"},
- {"Abi", "123abc"},
- });
- std::string ss = Strings::serialize(pgh);
- auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO);
-
- REQUIRE(pghs.size() == 1);
- REQUIRE(pghs[0]["Abi"].first == "123abc");
-}
diff --git a/toolsrc/src/vcpkg-test/plan.cpp b/toolsrc/src/vcpkg-test/plan.cpp
deleted file mode 100644
index 363a2d9b4..000000000
--- a/toolsrc/src/vcpkg-test/plan.cpp
+++ /dev/null
@@ -1,1297 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/graphs.h>
-
-#include <vcpkg/dependencies.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/triplet.h>
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include <vcpkg-test/mockcmakevarprovider.h>
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-
-using Test::make_control_file;
-using Test::make_status_feature_pgh;
-using Test::make_status_pgh;
-using Test::MockCMakeVarProvider;
-using Test::PackageSpecMap;
-
-/// <summary>
-/// Assert that the given action an install of given features from given package.
-/// </summary>
-static void features_check(Dependencies::InstallPlanAction& plan,
- std::string pkg_name,
- std::vector<std::string> expected_features,
- Triplet triplet = Test::X86_WINDOWS)
-{
- const auto& feature_list = plan.feature_list;
-
- REQUIRE(plan.spec.triplet().to_string() == triplet.to_string());
- REQUIRE(pkg_name == plan.spec.name());
- REQUIRE(feature_list.size() == expected_features.size());
-
- for (auto&& feature_name : expected_features)
- {
- // TODO: see if this can be simplified
- if (feature_name == "core" || feature_name.empty())
- {
- REQUIRE((Util::find(feature_list, "core") != feature_list.end() ||
- Util::find(feature_list, "") != feature_list.end()));
- continue;
- }
- REQUIRE(Util::find(feature_list, feature_name) != feature_list.end());
- }
-}
-
-/// <summary>
-/// Assert that the given action is a remove of given package.
-/// </summary>
-static void remove_plan_check(Dependencies::RemovePlanAction& plan,
- std::string pkg_name,
- Triplet triplet = Test::X86_WINDOWS)
-{
- REQUIRE(plan.spec.triplet().to_string() == triplet.to_string());
- REQUIRE(pkg_name == plan.spec.name());
-}
-
-TEST_CASE ("basic install scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "b");
- auto spec_b = spec_map.emplace("b", "c");
- auto spec_c = spec_map.emplace("c");
-
- PortFileProvider::MapPortFileProvider map_port(spec_map.map);
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {FullPackageSpec{spec_a, {}}}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 3);
- REQUIRE(install_plan.install_actions.at(0).spec.name() == "c");
- REQUIRE(install_plan.install_actions.at(1).spec.name() == "b");
- REQUIRE(install_plan.install_actions.at(2).spec.name() == "a");
-}
-
-TEST_CASE ("multiple install scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "d");
- auto spec_b = spec_map.emplace("b", "d, e");
- auto spec_c = spec_map.emplace("c", "e, h");
- auto spec_d = spec_map.emplace("d", "f, g, h");
- auto spec_e = spec_map.emplace("e", "g");
- auto spec_f = spec_map.emplace("f");
- auto spec_g = spec_map.emplace("g");
- auto spec_h = spec_map.emplace("h");
-
- PortFileProvider::MapPortFileProvider map_port(spec_map.map);
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port,
- var_provider,
- {FullPackageSpec{spec_a}, FullPackageSpec{spec_b}, FullPackageSpec{spec_c}},
- StatusParagraphs(std::move(status_paragraphs)));
-
- auto iterator_pos = [&](const PackageSpec& spec) {
- auto it = std::find_if(install_plan.install_actions.begin(),
- install_plan.install_actions.end(),
- [&](auto& action) { return action.spec == spec; });
- REQUIRE(it != install_plan.install_actions.end());
- return it - install_plan.install_actions.begin();
- };
-
- const auto a_pos = iterator_pos(spec_a);
- const auto b_pos = iterator_pos(spec_b);
- const auto c_pos = iterator_pos(spec_c);
- const auto d_pos = iterator_pos(spec_d);
- const auto e_pos = iterator_pos(spec_e);
- const auto f_pos = iterator_pos(spec_f);
- const auto g_pos = iterator_pos(spec_g);
- const auto h_pos = iterator_pos(spec_h);
-
- REQUIRE(a_pos > d_pos);
- REQUIRE(b_pos > e_pos);
- REQUIRE(b_pos > d_pos);
- REQUIRE(c_pos > e_pos);
- REQUIRE(c_pos > h_pos);
- REQUIRE(d_pos > f_pos);
- REQUIRE(d_pos > g_pos);
- REQUIRE(d_pos > h_pos);
- REQUIRE(e_pos > g_pos);
-}
-
-TEST_CASE ("existing package scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(vcpkg::Test::make_status_pgh("a"));
-
- PackageSpecMap spec_map;
- auto spec_a = FullPackageSpec{spec_map.emplace("a")};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 1);
- const auto p = &install_plan.already_installed.at(0);
- REQUIRE(p->spec.name() == "a");
- REQUIRE(p->plan_type == Dependencies::InstallPlanType::ALREADY_INSTALLED);
- REQUIRE(p->request_type == Dependencies::RequestType::USER_REQUESTED);
-}
-
-TEST_CASE ("user requested package scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map;
- const auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")};
- const auto spec_b = FullPackageSpec{spec_map.emplace("b")};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- const auto install_plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 2);
- const auto p = &install_plan.install_actions.at(0);
- REQUIRE(p->spec.name() == "b");
- REQUIRE(p->plan_type == Dependencies::InstallPlanType::BUILD_AND_INSTALL);
- REQUIRE(p->request_type == Dependencies::RequestType::AUTO_SELECTED);
-
- const auto p2 = &install_plan.install_actions.at(1);
- REQUIRE(p2->spec.name() == "a");
- REQUIRE(p2->plan_type == Dependencies::InstallPlanType::BUILD_AND_INSTALL);
- REQUIRE(p2->request_type == Dependencies::RequestType::USER_REQUESTED);
-}
-
-TEST_CASE ("long install scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("j", "k"));
- status_paragraphs.push_back(make_status_pgh("k"));
-
- PackageSpecMap spec_map;
-
- auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k");
- auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k");
- auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k");
- auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k");
- auto spec_e = spec_map.emplace("e", "f, g, h, j, k");
- auto spec_f = spec_map.emplace("f", "g, h, j, k");
- auto spec_g = spec_map.emplace("g", "h, j, k");
- auto spec_h = spec_map.emplace("h", "j, k");
- auto spec_j = spec_map.emplace("j", "k");
- auto spec_k = spec_map.emplace("k");
-
- PortFileProvider::MapPortFileProvider map_port(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {FullPackageSpec{spec_a}}, StatusParagraphs(std::move(status_paragraphs)));
-
- auto& install_plan = plan.install_actions;
- REQUIRE(install_plan.size() == 8);
- REQUIRE(install_plan.at(0).spec.name() == "h");
- REQUIRE(install_plan.at(1).spec.name() == "g");
- REQUIRE(install_plan.at(2).spec.name() == "f");
- REQUIRE(install_plan.at(3).spec.name() == "e");
- REQUIRE(install_plan.at(4).spec.name() == "d");
- REQUIRE(install_plan.at(5).spec.name() == "c");
- REQUIRE(install_plan.at(6).spec.name() == "b");
- REQUIRE(install_plan.at(7).spec.name() == "a");
-}
-
-TEST_CASE ("basic feature test 1", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]"));
- status_paragraphs.push_back(make_status_pgh("b"));
- status_paragraphs.push_back(make_status_feature_pgh("b", "b1"));
-
- PackageSpecMap spec_map;
- auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(plan.size() == 4);
- remove_plan_check(plan.remove_actions.at(0), "a");
- remove_plan_check(plan.remove_actions.at(1), "b");
- features_check(plan.install_actions.at(0), "b", {"b1", "core", "b1"});
- features_check(plan.install_actions.at(1), "a", {"a1", "core"});
-}
-
-TEST_CASE ("basic feature test 2", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map;
-
- auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
-
- auto& install_plan = plan.install_actions;
- REQUIRE(install_plan.size() == 2);
- features_check(install_plan.at(0), "b", {"b1", "b2", "core"});
- features_check(install_plan.at(1), "a", {"a1", "core"});
-}
-
-TEST_CASE ("basic feature test 3", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
-
- PackageSpecMap spec_map;
-
- auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b")};
- auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_c, spec_a}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(plan.size() == 4);
- remove_plan_check(plan.remove_actions.at(0), "a");
- auto& install_plan = plan.install_actions;
- features_check(install_plan.at(0), "b", {"core"});
- features_check(install_plan.at(1), "a", {"a1", "core"});
- features_check(install_plan.at(2), "c", {"core"});
-}
-
-TEST_CASE ("basic feature test 4", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.push_back(make_status_feature_pgh("a", "a1", ""));
-
- PackageSpecMap spec_map;
-
- auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})};
- auto spec_b = FullPackageSpec{spec_map.emplace("b")};
- auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_c}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "c", {"core"});
-}
-
-TEST_CASE ("basic feature test 5", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map;
-
- auto spec_a =
- FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 2);
- features_check(install_plan.install_actions.at(0), "b", {"core", "b2"});
- features_check(install_plan.install_actions.at(1), "a", {"core", "a3", "a2"});
-}
-
-TEST_CASE ("basic feature test 6", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("b"));
-
- PackageSpecMap spec_map;
- auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_a, spec_b}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(plan.size() == 3);
- remove_plan_check(plan.remove_actions.at(0), "b");
- features_check(plan.install_actions.at(0), "b", {"core", "b1"});
- features_check(plan.install_actions.at(1), "a", {"core"});
-}
-
-TEST_CASE ("basic feature test 7", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("x", "b"));
- status_paragraphs.push_back(make_status_pgh("b"));
-
- PackageSpecMap spec_map;
-
- auto spec_a = FullPackageSpec{spec_map.emplace("a")};
- auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = Dependencies::create_feature_install_plan(
- map_port, var_provider, {spec_b}, StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(plan.size() == 5);
- remove_plan_check(plan.remove_actions.at(0), "x");
- remove_plan_check(plan.remove_actions.at(1), "b");
-
- features_check(plan.install_actions.at(0), "a", {"core"});
- features_check(plan.install_actions.at(1), "b", {"core", "b1"});
- features_check(plan.install_actions.at(2), "x", {"core"});
-}
-
-TEST_CASE ("basic feature test 8", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.back()->package.spec = PackageSpec("a", Test::X64_WINDOWS);
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}};
- auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")};
- auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
-
- spec_map.triplet = Test::X86_WINDOWS;
- auto spec_a_86 = FullPackageSpec{PackageSpec{"a", Test::X86_WINDOWS}};
- auto spec_b_86 = FullPackageSpec{PackageSpec{"b", Test::X86_WINDOWS}};
- auto spec_c_86 = FullPackageSpec{PackageSpec{"c", Test::X86_WINDOWS}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {spec_c_64, spec_a_86, spec_a_64, spec_c_86},
- StatusParagraphs(std::move(status_paragraphs)));
-
- remove_plan_check(plan.remove_actions.at(0), "a", Test::X64_WINDOWS);
- remove_plan_check(plan.remove_actions.at(1), "a");
- auto& install_plan = plan.install_actions;
- features_check(install_plan.at(0), "b", {"core"}, Test::X64_WINDOWS);
- features_check(install_plan.at(1), "a", {"a1", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.at(2), "b", {"core"});
- features_check(install_plan.at(3), "a", {"a1", "core"});
- features_check(install_plan.at(4), "c", {"core"}, Test::X64_WINDOWS);
- features_check(install_plan.at(5), "c", {"core"});
-}
-
-TEST_CASE ("install all features test", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}};
-
- auto install_specs = FullPackageSpec::from_string("a[*]", Test::X64_WINDOWS);
- REQUIRE(install_specs.has_value());
- if (!install_specs.has_value()) return;
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "a", {"0", "1", "core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features test 1", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" with default features "1" and features "0" and "1".
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"});
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect the default feature "1" to be installed, but not "0"
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "a", {"1", "core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features test 2", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.back()->package.spec = PackageSpec("a", Test::X64_WINDOWS);
-
- // Add a port "a" of which "core" is already installed, but we will
- // install the default features "explicitly"
- // "a" has two features, of which "a1" is default.
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"});
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "a" to get removed for rebuild and then installed with default
- // features.
- REQUIRE(install_plan.size() == 2);
- remove_plan_check(install_plan.remove_actions.at(0), "a", Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(0), "a", {"a1", "core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features test 3", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // "a" has two features, of which "a1" is default.
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "", {{"a0", ""}, {"a1", ""}}, {"a1"});
-
- // Explicitly install "a" without default features
- auto install_specs = FullPackageSpec::from_string("a[core]", Test::X64_WINDOWS);
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect the default feature not to get installed.
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features of dependency test 1", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" which depends on the core of "b"
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "b[core]");
- // "b" has two features, of which "b1" is default.
- spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"});
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "a" to get installed and defaults of "b" through the dependency,
- // as no explicit features of "b" are installed by the user.
- REQUIRE(install_plan.size() == 2);
- features_check(install_plan.install_actions.at(0), "b", {"b1", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(1), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("do not install default features of dependency test 1", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" which depends on the core of "b"
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "b[core]");
- // "b" has two features, of which "b1" is default.
- spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"});
-
- // Install "a" (without explicit feature specification)
- auto spec_a = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- auto spec_b = FullPackageSpec::from_string("b[core]", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port,
- var_provider,
- {spec_a.value_or_exit(VCPKG_LINE_INFO), spec_b.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "a" to get installed and defaults of "b" through the dependency,
- // as no explicit features of "b" are installed by the user.
- REQUIRE(install_plan.size() == 2);
- features_check(install_plan.install_actions.at(0), "b", {"core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(1), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features of dependency test 2", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" which depends on the default features of "b"
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "b");
- // "b" has two features, of which "b1" is default.
- spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"});
-
- // Install "a" (without explicit feature specification)
- auto spec_a = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- auto spec_b = FullPackageSpec::from_string("b[core]", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(
- map_port,
- var_provider,
- {spec_a.value_or_exit(VCPKG_LINE_INFO), spec_b.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "a" to get installed and defaults of "b" through the dependency
- REQUIRE(install_plan.size() == 2);
- features_check(install_plan.install_actions.at(0), "b", {"b1", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(1), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("do not install default features of existing dependency", "[plan]")
-{
- // Add a port "a" which depends on the core of "b"
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "b[core]");
- // "b" has two features, of which "b1" is default.
- spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"});
-
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- // "b[core]" is already installed
- status_paragraphs.push_back(make_status_pgh("b"));
- status_paragraphs.back()->package.spec = PackageSpec("b", Test::X64_WINDOWS);
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "a" to get installed, but not require rebuilding "b"
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features of existing dependency", "[plan]")
-{
- // Add a port "a" which depends on the default features of "b"
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "b");
- // "b" has a default feature
- spec_map.emplace("b", "", {{"b1", ""}}, {"b1"});
-
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- // "b[core]" is already installed
- status_paragraphs.push_back(make_status_pgh("b", "", "b1"));
- status_paragraphs.back()->package.spec = PackageSpec("b", Test::X64_WINDOWS);
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "b" to be rebuilt
- REQUIRE(install_plan.install_actions.size() == 2);
- features_check(install_plan.install_actions.at(0), "b", {"core", "b1"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install default features of dependency test 3", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("b"));
- status_paragraphs.back()->package.spec = PackageSpec("b", Test::X64_WINDOWS);
-
- // Add a port "a" which depends on the core of "b", which was already
- // installed explicitly
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "b[core]");
- // "b" has two features, of which "b1" is default.
- spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b1"});
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- // Expect "a" to get installed, not the defaults of "b", as the required
- // dependencies are already there, installed explicitly by the user.
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("install plan action dependencies", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" which depends on the core of "b", which was already
- // installed explicitly
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_c = spec_map.emplace("c");
- auto spec_b = spec_map.emplace("b", "c");
- spec_map.emplace("a", "b");
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 3);
- features_check(install_plan.install_actions.at(0), "c", {"core"}, Test::X64_WINDOWS);
-
- // TODO: Figure out what to do with these tests
- features_check(install_plan.install_actions.at(1), "b", {"core"}, Test::X64_WINDOWS);
- // REQUIRE(install_plan.at(1).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_c});
-
- features_check(install_plan.install_actions.at(2), "a", {"core"}, Test::X64_WINDOWS);
- // REQUIRE(install_plan.at(2).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_b});
-}
-
-TEST_CASE ("install plan action dependencies 2", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" which depends on the core of "b", which was already
- // installed explicitly
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_c = spec_map.emplace("c");
- auto spec_b = spec_map.emplace("b", "c");
- spec_map.emplace("a", "c, b");
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 3);
- features_check(install_plan.install_actions.at(0), "c", {"core"}, Test::X64_WINDOWS);
-
- features_check(install_plan.install_actions.at(1), "b", {"core"}, Test::X64_WINDOWS);
- // REQUIRE(install_plan.at(1).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_c});
-
- features_check(install_plan.install_actions.at(2), "a", {"core"}, Test::X64_WINDOWS);
- // REQUIRE(install_plan.at(2).install_action.get()->computed_dependencies == std::vector<PackageSpec>{spec_b,
- // spec_c});
-}
-
-TEST_CASE ("install plan action dependencies 3", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- // Add a port "a" which depends on the core of "b", which was already
- // installed explicitly
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- spec_map.emplace("a", "", {{"0", ""}, {"1", "a[0]"}}, {"1"});
-
- // Install "a" (without explicit feature specification)
- auto install_specs = FullPackageSpec::from_string("a", Test::X64_WINDOWS);
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan = Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 1);
- features_check(install_plan.install_actions.at(0), "a", {"1", "0", "core"}, Test::X64_WINDOWS);
- // REQUIRE(install_plan.at(0).install_action.get()->computed_dependencies == std::vector<PackageSpec>{});
-}
-
-TEST_CASE ("install with default features", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a", ""));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto b_spec = spec_map.emplace("b", "", {{"0", ""}}, {"0"});
- auto a_spec = spec_map.emplace("a", "b[core]", {{"0", ""}});
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto install_plan =
- Dependencies::create_feature_install_plan(map_port,
- var_provider,
- {FullPackageSpec{a_spec, {"0"}}, FullPackageSpec{b_spec, {"core"}}},
- StatusParagraphs(std::move(status_db)));
-
- // Install "a" and indicate that "b" should not install default features
- REQUIRE(install_plan.size() == 3);
- remove_plan_check(install_plan.remove_actions.at(0), "a");
- features_check(install_plan.install_actions.at(0), "b", {"core"});
- features_check(install_plan.install_actions.at(1), "a", {"0", "core"});
-}
-
-TEST_CASE ("upgrade with default features 1", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a", "", "1"));
- pghs.push_back(make_status_feature_pgh("a", "0"));
- StatusParagraphs status_db(std::move(pghs));
-
- // Add a port "a" of which "core" and "0" are already installed.
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}, {"1"});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- // The upgrade should not install the default feature
- REQUIRE(plan.size() == 2);
-
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "a", {"core", "0"});
-}
-
-TEST_CASE ("upgrade with default features 2", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- // B is currently installed _without_ default feature b0
- pghs.push_back(make_status_pgh("b", "", "b0", "x64-windows"));
- pghs.push_back(make_status_pgh("a", "b[core]", "", "x64-windows"));
-
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a = spec_map.emplace("a", "b[core]");
- auto spec_b = spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0", "b1"});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a, spec_b}, status_db);
-
- // The upgrade should install the new default feature b1 but not b0
- REQUIRE(plan.size() == 4);
- remove_plan_check(plan.remove_actions.at(0), "a", Test::X64_WINDOWS);
- remove_plan_check(plan.remove_actions.at(1), "b", Test::X64_WINDOWS);
- features_check(plan.install_actions.at(0), "b", {"core", "b1"}, Test::X64_WINDOWS);
- features_check(plan.install_actions.at(1), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("upgrade with default features 3", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- // note: unrelated package due to x86 triplet
- pghs.push_back(make_status_pgh("b", "", "", "x86-windows"));
- pghs.push_back(make_status_pgh("a", "", "", "x64-windows"));
-
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a = spec_map.emplace("a", "b[core]");
- spec_map.emplace("b", "", {{"b0", ""}, {"b1", ""}}, {"b0"});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- // The upgrade should install the default feature
- REQUIRE(plan.size() == 3);
- remove_plan_check(plan.remove_actions.at(0), "a", Test::X64_WINDOWS);
- features_check(plan.install_actions.at(0), "b", {"b0", "core"}, Test::X64_WINDOWS);
- features_check(plan.install_actions.at(1), "a", {"core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("upgrade with new default feature", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a", "", "0", "x86-windows"));
-
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "", {{"0", ""}, {"1", ""}, {"2", ""}}, {"0", "1"});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- // The upgrade should install the new default feature but not the old default feature 0
- REQUIRE(plan.size() == 2);
- remove_plan_check(plan.remove_actions.at(0), "a", Test::X86_WINDOWS);
- features_check(plan.install_actions.at(0), "a", {"core", "1"}, Test::X86_WINDOWS);
-}
-
-TEST_CASE ("transitive features test", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", "b[0]"}}), {"core"}};
- auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", "c[0]"}}), {"core"}};
- auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}};
-
- auto install_specs = FullPackageSpec::from_string("a[*]", Test::X64_WINDOWS);
- REQUIRE(install_specs.has_value());
- if (!install_specs.has_value()) return;
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto install_plan = Dependencies::create_feature_install_plan(provider,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 3);
- features_check(install_plan.install_actions.at(0), "c", {"0", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(1), "b", {"0", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(2), "a", {"0", "core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("no transitive features test", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"0", ""}}), {"core"}};
- auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "c", {{"0", ""}}), {"core"}};
- auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}};
-
- auto install_specs = FullPackageSpec::from_string("a[*]", Test::X64_WINDOWS);
- REQUIRE(install_specs.has_value());
- if (!install_specs.has_value()) return;
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto install_plan = Dependencies::create_feature_install_plan(provider,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 3);
- features_check(install_plan.install_actions.at(0), "c", {"core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(1), "b", {"core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(2), "a", {"0", "core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("only transitive features test", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
-
- PackageSpecMap spec_map(Test::X64_WINDOWS);
- auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", "b[0]"}}), {"core"}};
- auto spec_b_64 = FullPackageSpec{spec_map.emplace("b", "", {{"0", "c[0]"}}), {"core"}};
- auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "", {{"0", ""}}), {"core"}};
-
- auto install_specs = FullPackageSpec::from_string("a[*]", Test::X64_WINDOWS);
- REQUIRE(install_specs.has_value());
- if (!install_specs.has_value()) return;
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto install_plan = Dependencies::create_feature_install_plan(provider,
- var_provider,
- {install_specs.value_or_exit(VCPKG_LINE_INFO)},
- StatusParagraphs(std::move(status_paragraphs)));
-
- REQUIRE(install_plan.size() == 3);
- features_check(install_plan.install_actions.at(0), "c", {"0", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(1), "b", {"0", "core"}, Test::X64_WINDOWS);
- features_check(install_plan.install_actions.at(2), "a", {"0", "core"}, Test::X64_WINDOWS);
-}
-
-TEST_CASE ("basic remove scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"a", Test::X86_WINDOWS}}, status_db);
-
- REQUIRE(remove_plan.size() == 1);
- REQUIRE(remove_plan.at(0).spec.name() == "a");
-}
-
-TEST_CASE ("recurse remove scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_pgh("b", "a"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"a", Test::X86_WINDOWS}}, status_db);
-
- REQUIRE(remove_plan.size() == 2);
- REQUIRE(remove_plan.at(0).spec.name() == "b");
- REQUIRE(remove_plan.at(1).spec.name() == "a");
-}
-
-TEST_CASE ("features depend remove scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_pgh("b"));
- pghs.push_back(make_status_feature_pgh("b", "0", "a"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"a", Test::X86_WINDOWS}}, status_db);
-
- REQUIRE(remove_plan.size() == 2);
- REQUIRE(remove_plan.at(0).spec.name() == "b");
- REQUIRE(remove_plan.at(1).spec.name() == "a");
-}
-
-TEST_CASE ("features depend remove scheme once removed", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("expat"));
- pghs.push_back(make_status_pgh("vtk", "expat"));
- pghs.push_back(make_status_pgh("opencv"));
- pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"expat", Test::X86_WINDOWS}}, status_db);
-
- REQUIRE(remove_plan.size() == 3);
- REQUIRE(remove_plan.at(0).spec.name() == "opencv");
- REQUIRE(remove_plan.at(1).spec.name() == "vtk");
- REQUIRE(remove_plan.at(2).spec.name() == "expat");
-}
-
-TEST_CASE ("features depend remove scheme once removed x64", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("expat", "", "", "x64"));
- pghs.push_back(make_status_pgh("vtk", "expat", "", "x64"));
- pghs.push_back(make_status_pgh("opencv", "", "", "x64"));
- pghs.push_back(make_status_feature_pgh("opencv", "vtk", "vtk", "x64"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"expat", Triplet::from_canonical_name("x64")}}, status_db);
-
- REQUIRE(remove_plan.size() == 3);
- REQUIRE(remove_plan.at(0).spec.name() == "opencv");
- REQUIRE(remove_plan.at(1).spec.name() == "vtk");
- REQUIRE(remove_plan.at(2).spec.name() == "expat");
-}
-
-TEST_CASE ("features depend core remove scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("curl", "", "", "x64"));
- pghs.push_back(make_status_pgh("cpr", "curl[core]", "", "x64"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"curl", Triplet::from_canonical_name("x64")}}, status_db);
-
- REQUIRE(remove_plan.size() == 2);
- REQUIRE(remove_plan.at(0).spec.name() == "cpr");
- REQUIRE(remove_plan.at(1).spec.name() == "curl");
-}
-
-TEST_CASE ("features depend core remove scheme 2", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("curl", "", "", "x64"));
- pghs.push_back(make_status_feature_pgh("curl", "a", "", "x64"));
- pghs.push_back(make_status_feature_pgh("curl", "b", "curl[a]", "x64"));
- StatusParagraphs status_db(std::move(pghs));
-
- auto remove_plan = Dependencies::create_remove_plan({{"curl", Triplet::from_canonical_name("x64")}}, status_db);
-
- REQUIRE(remove_plan.size() == 1);
- REQUIRE(remove_plan.at(0).spec.name() == "curl");
-}
-
-TEST_CASE ("basic upgrade scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 2);
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "a", {"core"});
-}
-
-TEST_CASE ("basic upgrade scheme with recurse", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_pgh("b", "a"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
- spec_map.emplace("b", "a");
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 4);
- remove_plan_check(plan.remove_actions.at(0), "b");
- remove_plan_check(plan.remove_actions.at(1), "a");
- features_check(plan.install_actions.at(0), "a", {"core"});
- features_check(plan.install_actions.at(1), "b", {"core"});
-}
-
-TEST_CASE ("basic upgrade scheme with bystander", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_pgh("b"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
- spec_map.emplace("b", "a");
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 2);
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "a", {"core"});
-}
-
-TEST_CASE ("basic upgrade scheme with new dep", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "b");
- spec_map.emplace("b");
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 3);
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "b", {"core"});
- features_check(plan.install_actions.at(1), "a", {"core"});
-}
-
-TEST_CASE ("basic upgrade scheme with features", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_feature_pgh("a", "a1"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "", {{"a1", ""}});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 2);
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "a", {"core", "a1"});
-}
-
-TEST_CASE ("basic upgrade scheme with new default feature", "[plan]")
-{
- // only core of package "a" is installed
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- StatusParagraphs status_db(std::move(pghs));
-
- // a1 was added as a default feature and should be installed in upgrade
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "", {{"a1", ""}}, {"a1"});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 2);
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "a", {"core", "a1"});
-}
-
-TEST_CASE ("basic upgrade scheme with self features", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_feature_pgh("a", "a1", ""));
- pghs.push_back(make_status_feature_pgh("a", "a2", "a[a1]"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "", {{"a1", ""}, {"a2", "a[a1]"}});
-
- PortFileProvider::MapPortFileProvider provider(spec_map.map);
- MockCMakeVarProvider var_provider;
- auto plan = Dependencies::create_upgrade_plan(provider, var_provider, {spec_a}, status_db);
-
- REQUIRE(plan.size() == 2);
- remove_plan_check(plan.remove_actions.at(0), "a");
- features_check(plan.install_actions.at(0), "a", {"a1", "a2", "core"});
-}
-
-TEST_CASE ("basic export scheme", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
-
- auto plan = Dependencies::create_export_plan({spec_a}, status_db);
-
- REQUIRE(plan.size() == 1);
- REQUIRE(plan.at(0).spec.name() == "a");
- REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT);
-}
-
-TEST_CASE ("basic export scheme with recurse", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_pgh("b", "a"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
- auto spec_b = spec_map.emplace("b", "a");
-
- auto plan = Dependencies::create_export_plan({spec_b}, status_db);
-
- REQUIRE(plan.size() == 2);
- REQUIRE(plan.at(0).spec.name() == "a");
- REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT);
-
- REQUIRE(plan.at(1).spec.name() == "b");
- REQUIRE(plan.at(1).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT);
-}
-
-TEST_CASE ("basic export scheme with bystander", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_pgh("b"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
- auto spec_b = spec_map.emplace("b", "a");
-
- auto plan = Dependencies::create_export_plan({spec_a}, status_db);
-
- REQUIRE(plan.size() == 1);
- REQUIRE(plan.at(0).spec.name() == "a");
- REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT);
-}
-
-TEST_CASE ("basic export scheme with missing", "[plan]")
-{
- StatusParagraphs status_db;
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a");
-
- auto plan = Dependencies::create_export_plan({spec_a}, status_db);
-
- REQUIRE(plan.size() == 1);
- REQUIRE(plan.at(0).spec.name() == "a");
- REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::NOT_BUILT);
-}
-
-TEST_CASE ("basic export scheme with features", "[plan]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> pghs;
- pghs.push_back(make_status_pgh("b"));
- pghs.push_back(make_status_pgh("a"));
- pghs.push_back(make_status_feature_pgh("a", "a1", "b[core]"));
- StatusParagraphs status_db(std::move(pghs));
-
- PackageSpecMap spec_map;
- auto spec_a = spec_map.emplace("a", "", {{"a1", ""}});
-
- auto plan = Dependencies::create_export_plan({spec_a}, status_db);
-
- REQUIRE(plan.size() == 2);
-
- REQUIRE(plan.at(0).spec.name() == "b");
- REQUIRE(plan.at(0).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT);
-
- REQUIRE(plan.at(1).spec.name() == "a");
- REQUIRE(plan.at(1).plan_type == Dependencies::ExportPlanType::ALREADY_BUILT);
-}
diff --git a/toolsrc/src/vcpkg-test/platform-expression.cpp b/toolsrc/src/vcpkg-test/platform-expression.cpp
deleted file mode 100644
index aef999230..000000000
--- a/toolsrc/src/vcpkg-test/platform-expression.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/platform-expression.h>
-
-using vcpkg::StringView;
-using namespace vcpkg::PlatformExpression;
-
-static vcpkg::ExpectedS<Expr> parse_expr(StringView s)
-{
- return parse_platform_expression(s, MultipleBinaryOperators::Deny);
-}
-
-TEST_CASE ("platform-expression-identifier", "[platform-expression]")
-{
- auto m_expr = parse_expr("windows");
- REQUIRE(m_expr);
- auto& expr = *m_expr.get();
-
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
-}
-
-TEST_CASE ("platform-expression-not", "[platform-expression]")
-{
- auto m_expr = parse_expr("!windows");
- REQUIRE(m_expr);
- auto& expr = *m_expr.get();
-
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
-}
-
-TEST_CASE ("platform-expression-and", "[platform-expression]")
-{
- auto m_expr = parse_expr("!windows & !arm");
- REQUIRE(m_expr);
- auto& expr = *m_expr.get();
-
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
- CHECK_FALSE(expr.evaluate({
- {"VCPKG_CMAKE_SYSTEM_NAME", "Linux"},
- {"VCPKG_TARGET_ARCHITECTURE", "arm"},
- }));
-}
-
-TEST_CASE ("platform-expression-or", "[platform-expression]")
-{
- auto m_expr = parse_expr("!windows | arm");
- REQUIRE(m_expr);
- auto& expr = *m_expr.get();
-
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "arm"}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
-}
-
-TEST_CASE ("weird platform-expressions whitespace", "[platform-expression]")
-{
- auto m_expr = parse_expr(" ! \t windows \n| arm \r");
- REQUIRE(m_expr);
- auto& expr = *m_expr.get();
-
- CHECK_FALSE(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}, {"VCPKG_TARGET_ARCHITECTURE", "arm"}}));
- CHECK(expr.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
-}
-
-TEST_CASE ("no mixing &, | in platform expressions", "[platform-expression]")
-{
- auto m_expr = parse_expr("windows & arm | linux");
- CHECK_FALSE(m_expr);
- m_expr = parse_expr("windows | !arm & linux");
- CHECK_FALSE(m_expr);
-}
diff --git a/toolsrc/src/vcpkg-test/registries.cpp b/toolsrc/src/vcpkg-test/registries.cpp
deleted file mode 100644
index 1c839409d..000000000
--- a/toolsrc/src/vcpkg-test/registries.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/jsonreader.h>
-
-#include <vcpkg/registries.h>
-
-using namespace vcpkg;
-
-namespace
-{
- struct TestRegistryImplementation final : RegistryImplementation
- {
- std::unique_ptr<RegistryEntry> get_port_entry(const VcpkgPaths&, StringView) const override { return nullptr; }
-
- void get_all_port_names(std::vector<std::string>&, const VcpkgPaths&) const override { }
-
- Optional<VersionT> get_baseline_version(const VcpkgPaths&, StringView) const override { return nullopt; }
-
- int number;
-
- TestRegistryImplementation(int n) : number(n) { }
- };
-
- Registry make_registry(int n, std::vector<std::string>&& port_names)
- {
- return {std::move(port_names), std::make_unique<TestRegistryImplementation>(n)};
- }
-
- int get_tri_num(const RegistryImplementation& r)
- {
- if (auto tri = dynamic_cast<const TestRegistryImplementation*>(&r))
- {
- return tri->number;
- }
- else
- {
- return -1;
- }
- }
-
- // test functions which parse string literals, so no concerns about failure
- Json::Value parse_json(StringView sv) { return Json::parse(sv).value_or_exit(VCPKG_LINE_INFO).first; }
-}
-
-TEST_CASE ("registry_set_selects_registry", "[registries]")
-{
- RegistrySet set;
- set.set_default_registry(std::make_unique<TestRegistryImplementation>(0));
-
- set.add_registry(make_registry(1, {"p1", "q1", "r1"}));
- set.add_registry(make_registry(2, {"p2", "q2", "r2"}));
-
- auto reg = set.registry_for_port("p1");
- REQUIRE(reg);
- CHECK(get_tri_num(*reg) == 1);
- reg = set.registry_for_port("r2");
- REQUIRE(reg);
- CHECK(get_tri_num(*reg) == 2);
- reg = set.registry_for_port("a");
- REQUIRE(reg);
- CHECK(get_tri_num(*reg) == 0);
-
- set.set_default_registry(nullptr);
-
- reg = set.registry_for_port("q1");
- REQUIRE(reg);
- CHECK(get_tri_num(*reg) == 1);
- reg = set.registry_for_port("p2");
- REQUIRE(reg);
- CHECK(get_tri_num(*reg) == 2);
- reg = set.registry_for_port("a");
- CHECK_FALSE(reg);
-}
-
-TEST_CASE ("registry_parsing", "[registries]")
-{
- Json::Reader r;
- auto registry_impl_des = get_registry_implementation_deserializer({});
-
- auto test_json = parse_json(R"json(
-{
- "kind": "builtin"
-}
- )json");
- auto registry_impl = r.visit(test_json, *registry_impl_des);
- REQUIRE(registry_impl);
- CHECK(*registry_impl.get());
- CHECK(r.errors().empty());
-
- test_json = parse_json(R"json(
-{
- "kind": "builtin",
- "baseline": "hi"
-}
- )json");
- registry_impl = r.visit(test_json, *registry_impl_des);
- REQUIRE(registry_impl);
- CHECK(*registry_impl.get());
- CHECK(r.errors().empty());
-
- test_json = parse_json(R"json(
-{
- "kind": "builtin",
- "path": "a/b"
-}
- )json");
- registry_impl = r.visit(test_json, *registry_impl_des);
- CHECK_FALSE(r.errors().empty());
- r.errors().clear();
-
- test_json = parse_json(R"json(
-{
- "kind": "filesystem",
- "path": "a/b/c"
-}
- )json");
- registry_impl = r.visit(test_json, *registry_impl_des);
- REQUIRE(registry_impl);
- CHECK(*registry_impl.get());
- CHECK(r.errors().empty());
-
- test_json = parse_json(R"json(
-{
- "kind": "filesystem",
- "path": "/a/b/c"
-}
- )json");
- registry_impl = r.visit(test_json, *registry_impl_des);
- REQUIRE(registry_impl);
- CHECK(*registry_impl.get());
- CHECK(r.errors().empty());
-}
diff --git a/toolsrc/src/vcpkg-test/specifier.cpp b/toolsrc/src/vcpkg-test/specifier.cpp
deleted file mode 100644
index f750f4144..000000000
--- a/toolsrc/src/vcpkg-test/specifier.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/packagespec.h>
-
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-
-TEST_CASE ("specifier conversion", "[specifier]")
-{
- SECTION ("full package spec to feature specs")
- {
- constexpr std::size_t SPEC_SIZE = 6;
-
- PackageSpec a_spec("a", Test::X64_WINDOWS);
- PackageSpec b_spec("b", Test::X64_WINDOWS);
-
- auto fspecs = FullPackageSpec{a_spec, {"0", "1"}}.to_feature_specs({}, {});
- auto fspecs2 = FullPackageSpec{b_spec, {"2", "3"}}.to_feature_specs({}, {});
- Util::Vectors::append(&fspecs, fspecs2);
- Util::sort(fspecs);
- REQUIRE(fspecs.size() == SPEC_SIZE);
-
- std::array<const char*, SPEC_SIZE> features = {"0", "1", "core", "2", "3", "core"};
- std::array<PackageSpec*, SPEC_SIZE> specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec};
-
- for (std::size_t i = 0; i < SPEC_SIZE; ++i)
- {
- REQUIRE(features.at(i) == fspecs.at(i).feature());
- REQUIRE(*specs.at(i) == fspecs.at(i).spec());
- }
- }
-}
-
-TEST_CASE ("specifier parsing", "[specifier]")
-{
- SECTION ("parsed specifier from string")
- {
- auto maybe_spec = vcpkg::parse_qualified_specifier("zlib");
- REQUIRE(maybe_spec.has_value());
-
- auto& spec = *maybe_spec.get();
- REQUIRE(spec.name == "zlib");
- REQUIRE(!spec.features);
- REQUIRE(!spec.triplet);
- }
-
- SECTION ("parsed specifier from string with triplet")
- {
- auto maybe_spec = vcpkg::parse_qualified_specifier("zlib:x64-uwp");
- REQUIRE(maybe_spec);
-
- auto& spec = *maybe_spec.get();
- REQUIRE(spec.name == "zlib");
- REQUIRE(spec.triplet.value_or("") == "x64-uwp");
- }
-
- SECTION ("parsed specifier from string with colons")
- {
- auto s = vcpkg::parse_qualified_specifier("zlib:x86-uwp:");
- REQUIRE(!s);
- }
-
- SECTION ("parsed specifier from string with feature")
- {
- auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[feature]:x64-uwp");
- REQUIRE(maybe_spec);
-
- auto& spec = *maybe_spec.get();
- REQUIRE(spec.name == "zlib");
- REQUIRE(spec.features.value_or(std::vector<std::string>{}) == std::vector<std::string>{"feature"});
- REQUIRE(spec.triplet.value_or("") == "x64-uwp");
- }
-
- SECTION ("parsed specifier from string with many features")
- {
- auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[0, 1,2]");
- REQUIRE(maybe_spec);
-
- auto& spec = *maybe_spec.get();
- REQUIRE(spec.features.value_or(std::vector<std::string>{}) == std::vector<std::string>{"0", "1", "2"});
- }
-
- SECTION ("parsed specifier wildcard feature")
- {
- auto maybe_spec = vcpkg::parse_qualified_specifier("zlib[*]");
- System::print2(maybe_spec.error());
- REQUIRE(maybe_spec);
-
- auto& spec = *maybe_spec.get();
- REQUIRE(spec.features.value_or(std::vector<std::string>{}) == std::vector<std::string>{"*"});
- }
-
- SECTION ("expand wildcards")
- {
- auto zlib = vcpkg::FullPackageSpec::from_string("zlib[0,1]", Test::X86_UWP).value_or_exit(VCPKG_LINE_INFO);
- auto openssl = vcpkg::FullPackageSpec::from_string("openssl[*]", Test::X86_UWP).value_or_exit(VCPKG_LINE_INFO);
- auto specs = zlib.to_feature_specs({}, {});
- auto specs2 = openssl.to_feature_specs({}, {});
- Util::Vectors::append(&specs, specs2);
- Util::sort(specs);
-
- std::vector<FeatureSpec> spectargets{
- {{"openssl", Test::X86_UWP}, "core"},
- {{"zlib", Test::X86_UWP}, "core"},
- {{"zlib", Test::X86_UWP}, "0"},
- {{"zlib", Test::X86_UWP}, "1"},
- };
- Util::sort(spectargets);
- REQUIRE(specs.size() == spectargets.size());
- REQUIRE(specs == spectargets);
- }
-
-#if defined(_WIN32)
- SECTION ("ASCII to utf16")
- {
- auto str = vcpkg::Strings::to_utf16("abc");
- REQUIRE(str == L"abc");
- }
-
- SECTION ("ASCII to utf16 with whitespace")
- {
- auto str = vcpkg::Strings::to_utf16("abc -x86-windows");
- REQUIRE(str == L"abc -x86-windows");
- }
-#endif
-}
diff --git a/toolsrc/src/vcpkg-test/statusparagraphs.cpp b/toolsrc/src/vcpkg-test/statusparagraphs.cpp
deleted file mode 100644
index f647484e6..000000000
--- a/toolsrc/src/vcpkg-test/statusparagraphs.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/statusparagraphs.h>
-
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-using namespace vcpkg::Paragraphs;
-using namespace vcpkg::Test;
-
-TEST_CASE ("find installed", "[statusparagraphs]")
-{
- auto pghs = parse_paragraphs(R"(
-Package: ffmpeg
-Version: 3.3.3
-Architecture: x64-windows
-Multi-Arch: same
-Description:
-Status: install ok installed
-)",
- "");
-
- REQUIRE(pghs);
-
- StatusParagraphs status_db(
- Util::fmap(*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
-
- auto it = status_db.find_installed({"ffmpeg", Test::X64_WINDOWS});
- REQUIRE(it != status_db.end());
-}
-
-TEST_CASE ("find not installed", "[statusparagraphs]")
-{
- auto pghs = parse_paragraphs(R"(
-Package: ffmpeg
-Version: 3.3.3
-Architecture: x64-windows
-Multi-Arch: same
-Description:
-Status: purge ok not-installed
-)",
- "");
-
- REQUIRE(pghs);
-
- StatusParagraphs status_db(
- Util::fmap(*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
-
- auto it = status_db.find_installed({"ffmpeg", Test::X64_WINDOWS});
- REQUIRE(it == status_db.end());
-}
-
-TEST_CASE ("find with feature packages", "[statusparagraphs]")
-{
- auto pghs = parse_paragraphs(R"(
-Package: ffmpeg
-Version: 3.3.3
-Architecture: x64-windows
-Multi-Arch: same
-Description:
-Status: install ok installed
-
-Package: ffmpeg
-Feature: openssl
-Depends: openssl
-Architecture: x64-windows
-Multi-Arch: same
-Description:
-Status: purge ok not-installed
-)",
- "");
-
- REQUIRE(pghs);
-
- StatusParagraphs status_db(
- Util::fmap(*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
-
- auto it = status_db.find_installed({"ffmpeg", Test::X64_WINDOWS});
- REQUIRE(it != status_db.end());
-
- // Feature "openssl" is not installed and should not be found
- auto it1 = status_db.find_installed({{"ffmpeg", Test::X64_WINDOWS}, "openssl"});
- REQUIRE(it1 == status_db.end());
-}
-
-TEST_CASE ("find for feature packages", "[statusparagraphs]")
-{
- auto pghs = parse_paragraphs(R"(
-Package: ffmpeg
-Version: 3.3.3
-Architecture: x64-windows
-Multi-Arch: same
-Description:
-Status: install ok installed
-
-Package: ffmpeg
-Feature: openssl
-Depends: openssl
-Architecture: x64-windows
-Multi-Arch: same
-Description:
-Status: install ok installed
-)",
- "");
- REQUIRE(pghs);
-
- StatusParagraphs status_db(
- Util::fmap(*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
-
- // Feature "openssl" is installed and should therefore be found
- auto it = status_db.find_installed({{"ffmpeg", Test::X64_WINDOWS}, "openssl"});
- REQUIRE(it != status_db.end());
-}
diff --git a/toolsrc/src/vcpkg-test/strings.cpp b/toolsrc/src/vcpkg-test/strings.cpp
deleted file mode 100644
index 32fe5b3af..000000000
--- a/toolsrc/src/vcpkg-test/strings.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/strings.h>
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#if defined(_MSC_VER)
-#pragma warning(disable : 6237)
-#endif
-
-TEST_CASE ("b32 encoding", "[strings]")
-{
- using u64 = uint64_t;
-
- std::vector<std::pair<u64, std::string>> map;
-
- map.emplace_back(0, "AAAAAAAAAAAAA");
- map.emplace_back(1, "BAAAAAAAAAAAA");
-
- map.emplace_back(u64(1) << 32, "AAAAAAEAAAAAA");
- map.emplace_back((u64(1) << 32) + 1, "BAAAAAEAAAAAA");
-
- map.emplace_back(0xE4D0'1065'D11E'0229, "JRA4RIXMQAUJO");
- map.emplace_back(0xA626'FE45'B135'07FF, "77BKTYWI6XJMK");
- map.emplace_back(0xEE36'D228'0C31'D405, "FAVDDGAFSWN4O");
- map.emplace_back(0x1405'64E7'FE7E'A88C, "MEK5H774ELBIB");
- map.emplace_back(0xFFFF'FFFF'FFFF'FFFF, "777777777777P");
-
- for (const auto& pr : map)
- {
- REQUIRE(vcpkg::Strings::b32_encode(pr.first) == pr.second);
- }
-}
-
-TEST_CASE ("split by char", "[strings]")
-{
- using vcpkg::Strings::split;
- using result_t = std::vector<std::string>;
- REQUIRE(split(",,,,,,", ',').empty());
- REQUIRE(split(",,a,,b,,", ',') == result_t{"a", "b"});
- REQUIRE(split("hello world", ' ') == result_t{"hello", "world"});
- REQUIRE(split(" hello world ", ' ') == result_t{"hello", "world"});
- REQUIRE(split("no delimiters", ',') == result_t{"no delimiters"});
-}
-
-TEST_CASE ("find_first_of", "[strings]")
-{
- using vcpkg::Strings::find_first_of;
- REQUIRE(find_first_of("abcdefg", "hij") == std::string());
- REQUIRE(find_first_of("abcdefg", "a") == std::string("abcdefg"));
- REQUIRE(find_first_of("abcdefg", "g") == std::string("g"));
- REQUIRE(find_first_of("abcdefg", "bg") == std::string("bcdefg"));
- REQUIRE(find_first_of("abcdefg", "gb") == std::string("bcdefg"));
-}
-
-TEST_CASE ("edit distance", "[strings]")
-{
- using vcpkg::Strings::byte_edit_distance;
- REQUIRE(byte_edit_distance("", "") == 0);
- REQUIRE(byte_edit_distance("a", "a") == 0);
- REQUIRE(byte_edit_distance("abcd", "abcd") == 0);
- REQUIRE(byte_edit_distance("aaa", "aa") == 1);
- REQUIRE(byte_edit_distance("aa", "aaa") == 1);
- REQUIRE(byte_edit_distance("abcdef", "bcdefa") == 2);
- REQUIRE(byte_edit_distance("hello", "world") == 4);
- REQUIRE(byte_edit_distance("CAPITAL", "capital") == 7);
- REQUIRE(byte_edit_distance("", "hello") == 5);
- REQUIRE(byte_edit_distance("world", "") == 5);
-}
-
-TEST_CASE ("replace_all", "[strings]")
-{
- REQUIRE(vcpkg::Strings::replace_all("literal", "ter", "x") == "lixal");
-}
-
-TEST_CASE ("inplace_replace_all", "[strings]")
-{
- using vcpkg::Strings::inplace_replace_all;
- std::string target;
- inplace_replace_all(target, "", "content");
- REQUIRE(target.empty());
- target = "aa";
- inplace_replace_all(target, "a", "content");
- REQUIRE(target == "contentcontent");
- inplace_replace_all(target, "content", "");
- REQUIRE(target.empty());
- target = "ababababa";
- inplace_replace_all(target, "aba", "X");
- REQUIRE(target == "XbXba");
- target = "ababababa";
- inplace_replace_all(target, "aba", "aba");
- REQUIRE(target == "ababababa");
-}
-
-TEST_CASE ("inplace_replace_all(char)", "[strings]")
-{
- using vcpkg::Strings::inplace_replace_all;
- static_assert(noexcept(inplace_replace_all(std::declval<std::string&>(), 'a', 'a')));
-
- std::string target;
- inplace_replace_all(target, ' ', '?');
- REQUIRE(target.empty());
- target = "hello";
- inplace_replace_all(target, 'l', 'w');
- REQUIRE(target == "hewwo");
- inplace_replace_all(target, 'w', 'w');
- REQUIRE(target == "hewwo");
- inplace_replace_all(target, 'x', '?');
- REQUIRE(target == "hewwo");
-}
diff --git a/toolsrc/src/vcpkg-test/stringview.cpp b/toolsrc/src/vcpkg-test/stringview.cpp
deleted file mode 100644
index 953a7de99..000000000
--- a/toolsrc/src/vcpkg-test/stringview.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/stringview.h>
-
-template<std::size_t N>
-static vcpkg::StringView sv(const char (&cstr)[N])
-{
- return cstr;
-}
-
-TEST_CASE ("string view operator==", "[stringview]")
-{
- // these are due to a bug in operator==
- // see commit 782723959399a1a0725ac49
- REQUIRE(sv("hey") != sv("heys"));
- REQUIRE(sv("heys") != sv("hey"));
- REQUIRE(sv("hey") == sv("hey"));
- REQUIRE(sv("hey") != sv("hex"));
-}
diff --git a/toolsrc/src/vcpkg-test/system.cpp b/toolsrc/src/vcpkg-test/system.cpp
deleted file mode 100644
index 4c8b533bc..000000000
--- a/toolsrc/src/vcpkg-test/system.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <vcpkg/base/system_headers.h>
-
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/optional.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/stringview.h>
-#include <vcpkg/base/system.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/zstringview.h>
-
-#include <string>
-
-#if defined(_MSC_VER)
-#pragma warning(disable : 6237)
-#endif
-
-using vcpkg::nullopt;
-using vcpkg::Optional;
-using vcpkg::StringView;
-using vcpkg::ZStringView;
-using vcpkg::Checks::check_exit;
-using vcpkg::System::CPUArchitecture;
-using vcpkg::System::get_environment_variable;
-using vcpkg::System::guess_visual_studio_prompt_target_architecture;
-using vcpkg::System::set_environment_variable;
-using vcpkg::System::to_cpu_architecture;
-
-namespace
-{
- struct environment_variable_resetter
- {
- explicit environment_variable_resetter(ZStringView varname_)
- : varname(varname_), old_value(get_environment_variable(varname))
- {
- }
-
- ~environment_variable_resetter() { set_environment_variable(varname, old_value); }
-
- environment_variable_resetter(const environment_variable_resetter&) = delete;
- environment_variable_resetter& operator=(const environment_variable_resetter&) = delete;
-
- private:
- ZStringView varname;
- Optional<std::string> old_value;
- };
-}
-
-TEST_CASE ("[to_cpu_architecture]", "system")
-{
- struct test_case
- {
- Optional<CPUArchitecture> expected;
- StringView input;
- };
-
- const test_case test_cases[] = {
- {CPUArchitecture::X86, "x86"},
- {CPUArchitecture::X86, "X86"},
- {CPUArchitecture::X64, "x64"},
- {CPUArchitecture::X64, "X64"},
- {CPUArchitecture::X64, "AmD64"},
- {CPUArchitecture::ARM, "ARM"},
- {CPUArchitecture::ARM64, "ARM64"},
- {nullopt, "ARM6"},
- {nullopt, "AR"},
- {nullopt, "Intel"},
- };
-
- for (auto&& instance : test_cases)
- {
- CHECK(to_cpu_architecture(instance.input) == instance.expected);
- }
-}
-
-TEST_CASE ("from_cpu_architecture", "[system]")
-{
- struct test_case
- {
- CPUArchitecture input;
- ZStringView expected;
- };
-
- const test_case test_cases[] = {
- {CPUArchitecture::X86, "x86"},
- {CPUArchitecture::X64, "x64"},
- {CPUArchitecture::ARM, "arm"},
- {CPUArchitecture::ARM64, "arm64"},
- };
-
- for (auto&& instance : test_cases)
- {
- CHECK(to_zstring_view(instance.input) == instance.expected);
- }
-}
-
-TEST_CASE ("guess_visual_studio_prompt", "[system]")
-{
- environment_variable_resetter reset_VSCMD_ARG_TGT_ARCH{"VSCMD_ARG_TGT_ARCH"};
- environment_variable_resetter reset_VCINSTALLDIR{"VCINSTALLDIR"};
- environment_variable_resetter reset_Platform{"Platform"};
-
- set_environment_variable("Platform", "x86"); // ignored if VCINSTALLDIR unset
- set_environment_variable("VCINSTALLDIR", nullopt);
- set_environment_variable("VSCMD_ARG_TGT_ARCH", nullopt);
- CHECK(!guess_visual_studio_prompt_target_architecture().has_value());
- set_environment_variable("VSCMD_ARG_TGT_ARCH", "x86");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::X86);
- set_environment_variable("VSCMD_ARG_TGT_ARCH", "x64");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::X64);
- set_environment_variable("VSCMD_ARG_TGT_ARCH", "arm");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::ARM);
- set_environment_variable("VSCMD_ARG_TGT_ARCH", "arm64");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::ARM64);
-
- // check that apparent "nested" prompts defer to "vsdevcmd"
- set_environment_variable("VCINSTALLDIR", "anything");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::ARM64);
- set_environment_variable("VSCMD_ARG_TGT_ARCH", nullopt);
- set_environment_variable("Platform", nullopt);
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::X86);
- set_environment_variable("Platform", "x86");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::X86);
- set_environment_variable("Platform", "x64");
- CHECK(guess_visual_studio_prompt_target_architecture().value_or_exit(VCPKG_LINE_INFO) == CPUArchitecture::X64);
-}
-
-TEST_CASE ("cmdlinebuilder", "[system]")
-{
- using vcpkg::System::Command;
-
- Command cmd;
- cmd.path_arg(fs::u8path("relative/path.exe"));
- cmd.string_arg("abc");
- cmd.string_arg("hello world!");
- cmd.string_arg("|");
- cmd.string_arg(";");
- REQUIRE(cmd.command_line() == "relative/path.exe abc \"hello world!\" \"|\" \";\"");
-
- cmd.clear();
-
- cmd.path_arg(fs::u8path("trailing\\slash\\"));
- cmd.string_arg("inner\"quotes");
-#ifdef _WIN32
- REQUIRE(cmd.command_line() == "\"trailing\\slash\\\\\" \"inner\\\"quotes\"");
-#else
- REQUIRE(cmd.command_line() == "\"trailing\\\\slash\\\\\" \"inner\\\"quotes\"");
-#endif
-}
diff --git a/toolsrc/src/vcpkg-test/uint128.cpp b/toolsrc/src/vcpkg-test/uint128.cpp
deleted file mode 100644
index a13b25e4f..000000000
--- a/toolsrc/src/vcpkg-test/uint128.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/uint128.h>
-
-TEST_CASE ("uint128 constructor and assign", "[uint128]")
-{
- vcpkg::UInt128 x = 120;
- REQUIRE(x.bottom_64_bits() == 120);
- REQUIRE(x.top_64_bits() == 0);
-
- x = 3201;
- REQUIRE(x.bottom_64_bits() == 3201);
- REQUIRE(x.top_64_bits() == 0);
-
- x = 0xFFFF'FFFF'FFFF'FFFF;
- REQUIRE(x.bottom_64_bits() == 0xFFFF'FFFF'FFFF'FFFF);
- REQUIRE(x.top_64_bits() == 0);
-}
-
-TEST_CASE ("uint128 add-assign", "[uint128]")
-{
- vcpkg::UInt128 x = 0xFFFF'FFFF'FFFF'FFFF;
- x += 1;
- REQUIRE(x.bottom_64_bits() == 0);
- REQUIRE(x.top_64_bits() == 1);
-}
-
-TEST_CASE ("uint128 shl-assign", "[uint128]")
-{
- vcpkg::UInt128 x = 0xFFFF'FFFF'FFFF'FFFF;
- x <<= 32;
- REQUIRE(x.bottom_64_bits() == 0xFFFF'FFFF'0000'0000);
- REQUIRE(x.top_64_bits() == 0x0000'0000'FFFF'FFFF);
-
- x <<= 60;
- REQUIRE(x.bottom_64_bits() == 0);
- REQUIRE(x.top_64_bits() == 0xFFFF'FFFF'F000'0000);
-
- x = 1;
- x <<= 96;
- REQUIRE(x.bottom_64_bits() == 0);
- REQUIRE(x.top_64_bits() == (uint64_t(1) << 32));
-}
-
-TEST_CASE ("uint128 shr-assign", "[uint128]")
-{
- vcpkg::UInt128 x = 0xFFFF'FFFF'FFFF'FFFF;
- x <<= 64;
- REQUIRE(x.bottom_64_bits() == 0x0000'0000'0000'0000);
- REQUIRE(x.top_64_bits() == 0xFFFF'FFFF'FFFF'FFFF);
-
- x >>= 32;
- REQUIRE(x.bottom_64_bits() == 0xFFFF'FFFF'0000'0000);
- REQUIRE(x.top_64_bits() == 0x0000'0000'FFFF'FFFF);
-
- x >>= 60;
- REQUIRE(x.bottom_64_bits() == 0x0000'000F'FFFF'FFFF);
- REQUIRE(x.top_64_bits() == 0x0000'0000'0000'0000);
-
- x = 0x8000'0000'0000'0000;
- x <<= 64;
- REQUIRE(x.bottom_64_bits() == 0);
- REQUIRE(x.top_64_bits() == 0x8000'0000'0000'0000);
-
- x >>= 96;
- REQUIRE(x.bottom_64_bits() == (uint64_t(1) << 31));
- REQUIRE(x.top_64_bits() == 0);
-}
diff --git a/toolsrc/src/vcpkg-test/update.cpp b/toolsrc/src/vcpkg-test/update.cpp
deleted file mode 100644
index bce663d28..000000000
--- a/toolsrc/src/vcpkg-test/update.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/sortedvector.h>
-
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/statusparagraphs.h>
-#include <vcpkg/update.h>
-
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-using namespace vcpkg::Update;
-using namespace vcpkg::Test;
-
-using Pgh = std::vector<std::unordered_map<std::string, std::string>>;
-
-TEST_CASE ("find outdated packages basic", "[update]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.back()->package.version = "2";
-
- StatusParagraphs status_db(std::move(status_paragraphs));
-
- std::unordered_map<std::string, SourceControlFileLocation> map;
- auto scf = unwrap(test_parse_control_file({{{"Source", "a"}, {"Version", "0"}}}));
- map.emplace("a", SourceControlFileLocation{std::move(scf), ""});
- PortFileProvider::MapPortFileProvider provider(map);
-
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
- &OutdatedPackage::compare_by_name);
-
- REQUIRE(pkgs.size() == 1);
- REQUIRE(pkgs[0].version_diff.left.to_string() == "2");
- REQUIRE(pkgs[0].version_diff.right.to_string() == "0");
-}
-
-TEST_CASE ("find outdated packages features", "[update]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.back()->package.version = "2";
-
- status_paragraphs.push_back(make_status_feature_pgh("a", "b"));
- status_paragraphs.back()->package.version = "2";
-
- StatusParagraphs status_db(std::move(status_paragraphs));
-
- std::unordered_map<std::string, SourceControlFileLocation> map;
- auto scf = unwrap(test_parse_control_file({{{"Source", "a"}, {"Version", "0"}}}));
- map.emplace("a", SourceControlFileLocation{std::move(scf), ""});
- PortFileProvider::MapPortFileProvider provider(map);
-
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
- &OutdatedPackage::compare_by_name);
-
- REQUIRE(pkgs.size() == 1);
- REQUIRE(pkgs[0].version_diff.left.to_string() == "2");
- REQUIRE(pkgs[0].version_diff.right.to_string() == "0");
-}
-
-TEST_CASE ("find outdated packages features 2", "[update]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.back()->package.version = "2";
-
- status_paragraphs.push_back(make_status_feature_pgh("a", "b"));
- status_paragraphs.back()->package.version = "0";
- status_paragraphs.back()->state = InstallState::NOT_INSTALLED;
- status_paragraphs.back()->want = Want::PURGE;
-
- StatusParagraphs status_db(std::move(status_paragraphs));
-
- std::unordered_map<std::string, SourceControlFileLocation> map;
- auto scf = unwrap(test_parse_control_file({{{"Source", "a"}, {"Version", "0"}}}));
- map.emplace("a", SourceControlFileLocation{std::move(scf), ""});
- PortFileProvider::MapPortFileProvider provider(map);
-
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
- &OutdatedPackage::compare_by_name);
-
- REQUIRE(pkgs.size() == 1);
- REQUIRE(pkgs[0].version_diff.left.to_string() == "2");
- REQUIRE(pkgs[0].version_diff.right.to_string() == "0");
-}
-
-TEST_CASE ("find outdated packages none", "[update]")
-{
- std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(make_status_pgh("a"));
- status_paragraphs.back()->package.version = "2";
-
- StatusParagraphs status_db(std::move(status_paragraphs));
-
- std::unordered_map<std::string, SourceControlFileLocation> map;
- auto scf = unwrap(test_parse_control_file({{{"Source", "a"}, {"Version", "2"}}}));
- map.emplace("a", SourceControlFileLocation{std::move(scf), ""});
- PortFileProvider::MapPortFileProvider provider(map);
-
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
- &OutdatedPackage::compare_by_name);
-
- REQUIRE(pkgs.size() == 0);
-}
diff --git a/toolsrc/src/vcpkg-test/util.cpp b/toolsrc/src/vcpkg-test/util.cpp
deleted file mode 100644
index 73ff9db5c..000000000
--- a/toolsrc/src/vcpkg-test/util.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-#include <vcpkg/base/system_headers.h>
-
-#include <catch2/catch.hpp>
-
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/statusparagraph.h>
-
-#include <vcpkg-test/util.h>
-
-// used to get the implementation specific compiler flags (i.e., __cpp_lib_filesystem)
-#include <ciso646>
-#include <iostream>
-#include <memory>
-
-#if defined(_WIN32)
-#include <windows.h>
-#endif
-
-#define FILESYSTEM_SYMLINK_STD 0
-#define FILESYSTEM_SYMLINK_UNIX 1
-#define FILESYSTEM_SYMLINK_NONE 2
-
-#if VCPKG_USE_STD_FILESYSTEM
-
-#define FILESYSTEM_SYMLINK FILESYSTEM_SYMLINK_STD
-
-#elif !defined(_MSC_VER)
-
-#define FILESYSTEM_SYMLINK FILESYSTEM_SYMLINK_UNIX
-
-#else
-
-#define FILESYSTEM_SYMLINK FILESYSTEM_SYMLINK_NONE
-
-#endif
-
-namespace vcpkg::Test
-{
- const Triplet X86_WINDOWS = Triplet::from_canonical_name("x86-windows");
- const Triplet X64_WINDOWS = Triplet::from_canonical_name("x64-windows");
- const Triplet X86_UWP = Triplet::from_canonical_name("x86-uwp");
- const Triplet ARM_UWP = Triplet::from_canonical_name("arm-uwp");
- const Triplet X64_ANDROID = Triplet::from_canonical_name("x64-android");
-
- std::unique_ptr<SourceControlFile> make_control_file(
- const char* name,
- const char* depends,
- const std::vector<std::pair<const char*, const char*>>& features,
- const std::vector<const char*>& default_features)
- {
- using Pgh = std::unordered_map<std::string, std::string>;
- std::vector<Pgh> scf_pghs;
- scf_pghs.push_back(Pgh{{"Source", name},
- {"Version", "0"},
- {"Build-Depends", depends},
- {"Default-Features", Strings::join(", ", default_features)}});
- for (auto&& feature : features)
- {
- scf_pghs.push_back(Pgh{
- {"Feature", feature.first},
- {"Description", "feature"},
- {"Build-Depends", feature.second},
- });
- }
- auto m_pgh = test_parse_control_file(std::move(scf_pghs));
- REQUIRE(m_pgh.has_value());
- return std::move(*m_pgh.get());
- }
-
- std::unique_ptr<vcpkg::StatusParagraph> make_status_pgh(const char* name,
- const char* depends,
- const char* default_features,
- const char* triplet)
- {
- return std::make_unique<StatusParagraph>(Parse::Paragraph{{"Package", {name, {}}},
- {"Version", {"1", {}}},
- {"Architecture", {triplet, {}}},
- {"Multi-Arch", {"same", {}}},
- {"Depends", {depends, {}}},
- {"Default-Features", {default_features, {}}},
- {"Status", {"install ok installed", {}}}});
- }
-
- std::unique_ptr<StatusParagraph> make_status_feature_pgh(const char* name,
- const char* feature,
- const char* depends,
- const char* triplet)
- {
- return std::make_unique<StatusParagraph>(Parse::Paragraph{{"Package", {name, {}}},
- {"Feature", {feature, {}}},
- {"Architecture", {triplet, {}}},
- {"Multi-Arch", {"same", {}}},
- {"Depends", {depends, {}}},
- {"Status", {"install ok installed", {}}}});
- }
-
- PackageSpec PackageSpecMap::emplace(const char* name,
- const char* depends,
- const std::vector<std::pair<const char*, const char*>>& features,
- const std::vector<const char*>& default_features)
- {
- auto scfl = SourceControlFileLocation{make_control_file(name, depends, features, default_features), ""};
- return emplace(std::move(scfl));
- }
-
- PackageSpec PackageSpecMap::emplace(vcpkg::SourceControlFileLocation&& scfl)
- {
- const auto& name = scfl.source_control_file->core_paragraph->name;
- REQUIRE(map.find(name) == map.end());
- map.emplace(name, std::move(scfl));
- return {name, triplet};
- }
-
- static AllowSymlinks internal_can_create_symlinks() noexcept
- {
-#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_NONE
- return AllowSymlinks::No;
-#elif FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_UNIX
- return AllowSymlinks::Yes;
-#elif !defined(_WIN32) // FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD
- return AllowSymlinks::Yes;
-#else
- constexpr static const wchar_t regkey[] = LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock)";
- constexpr static const wchar_t regkey_member[] = LR"(AllowDevelopmentWithoutDevLicense)";
-
- DWORD data;
- DWORD dataSize = sizeof(data);
- const auto status =
- RegGetValueW(HKEY_LOCAL_MACHINE, regkey, regkey_member, RRF_RT_DWORD, nullptr, &data, &dataSize);
-
- if (status == ERROR_SUCCESS && data == 1)
- {
- return AllowSymlinks::Yes;
- }
- else
- {
- std::cout << "Symlinks are not allowed on this system\n";
- return AllowSymlinks::No;
- }
-#endif
- }
- const static AllowSymlinks CAN_CREATE_SYMLINKS = internal_can_create_symlinks();
-
- AllowSymlinks can_create_symlinks() noexcept { return CAN_CREATE_SYMLINKS; }
-
- static fs::path internal_base_temporary_directory()
- {
-#if defined(_WIN32)
- wchar_t* tmp = static_cast<wchar_t*>(std::calloc(32'767, 2));
-
- if (!GetEnvironmentVariableW(L"TEMP", tmp, 32'767))
- {
- std::cerr << "No temporary directory found.\n";
- std::abort();
- }
-
- fs::path result = tmp;
- std::free(tmp);
-
- return result / L"vcpkg-test";
-#else
- return "/tmp/vcpkg-test";
-#endif
- }
-
- const fs::path& base_temporary_directory() noexcept
- {
- const static fs::path BASE_TEMPORARY_DIRECTORY = internal_base_temporary_directory();
- return BASE_TEMPORARY_DIRECTORY;
- }
-
-#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_NONE
- constexpr char no_filesystem_message[] =
- "<filesystem> doesn't exist; on windows, we don't attempt to use the win32 calls to create symlinks";
-#endif
-
- void create_symlink(const fs::path& target, const fs::path& file, std::error_code& ec)
- {
-#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD
- if (can_create_symlinks())
- {
- fs::path targetp = target.native();
- fs::path filep = file.native();
-
- fs::stdfs::create_symlink(targetp, filep, ec);
- }
- else
- {
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Symlinks are not allowed on this system");
- }
-#elif FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_UNIX
- if (symlink(target.c_str(), file.c_str()) != 0)
- {
- ec.assign(errno, std::system_category());
- }
-#else
- (void)target;
- (void)file;
- (void)ec;
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, no_filesystem_message);
-#endif
- }
-
- void create_directory_symlink(const fs::path& target, const fs::path& file, std::error_code& ec)
- {
-#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD
- if (can_create_symlinks())
- {
- std::filesystem::path targetp = target.native();
- std::filesystem::path filep = file.native();
-
- std::filesystem::create_directory_symlink(targetp, filep, ec);
- }
- else
- {
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Symlinks are not allowed on this system");
- }
-#elif FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_UNIX
- ::vcpkg::Test::create_symlink(target, file, ec);
-#else
- (void)target;
- (void)file;
- (void)ec;
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, no_filesystem_message);
-#endif
- }
-}
diff --git a/toolsrc/src/vcpkg-test/versionplan.cpp b/toolsrc/src/vcpkg-test/versionplan.cpp
deleted file mode 100644
index 2f82d21b4..000000000
--- a/toolsrc/src/vcpkg-test/versionplan.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-#include <catch2/catch.hpp>
-
-#include <vcpkg/dependencies.h>
-#include <vcpkg/paragraphparser.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/sourceparagraph.h>
-
-#include <vcpkg-test/mockcmakevarprovider.h>
-#include <vcpkg-test/util.h>
-
-using namespace vcpkg;
-using namespace vcpkg::Parse;
-
-TEST_CASE ("parse depends", "[dependencies]")
-{
- auto w = parse_dependencies_list("liba (windows)");
- REQUIRE(w);
- auto& v = *w.get();
- REQUIRE(v.size() == 1);
- REQUIRE(v.at(0).name == "liba");
- REQUIRE(v.at(0).platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- REQUIRE(v.at(0).platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}}));
- REQUIRE(!v.at(0).platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
-}
-
-TEST_CASE ("filter depends", "[dependencies]")
-{
- const std::unordered_map<std::string, std::string> x64_win_cmake_vars{{"VCPKG_TARGET_ARCHITECTURE", "x64"},
- {"VCPKG_CMAKE_SYSTEM_NAME", ""}};
-
- const std::unordered_map<std::string, std::string> arm_uwp_cmake_vars{{"VCPKG_TARGET_ARCHITECTURE", "arm"},
- {"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}};
-
- auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)");
- REQUIRE(deps_);
- auto& deps = *deps_.get();
- auto v = filter_dependencies(deps, Test::X64_WINDOWS, x64_win_cmake_vars);
- REQUIRE(v.size() == 2);
- REQUIRE(v.at(0).package_spec.name() == "liba");
- REQUIRE(v.at(1).package_spec.name() == "libb");
-
- auto v2 = filter_dependencies(deps, Test::ARM_UWP, arm_uwp_cmake_vars);
- REQUIRE(v.size() == 2);
- REQUIRE(v2.at(0).package_spec.name() == "libb");
- REQUIRE(v2.at(1).package_spec.name() == "libc");
-}
-
-TEST_CASE ("parse feature depends", "[dependencies]")
-{
- auto u_ = parse_dependencies_list("libwebp[anim, gif2webp, img2webp, info, mux, nearlossless, "
- "simd, cwebp, dwebp], libwebp[vwebp-sdl, extras] (!osx)");
- REQUIRE(u_);
- auto& v = *u_.get();
- REQUIRE(v.size() == 2);
- auto&& a0 = v.at(0);
- REQUIRE(a0.name == "libwebp");
- REQUIRE(a0.features.size() == 9);
- REQUIRE(a0.platform.is_empty());
-
- auto&& a1 = v.at(1);
- REQUIRE(a1.name == "libwebp");
- REQUIRE(a1.features.size() == 2);
- REQUIRE(!a1.platform.is_empty());
- REQUIRE(a1.platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", ""}}));
- REQUIRE(a1.platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Linux"}}));
- REQUIRE_FALSE(a1.platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "Darwin"}}));
-}
-
-TEST_CASE ("qualified dependency", "[dependencies]")
-{
- using namespace Test;
- PackageSpecMap spec_map;
- auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1] (linux)"), {}};
- auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
-
- auto plan = vcpkg::Dependencies::create_feature_install_plan(map_port, var_provider, {spec_a}, {});
- REQUIRE(plan.install_actions.size() == 2);
- REQUIRE(plan.install_actions.at(0).feature_list == std::vector<std::string>{"core"});
-
- FullPackageSpec linspec_a{{"a", Triplet::from_canonical_name("x64-linux")}, {}};
- var_provider.dep_info_vars[linspec_a.package_spec].emplace("VCPKG_CMAKE_SYSTEM_NAME", "Linux");
- auto plan2 = vcpkg::Dependencies::create_feature_install_plan(map_port, var_provider, {linspec_a}, {});
- REQUIRE(plan2.install_actions.size() == 2);
- REQUIRE(plan2.install_actions.at(0).feature_list == std::vector<std::string>{"b1", "core"});
-}
-
-TEST_CASE ("resolve_deps_as_top_level", "[dependencies]")
-{
- using namespace Test;
- PackageSpecMap spec_map;
- FullPackageSpec spec_a{spec_map.emplace("a", "b, b[b1] (linux)"), {}};
- FullPackageSpec spec_b{spec_map.emplace("b", "", {{"b1", ""}}), {}};
- FullPackageSpec spec_c{spec_map.emplace("c", "b", {{"c1", "b[b1]"}, {"c2", "c[c1], a"}}, {"c1"}), {"core"}};
- FullPackageSpec spec_d{spec_map.emplace("d", "c[core]"), {}};
-
- PortFileProvider::MapPortFileProvider map_port{spec_map.map};
- MockCMakeVarProvider var_provider;
- Triplet t_linux = Triplet::from_canonical_name("x64-linux");
- var_provider.dep_info_vars[{"a", t_linux}].emplace("VCPKG_CMAKE_SYSTEM_NAME", "Linux");
- {
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("a").source_control_file, Test::X86_WINDOWS, {}, var_provider);
- REQUIRE(deps.size() == 1);
- REQUIRE(deps.at(0) == spec_b);
- }
- {
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("a").source_control_file, t_linux, {}, var_provider);
- REQUIRE(deps.size() == 1);
- REQUIRE(deps.at(0) == FullPackageSpec({"b", t_linux}, {"b1"}));
- }
- {
- // without defaults
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {}, var_provider);
- REQUIRE(deps.size() == 1);
- REQUIRE(deps.at(0) == spec_b);
- }
- FullPackageSpec spec_b_with_b1{spec_b.package_spec, {"b1"}};
- {
- // with defaults of c (c1)
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {"default"}, var_provider);
- REQUIRE(deps.size() == 1);
- REQUIRE(deps.at(0) == spec_b_with_b1);
- }
- {
- // with c1
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {"c1"}, var_provider);
- REQUIRE(deps.size() == 1);
- REQUIRE(deps.at(0) == spec_b_with_b1);
- }
- {
- // with c2 implying c1
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {"c2"}, var_provider);
- REQUIRE(deps.size() == 2);
- REQUIRE(deps.at(0) == spec_a);
- REQUIRE(deps.at(1) == spec_b_with_b1);
- }
- {
- // d -> c[core]
- auto deps = vcpkg::Dependencies::resolve_deps_as_top_level(
- *spec_map.map.at("d").source_control_file, Test::X86_WINDOWS, {}, var_provider);
- REQUIRE(deps.size() == 1);
- REQUIRE(deps.at(0) == spec_c);
- }
-}
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
deleted file mode 100644
index f25a0c3b6..000000000
--- a/toolsrc/src/vcpkg.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-#include <vcpkg/base/system_headers.h>
-
-#include <vcpkg/base/chrono.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/pragmas.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/commands.contact.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/commands.version.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/userconfig.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/vcpkgpaths.h>
-
-#include <cassert>
-#include <fstream>
-#include <memory>
-#include <random>
-
-#if defined(_WIN32)
-#pragma comment(lib, "ole32")
-#pragma comment(lib, "shell32")
-#endif
-
-using namespace vcpkg;
-
-// 24 hours/day * 30 days/month * 6 months
-static constexpr int SURVEY_INTERVAL_IN_HOURS = 24 * 30 * 6;
-
-// Initial survey appears after 10 days. Therefore, subtract 24 hours/day * 10 days
-static constexpr int SURVEY_INITIAL_OFFSET_IN_HOURS = SURVEY_INTERVAL_IN_HOURS - 24 * 10;
-
-static void invalid_command(const std::string& cmd)
-{
- System::print2(System::Color::error, "invalid command: ", cmd, '\n');
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
-}
-
-static void inner(vcpkg::Files::Filesystem& fs, const VcpkgCmdArguments& args)
-{
- Metrics::g_metrics.lock()->track_property("command", args.command);
- if (args.command.empty())
- {
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- static const auto find_command = [&](auto&& commands) {
- auto it = Util::find_if(commands, [&](auto&& commandc) {
- return Strings::case_insensitive_ascii_equals(commandc.name, args.command);
- });
- using std::end;
- if (it != end(commands))
- {
- return &*it;
- }
- else
- {
- return static_cast<decltype(&*it)>(nullptr);
- }
- };
-
- if (const auto command_function = find_command(Commands::get_available_basic_commands()))
- {
- return command_function->function->perform_and_exit(args, fs);
- }
-
- const VcpkgPaths paths(fs, args);
- paths.track_feature_flag_metrics();
-
- fs.current_path(paths.root, VCPKG_LINE_INFO);
-
- if (const auto command_function = find_command(Commands::get_available_paths_commands()))
- {
- return command_function->function->perform_and_exit(args, paths);
- }
-
- Triplet default_triplet = vcpkg::default_triplet(args);
- Input::check_triplet(default_triplet, paths);
-
- if (const auto command_function = find_command(Commands::get_available_triplet_commands()))
- {
- return command_function->function->perform_and_exit(args, paths, default_triplet);
- }
-
- return invalid_command(args.command);
-}
-
-static void load_config(vcpkg::Files::Filesystem& fs)
-{
- auto config = UserConfig::try_read_data(fs);
-
- bool write_config = false;
-
- // config file not found, could not be read, or invalid
- if (config.user_id.empty() || config.user_time.empty())
- {
- ::vcpkg::Metrics::Metrics::init_user_information(config.user_id, config.user_time);
- write_config = true;
- }
-
-#if defined(_WIN32)
- if (config.user_mac.empty())
- {
- config.user_mac = Metrics::get_MAC_user();
- write_config = true;
- }
-#endif
-
- {
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->set_user_information(config.user_id, config.user_time);
-#if defined(_WIN32)
- locked_metrics->track_property("user_mac", config.user_mac);
-#endif
- }
-
- if (config.last_completed_survey.empty())
- {
- const auto now = Chrono::CTime::parse(config.user_time).value_or_exit(VCPKG_LINE_INFO);
- const Chrono::CTime offset = now.add_hours(-SURVEY_INITIAL_OFFSET_IN_HOURS);
- config.last_completed_survey = offset.to_string();
- }
-
- GlobalState::g_surveydate.lock()->assign(config.last_completed_survey);
-
- if (write_config)
- {
- config.try_write_data(fs);
- }
-}
-
-#if defined(_WIN32)
-// note: this prevents a false positive for -Wmissing-prototypes on clang-cl
-int wmain(int, const wchar_t* const* const);
-
-#if !defined(_MSC_VER)
-#include <shellapi.h>
-int main(int argc, const char* const* const /*argv*/)
-{
- wchar_t** wargv;
- wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
- return wmain(argc, wargv);
-}
-#endif
-
-int wmain(const int argc, const wchar_t* const* const argv)
-#else
-int main(const int argc, const char* const* const argv)
-#endif
-{
- if (argc == 0) std::abort();
-
- auto& fs = Files::get_real_filesystem();
- *GlobalState::timer.lock() = Chrono::ElapsedTimer::create_started();
-
-#if defined(_WIN32)
- GlobalState::g_init_console_cp = GetConsoleCP();
- GlobalState::g_init_console_output_cp = GetConsoleOutputCP();
- GlobalState::g_init_console_initialized = true;
-
- SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);
-
- System::initialize_global_job_object();
-#endif
- System::set_environment_variable("VCPKG_COMMAND", fs::generic_u8string(System::get_exe_path_of_current_process()));
-
- Checks::register_global_shutdown_handler([]() {
- const auto elapsed_us_inner = GlobalState::timer.lock()->microseconds();
-
- bool debugging = Debug::g_debugging;
-
- auto metrics = Metrics::g_metrics.lock();
- metrics->track_metric("elapsed_us", elapsed_us_inner);
- Debug::g_debugging = false;
- metrics->flush(Files::get_real_filesystem());
-
-#if defined(_WIN32)
- if (GlobalState::g_init_console_initialized)
- {
- SetConsoleCP(GlobalState::g_init_console_cp);
- SetConsoleOutputCP(GlobalState::g_init_console_output_cp);
- }
-#endif
-
- auto elapsed_us = GlobalState::timer.lock()->microseconds();
- if (debugging)
- System::printf("[DEBUG] Exiting after %d us (%d us)\n",
- static_cast<int>(elapsed_us),
- static_cast<int>(elapsed_us_inner));
- });
-
- {
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->track_property("version", Commands::Version::version());
- }
-
- System::register_console_ctrl_handler();
-
- load_config(fs);
-
-#if (defined(__aarch64__) || defined(__arm__) || defined(__s390x__) || \
- ((defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) && \
- defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
- defined(_M_ARM) || defined(_M_ARM64)) && \
- !defined(_WIN32) && !defined(__APPLE__)
- if (!System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "Environment variable VCPKG_FORCE_SYSTEM_BINARIES must be set on arm, s390x, and ppc64le platforms.");
- }
-#endif
-
- VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(fs, argc, argv);
- if (const auto p = args.debug.get()) Debug::g_debugging = *p;
- args.imbue_from_environment();
- VcpkgCmdArguments::imbue_or_apply_process_recursion(args);
- args.check_feature_flag_consistency();
-
- {
- auto metrics = Metrics::g_metrics.lock();
- if (const auto p = args.disable_metrics.get())
- {
- metrics->set_disabled(*p);
- }
-
- auto disable_metrics_tag_file_path =
- System::get_exe_path_of_current_process().replace_filename(fs::u8path("vcpkg.disable-metrics"));
- std::error_code ec;
- if (fs.exists(disable_metrics_tag_file_path, ec) || ec)
- {
- metrics->set_disabled(true);
- }
-
- if (const auto p = args.print_metrics.get())
- {
- metrics->set_print_metrics(*p);
- }
-
- if (const auto p = args.send_metrics.get())
- {
- metrics->set_send_metrics(*p);
- }
-
- if (args.send_metrics.value_or(false) && !metrics->metrics_enabled())
- {
- System::print2(System::Color::warning, "Warning: passed --sendmetrics, but metrics are disabled.\n");
- }
- } // unlock Metrics::g_metrics
-
- args.debug_print_feature_flags();
- args.track_feature_flag_metrics();
-
- if (Debug::g_debugging)
- {
- inner(fs, args);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- std::string exc_msg;
- try
- {
- inner(fs, args);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- catch (std::exception& e)
- {
- exc_msg = e.what();
- }
- catch (...)
- {
- exc_msg = "unknown error(...)";
- }
- Metrics::g_metrics.lock()->track_property("error", exc_msg);
-
- fflush(stdout);
- System::printf("vcpkg.exe has crashed.\n"
- "Please send an email to:\n"
- " %s\n"
- "containing a brief summary of what you were trying to do and the following data blob:\n"
- "\n"
- "Version=%s\n"
- "EXCEPTION='%s'\n"
- "CMD=\n",
- Commands::Contact::email(),
- Commands::Version::version(),
- exc_msg);
- fflush(stdout);
- for (int x = 0; x < argc; ++x)
- {
-#if defined(_WIN32)
- System::print2(Strings::to_utf8(argv[x]), "|\n");
-#else
- System::print2(argv[x], "|\n");
-#endif
- }
- fflush(stdout);
-
- // It is expected that one of the sub-commands will exit cleanly before we get here.
- Checks::exit_fail(VCPKG_LINE_INFO);
-}
diff --git a/toolsrc/src/vcpkg/archives.cpp b/toolsrc/src/vcpkg/archives.cpp
deleted file mode 100644
index 5008b3223..000000000
--- a/toolsrc/src/vcpkg/archives.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/archives.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg::Archives
-{
- void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
- {
- Files::Filesystem& fs = paths.get_filesystem();
- const fs::path to_path_partial = fs::u8string(to_path) + ".partial"
-#if defined(_WIN32)
- + "." + std::to_string(GetCurrentProcessId())
-#endif
- ;
-
- fs.remove_all(to_path, VCPKG_LINE_INFO);
- fs.remove_all(to_path_partial, VCPKG_LINE_INFO);
- // TODO: check this error code
- std::error_code ec;
- fs.create_directories(to_path_partial, ec);
- const auto ext = archive.extension();
-#if defined(_WIN32)
- if (ext == ".nupkg")
- {
- static bool recursion_limiter_sevenzip_old = false;
- Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip_old);
- recursion_limiter_sevenzip_old = true;
- const auto nuget_exe = paths.get_tool_exe(Tools::NUGET);
-
- const std::string stem = fs::u8string(archive.stem());
- // assuming format of [name].[version in the form d.d.d]
- // This assumption may not always hold
- std::smatch match;
- const bool has_match = std::regex_match(stem, match, std::regex{R"###(^(.+)\.(\d+\.\d+\.\d+)$)###"});
- Checks::check_exit(VCPKG_LINE_INFO,
- has_match,
- "Could not deduce nuget id and version from filename: %s",
- fs::u8string(archive));
-
- const std::string nugetid = match[1];
- const std::string version = match[2];
-
- const auto code_and_output = System::cmd_execute_and_capture_output(System::Command{nuget_exe}
- .string_arg("install")
- .string_arg(nugetid)
- .string_arg("-Version")
- .string_arg(version)
- .string_arg("-OutputDirectory")
- .path_arg(to_path_partial)
- .string_arg("-Source")
- .path_arg(paths.downloads)
- .string_arg("-nocache")
- .string_arg("-DirectDownload")
- .string_arg("-NonInteractive")
- .string_arg("-ForceEnglishOutput")
- .string_arg("-PackageSaveMode")
- .string_arg("nuspec"));
-
- Checks::check_exit(VCPKG_LINE_INFO,
- code_and_output.exit_code == 0,
- "Failed to extract '%s' with message:\n%s",
- fs::u8string(archive),
- code_and_output.output);
- recursion_limiter_sevenzip_old = false;
- }
- else
- {
- static bool recursion_limiter_sevenzip = false;
- Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip);
- recursion_limiter_sevenzip = true;
- const auto seven_zip = paths.get_tool_exe(Tools::SEVEN_ZIP);
- const auto code_and_output = System::cmd_execute_and_capture_output(
- System::Command{seven_zip}
- .string_arg("x")
- .path_arg(archive)
- .string_arg(Strings::format("-o%s", fs::u8string(to_path_partial)))
- .string_arg("-y"));
- Checks::check_exit(VCPKG_LINE_INFO,
- code_and_output.exit_code == 0,
- "7zip failed while extracting '%s' with message:\n%s",
- fs::u8string(archive),
- code_and_output.output);
- recursion_limiter_sevenzip = false;
- }
-#else
- if (ext == ".gz" && ext.extension() != ".tar")
- {
- const auto code = System::cmd_execute(System::Command{"tar"}.string_arg("xzf").path_arg(archive),
- System::InWorkingDirectory{to_path_partial});
- Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", fs::u8string(archive));
- }
- else if (ext == ".zip")
- {
- const auto code = System::cmd_execute(System::Command{"unzip"}.string_arg("-qqo").path_arg(archive),
- System::InWorkingDirectory{to_path_partial});
- Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", fs::u8string(archive));
- }
- else
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Unexpected archive extension: %s", fs::u8string(ext));
- }
-#endif
-
- fs.rename(to_path_partial, to_path, ec);
-
- using namespace std::chrono_literals;
-
- auto retry_delay = 8ms;
-
- for (int i = 0; i < 10 && ec; i++)
- {
- using namespace std::chrono_literals;
- std::this_thread::sleep_for(retry_delay);
- fs.rename(to_path_partial, to_path, ec);
- retry_delay *= 2;
- }
-
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Failed to do post-extract rename-in-place.\n"
- "fs.rename(%s, %s, %s)",
- fs::u8string(to_path_partial),
- fs::u8string(to_path),
- ec.message());
- }
-}
diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp
deleted file mode 100644
index e3ab22dae..000000000
--- a/toolsrc/src/vcpkg/base/checks.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/stringview.h>
-#include <vcpkg/base/system.debug.h>
-
-#include <stdlib.h>
-
-namespace vcpkg
-{
- static void (*g_shutdown_handler)() = nullptr;
-
- void Checks::register_global_shutdown_handler(void (*func)())
- {
- if (g_shutdown_handler)
- // Setting the handler twice is a program error. Terminate.
- std::abort();
- g_shutdown_handler = func;
- }
-
- [[noreturn]] void Checks::final_cleanup_and_exit(const int exit_code)
- {
- static std::atomic<bool> have_entered{false};
- if (have_entered.exchange(true))
- {
-#if defined(_WIN32)
- ::TerminateProcess(::GetCurrentProcess(), exit_code);
-#else
- std::abort();
-#endif
- }
-
- if (g_shutdown_handler) g_shutdown_handler();
-
- fflush(nullptr);
-
-#if defined(_WIN32)
- ::TerminateProcess(::GetCurrentProcess(), exit_code);
-#endif
- std::exit(exit_code);
- }
-
- [[noreturn]] void Checks::unreachable(const LineInfo& line_info)
- {
- System::printf(System::Color::error,
- "Error: Unreachable code was reached\n%s(%d)\n",
- line_info.file_name,
- line_info.line_number);
-#ifndef NDEBUG
- std::abort();
-#else
- final_cleanup_and_exit(EXIT_FAILURE);
-#endif
- }
-
- [[noreturn]] void Checks::exit_with_code(const LineInfo& line_info, const int exit_code)
- {
- Debug::print(Strings::format("%s(%d)\n", line_info.file_name, line_info.line_number));
- final_cleanup_and_exit(exit_code);
- }
-
- [[noreturn]] void Checks::exit_fail(const LineInfo& line_info) { exit_with_code(line_info, EXIT_FAILURE); }
-
- [[noreturn]] void Checks::exit_success(const LineInfo& line_info) { exit_with_code(line_info, EXIT_SUCCESS); }
-
- [[noreturn]] void Checks::exit_with_message(const LineInfo& line_info, StringView error_message)
- {
- System::print2(System::Color::error, error_message, '\n');
- exit_fail(line_info);
- }
-
- void Checks::check_exit(const LineInfo& line_info, bool expression)
- {
- if (!expression)
- {
- exit_fail(line_info);
- }
- }
-
- void Checks::check_exit(const LineInfo& line_info, bool expression, StringView error_message)
- {
- if (!expression)
- {
- exit_with_message(line_info, error_message);
- }
- }
-
- static void display_upgrade_message()
- {
- System::print2(System::Color::error,
- "Note: Updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.\n");
- }
-
- [[noreturn]] void Checks::exit_maybe_upgrade(const LineInfo& line_info)
- {
- display_upgrade_message();
- exit_fail(line_info);
- }
-
- [[noreturn]] void Checks::exit_maybe_upgrade(const LineInfo& line_info, StringView error_message)
- {
- System::print2(System::Color::error, error_message, '\n');
- display_upgrade_message();
- exit_fail(line_info);
- }
-
- void Checks::check_maybe_upgrade(const LineInfo& line_info, bool expression)
- {
- if (!expression)
- {
- exit_maybe_upgrade(line_info);
- }
- }
-
- void Checks::check_maybe_upgrade(const LineInfo& line_info, bool expression, StringView error_message)
- {
- if (!expression)
- {
- exit_maybe_upgrade(line_info, error_message);
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp
deleted file mode 100644
index 971d5f37e..000000000
--- a/toolsrc/src/vcpkg/base/chrono.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/chrono.h>
-
-namespace vcpkg::Chrono
-{
- static std::time_t get_current_time_as_time_since_epoch()
- {
- using std::chrono::system_clock;
- return system_clock::to_time_t(system_clock::now());
- }
-
- static std::time_t utc_mktime(tm* time_ptr)
- {
-#if defined(_WIN32)
- return _mkgmtime(time_ptr);
-#else
- return timegm(time_ptr);
-#endif
- }
-
- static tm to_local_time(const std::time_t& t)
- {
- tm parts{};
-#if defined(_WIN32)
- localtime_s(&parts, &t);
-#else
- parts = *localtime(&t);
-#endif
- return parts;
- }
-
- static Optional<tm> to_utc_time(const std::time_t& t)
- {
- tm parts{};
-#if defined(_WIN32)
- const errno_t err = gmtime_s(&parts, &t);
- if (err)
- {
- return nullopt;
- }
-#else
- auto null_if_failed = gmtime_r(&t, &parts);
- if (null_if_failed == nullptr)
- {
- return nullopt;
- }
-#endif
- return parts;
- }
-
- static tm date_plus_hours(tm* date, const int hours)
- {
- using namespace std::chrono_literals;
- static constexpr std::chrono::seconds SECONDS_IN_ONE_HOUR =
- std::chrono::duration_cast<std::chrono::seconds>(1h);
-
- const std::time_t date_in_seconds = utc_mktime(date) + (hours * SECONDS_IN_ONE_HOUR.count());
- return to_utc_time(date_in_seconds).value_or_exit(VCPKG_LINE_INFO);
- }
-
- static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos)
- {
- using std::chrono::duration_cast;
- using std::chrono::hours;
- using std::chrono::microseconds;
- using std::chrono::milliseconds;
- using std::chrono::minutes;
- using std::chrono::nanoseconds;
- using std::chrono::seconds;
-
- const auto nanos_as_double = static_cast<double>(nanos.count());
-
- if (duration_cast<hours>(nanos) > hours())
- {
- const auto t = nanos_as_double / duration_cast<nanoseconds>(hours(1)).count();
- return Strings::format("%.4g h", t);
- }
-
- if (duration_cast<minutes>(nanos) > minutes())
- {
- const auto t = nanos_as_double / duration_cast<nanoseconds>(minutes(1)).count();
- return Strings::format("%.4g min", t);
- }
-
- if (duration_cast<seconds>(nanos) > seconds())
- {
- const auto t = nanos_as_double / duration_cast<nanoseconds>(seconds(1)).count();
- return Strings::format("%.4g s", t);
- }
-
- if (duration_cast<milliseconds>(nanos) > milliseconds())
- {
- const auto t = nanos_as_double / duration_cast<nanoseconds>(milliseconds(1)).count();
- return Strings::format("%.4g ms", t);
- }
-
- if (duration_cast<microseconds>(nanos) > microseconds())
- {
- const auto t = nanos_as_double / duration_cast<nanoseconds>(microseconds(1)).count();
- return Strings::format("%.4g us", t);
- }
-
- return Strings::format("%.4g ns", nanos_as_double);
- }
-
- ElapsedTimer ElapsedTimer::create_started()
- {
- ElapsedTimer t;
- t.m_start_tick = std::chrono::high_resolution_clock::now();
- return t;
- }
-
- std::string ElapsedTime::to_string() const { return format_time_userfriendly(as<std::chrono::nanoseconds>()); }
- void ElapsedTime::to_string(std::string& into) const
- {
- into += format_time_userfriendly(as<std::chrono::nanoseconds>());
- }
-
- std::string ElapsedTimer::to_string() const { return elapsed().to_string(); }
- void ElapsedTimer::to_string(std::string& into) const { return elapsed().to_string(into); }
-
- Optional<CTime> CTime::get_current_date_time()
- {
- const std::time_t ct = get_current_time_as_time_since_epoch();
- const Optional<tm> opt = to_utc_time(ct);
- if (auto p_tm = opt.get())
- {
- return CTime{*p_tm};
- }
-
- return nullopt;
- }
-
- Optional<CTime> CTime::parse(CStringView str)
- {
- CTime ret;
- const auto assigned =
-#if defined(_WIN32)
- sscanf_s
-#else
- sscanf
-#endif
- (str.c_str(),
- "%d-%d-%dT%d:%d:%d.",
- &ret.m_tm.tm_year,
- &ret.m_tm.tm_mon,
- &ret.m_tm.tm_mday,
- &ret.m_tm.tm_hour,
- &ret.m_tm.tm_min,
- &ret.m_tm.tm_sec);
- if (assigned != 6) return nullopt;
- if (ret.m_tm.tm_year < 1900) return nullopt;
- ret.m_tm.tm_year -= 1900;
- if (ret.m_tm.tm_mon < 1) return nullopt;
- ret.m_tm.tm_mon -= 1;
- utc_mktime(&ret.m_tm);
-
- return ret;
- }
-
- CTime CTime::add_hours(const int hours) const { return CTime{date_plus_hours(&this->m_tm, hours)}; }
-
- std::string CTime::to_string() const
- {
- std::array<char, 80> date{};
- strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S.0Z", &m_tm);
- return &date[0];
- }
- std::chrono::system_clock::time_point CTime::to_time_point() const
- {
- const time_t t = utc_mktime(&m_tm);
- return std::chrono::system_clock::from_time_t(t);
- }
-
- tm get_current_date_time_local()
- {
- const std::time_t now_time = get_current_time_as_time_since_epoch();
- return Chrono::to_local_time(now_time);
- }
-}
diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp
deleted file mode 100644
index 30e0f8588..000000000
--- a/toolsrc/src/vcpkg/base/cofffilereader.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/cofffilereader.h>
-#include <vcpkg/base/stringliteral.h>
-
-using namespace std;
-
-namespace vcpkg::CoffFileReader
-{
-#if defined(_WIN32)
- template<class T>
- static T reinterpret_bytes(const char* data)
- {
- return (*reinterpret_cast<const T*>(&data[0]));
- }
-
- template<class T>
- static T read_value_from_stream(fstream& fs)
- {
- T data;
- fs.read(reinterpret_cast<char*>(&data), sizeof data);
- return data;
- }
-
- template<class T>
- static T peek_value_from_stream(fstream& fs)
- {
- const std::streampos original_pos = fs.tellg();
- T data;
- fs.read(reinterpret_cast<char*>(&data), sizeof data);
- fs.seekg(original_pos);
- return data;
- }
-
- static void verify_equal_strings(const LineInfo& line_info,
- StringView expected,
- StringView actual,
- const char* label)
- {
- Checks::check_exit(line_info,
- expected == actual,
- "Incorrect string (%s) found. Expected: (%s) but found (%s)",
- label,
- expected,
- actual);
- }
-
- static void read_and_verify_pe_signature(fstream& fs)
- {
- static constexpr size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c;
-
- static constexpr StringLiteral PE_SIGNATURE = "PE\0\0";
- static constexpr size_t PE_SIGNATURE_SIZE = 4;
-
- fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg);
- const auto offset_to_pe_signature = read_value_from_stream<int32_t>(fs);
-
- fs.seekg(offset_to_pe_signature);
- char signature[PE_SIGNATURE_SIZE];
- fs.read(signature, PE_SIGNATURE_SIZE);
- verify_equal_strings(VCPKG_LINE_INFO, PE_SIGNATURE, {signature, PE_SIGNATURE_SIZE}, "PE_SIGNATURE");
- fs.seekg(offset_to_pe_signature + PE_SIGNATURE_SIZE, ios_base::beg);
- }
-
- static fpos_t align_to_size(const uint64_t unaligned, const uint64_t alignment_size)
- {
- fpos_t aligned = unaligned - 1;
- aligned /= alignment_size;
- aligned += 1;
- aligned *= alignment_size;
- return aligned;
- }
-
- struct CoffFileHeader
- {
- static constexpr size_t HEADER_SIZE = 20;
-
- static CoffFileHeader read(fstream& fs)
- {
- CoffFileHeader ret;
- ret.data.resize(HEADER_SIZE);
- fs.read(&ret.data[0], HEADER_SIZE);
- return ret;
- }
-
- MachineType machine_type() const
- {
- static constexpr size_t MACHINE_TYPE_OFFSET = 0;
- static constexpr size_t MACHINE_TYPE_SIZE = 2;
-
- std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE);
- const auto machine = reinterpret_bytes<uint16_t>(machine_field_as_string.c_str());
- return to_machine_type(machine);
- }
-
- private:
- std::string data;
- };
-
- struct ArchiveMemberHeader
- {
- static constexpr size_t HEADER_SIZE = 60;
-
- static ArchiveMemberHeader read(fstream& fs)
- {
- static constexpr size_t HEADER_END_OFFSET = 58;
- static constexpr StringLiteral HEADER_END = "`\n";
- static constexpr size_t HEADER_END_SIZE = 2;
-
- ArchiveMemberHeader ret;
- ret.data.resize(HEADER_SIZE);
- fs.read(&ret.data[0], HEADER_SIZE);
-
- if (ret.data[0] != '\0') // Due to freeglut. github issue #223
- {
- const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE);
- verify_equal_strings(VCPKG_LINE_INFO, HEADER_END, header_end, "LIB HEADER_END");
- }
-
- return ret;
- }
-
- std::string name() const
- {
- static constexpr size_t HEADER_NAME_OFFSET = 0;
- static constexpr size_t HEADER_NAME_SIZE = 16;
- return data.substr(HEADER_NAME_OFFSET, HEADER_NAME_SIZE);
- }
-
- uint64_t member_size() const
- {
- static constexpr size_t ALIGNMENT_SIZE = 2;
-
- static constexpr size_t HEADER_SIZE_OFFSET = 48;
- static constexpr size_t HEADER_SIZE_FIELD_SIZE = 10;
- const std::string as_string = data.substr(HEADER_SIZE_OFFSET, HEADER_SIZE_FIELD_SIZE);
- // This is in ASCII decimal representation
- const uint64_t value = std::strtoull(as_string.c_str(), nullptr, 10);
-
- const uint64_t aligned = align_to_size(value, ALIGNMENT_SIZE);
- return aligned;
- }
-
- std::string data;
- };
-
- struct OffsetsArray
- {
- static OffsetsArray read(fstream& fs, const uint32_t offset_count)
- {
- static constexpr uint32_t OFFSET_WIDTH = 4;
-
- std::string raw_offsets;
- const uint32_t raw_offset_size = offset_count * OFFSET_WIDTH;
- raw_offsets.resize(raw_offset_size);
- fs.read(&raw_offsets[0], raw_offset_size);
-
- OffsetsArray ret;
- for (uint32_t i = 0; i < offset_count; ++i)
- {
- const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * static_cast<size_t>(i),
- OFFSET_WIDTH * (static_cast<size_t>(i) + 1));
- const auto value = reinterpret_bytes<uint32_t>(value_as_string.c_str());
-
- // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292
- if (value != 0)
- {
- ret.data.push_back(value);
- }
- }
-
- // Sort the offsets, because it is possible for them to be unsorted. See vcpkg github #292
- std::sort(ret.data.begin(), ret.data.end());
- return ret;
- }
-
- std::vector<uint32_t> data;
- };
-
- struct ImportHeader
- {
- static constexpr size_t HEADER_SIZE = 20;
-
- static ImportHeader read(fstream& fs)
- {
- static constexpr size_t SIG1_OFFSET = 0;
- static constexpr auto SIG1 = static_cast<uint16_t>(MachineType::UNKNOWN);
- static constexpr size_t SIG1_SIZE = 2;
-
- static constexpr size_t SIG2_OFFSET = 2;
- static constexpr uint16_t SIG2 = 0xFFFF;
- static constexpr size_t SIG2_SIZE = 2;
-
- ImportHeader ret;
- ret.data.resize(HEADER_SIZE);
- fs.read(&ret.data[0], HEADER_SIZE);
-
- const std::string sig1_as_string = ret.data.substr(SIG1_OFFSET, SIG1_SIZE);
- const auto sig1 = reinterpret_bytes<uint16_t>(sig1_as_string.c_str());
- Checks::check_exit(VCPKG_LINE_INFO, sig1 == SIG1, "Sig1 was incorrect. Expected %s but got %s", SIG1, sig1);
-
- const std::string sig2_as_string = ret.data.substr(SIG2_OFFSET, SIG2_SIZE);
- const auto sig2 = reinterpret_bytes<uint16_t>(sig2_as_string.c_str());
- Checks::check_exit(VCPKG_LINE_INFO, sig2 == SIG2, "Sig2 was incorrect. Expected %s but got %s", SIG2, sig2);
-
- return ret;
- }
-
- MachineType machine_type() const
- {
- static constexpr size_t MACHINE_TYPE_OFFSET = 6;
- static constexpr size_t MACHINE_TYPE_SIZE = 2;
-
- std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE);
- const auto machine = reinterpret_bytes<uint16_t>(machine_field_as_string.c_str());
- return to_machine_type(machine);
- }
-
- private:
- std::string data;
- };
-
- static void read_and_verify_archive_file_signature(fstream& fs)
- {
- static constexpr StringLiteral FILE_START = "!<arch>\n";
- static constexpr size_t FILE_START_SIZE = 8;
-
- fs.seekg(std::fstream::beg);
-
- char file_start[FILE_START_SIZE];
- fs.read(file_start, FILE_START_SIZE);
- verify_equal_strings(VCPKG_LINE_INFO, FILE_START, {file_start, FILE_START_SIZE}, "LIB FILE_START");
- }
-
- DllInfo read_dll(const fs::path& path)
- {
- std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate);
- Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string());
-
- read_and_verify_pe_signature(fs);
- CoffFileHeader header = CoffFileHeader::read(fs);
- const MachineType machine = header.machine_type();
- return {machine};
- }
-
- struct Marker
- {
- void set_to_offset(const fpos_t position) { this->m_absolute_position = position; }
-
- void set_to_current_pos(fstream& fs) { this->m_absolute_position = fs.tellg(); }
-
- void seek_to_marker(fstream& fs) const { fs.seekg(this->m_absolute_position, ios_base::beg); }
-
- void advance_by(const uint64_t offset) { this->m_absolute_position += offset; }
-
- private:
- fpos_t m_absolute_position = 0;
- };
-
- LibInfo read_lib(const fs::path& path)
- {
- std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate);
- Checks::check_exit(VCPKG_LINE_INFO, fs.is_open(), "Could not open file %s for reading", path.generic_string());
-
- read_and_verify_archive_file_signature(fs);
-
- Marker marker;
- marker.set_to_current_pos(fs);
-
- // First Linker Member
- const ArchiveMemberHeader first_linker_member_header = ArchiveMemberHeader::read(fs);
- Checks::check_exit(VCPKG_LINE_INFO,
- first_linker_member_header.name().substr(0, 2) == "/ ",
- "Could not find proper first linker member");
- marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + first_linker_member_header.member_size());
- marker.seek_to_marker(fs);
-
- const ArchiveMemberHeader second_linker_member_header = ArchiveMemberHeader::read(fs);
- Checks::check_exit(VCPKG_LINE_INFO,
- second_linker_member_header.name().substr(0, 2) == "/ ",
- "Could not find proper second linker member");
- // The first 4 bytes contains the number of archive members
- const auto archive_member_count = read_value_from_stream<uint32_t>(fs);
- const OffsetsArray offsets = OffsetsArray::read(fs, archive_member_count);
- marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size());
- marker.seek_to_marker(fs);
-
- const bool has_longname_member_header = peek_value_from_stream<uint16_t>(fs) == 0x2F2F;
- if (has_longname_member_header)
- {
- const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs);
- marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + longnames_member_header.member_size());
- marker.seek_to_marker(fs);
- }
-
- std::set<MachineType> machine_types;
- // Next we have the obj and pseudo-object files
- for (const uint32_t offset : offsets.data)
- {
- marker.set_to_offset(offset + ArchiveMemberHeader::HEADER_SIZE); // Skip the header, no need to read it.
- marker.seek_to_marker(fs);
- const auto first_two_bytes = peek_value_from_stream<uint16_t>(fs);
- const bool is_import_header = to_machine_type(first_two_bytes) == MachineType::UNKNOWN;
- const MachineType machine =
- is_import_header ? ImportHeader::read(fs).machine_type() : CoffFileHeader::read(fs).machine_type();
- machine_types.insert(machine);
- }
-
- return {std::vector<MachineType>(machine_types.cbegin(), machine_types.cend())};
- }
-#endif
-}
diff --git a/toolsrc/src/vcpkg/base/downloads.cpp b/toolsrc/src/vcpkg/base/downloads.cpp
deleted file mode 100644
index 9fd3351d0..000000000
--- a/toolsrc/src/vcpkg/base/downloads.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-#include <vcpkg/base/cache.h>
-#include <vcpkg/base/downloads.h>
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/lockguarded.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#if defined(_WIN32)
-#include <VersionHelpers.h>
-#endif
-
-namespace vcpkg::Downloads
-{
-#if defined(_WIN32)
- struct WinHttpHandleDeleter
- {
- void operator()(HINTERNET h) const { WinHttpCloseHandle(h); }
- };
-
- struct WinHttpRequest
- {
- static ExpectedS<WinHttpRequest> make(HINTERNET hConnect, StringView url_path, const wchar_t* method = L"GET")
- {
- WinHttpRequest ret;
- // Create an HTTP request handle.
- auto h = WinHttpOpenRequest(hConnect,
- method,
- Strings::to_utf16(url_path).c_str(),
- nullptr,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- WINHTTP_FLAG_SECURE);
- if (!h) return Strings::concat("WinHttpOpenRequest() failed: ", GetLastError());
- ret.m_hRequest.reset(h);
-
- // Send a request.
- auto bResults = WinHttpSendRequest(
- ret.m_hRequest.get(), WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
-
- if (!bResults) return Strings::concat("WinHttpSendRequest() failed: ", GetLastError());
-
- // End the request.
- bResults = WinHttpReceiveResponse(ret.m_hRequest.get(), NULL);
- if (!bResults) return Strings::concat("WinHttpReceiveResponse() failed: ", GetLastError());
-
- DWORD dwStatusCode = 0;
- DWORD dwSize = sizeof(dwStatusCode);
-
- bResults = WinHttpQueryHeaders(ret.m_hRequest.get(),
- WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
- WINHTTP_HEADER_NAME_BY_INDEX,
- &dwStatusCode,
- &dwSize,
- WINHTTP_NO_HEADER_INDEX);
- if (!bResults) return Strings::concat("WinHttpQueryHeaders() failed: ", GetLastError());
- if (dwStatusCode < 200 || dwStatusCode >= 300) return Strings::concat("failed: status code ", dwStatusCode);
-
- return std::move(ret);
- }
-
- template<class F>
- ExpectedS<int> forall_data(F f)
- {
- std::vector<char> buf;
-
- size_t total_downloaded_size = 0;
- DWORD dwSize = 0;
- do
- {
- DWORD downloaded_size = 0;
- auto bResults = WinHttpQueryDataAvailable(m_hRequest.get(), &dwSize);
- if (!bResults) return Strings::concat("WinHttpQueryDataAvailable() failed: ", GetLastError());
-
- if (buf.size() < dwSize) buf.resize(static_cast<size_t>(dwSize) * 2);
-
- bResults = WinHttpReadData(m_hRequest.get(), (LPVOID)buf.data(), dwSize, &downloaded_size);
- if (!bResults) return Strings::concat("WinHttpReadData() failed: ", GetLastError());
- f(Span<char>(buf.data(), downloaded_size));
-
- total_downloaded_size += downloaded_size;
- } while (dwSize > 0);
- return 1;
- }
-
- std::unique_ptr<void, WinHttpHandleDeleter> m_hRequest;
- };
-
- struct WinHttpSession
- {
- static ExpectedS<WinHttpSession> make()
- {
- auto h = 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);
- if (!h) return Strings::concat("WinHttpOpen() failed: ", GetLastError());
- WinHttpSession ret;
- ret.m_hSession.reset(h);
-
- // 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(ret.m_hSession.get(), 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(ret.m_hSession.get(), 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(ret.m_hSession.get(), 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_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
- WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2);
- WinHttpSetOption(
- ret.m_hSession.get(), WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
-
- return ret;
- }
-
- std::unique_ptr<void, WinHttpHandleDeleter> m_hSession;
- };
-
- struct WinHttpConnection
- {
- static ExpectedS<WinHttpConnection> make(HINTERNET hSession, StringView hostname, INTERNET_PORT port)
- {
- // Specify an HTTP server.
- auto h = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), port, 0);
- if (!h) return Strings::concat("WinHttpConnect() failed: ", GetLastError());
- WinHttpConnection ret;
- ret.m_hConnect.reset(h);
- return ret;
- }
-
- std::unique_ptr<void, WinHttpHandleDeleter> m_hConnect;
- };
-#endif
-
- Optional<details::SplitURIView> details::split_uri_view(StringView uri)
- {
- auto sep = std::find(uri.begin(), uri.end(), ':');
- if (sep == uri.end()) return nullopt;
-
- StringView scheme(uri.begin(), sep);
- if (Strings::starts_with({sep + 1, uri.end()}, "//"))
- {
- auto path_start = std::find(sep + 3, uri.end(), '/');
- return details::SplitURIView{scheme, StringView{sep + 1, path_start}, {path_start, uri.end()}};
- }
- // no authority
- return details::SplitURIView{scheme, {}, {sep + 1, uri.end()}};
- }
-
- void verify_downloaded_file_hash(const Files::Filesystem& fs,
- const std::string& url,
- const fs::path& path,
- const std::string& sha512)
- {
- std::string actual_hash = vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO, fs, path, Hash::Algorithm::Sha512);
-
- // <HACK to handle NuGet.org changing nupkg hashes.>
- // This is the NEW hash for 7zip
- if (actual_hash == "a9dfaaafd15d98a2ac83682867ec5766720acf6e99d40d1a00d480692752603bf3f3742623f0ea85647a92374df"
- "405f331afd6021c5cf36af43ee8db198129c0")
- // This is the OLD hash for 7zip
- actual_hash = "8c75314102e68d2b2347d592f8e3eb05812e1ebb525decbac472231633753f1d4ca31c8e6881a36144a8da26b257"
- "1305b3ae3f4e2b85fc4a290aeda63d1a13b8";
- // </HACK>
-
- Checks::check_exit(VCPKG_LINE_INFO,
- sha512 == actual_hash,
- "File does not have the expected hash:\n"
- " url : [ %s ]\n"
- " File path : [ %s ]\n"
- " Expected hash : [ %s ]\n"
- " Actual hash : [ %s ]\n",
- url,
- fs::u8string(path),
- sha512,
- actual_hash);
- }
-
- static void url_heads_inner(View<std::string> urls, std::vector<int>* out)
- {
- static constexpr StringLiteral guid_marker = "8a1db05f-a65d-419b-aa72-037fb4d0672e";
-
- System::Command cmd;
- cmd.string_arg("curl")
- .string_arg("--head")
- .string_arg("--location")
- .string_arg("-w")
- .string_arg(Strings::concat(guid_marker, " %{http_code}\\n"));
- for (auto&& url : urls)
- {
- cmd.string_arg(url);
- }
- auto res = System::cmd_execute_and_stream_lines(cmd, [out](StringView line) {
- if (Strings::starts_with(line, guid_marker))
- {
- 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);
- }
- std::vector<int> url_heads(View<std::string> urls)
- {
- static constexpr size_t batch_size = 100;
-
- std::vector<int> ret;
-
- size_t i = 0;
- for (; i + batch_size <= urls.size(); i += batch_size)
- {
- url_heads_inner({urls.data() + i, batch_size}, &ret);
- }
- if (i != urls.size()) url_heads_inner({urls.begin() + i, urls.end()}, &ret);
-
- return ret;
- }
-
- static void download_files_inner(Files::Filesystem&,
- View<std::pair<std::string, fs::path>> url_pairs,
- std::vector<int>* out)
- {
- static constexpr StringLiteral guid_marker = "8a1db05f-a65d-419b-aa72-037fb4d0672e";
-
- System::Command cmd;
- cmd.string_arg("curl")
- .string_arg("--location")
- .string_arg("-w")
- .string_arg(Strings::concat(guid_marker, " %{http_code}\\n"));
- for (auto&& url : url_pairs)
- {
- cmd.string_arg(url.first).string_arg("-o").path_arg(url.second);
- }
- auto res = System::cmd_execute_and_stream_lines(cmd, [out](StringView line) {
- if (Strings::starts_with(line, guid_marker))
- {
- 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);
- }
- std::vector<int> download_files(Files::Filesystem& fs, View<std::pair<std::string, fs::path>> url_pairs)
- {
- 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)
- {
- download_files_inner(fs, {url_pairs.data() + i, batch_size}, &ret);
- }
- 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());
- return ret;
- }
-
- int put_file(const Files::Filesystem&, StringView url, const fs::path& file)
- {
- static constexpr StringLiteral guid_marker = "9a1db05f-a65d-419b-aa72-037fb4d0672e";
-
- System::Command cmd;
- cmd.string_arg("curl").string_arg("-X").string_arg("PUT");
- 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))
- {
- code = std::strtol(line.data() + guid_marker.size(), nullptr, 10);
- }
- });
- if (res != 0)
- {
- System::print2(System::Color::warning, "curl failed to execute with exit code: ", res, '\n');
- }
- return code;
- }
-
- void download_file(Files::Filesystem& fs,
- const std::string& url,
- const fs::path& download_path,
- const std::string& sha512)
- {
- download_file(fs, {&url, 1}, download_path, sha512);
- }
-
-#if defined(_WIN32)
- namespace
- {
- struct WriteFlushFile
- {
- WriteFlushFile(const fs::path& p)
- {
- auto err = _wfopen_s(&f, p.c_str(), L"wb");
- Checks::check_exit(VCPKG_LINE_INFO,
- !err,
- "Failed to open file %s. Error code was %s",
- fs::u8string(p),
- std::to_string(err));
- ASSUME(f != nullptr);
- }
- ~WriteFlushFile()
- {
- if (f)
- {
- fflush(f);
- fclose(f);
- }
- }
- FILE* f = nullptr;
- };
-
- /// <summary>
- /// Download a file using WinHTTP -- only supports HTTP and HTTPS
- /// </summary>
- static bool download_winhttp(Files::Filesystem& fs,
- const fs::path& download_path_part_path,
- details::SplitURIView split_uri,
- const std::string& url,
- std::string& errors)
- {
- // `download_winhttp` does not support user or port syntax in authorities
- auto hostname = split_uri.authority.value_or_exit(VCPKG_LINE_INFO).substr(2);
- INTERNET_PORT port;
- if (split_uri.scheme == "https")
- {
- port = INTERNET_DEFAULT_HTTPS_PORT;
- }
- else if (split_uri.scheme == "http")
- {
- port = INTERNET_DEFAULT_HTTP_PORT;
- }
- else
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- // Make sure the directories are present, otherwise fopen_s fails
- const auto dir = download_path_part_path.parent_path();
- fs.create_directories(dir, VCPKG_LINE_INFO);
-
- WriteFlushFile f(download_path_part_path);
-
- Debug::print("Downloading ", url, "\n");
- static auto s = WinHttpSession::make().value_or_exit(VCPKG_LINE_INFO);
- auto conn = WinHttpConnection::make(s.m_hSession.get(), hostname, port);
- if (!conn)
- {
- Strings::append(errors, url, ": ", conn.error(), '\n');
- return false;
- }
- auto req = WinHttpRequest::make(conn.get()->m_hConnect.get(), split_uri.path_query_fragment);
- if (!req)
- {
- Strings::append(errors, url, ": ", req.error(), '\n');
- return false;
- }
- auto forall_data =
- req.get()->forall_data([&](Span<char> span) { fwrite(span.data(), 1, span.size(), f.f); });
- if (!forall_data)
- {
- Strings::append(errors, url, ": ", forall_data.error(), '\n');
- return false;
- }
- return true;
- }
- }
-#endif
-
- std::string download_file(vcpkg::Files::Filesystem& fs,
- View<std::string> urls,
- const fs::path& download_path,
- const std::string& sha512)
- {
- Checks::check_exit(VCPKG_LINE_INFO, urls.size() > 0);
-
- auto download_path_part_path = download_path;
- download_path_part_path += fs::u8path(".part");
- fs.remove(download_path, ignore_errors);
- fs.remove(download_path_part_path, ignore_errors);
-
- std::string errors;
- for (const std::string& url : urls)
- {
-#if defined(_WIN32)
- 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")
- {
- // This check causes complex URLs (non-default port, embedded basic auth) to be passed down to curl.exe
- if (Strings::find_first_of(authority, ":@") == authority.end())
- {
- if (download_winhttp(fs, download_path_part_path, split_uri, url, errors))
- {
- verify_downloaded_file_hash(fs, url, download_path_part_path, sha512);
- fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
- return url;
- }
- continue;
- }
- }
-#endif
- System::Command cmd;
- cmd.string_arg("curl")
- .string_arg("--fail")
- .string_arg("-L")
- .string_arg(url)
- .string_arg("--create-dirs")
- .string_arg("--output")
- .path_arg(download_path_part_path);
- const auto out = System::cmd_execute_and_capture_output(cmd);
- if (out.exit_code != 0)
- {
- Strings::append(errors, url, ": ", out.output, '\n');
- continue;
- }
-
- verify_downloaded_file_hash(fs, url, download_path_part_path, sha512);
- fs.rename(download_path_part_path, download_path, VCPKG_LINE_INFO);
- return url;
- }
- Checks::exit_with_message(VCPKG_LINE_INFO, Strings::concat("Failed to download from mirror set:\n", errors));
- }
-}
diff --git a/toolsrc/src/vcpkg/base/enums.cpp b/toolsrc/src/vcpkg/base/enums.cpp
deleted file mode 100644
index 8b99ddf7b..000000000
--- a/toolsrc/src/vcpkg/base/enums.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/enums.h>
-
-namespace vcpkg::Enums
-{
- std::string nullvalue_to_string(const CStringView enum_name) { return Strings::format("%s_NULLVALUE", enum_name); }
-
- [[noreturn]] void nullvalue_used(const LineInfo& line_info, const CStringView enum_name)
- {
- Checks::exit_with_message(line_info, "NULLVALUE of enum %s was used", enum_name);
- }
-}
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
deleted file mode 100644
index 3d66d5629..000000000
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ /dev/null
@@ -1,1595 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#if defined(_WIN32)
-#include <vcpkg/base/system_headers.h>
-#else // ^^^ _WIN32 // !_WIN32 vvv
-#include <fcntl.h>
-
-#include <sys/file.h>
-#include <sys/stat.h>
-#endif // _WIN32
-
-#if defined(__linux__)
-#include <sys/sendfile.h>
-#elif defined(__APPLE__)
-#include <copyfile.h>
-#endif // ^^^ defined(__APPLE__)
-
-#include <algorithm>
-#include <list>
-#include <string>
-
-namespace
-{
- struct NativeStringView
- {
- const fs::path::value_type* first;
- const fs::path::value_type* last;
- NativeStringView() = default;
- NativeStringView(const fs::path::value_type* first, const fs::path::value_type* last) : first(first), last(last)
- {
- }
- bool empty() const { return first == last; }
- bool is_dot() const { return (last - first) == 1 && *first == '.'; }
- bool is_dot_dot() const { return (last - first) == 2 && *first == '.' && *(first + 1) == '.'; }
- };
-}
-
-#if defined(_WIN32)
-namespace
-{
- template<size_t N>
- bool wide_starts_with(const std::wstring& haystack, const wchar_t (&needle)[N]) noexcept
- {
- const size_t without_null = N - 1;
- return haystack.size() >= without_null && std::equal(needle, needle + without_null, haystack.begin());
- }
-
- bool starts_with_drive_letter(std::wstring::const_iterator first, const std::wstring::const_iterator last) noexcept
- {
- if (last - first < 2)
- {
- return false;
- }
-
- if (!(first[0] >= L'a' && first[0] <= L'z') && !(first[0] >= L'A' && first[0] <= L'Z'))
- {
- return false;
- }
-
- if (first[1] != L':')
- {
- return false;
- }
-
- return true;
- }
-
- struct FindFirstOp
- {
- HANDLE h_find = INVALID_HANDLE_VALUE;
- WIN32_FIND_DATAW find_data;
-
- unsigned long find_first(const wchar_t* const path) noexcept
- {
- assert(h_find == INVALID_HANDLE_VALUE);
- h_find = FindFirstFileW(path, &find_data);
- if (h_find == INVALID_HANDLE_VALUE)
- {
- return GetLastError();
- }
-
- return ERROR_SUCCESS;
- }
-
- FindFirstOp() = default;
- FindFirstOp(const FindFirstOp&) = delete;
- FindFirstOp& operator=(const FindFirstOp&) = delete;
-
- ~FindFirstOp()
- {
- if (h_find != INVALID_HANDLE_VALUE)
- {
- (void)FindClose(h_find);
- }
- }
- };
-} // unnamed namespace
-#endif // _WIN32
-
-fs::path fs::u8path(vcpkg::StringView s)
-{
- if (s.size() == 0)
- {
- return fs::path();
- }
-
-#if defined(_WIN32)
- return fs::path(vcpkg::Strings::to_utf16(s));
-#else
- return fs::path(s.begin(), s.end());
-#endif
-}
-
-std::string fs::u8string(const fs::path& p)
-{
-#if defined(_WIN32)
- return vcpkg::Strings::to_utf8(p.native());
-#else
- return p.native();
-#endif
-}
-std::string fs::generic_u8string(const fs::path& p)
-{
-#if defined(_WIN32)
- return vcpkg::Strings::to_utf8(p.generic_wstring());
-#else
- return p.generic_string();
-#endif
-}
-
-fs::path fs::lexically_normal(const fs::path& p)
-{
- // copied from microsoft/STL, stl/inc/filesystem:lexically_normal()
- // relicensed under MIT for the vcpkg repository.
-
- // N4810 29.11.7.1 [fs.path.generic]/6:
- // "Normalization of a generic format pathname means:"
-
- // "1. If the path is empty, stop."
- if (p.empty())
- {
- return {};
- }
-
- // "2. Replace each slash character in the root-name with a preferred-separator."
- const auto first = p.native().data();
- const auto last = first + p.native().size();
- const auto root_name_end = first + p.root_name().native().size();
-
- fs::path::string_type normalized(first, root_name_end);
-
-#if defined(_WIN32)
- std::replace(normalized.begin(), normalized.end(), L'/', L'\\');
-#endif
-
- // "3. Replace each directory-separator with a preferred-separator.
- // [ Note: The generic pathname grammar (29.11.7.1) defines directory-separator
- // as one or more slashes and preferred-separators. -end note ]"
- std::list<NativeStringView> lst; // Empty string_view means directory-separator
- // that will be normalized to a preferred-separator.
- // Non-empty string_view means filename.
- for (auto next = root_name_end; next != last;)
- {
- if (is_slash(*next))
- {
- if (lst.empty() || !lst.back().empty())
- {
- // collapse one or more slashes and preferred-separators to one empty wstring_view
- lst.emplace_back();
- }
-
- ++next;
- }
- else
- {
- const auto filename_end = std::find_if(next + 1, last, is_slash);
- lst.emplace_back(next, filename_end);
- next = filename_end;
- }
- }
-
- // "4. Remove each dot filename and any immediately following directory-separator."
- for (auto next = lst.begin(); next != lst.end();)
- {
- if (next->is_dot())
- {
- next = lst.erase(next); // erase dot filename
-
- if (next != lst.end())
- {
- next = lst.erase(next); // erase immediately following directory-separator
- }
- }
- else
- {
- ++next;
- }
- }
-
- // "5. As long as any appear, remove a non-dot-dot filename immediately followed by a
- // directory-separator and a dot-dot filename, along with any immediately following directory-separator."
- for (auto next = lst.begin(); next != lst.end();)
- {
- auto prev = next;
-
- // If we aren't going to erase, keep advancing.
- // If we're going to erase, next now points past the dot-dot filename.
- ++next;
-
- if (prev->is_dot_dot() && prev != lst.begin() && --prev != lst.begin() && !(--prev)->is_dot_dot())
- {
- if (next != lst.end())
- { // dot-dot filename has an immediately following directory-separator
- ++next;
- }
-
- lst.erase(prev, next); // next remains valid
- }
- }
-
- // "6. If there is a root-directory, remove all dot-dot filenames
- // and any directory-separators immediately following them.
- // [ Note: These dot-dot filenames attempt to refer to nonexistent parent directories. -end note ]"
- if (!lst.empty() && lst.front().empty())
- { // we have a root-directory
- for (auto next = lst.begin(); next != lst.end();)
- {
- if (next->is_dot_dot())
- {
- next = lst.erase(next); // erase dot-dot filename
-
- if (next != lst.end())
- {
- next = lst.erase(next); // erase immediately following directory-separator
- }
- }
- else
- {
- ++next;
- }
- }
- }
-
- // "7. If the last filename is dot-dot, remove any trailing directory-separator."
- if (lst.size() >= 2 && lst.back().empty() && std::prev(lst.end(), 2)->is_dot_dot())
- {
- lst.pop_back();
- }
-
- // Build up normalized by flattening lst.
- for (const auto& elem : lst)
- {
- if (elem.empty())
- {
- normalized += fs::path::preferred_separator;
- }
- else
- {
- normalized.append(elem.first, elem.last);
- }
- }
-
- // "8. If the path is empty, add a dot."
- if (normalized.empty())
- {
- normalized.push_back('.');
- }
-
- // "The result of normalization is a path in normal form, which is said to be normalized."
- return std::move(normalized);
-}
-
-namespace vcpkg::Files
-{
- static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])");
-
- namespace
- {
- fs::file_status status_implementation(bool follow_symlinks, const fs::path& p, std::error_code& ec) noexcept
- {
- using fs::file_type;
- using fs::perms;
-#if defined(_WIN32)
- WIN32_FILE_ATTRIBUTE_DATA file_attributes;
- auto ft = file_type::unknown;
- auto permissions = perms::unknown;
- ec.clear();
- if (!GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &file_attributes))
- {
- const auto err = GetLastError();
- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
- {
- ft = file_type::not_found;
- }
- else
- {
- ec.assign(err, std::system_category());
- }
- }
- else if (!follow_symlinks && file_attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- {
- // this also gives junctions file_type::directory_symlink
- if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- ft = file_type::directory_symlink;
- }
- else
- {
- ft = file_type::symlink;
- }
- }
- else if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- ft = file_type::directory;
- }
- else
- {
- // otherwise, the file is a regular file
- ft = file_type::regular;
- }
-
- if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- {
- constexpr auto all_write = perms::group_write | perms::owner_write | perms::others_write;
- permissions = perms::all & ~all_write;
- }
- else if (ft != file_type::none)
- {
- permissions = perms::all;
- }
-
- return fs::file_status(ft, permissions);
-
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- auto result = follow_symlinks ? fs::stdfs::status(p, ec) : fs::stdfs::symlink_status(p, ec);
- // libstdc++ doesn't correctly not-set ec on nonexistent paths
- if (ec.value() == ENOENT || ec.value() == ENOTDIR)
- {
- ec.clear();
- return fs::file_status(file_type::not_found, perms::unknown);
- }
- return fs::file_status(result.type(), result.permissions());
-#endif // ^^^ !defined(_WIN32)
- }
-
- fs::file_status status(const fs::path& p, std::error_code& ec) noexcept
- {
- return status_implementation(true, p, ec);
- }
- fs::file_status symlink_status(const fs::path& p, std::error_code& ec) noexcept
- {
- return status_implementation(false, p, ec);
- }
-
-#if defined(_WIN32) && !VCPKG_USE_STD_FILESYSTEM
- fs::path read_symlink_implementation(const fs::path& oldpath, std::error_code& ec)
- {
- ec.clear();
- auto handle = CreateFileW(oldpath.c_str(),
- 0, // open just the metadata
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- nullptr /* no security attributes */,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- nullptr /* no template file */);
- if (handle == INVALID_HANDLE_VALUE)
- {
- ec.assign(GetLastError(), std::system_category());
- return oldpath;
- }
- fs::path target;
- const DWORD maxsize = 32768;
- const std::unique_ptr<wchar_t[]> buffer(new wchar_t[maxsize]);
- const auto rc = GetFinalPathNameByHandleW(handle, buffer.get(), maxsize, 0);
- if (rc > 0 && rc < maxsize)
- {
- target = buffer.get();
- }
- else
- {
- ec.assign(GetLastError(), std::system_category());
- }
- CloseHandle(handle);
- return target;
- }
-#endif // ^^^ defined(_WIN32) && !VCPKG_USE_STD_FILESYSTEM
-
- void copy_symlink_implementation(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec)
- {
-#if defined(_WIN32) && !VCPKG_USE_STD_FILESYSTEM
- const auto target = read_symlink_implementation(oldpath, ec);
- if (ec) return;
-
- const DWORD flags =
-#if defined(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
- SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
-#else
- 0;
-#endif
- if (!CreateSymbolicLinkW(newpath.c_str(), target.c_str(), flags))
- {
- const auto err = GetLastError();
- ec.assign(err, std::system_category());
- return;
- }
- ec.clear();
- return;
-#else // ^^^ defined(_WIN32) && !VCPKG_USE_STD_FILESYSTEM // !defined(_WIN32) || VCPKG_USE_STD_FILESYSTEM vvv
- return fs::stdfs::copy_symlink(oldpath, newpath, ec);
-#endif // ^^^ !defined(_WIN32) || VCPKG_USE_STD_FILESYSTEM
- }
-
- // does _not_ follow symlinks
- void set_writeable(const fs::path& path, std::error_code& ec) noexcept
- {
-#if defined(_WIN32)
- auto const file_name = path.c_str();
- WIN32_FILE_ATTRIBUTE_DATA attributes;
- if (!GetFileAttributesExW(file_name, GetFileExInfoStandard, &attributes))
- {
- ec.assign(GetLastError(), std::system_category());
- return;
- }
-
- auto dw_attributes = attributes.dwFileAttributes;
- dw_attributes &= ~FILE_ATTRIBUTE_READONLY;
- if (!SetFileAttributesW(file_name, dw_attributes))
- {
- ec.assign(GetLastError(), std::system_category());
- }
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- struct stat s;
- if (lstat(path.c_str(), &s))
- {
- ec.assign(errno, std::system_category());
- return;
- }
-
- auto mode = s.st_mode;
- // if the file is a symlink, perms don't matter
- if (!(mode & S_IFLNK))
- {
- mode |= S_IWUSR;
- if (chmod(path.c_str(), mode))
- {
- ec.assign(errno, std::system_category());
- }
- }
-#endif // ^^^ !defined(_WIN32)
- }
- }
-
- std::string Filesystem::read_contents(const fs::path& path, LineInfo linfo) const
- {
- auto maybe_contents = this->read_contents(path);
- if (auto p = maybe_contents.get())
- {
- return std::move(*p);
- }
-
- Checks::exit_with_message(
- linfo, "error reading file: %s: %s", fs::u8string(path), maybe_contents.error().message());
- }
- void Filesystem::write_contents(const fs::path& path, const std::string& data, LineInfo linfo)
- {
- std::error_code ec;
- this->write_contents(path, data, ec);
- if (ec)
- {
- Checks::exit_with_message(linfo, "error writing file: %s: %s", fs::u8string(path), ec.message());
- }
- }
- void Filesystem::write_contents_and_dirs(const fs::path& path, const std::string& data, LineInfo linfo)
- {
- std::error_code ec;
- this->write_contents_and_dirs(path, data, ec);
- if (ec)
- {
- Checks::exit_with_message(
- linfo, "error writing file and creating directories: %s: %s", fs::u8string(path), ec.message());
- }
- }
- void Filesystem::rename(const fs::path& oldpath, const fs::path& newpath, LineInfo linfo)
- {
- std::error_code ec;
- this->rename(oldpath, newpath, ec);
- if (ec)
- {
- Checks::exit_with_message(
- linfo, "error renaming file: %s: %s: %s", fs::u8string(oldpath), fs::u8string(newpath), ec.message());
- }
- }
-
- bool Filesystem::remove(const fs::path& path, LineInfo linfo)
- {
- std::error_code ec;
- auto r = this->remove(path, ec);
- if (ec)
- {
- Checks::exit_with_message(linfo, "error removing file: %s: %s", fs::u8string(path), ec.message());
- }
-
- return r;
- }
-
- bool Filesystem::remove(const fs::path& path, ignore_errors_t)
- {
- std::error_code ec;
- return this->remove(path, ec);
- }
-
- bool Filesystem::exists(const fs::path& path, std::error_code& ec) const
- {
- return fs::exists(this->symlink_status(path, ec));
- }
-
- bool Filesystem::exists(LineInfo li, const fs::path& path) const
- {
- std::error_code ec;
- auto result = this->exists(path, ec);
- if (ec)
- Checks::exit_with_message(li, "error checking existence of file %s: %s", fs::u8string(path), ec.message());
- return result;
- }
-
- bool Filesystem::exists(const fs::path& path, ignore_errors_t) const
- {
- std::error_code ec;
- return this->exists(path, ec);
- }
-
- bool Filesystem::create_directory(const fs::path& path, ignore_errors_t)
- {
- std::error_code ec;
- return this->create_directory(path, ec);
- }
-
- bool Filesystem::create_directory(const fs::path& path, LineInfo li)
- {
- std::error_code ec;
- bool result = this->create_directory(path, ec);
- if (ec)
- {
- vcpkg::Checks::exit_with_message(li, "error creating directory %s", fs::u8string(path), ec.message());
- }
-
- return result;
- }
-
- bool Filesystem::create_directories(const fs::path& path, ignore_errors_t)
- {
- std::error_code ec;
- return this->create_directories(path, ec);
- }
-
- bool Filesystem::create_directories(const fs::path& path, LineInfo li)
- {
- std::error_code ec;
- bool result = this->create_directories(path, ec);
- if (ec)
- {
- vcpkg::Checks::exit_with_message(li, "error creating directories %s", fs::u8string(path), ec.message());
- }
-
- return result;
- }
-
- void Filesystem::copy_file(const fs::path& oldpath, const fs::path& newpath, fs::copy_options opts, LineInfo li)
- {
- std::error_code ec;
- this->copy_file(oldpath, newpath, opts, ec);
- if (ec)
- {
- vcpkg::Checks::exit_with_message(
- li, "error copying file from %s to %s: %s", fs::u8string(oldpath), fs::u8string(newpath), ec.message());
- }
- }
-
- fs::file_status Filesystem::status(vcpkg::LineInfo li, const fs::path& p) const noexcept
- {
- std::error_code ec;
- auto result = this->status(p, ec);
- if (ec)
- {
- vcpkg::Checks::exit_with_message(li, "error getting status of path %s: %s", p.string(), ec.message());
- }
-
- return result;
- }
-
- fs::file_status Filesystem::status(const fs::path& p, ignore_errors_t) const noexcept
- {
- std::error_code ec;
- return this->status(p, ec);
- }
-
- fs::file_status Filesystem::symlink_status(vcpkg::LineInfo li, const fs::path& p) const noexcept
- {
- std::error_code ec;
- auto result = this->symlink_status(p, ec);
- if (ec)
- {
- vcpkg::Checks::exit_with_message(li, "error getting status of path %s: %s", p.string(), ec.message());
- }
-
- return result;
- }
-
- fs::file_status Filesystem::symlink_status(const fs::path& p, ignore_errors_t) const noexcept
- {
- std::error_code ec;
- return this->symlink_status(p, ec);
- }
-
- void Filesystem::write_lines(const fs::path& path, const std::vector<std::string>& lines, LineInfo linfo)
- {
- std::error_code ec;
- this->write_lines(path, lines, ec);
- if (ec)
- {
- Checks::exit_with_message(linfo, "error writing lines: %s: %s", fs::u8string(path), ec.message());
- }
- }
-
- void Filesystem::remove_all(const fs::path& path, LineInfo li)
- {
- std::error_code ec;
- fs::path failure_point;
-
- this->remove_all(path, ec, failure_point);
-
- if (ec)
- {
- Checks::exit_with_message(li,
- "Failure to remove_all(%s) due to file %s: %s",
- path.string(),
- failure_point.string(),
- ec.message());
- }
- }
-
- void Filesystem::remove_all(const fs::path& path, ignore_errors_t)
- {
- std::error_code ec;
- fs::path failure_point;
-
- this->remove_all(path, ec, failure_point);
- }
-
- void Filesystem::remove_all_inside(const fs::path& path, LineInfo li)
- {
- std::error_code ec;
- fs::path failure_point;
-
- this->remove_all_inside(path, ec, failure_point);
-
- if (ec)
- {
- Checks::exit_with_message(li,
- "Failure to remove_all_inside(%s) due to file %s: %s",
- path.string(),
- failure_point.string(),
- ec.message());
- }
- }
-
- void Filesystem::remove_all_inside(const fs::path& path, ignore_errors_t)
- {
- std::error_code ec;
- fs::path failure_point;
-
- this->remove_all_inside(path, ec, failure_point);
- }
-
- fs::path Filesystem::absolute(LineInfo li, const fs::path& path) const
- {
- std::error_code ec;
- const auto result = this->absolute(path, ec);
- if (ec)
- {
- Checks::exit_with_message(li, "Error getting absolute path of %s: %s", path.string(), ec.message());
- }
-
- return result;
- }
-
- fs::path Filesystem::canonical(LineInfo li, const fs::path& path) const
- {
- std::error_code ec;
- const auto result = this->canonical(path, ec);
- if (ec)
- {
- Checks::exit_with_message(li, "Error getting canonicalization of %s: %s", path.string(), ec.message());
- }
-
- return result;
- }
- fs::path Filesystem::canonical(const fs::path& path, ignore_errors_t) const
- {
- std::error_code ec;
- return this->canonical(path, ec);
- }
- fs::path Filesystem::current_path(LineInfo li) const
- {
- std::error_code ec;
- const auto result = this->current_path(ec);
- if (ec)
- {
- Checks::exit_with_message(li, "Error getting current path: %s", ec.message());
- }
-
- return result;
- }
- void Filesystem::current_path(const fs::path& path, LineInfo li)
- {
- std::error_code ec;
- this->current_path(path, ec);
- if (ec)
- {
- Checks::exit_with_message(li, "Error setting current path: %s", ec.message());
- }
- }
-
- struct RealFilesystem final : Filesystem
- {
- virtual Expected<std::string> read_contents(const fs::path& file_path) const override
- {
- std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
- if (file_stream.fail())
- {
- return std::make_error_code(std::errc::no_such_file_or_directory);
- }
-
- file_stream.seekg(0, file_stream.end);
- auto length = file_stream.tellg();
- file_stream.seekg(0, file_stream.beg);
-
- if (length == std::streampos(-1))
- {
- return std::make_error_code(std::errc::io_error);
- }
-
- std::string output;
- output.resize(static_cast<size_t>(length));
- file_stream.read(&output[0], length);
-
- return output;
- }
- virtual Expected<std::vector<std::string>> read_lines(const fs::path& file_path) const override
- {
- std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
- if (file_stream.fail())
- {
- Debug::print("Missing path: ", fs::u8string(file_path), '\n');
- return std::make_error_code(std::errc::no_such_file_or_directory);
- }
-
- std::vector<std::string> output;
- std::string line;
- while (std::getline(file_stream, line))
- {
- // Remove the trailing \r to accomodate Windows line endings.
- if ((!line.empty()) && (line.back() == '\r')) line.pop_back();
-
- output.push_back(line);
- }
-
- return output;
- }
- virtual fs::path find_file_recursively_up(const fs::path& starting_dir, const fs::path& filename) const override
- {
- fs::path current_dir = starting_dir;
- if (exists(VCPKG_LINE_INFO, current_dir / filename))
- {
- return current_dir;
- }
-
- int counter = 10000;
- for (;;)
- {
- // This is a workaround for VS2015's experimental filesystem implementation
- if (!current_dir.has_relative_path())
- {
- current_dir.clear();
- return current_dir;
- }
-
- auto parent = current_dir.parent_path();
- if (parent == current_dir)
- {
- current_dir.clear();
- return current_dir;
- }
-
- current_dir = std::move(parent);
-
- const fs::path candidate = current_dir / filename;
- if (exists(VCPKG_LINE_INFO, candidate))
- {
- return current_dir;
- }
-
- --counter;
- Checks::check_exit(VCPKG_LINE_INFO,
- counter > 0,
- "infinite loop encountered while trying to find_file_recursively_up()");
- }
- }
-
- virtual std::vector<fs::path> get_files_recursive(const fs::path& dir) const override
- {
- std::vector<fs::path> ret;
-
- std::error_code ec;
- fs::stdfs::recursive_directory_iterator b(dir, ec), e{};
- if (ec) return ret;
- for (; b != e; ++b)
- {
- ret.push_back(b->path());
- }
-
- return ret;
- }
-
- virtual std::vector<fs::path> get_files_non_recursive(const fs::path& dir) const override
- {
- std::vector<fs::path> ret;
-
- std::error_code ec;
- fs::stdfs::directory_iterator b(dir, ec), e{};
- if (ec) return ret;
- for (; b != e; ++b)
- {
- ret.push_back(b->path());
- }
-
- return ret;
- }
-
- virtual void write_lines(const fs::path& file_path,
- const std::vector<std::string>& lines,
- std::error_code& ec) override
- {
- std::fstream output(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
- auto first = lines.begin();
- const auto last = lines.end();
- for (;;)
- {
- if (!output)
- {
- ec.assign(static_cast<int>(std::errc::io_error), std::generic_category());
- return;
- }
-
- if (first == last)
- {
- return;
- }
-
- output << *first << "\n";
- ++first;
- }
- }
- virtual void rename(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec) override
- {
- fs::stdfs::rename(oldpath, newpath, ec);
- }
- virtual void rename_or_copy(const fs::path& oldpath,
- const fs::path& newpath,
- StringLiteral temp_suffix,
- std::error_code& ec) override
- {
- this->rename(oldpath, newpath, ec);
- (void)temp_suffix;
-#if !defined(_WIN32)
- if (ec)
- {
- auto dst = newpath;
- dst.replace_filename(dst.filename() + temp_suffix.c_str());
-
- int i_fd = open(oldpath.c_str(), O_RDONLY);
- if (i_fd == -1) return;
-
- int o_fd = creat(dst.c_str(), 0664);
- if (o_fd == -1)
- {
- close(i_fd);
- return;
- }
-
-#if defined(__linux__)
- off_t bytes = 0;
- struct stat info = {0};
- fstat(i_fd, &info);
- auto written_bytes = sendfile(o_fd, i_fd, &bytes, info.st_size);
-#elif defined(__APPLE__)
- auto written_bytes = fcopyfile(i_fd, o_fd, 0, COPYFILE_ALL);
-#else // ^^^ defined(__APPLE__) // !(defined(__APPLE__) || defined(__linux__)) vvv
- ssize_t written_bytes = 0;
- {
- constexpr std::size_t buffer_length = 4096;
- auto buffer = std::make_unique<unsigned char[]>(buffer_length);
- while (auto read_bytes = read(i_fd, buffer.get(), buffer_length))
- {
- if (read_bytes == -1)
- {
- written_bytes = -1;
- break;
- }
- auto remaining = read_bytes;
- while (remaining > 0)
- {
- auto read_result = write(o_fd, buffer.get(), remaining);
- if (read_result == -1)
- {
- written_bytes = -1;
- // break two loops
- goto copy_failure;
- }
- remaining -= read_result;
- }
- }
-
- copy_failure:;
- }
-#endif // ^^^ !(defined(__APPLE__) || defined(__linux__))
- if (written_bytes == -1)
- {
- ec.assign(errno, std::generic_category());
- close(i_fd);
- close(o_fd);
-
- return;
- }
-
- close(i_fd);
- close(o_fd);
-
- this->rename(dst, newpath, ec);
- if (ec) return;
- this->remove(oldpath, ec);
- }
-#endif // ^^^ !defined(_WIN32)
- }
- virtual bool remove(const fs::path& path, std::error_code& ec) override { return fs::stdfs::remove(path, ec); }
- virtual void remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) override
- {
- /*
- does not use the std::experimental::filesystem call since this is
- quite a bit faster, and also supports symlinks
- */
-
- struct remove
- {
- struct ErrorInfo : Util::ResourceBase
- {
- std::error_code ec;
- fs::path failure_point;
- };
- /*
- if `current_path` is a directory, first `remove`s all
- elements of the directory, then removes current_path.
-
- else if `current_path` exists, removes current_path
-
- else does nothing
- */
- static void do_remove(const fs::path& current_path, ErrorInfo& err)
- {
- std::error_code ec;
- const auto path_status = Files::symlink_status(current_path, ec);
- if (check_ec(ec, current_path, err)) return;
- if (!fs::exists(path_status)) return;
-
- const auto path_type = path_status.type();
-
- if ((path_status.permissions() & fs::perms::owner_write) != fs::perms::owner_write)
- {
- set_writeable(current_path, ec);
- if (check_ec(ec, current_path, err)) return;
- }
-
- if (path_type == fs::file_type::directory)
- {
- for (const auto& entry : fs::stdfs::directory_iterator(current_path))
- {
- do_remove(entry, err);
- if (err.ec) return;
- }
-#if defined(_WIN32)
- if (!RemoveDirectoryW(current_path.c_str()))
- {
- ec.assign(GetLastError(), std::system_category());
- }
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- if (rmdir(current_path.c_str()))
- {
- ec.assign(errno, std::system_category());
- }
-#endif // ^^^ !defined(_WIN32)
- }
-#if VCPKG_USE_STD_FILESYSTEM
- else
- {
- fs::stdfs::remove(current_path, ec);
- if (check_ec(ec, current_path, err)) return;
- }
-#else // ^^^ VCPKG_USE_STD_FILESYSTEM // !VCPKG_USE_STD_FILESYSTEM vvv
-#if defined(_WIN32)
- else if (path_type == fs::file_type::directory_symlink)
- {
- if (!RemoveDirectoryW(current_path.c_str()))
- {
- ec.assign(GetLastError(), std::system_category());
- }
- }
- else
- {
- if (!DeleteFileW(current_path.c_str()))
- {
- ec.assign(GetLastError(), std::system_category());
- }
- }
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- else
- {
- if (unlink(current_path.c_str()))
- {
- ec.assign(errno, std::system_category());
- }
- }
-#endif // ^^^ !defined(_WIN32)
-#endif // ^^^ !VCPKG_USE_STD_FILESYSTEM
-
- check_ec(ec, current_path, err);
- }
-
- static bool check_ec(const std::error_code& ec, const fs::path& current_path, ErrorInfo& err)
- {
- if (ec)
- {
- err.ec = ec;
- err.failure_point = current_path;
-
- return true;
- }
- else
- {
- return false;
- }
- }
- };
-
- /*
- we need to do backoff on the removal of the top level directory,
- so we can only delete the directory after all the
- lower levels have been deleted.
- */
-
- remove::ErrorInfo err;
- for (int backoff = 0; backoff < 5; ++backoff)
- {
- if (backoff)
- {
- using namespace std::chrono_literals;
- auto backoff_time = 100ms * backoff;
- std::this_thread::sleep_for(backoff_time);
- }
-
- remove::do_remove(path, err);
- if (!err.ec)
- {
- break;
- }
- }
-
- ec = std::move(err.ec);
- failure_point = std::move(err.failure_point);
- }
-
- virtual void remove_all_inside(const fs::path& path, std::error_code& ec, fs::path& failure_point) override
- {
- fs::directory_iterator last{};
- fs::directory_iterator first(path, ec);
- if (ec)
- {
- failure_point = path;
- return;
- }
-
- for (;;)
- {
- if (first == last)
- {
- return;
- }
-
- auto stats = first->status(ec);
- if (ec)
- {
- break;
- }
-
- auto& thisPath = first->path();
- if (stats.type() == fs::stdfs::file_type::directory)
- {
- this->remove_all(thisPath, ec, failure_point);
- if (ec)
- {
- return; // keep inner failure_point
- }
- }
- else
- {
- this->remove(thisPath, ec);
- if (ec)
- {
- break;
- }
- }
-
- first.increment(ec);
- if (ec)
- {
- break;
- }
- }
-
- failure_point = first->path();
- }
-
- virtual bool is_directory(const fs::path& path) const override { return fs::stdfs::is_directory(path); }
- virtual bool is_regular_file(const fs::path& path) const override { return fs::stdfs::is_regular_file(path); }
- virtual bool is_empty(const fs::path& path) const override { return fs::stdfs::is_empty(path); }
- virtual bool create_directory(const fs::path& path, std::error_code& ec) override
- {
- return fs::stdfs::create_directory(path, ec);
- }
- virtual bool create_directories(const fs::path& path, std::error_code& ec) override
- {
- return fs::stdfs::create_directories(path, ec);
- }
- virtual void copy(const fs::path& oldpath, const fs::path& newpath, fs::copy_options opts) override
- {
- fs::stdfs::copy(oldpath, newpath, opts);
- }
- virtual bool copy_file(const fs::path& oldpath,
- const fs::path& newpath,
- fs::copy_options opts,
- std::error_code& ec) override
- {
- return fs::stdfs::copy_file(oldpath, newpath, opts, ec);
- }
- virtual void copy_symlink(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec) override
- {
- return Files::copy_symlink_implementation(oldpath, newpath, ec);
- }
-
- virtual fs::file_status status(const fs::path& path, std::error_code& ec) const override
- {
- return Files::status(path, ec);
- }
- virtual fs::file_status symlink_status(const fs::path& path, std::error_code& ec) const override
- {
- return Files::symlink_status(path, ec);
- }
- virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) override
- {
- ec.clear();
-
- FILE* f = nullptr;
-#if defined(_WIN32)
- auto err = _wfopen_s(&f, file_path.native().c_str(), L"wb");
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- f = fopen(file_path.native().c_str(), "wb");
- int err = f != nullptr ? 0 : 1;
-#endif // ^^^ !defined(_WIN32)
- if (err != 0)
- {
- ec.assign(err, std::system_category());
- return;
- }
-
- if (f != nullptr)
- {
- auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f);
- fclose(f);
-
- if (count != data.size())
- {
- ec = std::make_error_code(std::errc::no_space_on_device);
- }
- }
- }
-
- virtual void write_contents_and_dirs(const fs::path& file_path,
- const std::string& data,
- std::error_code& ec) override
- {
- write_contents(file_path, data, ec);
- if (ec)
- {
- create_directories(file_path.parent_path(), ec);
- if (ec)
- {
- return;
- }
- write_contents(file_path, data, ec);
- }
- }
-
- virtual fs::path absolute(const fs::path& path, std::error_code& ec) const override
- {
-#if VCPKG_USE_STD_FILESYSTEM
- return fs::stdfs::absolute(path, ec);
-#else // ^^^ VCPKG_USE_STD_FILESYSTEM / !VCPKG_USE_STD_FILESYSTEM vvv
-#if defined(_WIN32)
- // absolute was called system_complete in experimental filesystem
- return fs::stdfs::system_complete(path, ec);
-#else // ^^^ defined(_WIN32) / !defined(_WIN32) vvv
- if (path.is_absolute())
- {
- return path;
- }
- else
- {
- auto current_path = this->current_path(ec);
- if (ec) return fs::path();
- return std::move(current_path) / path;
- }
-#endif // ^^^ !defined(_WIN32)
-#endif // ^^^ !VCPKG_USE_STD_FILESYSTEM
- }
-
- virtual fs::path canonical(const fs::path& path, std::error_code& ec) const override
- {
- return fs::stdfs::canonical(path, ec);
- }
-
- virtual fs::path current_path(std::error_code& ec) const override { return fs::stdfs::current_path(ec); }
- virtual void current_path(const fs::path& path, std::error_code& ec) override
- {
- fs::stdfs::current_path(path, ec);
- }
-
- struct TakeExclusiveFileLockHelper
- {
- fs::SystemHandle& res;
- const fs::path::string_type& native;
- TakeExclusiveFileLockHelper(fs::SystemHandle& res, const fs::path::string_type& native)
- : res(res), native(native)
- {
- }
-
-#if defined(_WIN32)
- void assign_busy_error(std::error_code& ec) { ec.assign(ERROR_BUSY, std::system_category()); }
-
- bool operator()(std::error_code& ec)
- {
- ec.clear();
- auto handle = CreateFileW(native.c_str(),
- GENERIC_READ,
- 0 /* no sharing */,
- nullptr /* no security attributes */,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- nullptr /* no template file */);
- if (handle == INVALID_HANDLE_VALUE)
- {
- const auto err = GetLastError();
- if (err != ERROR_SHARING_VIOLATION)
- {
- ec.assign(err, std::system_category());
- }
- return false;
- }
-
- res.system_handle = reinterpret_cast<intptr_t>(handle);
- return true;
- }
-#else // ^^^ _WIN32 / !_WIN32 vvv
- int fd = -1;
-
- void assign_busy_error(std::error_code& ec) { ec.assign(EBUSY, std::generic_category()); }
-
- bool operator()(std::error_code& ec)
- {
- ec.clear();
- if (fd == -1)
- {
- fd = ::open(native.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (fd < 0)
- {
- ec.assign(errno, std::generic_category());
- return false;
- }
- }
-
- if (::flock(fd, LOCK_EX | LOCK_NB) != 0)
- {
- if (errno != EWOULDBLOCK)
- {
- ec.assign(errno, std::generic_category());
- }
- return false;
- }
-
- res.system_handle = fd;
- fd = -1;
- return true;
- };
-
- ~TakeExclusiveFileLockHelper()
- {
- if (fd != -1)
- {
- ::close(fd);
- }
- }
-#endif
- };
-
- virtual fs::SystemHandle take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
- {
- fs::SystemHandle res;
- TakeExclusiveFileLockHelper helper(res, path.native());
-
- if (helper(ec) || ec)
- {
- return res;
- }
-
- System::printf("Waiting to take filesystem lock on %s...\n", fs::u8string(path));
- const auto wait = std::chrono::milliseconds(1000);
- for (;;)
- {
- std::this_thread::sleep_for(wait);
- if (helper(ec) || ec)
- {
- return res;
- }
- }
- }
-
- virtual fs::SystemHandle try_take_exclusive_file_lock(const fs::path& path, std::error_code& ec) override
- {
- fs::SystemHandle res;
- TakeExclusiveFileLockHelper helper(res, path.native());
-
- if (helper(ec) || ec)
- {
- return res;
- }
-
- Debug::print("Waiting to take filesystem lock on ", fs::u8string(path), "...\n");
- auto wait = std::chrono::milliseconds(100);
- // waits, at most, a second and a half.
- while (wait < std::chrono::milliseconds(1000))
- {
- std::this_thread::sleep_for(wait);
- if (helper(ec) || ec)
- {
- return res;
- }
- wait *= 2;
- }
-
- helper.assign_busy_error(ec);
- return res;
- }
-
- virtual void unlock_file_lock(fs::SystemHandle handle, std::error_code& ec) override
- {
-#if defined(_WIN32)
- if (CloseHandle(reinterpret_cast<HANDLE>(handle.system_handle)) == 0)
- {
- ec.assign(GetLastError(), std::system_category());
- }
-#else
- if (flock(handle.system_handle, LOCK_UN) != 0 || close(handle.system_handle) != 0)
- {
- ec.assign(errno, std::generic_category());
- }
-#endif
- }
-
- virtual std::vector<fs::path> find_from_PATH(const std::string& name) const override
- {
-#if defined(_WIN32)
- static constexpr wchar_t const* EXTS[] = {L".cmd", L".exe", L".bat"};
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- static constexpr char const* EXTS[] = {""};
-#endif // ^^^!defined(_WIN32)
- auto paths = Strings::split_paths(System::get_environment_variable("PATH").value_or_exit(VCPKG_LINE_INFO));
-
- std::vector<fs::path> ret;
- for (auto&& path : paths)
- {
- auto base = fs::u8path(path);
- base /= fs::u8path(name);
-
- for (auto&& ext : EXTS)
- {
- auto p = fs::path(base.native() + ext);
- if (Util::find(ret, p) == ret.end() && this->exists(p, ignore_errors))
- {
- ret.push_back(p);
- Debug::print("Found path: ", fs::u8string(p), '\n');
- }
- }
- }
-
- return ret;
- }
- };
-
- Filesystem& get_real_filesystem()
- {
- static RealFilesystem real_fs;
- return real_fs;
- }
-
- bool has_invalid_chars_for_filesystem(const std::string& s)
- {
- return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX);
- }
-
- void print_paths(const std::vector<fs::path>& paths)
- {
- std::string message = "\n";
- for (const fs::path& p : paths)
- {
- Strings::append(message, " ", p.generic_string(), '\n');
- }
- message.push_back('\n');
- System::print2(message);
- }
-
- fs::path combine(const fs::path& lhs, const fs::path& rhs)
- {
-#if VCPKG_USE_STD_FILESYSTEM
- return lhs / rhs;
-#else // ^^^ std::filesystem // std::experimental::filesystem vvv
-#if !defined(_WIN32)
- if (rhs.is_absolute())
- {
- return rhs;
- }
- else
- {
- return lhs / rhs;
- }
-#else // ^^^ unix // windows vvv
- auto rhs_root_directory = rhs.root_directory();
- auto rhs_root_name = rhs.root_name();
-
- if (rhs_root_directory.empty() && rhs_root_name.empty())
- {
- return lhs / rhs;
- }
- else if (rhs_root_directory.empty())
- {
- // !rhs_root_name.empty()
- if (rhs_root_name == lhs.root_name())
- {
- return lhs / rhs.relative_path();
- }
- else
- {
- return rhs;
- }
- }
- else if (rhs_root_name.empty())
- {
- // !rhs_root_directory.empty()
- return lhs.root_name() / rhs;
- }
- else
- {
- // rhs.absolute()
- return rhs;
- }
-#endif // ^^^ windows
-#endif // ^^^ std::experimental::filesystem
- }
-
-#ifdef _WIN32
- fs::path win32_fix_path_case(const fs::path& source)
- {
- using fs::is_slash;
- const std::wstring& native = source.native();
- if (native.empty())
- {
- return fs::path{};
- }
-
- if (wide_starts_with(native, L"\\\\?\\") || wide_starts_with(native, L"\\??\\") ||
- wide_starts_with(native, L"\\\\.\\"))
- {
- // no support to attempt to fix paths in the NT, \\GLOBAL??, or device namespaces at this time
- return source;
- }
-
- const auto last = native.end();
- auto first = native.begin();
- auto is_wildcard = [](wchar_t c) { return c == L'?' || c == L'*'; };
- if (std::any_of(first, last, is_wildcard))
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Attempt to fix case of a path containing wildcards: %s", fs::u8string(source));
- }
-
- std::wstring in_progress;
- in_progress.reserve(native.size());
- if (last - first >= 3 && is_slash(first[0]) && is_slash(first[1]) && !is_slash(first[2]))
- {
- // path with UNC prefix \\server\share; this will be rejected by FindFirstFile so we skip over that
- in_progress.push_back(L'\\');
- in_progress.push_back(L'\\');
- first += 2;
- auto next_slash = std::find_if(first, last, is_slash);
- in_progress.append(first, next_slash);
- in_progress.push_back(L'\\');
- first = std::find_if_not(next_slash, last, is_slash);
- next_slash = std::find_if(first, last, is_slash);
- in_progress.append(first, next_slash);
- first = std::find_if_not(next_slash, last, is_slash);
- if (first != next_slash)
- {
- in_progress.push_back(L'\\');
- }
- }
- else if (last - first >= 1 && is_slash(first[0]))
- {
- // root relative path
- in_progress.push_back(L'\\');
- first = std::find_if_not(first, last, is_slash);
- }
- else if (starts_with_drive_letter(first, last))
- {
- // path with drive letter root
- auto letter = first[0];
- if (letter >= L'a' && letter <= L'z')
- {
- letter = letter - L'a' + L'A';
- }
-
- in_progress.push_back(letter);
- in_progress.push_back(L':');
- first += 2;
- if (first != last && is_slash(*first))
- {
- // absolute path
- in_progress.push_back(L'\\');
- first = std::find_if_not(first, last, is_slash);
- }
- }
-
- assert(!fs::path(first, last).has_root_path());
-
- while (first != last)
- {
- auto next_slash = std::find_if(first, last, is_slash);
- auto original_size = in_progress.size();
- in_progress.append(first, next_slash);
- FindFirstOp this_find;
- unsigned long last_error = this_find.find_first(in_progress.c_str());
- if (last_error == ERROR_SUCCESS)
- {
- in_progress.resize(original_size);
- in_progress.append(this_find.find_data.cFileName);
- }
- else
- {
- // we might not have access to this intermediate part of the path;
- // just guess that the case of that element is correct and move on
- }
-
- first = std::find_if_not(next_slash, last, is_slash);
- if (first != next_slash)
- {
- in_progress.push_back(L'\\');
- }
- }
-
- return fs::path(std::move(in_progress));
- }
-#endif // _WIN32
-
-}
diff --git a/toolsrc/src/vcpkg/base/hash.cpp b/toolsrc/src/vcpkg/base/hash.cpp
deleted file mode 100644
index 825489d6d..000000000
--- a/toolsrc/src/vcpkg/base/hash.cpp
+++ /dev/null
@@ -1,703 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/uint128.h>
-#include <vcpkg/base/util.h>
-
-#if defined(_WIN32)
-#include <bcrypt.h>
-#pragma comment(lib, "bcrypt")
-
-#ifndef NT_SUCCESS
-#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
-#endif
-
-#endif
-
-namespace vcpkg::Hash
-{
- using uchar = unsigned char;
-
- Optional<Algorithm> algorithm_from_string(StringView sv) noexcept
- {
- if (Strings::case_insensitive_ascii_equals(sv, "SHA1"))
- {
- return {Algorithm::Sha1};
- }
- if (Strings::case_insensitive_ascii_equals(sv, "SHA256"))
- {
- return {Algorithm::Sha256};
- }
- if (Strings::case_insensitive_ascii_equals(sv, "SHA512"))
- {
- return {Algorithm::Sha512};
- }
-
- return {};
- }
-
- const char* to_string(Algorithm algo) noexcept
- {
- switch (algo)
- {
- case Algorithm::Sha1: return "SHA1";
- case Algorithm::Sha256: return "SHA256";
- case Algorithm::Sha512: return "SHA512";
- default: vcpkg::Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- template<class UIntTy>
- auto top_bits(UIntTy x) -> std::enable_if_t<std::is_unsigned<UIntTy>::value, uchar>
- {
- return static_cast<uchar>(x >> ((sizeof(x) - 1) * 8));
- }
- template<class UIntTy>
- auto top_bits(UIntTy x) -> decltype(top_bits(x.top_64_bits()))
- {
- return top_bits(x.top_64_bits());
- }
-
- // treats UIntTy as big endian for the purpose of this mapping
- template<class UIntTy>
- static std::string to_hex(const UIntTy* start, const UIntTy* end) noexcept
- {
- static constexpr char HEX_MAP[] = "0123456789abcdef";
-
- std::string output;
- output.resize(2 * sizeof(UIntTy) * (end - start));
-
- std::size_t output_index = 0;
- for (const UIntTy* it = start; it != end; ++it)
- {
- // holds *it in a big-endian buffer, for copying into output
- uchar buff[sizeof(UIntTy)];
- UIntTy tmp = *it;
- for (uchar& ch : buff)
- {
- ch = top_bits(tmp);
- tmp = UIntTy(tmp << 8);
- }
-
- for (const auto byte : buff)
- {
- // high
- output[output_index] = HEX_MAP[(byte & 0xF0) >> 4];
- ++output_index;
- // low
- output[output_index] = HEX_MAP[byte & 0x0F];
- ++output_index;
- }
- }
-
- return output;
- }
-
- namespace
- {
-#if defined(_WIN32)
- BCRYPT_ALG_HANDLE get_alg_handle(LPCWSTR algorithm_identifier) noexcept
- {
- BCRYPT_ALG_HANDLE result;
- auto error = BCryptOpenAlgorithmProvider(&result, algorithm_identifier, nullptr, 0);
- if (!NT_SUCCESS(error))
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "Failure to open algorithm: %ls", algorithm_identifier);
- }
-
- return result;
- }
-
- struct BCryptHasher : Hasher
- {
- static const BCRYPT_ALG_HANDLE sha1_alg_handle;
- static const BCRYPT_ALG_HANDLE sha256_alg_handle;
- static const BCRYPT_ALG_HANDLE sha512_alg_handle;
-
- explicit BCryptHasher(Algorithm algo) noexcept
- {
- switch (algo)
- {
- case Algorithm::Sha1: alg_handle = sha1_alg_handle; break;
- case Algorithm::Sha256: alg_handle = sha256_alg_handle; break;
- case Algorithm::Sha512: alg_handle = sha512_alg_handle; break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- clear();
- }
-
- virtual void add_bytes(const void* start_, const void* end_) noexcept override
- {
- // BCryptHashData takes its input as non-const, but does not modify it
- uchar* start = const_cast<uchar*>(static_cast<const uchar*>(start_));
- const uchar* end = static_cast<const uchar*>(end_);
- Checks::check_exit(VCPKG_LINE_INFO, end - start >= 0);
-
- // only matters on 64-bit -- BCryptHasher takes an unsigned long
- // length, so if you have an array bigger than 2**32-1 elements,
- // you have a problem.
-#if defined(_M_AMD64) || defined(_M_ARM64)
- constexpr std::ptrdiff_t max = std::numeric_limits<unsigned long>::max();
- Checks::check_exit(VCPKG_LINE_INFO, end - start <= max);
-#endif
-
- const auto length = static_cast<unsigned long>(end - start);
- const NTSTATUS error_code = BCryptHashData(hash_handle, start, length, 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to process a chunk");
- }
-
- virtual void clear() noexcept override
- {
- if (hash_handle) BCryptDestroyHash(hash_handle);
- const NTSTATUS error_code = BCryptCreateHash(alg_handle, &hash_handle, nullptr, 0, nullptr, 0, 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher");
- }
-
- virtual std::string get_hash() noexcept override
- {
- const auto hash_size = get_hash_buffer_size();
- const auto buffer = std::make_unique<uchar[]>(hash_size);
- const auto hash = buffer.get();
-
- const NTSTATUS error_code = BCryptFinishHash(hash_handle, hash, hash_size, 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash");
- return to_hex(hash, hash + hash_size);
- }
-
- ~BCryptHasher() { BCryptDestroyHash(hash_handle); }
-
- private:
- unsigned long get_hash_buffer_size() const
- {
- unsigned long hash_buffer_bytes;
- unsigned long cb_data;
- const NTSTATUS error_code = BCryptGetProperty(alg_handle,
- BCRYPT_HASH_LENGTH,
- reinterpret_cast<uchar*>(&hash_buffer_bytes),
- sizeof(hash_buffer_bytes),
- &cb_data,
- 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length");
-
- return hash_buffer_bytes;
- }
-
- BCRYPT_HASH_HANDLE hash_handle = nullptr;
- BCRYPT_ALG_HANDLE alg_handle = nullptr;
- };
-
- const BCRYPT_ALG_HANDLE BCryptHasher::sha1_alg_handle = get_alg_handle(BCRYPT_SHA1_ALGORITHM);
- const BCRYPT_ALG_HANDLE BCryptHasher::sha256_alg_handle = get_alg_handle(BCRYPT_SHA256_ALGORITHM);
- const BCRYPT_ALG_HANDLE BCryptHasher::sha512_alg_handle = get_alg_handle(BCRYPT_SHA512_ALGORITHM);
-#else
-
- template<class WordTy>
- static WordTy shl(WordTy value, int by) noexcept
- {
- return value << by;
- }
-
- static std::uint32_t shr32(std::uint32_t value, int by) noexcept { return value >> by; }
- static std::uint32_t rol32(std::uint32_t value, int by) noexcept
- {
- return (value << by) | (value >> (32 - by));
- }
- static std::uint32_t ror32(std::uint32_t value, int by) noexcept
- {
- return (value >> by) | (value << (32 - by));
- }
-
- static std::uint64_t shr64(std::uint64_t value, int by) noexcept { return value >> by; }
- static std::uint64_t ror64(std::uint64_t value, int by) noexcept
- {
- return (value >> by) | (value << (64 - by));
- }
-
- template<class ShaAlgorithm>
- struct ShaHasher final : Hasher
- {
- ShaHasher() = default;
-
- virtual void add_bytes(const void* start, const void* end) noexcept override
- {
- for (;;)
- {
- start = add_to_unprocessed(start, end);
- if (!start)
- {
- break; // done
- }
-
- m_impl.process_full_chunk(m_chunk);
- m_current_chunk_size = 0;
- }
- }
-
- virtual void clear() noexcept override
- {
- m_impl.clear();
-
- // m_chunk is theoretically uninitialized, so no need to reset it
- m_current_chunk_size = 0;
- m_message_length = 0;
- }
-
- virtual std::string get_hash() noexcept override
- {
- process_last_chunk();
- return to_hex(m_impl.begin(), m_impl.end());
- }
-
- private:
- // if unprocessed gets filled,
- // returns a pointer to the remainder of the block (which might be end)
- // else, returns nullptr
- const void* add_to_unprocessed(const void* start_, const void* end_) noexcept
- {
- const uchar* start = static_cast<const uchar*>(start_);
- const uchar* end = static_cast<const uchar*>(end_);
-
- const auto remaining = chunk_size - m_current_chunk_size;
-
- const std::size_t message_length = end - start;
- if (message_length >= remaining)
- {
- std::copy(start, start + remaining, chunk_begin());
- m_current_chunk_size += remaining;
- m_message_length += remaining * 8;
- return start + remaining;
- }
- else
- {
- std::copy(start, end, chunk_begin());
- m_current_chunk_size += message_length;
- m_message_length += message_length * 8;
- return nullptr;
- }
- }
-
- // called before `get_hash`
- void process_last_chunk() noexcept
- {
- const auto message_length = m_message_length;
-
- // append the bit '1' to the message
- {
- const uchar temp = 0x80;
- add_to_unprocessed(&temp, &temp + 1);
- }
-
- // append 0 to the message so that the resulting length is just enough
- // to add the message length
- if (chunk_size - m_current_chunk_size < sizeof(m_message_length))
- {
- // not enough space to add the message length
- // just resize and process full chunk
- std::fill(chunk_begin(), m_chunk.end(), static_cast<uchar>(0));
- m_impl.process_full_chunk(m_chunk);
- m_current_chunk_size = 0;
- }
-
- const auto before_length = m_chunk.end() - sizeof(m_message_length);
- std::fill(chunk_begin(), before_length, static_cast<uchar>(0));
- std::generate(before_length, m_chunk.end(), [length = message_length]() mutable {
- const auto result = top_bits(length);
- length <<= 8;
- return result;
- });
-
- m_impl.process_full_chunk(m_chunk);
- }
-
- auto chunk_begin() { return m_chunk.begin() + m_current_chunk_size; }
-
- using underlying_type = typename ShaAlgorithm::underlying_type;
- using message_length_type = typename ShaAlgorithm::message_length_type;
- constexpr static std::size_t chunk_size = ShaAlgorithm::chunk_size;
-
- ShaAlgorithm m_impl{};
-
- std::array<uchar, chunk_size> m_chunk{};
- std::size_t m_current_chunk_size = 0;
- message_length_type m_message_length = 0;
- };
- template<class WordTy>
- inline void sha_fill_initial_words(const uchar* chunk, WordTy* words)
- {
- // break chunk into 16 N-bit words
- for (std::size_t word = 0; word < 16; ++word)
- {
- words[word] = 0;
- // big-endian -- so the earliest i becomes the most significant
- for (std::size_t byte = 0; byte < sizeof(WordTy); ++byte)
- {
- const auto bits_to_shift = static_cast<int>(8 * (sizeof(WordTy) - 1 - byte));
- words[word] |= shl<WordTy>(chunk[word * sizeof(WordTy) + byte], bits_to_shift);
- }
- }
- }
-
- struct Sha1Algorithm
- {
- using underlying_type = std::uint32_t;
- using message_length_type = std::uint64_t;
- constexpr static std::size_t chunk_size = 64; // = 512 / 8
- constexpr static std::size_t number_of_rounds = 80;
-
- Sha1Algorithm() noexcept { clear(); }
-
- void process_full_chunk(const std::array<uchar, chunk_size>& chunk) noexcept
- {
- std::uint32_t words[80];
-
- sha_fill_initial_words(&chunk[0], words);
- for (std::size_t i = 16; i < number_of_rounds; ++i)
- {
- const auto sum = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
- words[i] = rol32(sum, 1);
- }
-
- std::uint32_t a = m_digest[0];
- std::uint32_t b = m_digest[1];
- std::uint32_t c = m_digest[2];
- std::uint32_t d = m_digest[3];
- std::uint32_t e = m_digest[4];
-
- for (std::size_t i = 0; i < number_of_rounds; ++i)
- {
- std::uint32_t f;
- std::uint32_t k;
-
- if (i < 20)
- {
- f = (b & c) | (~b & d);
- k = 0x5A827999;
- }
- else if (i < 40)
- {
- f = b ^ c ^ d;
- k = 0x6ED9EBA1;
- }
- else if (i < 60)
- {
- f = (b & c) | (b & d) | (c & d);
- k = 0x8F1BBCDC;
- }
- else
- {
- f = b ^ c ^ d;
- k = 0xCA62C1D6;
- }
-
- auto tmp = rol32(a, 5) + f + e + k + words[i];
- e = d;
- d = c;
- c = rol32(b, 30);
- b = a;
- a = tmp;
- }
-
- m_digest[0] += a;
- m_digest[1] += b;
- m_digest[2] += c;
- m_digest[3] += d;
- m_digest[4] += e;
- }
-
- void clear() noexcept
- {
- m_digest[0] = 0x67452301;
- m_digest[1] = 0xEFCDAB89;
- m_digest[2] = 0x98BADCFE;
- m_digest[3] = 0x10325476;
- m_digest[4] = 0xC3D2E1F0;
- }
-
- const std::uint32_t* begin() const noexcept { return &m_digest[0]; }
- const std::uint32_t* end() const noexcept { return &m_digest[5]; }
-
- std::uint32_t m_digest[5];
- };
-
- struct Sha256Algorithm
- {
- using underlying_type = std::uint32_t;
- using message_length_type = std::uint64_t;
- constexpr static std::size_t chunk_size = 64;
-
- constexpr static std::size_t number_of_rounds = 64;
-
- Sha256Algorithm() noexcept { clear(); }
-
- void process_full_chunk(const std::array<uchar, chunk_size>& chunk) noexcept
- {
- std::uint32_t words[64];
-
- sha_fill_initial_words(&chunk[0], words);
-
- for (std::size_t i = 16; i < number_of_rounds; ++i)
- {
- const auto w0 = words[i - 15];
- const auto s0 = ror32(w0, 7) ^ ror32(w0, 18) ^ shr32(w0, 3);
- const auto w1 = words[i - 2];
- const auto s1 = ror32(w1, 17) ^ ror32(w1, 19) ^ shr32(w1, 10);
- words[i] = words[i - 16] + s0 + words[i - 7] + s1;
- }
-
- std::uint32_t local[8];
- std::copy(begin(), end(), std::begin(local));
-
- for (std::size_t i = 0; i < number_of_rounds; ++i)
- {
- const auto a = local[0];
- const auto b = local[1];
- const auto c = local[2];
-
- const auto s0 = ror32(a, 2) ^ ror32(a, 13) ^ ror32(a, 22);
- const auto maj = (a & b) ^ (a & c) ^ (b & c);
- const auto tmp1 = s0 + maj;
-
- const auto e = local[4];
-
- const auto s1 = ror32(e, 6) ^ ror32(e, 11) ^ ror32(e, 25);
- const auto ch = (e & local[5]) ^ (~e & local[6]);
- const auto tmp2 = local[7] + s1 + ch + round_constants[i] + words[i];
-
- for (std::size_t j = 7; j > 0; --j)
- {
- local[j] = local[j - 1];
- }
- local[4] += tmp2;
- local[0] = tmp1 + tmp2;
- }
-
- for (std::size_t i = 0; i < 8; ++i)
- {
- m_digest[i] += local[i];
- }
- }
-
- void clear() noexcept
- {
- m_digest[0] = 0x6a09e667;
- m_digest[1] = 0xbb67ae85;
- m_digest[2] = 0x3c6ef372;
- m_digest[3] = 0xa54ff53a;
- m_digest[4] = 0x510e527f;
- m_digest[5] = 0x9b05688c;
- m_digest[6] = 0x1f83d9ab;
- m_digest[7] = 0x5be0cd19;
- }
-
- constexpr static std::array<std::uint32_t, number_of_rounds> round_constants = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
-
- std::uint32_t* begin() noexcept { return &m_digest[0]; }
- std::uint32_t* end() noexcept { return &m_digest[8]; }
-
- std::uint32_t m_digest[8];
- };
-
- struct Sha512Algorithm
- {
- using underlying_type = std::uint64_t;
- using message_length_type = UInt128;
- constexpr static std::size_t chunk_size = 128; // = 1024 / 8
-
- constexpr static std::size_t number_of_rounds = 80;
-
- Sha512Algorithm() noexcept { clear(); }
-
- void process_full_chunk(const std::array<uchar, chunk_size>& chunk) noexcept
- {
- std::uint64_t words[80];
-
- sha_fill_initial_words(&chunk[0], words);
-
- for (std::size_t i = 16; i < number_of_rounds; ++i)
- {
- const auto w0 = words[i - 15];
- const auto s0 = ror64(w0, 1) ^ ror64(w0, 8) ^ shr64(w0, 7);
- const auto w1 = words[i - 2];
- const auto s1 = ror64(w1, 19) ^ ror64(w1, 61) ^ shr64(w1, 6);
- words[i] = words[i - 16] + s0 + words[i - 7] + s1;
- }
-
- std::uint64_t local[8];
- std::copy(begin(), end(), std::begin(local));
-
- for (std::size_t i = 0; i < number_of_rounds; ++i)
- {
- const auto a = local[0];
- const auto b = local[1];
- const auto c = local[2];
-
- const auto s0 = ror64(a, 28) ^ ror64(a, 34) ^ ror64(a, 39);
- const auto maj = (a & b) ^ (a & c) ^ (b & c);
- const auto tmp0 = s0 + maj;
-
- const auto e = local[4];
-
- const auto s1 = ror64(e, 14) ^ ror64(e, 18) ^ ror64(e, 41);
- const auto ch = (e & local[5]) ^ (~e & local[6]);
- const auto tmp1 = local[7] + s1 + ch + round_constants[i] + words[i];
-
- for (std::size_t j = 7; j > 0; --j)
- {
- local[j] = local[j - 1];
- }
- local[4] += tmp1;
- local[0] = tmp0 + tmp1;
- }
-
- for (std::size_t i = 0; i < 8; ++i)
- {
- m_digest[i] += local[i];
- }
- }
-
- void clear() noexcept
- {
- m_digest[0] = 0x6a09e667f3bcc908;
- m_digest[1] = 0xbb67ae8584caa73b;
- m_digest[2] = 0x3c6ef372fe94f82b;
- m_digest[3] = 0xa54ff53a5f1d36f1;
- m_digest[4] = 0x510e527fade682d1;
- m_digest[5] = 0x9b05688c2b3e6c1f;
- m_digest[6] = 0x1f83d9abfb41bd6b;
- m_digest[7] = 0x5be0cd19137e2179;
- }
-
- constexpr static std::array<std::uint64_t, number_of_rounds> round_constants = {
- 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
- 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
- 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
- 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
- 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
- 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
- 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
- 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
- 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
- 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
- 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
- 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
- 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
- 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
- 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
- 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
-
- std::uint64_t* begin() noexcept { return &m_digest[0]; }
- std::uint64_t* end() noexcept { return &m_digest[8]; }
-
- std::uint64_t m_digest[8];
- };
-
- // This is required on older compilers, since it was required in C++14
- constexpr std::array<std::uint32_t, Sha256Algorithm::number_of_rounds> Sha256Algorithm::round_constants;
- constexpr std::array<std::uint64_t, Sha512Algorithm::number_of_rounds> Sha512Algorithm::round_constants;
-#endif
- }
-
- std::unique_ptr<Hasher> get_hasher_for(Algorithm algo) noexcept
- {
-#if defined(_WIN32)
- return std::make_unique<BCryptHasher>(algo);
-#else
- switch (algo)
- {
- case Algorithm::Sha1: return std::make_unique<ShaHasher<Sha1Algorithm>>();
- case Algorithm::Sha256: return std::make_unique<ShaHasher<Sha256Algorithm>>();
- case Algorithm::Sha512: return std::make_unique<ShaHasher<Sha512Algorithm>>();
- default: vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown hashing algorithm: %s", algo);
- }
-#endif
- }
-
- template<class F>
- static std::string do_hash(Algorithm algo, const F& f) noexcept
- {
-#if defined(_WIN32)
- auto hasher = BCryptHasher(algo);
- return f(hasher);
-#else
- switch (algo)
- {
- case Algorithm::Sha1:
- {
- auto hasher = ShaHasher<Sha1Algorithm>();
- return f(hasher);
- }
- case Algorithm::Sha256:
- {
- auto hasher = ShaHasher<Sha256Algorithm>();
- return f(hasher);
- }
- case Algorithm::Sha512:
- {
- auto hasher = ShaHasher<Sha512Algorithm>();
- return f(hasher);
- }
- default: vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown hashing algorithm: %s", algo);
- }
-#endif
- }
-
- std::string get_bytes_hash(const void* first, const void* last, Algorithm algo) noexcept
- {
- return do_hash(algo, [first, last](Hasher& hasher) {
- hasher.add_bytes(first, last);
- return hasher.get_hash();
- });
- }
-
- std::string get_string_hash(StringView sv, Algorithm algo) noexcept
- {
- return get_bytes_hash(sv.data(), sv.data() + sv.size(), algo);
- }
-
- // TODO: use Files::Filesystem to open a file
- std::string get_file_hash(const Files::Filesystem&,
- const fs::path& path,
- Algorithm algo,
- std::error_code& ec) noexcept
- {
- auto file = std::fstream(path.c_str(), std::ios_base::in | std::ios_base::binary);
- if (!file)
- {
- ec.assign(ENOENT, std::system_category());
- return {};
- }
-
- return do_hash(algo, [&file, &ec](Hasher& hasher) {
- constexpr std::size_t buffer_size = 1024 * 32;
- auto buffer = std::make_unique<char[]>(buffer_size);
- for (;;)
- {
- file.read(buffer.get(), buffer_size);
- if (file.eof())
- {
- hasher.add_bytes(buffer.get(), buffer.get() + file.gcount());
- return hasher.get_hash();
- }
- else if (file)
- {
- hasher.add_bytes(buffer.get(), buffer.get() + buffer_size);
- }
- else
- {
- ec = std::io_errc::stream;
- return std::string();
- }
- }
- });
- }
-}
diff --git a/toolsrc/src/vcpkg/base/json.cpp b/toolsrc/src/vcpkg/base/json.cpp
deleted file mode 100644
index c287eae78..000000000
--- a/toolsrc/src/vcpkg/base/json.cpp
+++ /dev/null
@@ -1,1411 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/jsonreader.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/unicode.h>
-
-#include <inttypes.h>
-
-#include <regex>
-
-namespace vcpkg::Json
-{
- using VK = ValueKind;
-
- // struct Value {
- namespace impl
- {
- // TODO: add a value_kind value template once we get rid of VS2015 support
- template<ValueKind Vk>
- using ValueKindConstant = std::integral_constant<ValueKind, Vk>;
-
- struct ValueImpl
- {
- VK tag;
- union
- {
- std::nullptr_t null;
- bool boolean;
- int64_t integer;
- double number;
- std::string string;
- Array array;
- Object object;
- };
-
- ValueImpl(ValueKindConstant<VK::Null> vk, std::nullptr_t) : tag(vk), null() { }
- ValueImpl(ValueKindConstant<VK::Boolean> vk, bool b) : tag(vk), boolean(b) { }
- ValueImpl(ValueKindConstant<VK::Integer> vk, int64_t i) : tag(vk), integer(i) { }
- ValueImpl(ValueKindConstant<VK::Number> vk, double d) : tag(vk), number(d) { }
- ValueImpl(ValueKindConstant<VK::String> vk, std::string&& s) : tag(vk), string(std::move(s)) { }
- ValueImpl(ValueKindConstant<VK::String> vk, const std::string& s) : tag(vk), string(s) { }
- ValueImpl(ValueKindConstant<VK::Array> vk, Array&& arr) : tag(vk), array(std::move(arr)) { }
- ValueImpl(ValueKindConstant<VK::Array> vk, const Array& arr) : tag(vk), array(arr) { }
- ValueImpl(ValueKindConstant<VK::Object> vk, Object&& obj) : tag(vk), object(std::move(obj)) { }
- ValueImpl(ValueKindConstant<VK::Object> vk, const Object& obj) : tag(vk), object(obj) { }
-
- ValueImpl& operator=(ValueImpl&& other) noexcept
- {
- switch (other.tag)
- {
- case VK::Null: return internal_assign(VK::Null, &ValueImpl::null, other);
- case VK::Boolean: return internal_assign(VK::Boolean, &ValueImpl::boolean, other);
- case VK::Integer: return internal_assign(VK::Integer, &ValueImpl::integer, other);
- case VK::Number: return internal_assign(VK::Number, &ValueImpl::number, other);
- case VK::String: return internal_assign(VK::String, &ValueImpl::string, other);
- case VK::Array: return internal_assign(VK::Array, &ValueImpl::array, other);
- case VK::Object: return internal_assign(VK::Object, &ValueImpl::object, other);
- }
- }
-
- ~ValueImpl() { destroy_underlying(); }
-
- private:
- template<class T>
- ValueImpl& internal_assign(ValueKind vk, T ValueImpl::*mp, ValueImpl& other) noexcept
- {
- if (tag == vk)
- {
- this->*mp = std::move(other.*mp);
- }
- else
- {
- destroy_underlying();
- auto* address = &(this->*mp);
- new (address) T(std::move(other.*mp));
- tag = vk;
- }
-
- return *this;
- }
-
- void destroy_underlying() noexcept
- {
- switch (tag)
- {
- case VK::String: string.~basic_string(); break;
- case VK::Array: array.~Array(); break;
- case VK::Object: object.~Object(); break;
- default: break;
- }
- new (&null) std::nullptr_t();
- tag = VK::Null;
- }
- };
- }
-
- using impl::ValueImpl;
- using impl::ValueKindConstant;
-
- VK Value::kind() const noexcept
- {
- if (underlying_)
- {
- return underlying_->tag;
- }
- else
- {
- return VK::Null;
- }
- }
-
- bool Value::is_null() const noexcept { return kind() == VK::Null; }
- bool Value::is_boolean() const noexcept { return kind() == VK::Boolean; }
- bool Value::is_integer() const noexcept { return kind() == VK::Integer; }
- bool Value::is_number() const noexcept
- {
- auto k = kind();
- return k == VK::Integer || k == VK::Number;
- }
- bool Value::is_string() const noexcept { return kind() == VK::String; }
- bool Value::is_array() const noexcept { return kind() == VK::Array; }
- bool Value::is_object() const noexcept { return kind() == VK::Object; }
-
- bool Value::boolean() const noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_boolean());
- return underlying_->boolean;
- }
- int64_t Value::integer() const noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_integer());
- return underlying_->integer;
- }
- double Value::number() const noexcept
- {
- auto k = kind();
- if (k == VK::Number)
- {
- return underlying_->number;
- }
- else
- {
- return static_cast<double>(integer());
- }
- }
- StringView Value::string() const noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_string(), "json value is not string");
- return underlying_->string;
- }
-
- const Array& Value::array() const& noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_array(), "json value is not array");
- return underlying_->array;
- }
- Array& Value::array() & noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_array(), "json value is not array");
- return underlying_->array;
- }
- Array&& Value::array() && noexcept { return std::move(this->array()); }
-
- const Object& Value::object() const& noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_object(), "json value is not object");
- return underlying_->object;
- }
- Object& Value::object() & noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_object(), "json value is not object");
- return underlying_->object;
- }
- Object&& Value::object() && noexcept { return std::move(this->object()); }
-
- Value::Value() noexcept = default;
- Value::Value(Value&&) noexcept = default;
- Value& Value::operator=(Value&&) noexcept = default;
-
- Value::Value(const Value& other)
- {
- switch (other.kind())
- {
- case ValueKind::Null: return; // default construct underlying_
- case ValueKind::Boolean:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Boolean>(), other.underlying_->boolean));
- break;
- case ValueKind::Integer:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Integer>(), other.underlying_->integer));
- break;
- case ValueKind::Number:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Number>(), other.underlying_->number));
- break;
- case ValueKind::String:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::String>(), other.underlying_->string));
- break;
- case ValueKind::Array:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Array>(), other.underlying_->array));
- break;
- case ValueKind::Object:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Object>(), other.underlying_->object));
- break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- Value& Value::operator=(const Value& other)
- {
- switch (other.kind())
- {
- case ValueKind::Null: underlying_.reset(); break;
- case ValueKind::Boolean:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Boolean>(), other.underlying_->boolean));
- break;
- case ValueKind::Integer:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Integer>(), other.underlying_->integer));
- break;
- case ValueKind::Number:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Number>(), other.underlying_->number));
- break;
- case ValueKind::String:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::String>(), other.underlying_->string));
- break;
- case ValueKind::Array:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Array>(), other.underlying_->array));
- break;
- case ValueKind::Object:
- underlying_.reset(new ValueImpl(ValueKindConstant<VK::Object>(), other.underlying_->object));
- break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- return *this;
- }
-
- Value::~Value() = default;
-
- Value Value::null(std::nullptr_t) noexcept { return Value(); }
- Value Value::boolean(bool b) noexcept
- {
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Boolean>(), b);
- return val;
- }
- Value Value::integer(int64_t i) noexcept
- {
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Integer>(), i);
- return val;
- }
- Value Value::number(double d) noexcept
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, isfinite(d));
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Number>(), d);
- return val;
- }
- Value Value::string(std::string s) noexcept
- {
- if (!Unicode::utf8_is_valid_string(s.data(), s.data() + s.size()))
- {
- Debug::print("Invalid string: ", s, '\n');
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid utf8 passed to Value::string(std::string)");
- }
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::String>(), std::move(s));
- return val;
- }
- Value Value::array(Array&& arr) noexcept
- {
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Array>(), std::move(arr));
- return val;
- }
- Value Value::array(const Array& arr) noexcept
- {
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Array>(), arr);
- return val;
- }
- Value Value::object(Object&& obj) noexcept
- {
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Object>(), std::move(obj));
- return val;
- }
- Value Value::object(const Object& obj) noexcept
- {
- Value val;
- val.underlying_ = std::make_unique<ValueImpl>(ValueKindConstant<VK::Object>(), obj);
- return val;
- }
-
- bool operator==(const Value& lhs, const Value& rhs)
- {
- if (lhs.kind() != rhs.kind()) return false;
-
- switch (lhs.kind())
- {
- case ValueKind::Null: return true;
- case ValueKind::Boolean: return lhs.underlying_->boolean == rhs.underlying_->boolean;
- case ValueKind::Integer: return lhs.underlying_->integer == rhs.underlying_->integer;
- case ValueKind::Number: return lhs.underlying_->number == rhs.underlying_->number;
- case ValueKind::String: return lhs.underlying_->string == rhs.underlying_->string;
- case ValueKind::Array: return lhs.underlying_->string == rhs.underlying_->string;
- case ValueKind::Object: return lhs.underlying_->string == rhs.underlying_->string;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- // } struct Value
- // struct Array {
- Value& Array::push_back(Value&& value)
- {
- underlying_.push_back(std::move(value));
- return underlying_.back();
- }
- Object& Array::push_back(Object&& obj) { return push_back(Value::object(std::move(obj))).object(); }
- Array& Array::push_back(Array&& arr) { return push_back(Value::array(std::move(arr))).array(); }
- Value& Array::insert_before(iterator it, Value&& value)
- {
- size_t index = it - underlying_.begin();
- underlying_.insert(it, std::move(value));
- return underlying_[index];
- }
- Object& Array::insert_before(iterator it, Object&& obj)
- {
- return insert_before(it, Value::object(std::move(obj))).object();
- }
- Array& Array::insert_before(iterator it, Array&& arr)
- {
- return insert_before(it, Value::array(std::move(arr))).array();
- }
- bool operator==(const Array& lhs, const Array& rhs) { return lhs.underlying_ == rhs.underlying_; }
- // } struct Array
- // struct Object {
- Value& Object::insert(std::string key, Value&& value)
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, !contains(key));
- underlying_.push_back({std::move(key), std::move(value)});
- return underlying_.back().second;
- }
- Value& Object::insert(std::string key, const Value& value)
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, !contains(key));
- underlying_.push_back({std::move(key), value});
- return underlying_.back().second;
- }
- Array& Object::insert(std::string key, Array&& value)
- {
- return insert(std::move(key), Value::array(std::move(value))).array();
- }
- Array& Object::insert(std::string key, const Array& value)
- {
- return insert(std::move(key), Value::array(value)).array();
- }
- Object& Object::insert(std::string key, Object&& value)
- {
- return insert(std::move(key), Value::object(std::move(value))).object();
- }
- Object& Object::insert(std::string key, const Object& value)
- {
- return insert(std::move(key), Value::object(value)).object();
- }
-
- Value& Object::insert_or_replace(std::string key, Value&& value)
- {
- auto v = get(key);
- if (v)
- {
- *v = std::move(value);
- return *v;
- }
- else
- {
- underlying_.push_back({std::move(key), std::move(value)});
- return underlying_.back().second;
- }
- }
- Value& Object::insert_or_replace(std::string key, const Value& value)
- {
- auto v = get(key);
- if (v)
- {
- *v = value;
- return *v;
- }
- else
- {
- underlying_.push_back({std::move(key), std::move(value)});
- return underlying_.back().second;
- }
- }
- Array& Object::insert_or_replace(std::string key, Array&& value)
- {
- return insert_or_replace(std::move(key), Value::array(std::move(value))).array();
- }
- Array& Object::insert_or_replace(std::string key, const Array& value)
- {
- return insert_or_replace(std::move(key), Value::array(value)).array();
- }
- Object& Object::insert_or_replace(std::string key, Object&& value)
- {
- return insert_or_replace(std::move(key), Value::object(std::move(value))).object();
- }
- Object& Object::insert_or_replace(std::string key, const Object& value)
- {
- return insert_or_replace(std::move(key), Value::object(value)).object();
- }
-
- auto Object::internal_find_key(StringView key) const noexcept -> underlying_t::const_iterator
- {
- return std::find_if(
- underlying_.begin(), underlying_.end(), [key](const auto& pair) { return pair.first == key; });
- }
-
- // returns whether the key existed
- bool Object::remove(StringView key) noexcept
- {
- auto it = internal_find_key(key);
- if (it == underlying_.end())
- {
- return false;
- }
- else
- {
- underlying_.erase(it);
- return true;
- }
- }
-
- Value* Object::get(StringView key) noexcept
- {
- auto it = internal_find_key(key);
- if (it == underlying_.end())
- {
- return nullptr;
- }
- else
- {
- return &underlying_[it - underlying_.begin()].second;
- }
- }
- const Value* Object::get(StringView key) const noexcept
- {
- auto it = internal_find_key(key);
- if (it == underlying_.end())
- {
- return nullptr;
- }
- else
- {
- return &it->second;
- }
- }
-
- void Object::sort_keys()
- {
- std::sort(underlying_.begin(), underlying_.end(), [](const value_type& lhs, const value_type& rhs) {
- return lhs.first < rhs.first;
- });
- }
-
- bool operator==(const Object& lhs, const Object& rhs) { return lhs.underlying_ == rhs.underlying_; }
- // } struct Object
-
- // auto parse() {
- namespace
- {
- struct Parser : private Parse::ParserBase
- {
- Parser(StringView text, StringView origin) : Parse::ParserBase(text, origin), style_() { }
-
- char32_t next() noexcept
- {
- auto ch = cur();
- if (ch == '\r') style_.newline_kind = JsonStyle::Newline::CrLf;
- if (ch == '\t') style_.set_tabs();
- return Parse::ParserBase::next();
- }
-
- static constexpr bool is_digit(char32_t code_point) noexcept
- {
- return code_point >= '0' && code_point <= '9';
- }
- static constexpr bool is_hex_digit(char32_t code_point) noexcept
- {
- return is_digit(code_point) || (code_point >= 'a' && code_point <= 'f') ||
- (code_point >= 'A' && code_point <= 'F');
- }
- static bool is_number_start(char32_t code_point) noexcept
- {
- return code_point == '-' || is_digit(code_point);
- }
-
- static unsigned char from_hex_digit(char32_t code_point) noexcept
- {
- if (is_digit(code_point))
- {
- return static_cast<unsigned char>(code_point) - '0';
- }
- else if (code_point >= 'a' && code_point <= 'f')
- {
- return static_cast<unsigned char>(code_point) - 'a' + 10;
- }
- else if (code_point >= 'A' && code_point <= 'F')
- {
- return static_cast<unsigned char>(code_point) - 'A' + 10;
- }
- else
- {
- vcpkg::Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- // parses a _single_ code point of a string -- either a literal code point, or an escape sequence
- // returns end_of_file if it reaches an unescaped '"'
- // _does not_ pair escaped surrogates -- returns the literal surrogate.
- char32_t parse_string_code_point() noexcept
- {
- char32_t current = cur();
- if (current == '"')
- {
- next();
- return Unicode::end_of_file;
- }
- else if (current <= 0x001F)
- {
- add_error("Control character in string");
- next();
- return Unicode::end_of_file;
- }
- else if (current != '\\')
- {
- next();
- return current;
- }
-
- // cur == '\\'
- if (at_eof())
- {
- add_error("Unexpected EOF after escape character");
- return Unicode::end_of_file;
- }
- current = next();
-
- switch (current)
- {
- case '"': next(); return '"';
- case '\\': next(); return '\\';
- case '/': next(); return '/';
- case 'b': next(); return '\b';
- case 'f': next(); return '\f';
- case 'n': next(); return '\n';
- case 'r': next(); return '\r';
- case 't': next(); return '\t';
- case 'u':
- {
- char16_t code_unit = 0;
- for (int i = 0; i < 4; ++i)
- {
- current = next();
-
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected end of file in middle of unicode escape");
- return Unicode::end_of_file;
- }
- if (is_hex_digit(current))
- {
- code_unit *= 16;
- code_unit += from_hex_digit(current);
- }
- else
- {
- add_error("Invalid hex digit in unicode escape");
- return Unicode::end_of_file;
- }
- }
- next();
-
- return code_unit;
- }
- default: add_error("Unexpected escape sequence continuation"); return Unicode::end_of_file;
- }
- }
-
- std::string parse_string() noexcept
- {
- Checks::check_exit(VCPKG_LINE_INFO, cur() == '"');
- next();
-
- std::string res;
- char32_t previous_leading_surrogate = Unicode::end_of_file;
- while (!at_eof())
- {
- auto code_point = parse_string_code_point();
-
- if (previous_leading_surrogate != Unicode::end_of_file)
- {
- if (Unicode::utf16_is_trailing_surrogate_code_point(code_point))
- {
- const auto full_code_point =
- Unicode::utf16_surrogates_to_code_point(previous_leading_surrogate, code_point);
- Unicode::utf8_append_code_point(res, full_code_point);
- previous_leading_surrogate = Unicode::end_of_file;
- continue;
- }
- else
- {
- Unicode::utf8_append_code_point(res, previous_leading_surrogate);
- }
- }
- previous_leading_surrogate = Unicode::end_of_file;
-
- if (Unicode::utf16_is_leading_surrogate_code_point(code_point))
- {
- previous_leading_surrogate = code_point;
- }
- else if (code_point == Unicode::end_of_file)
- {
- return res;
- }
- else
- {
- Unicode::utf8_append_code_point(res, code_point);
- }
- }
-
- add_error("Unexpected EOF in middle of string");
- return res;
- }
-
- Value parse_number() noexcept
- {
- Checks::check_exit(VCPKG_LINE_INFO, is_number_start(cur()));
-
- bool floating = false;
- bool negative = false; // negative & 0 -> floating, so keep track of it
- std::string number_to_parse;
-
- char32_t current = cur();
- if (cur() == '-')
- {
- number_to_parse.push_back('-');
- negative = true;
- current = next();
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF after minus sign");
- return Value();
- }
- }
-
- if (current == '0')
- {
- current = next();
- if (current == '.')
- {
- number_to_parse.append("0.");
- floating = true;
- current = next();
- }
- else if (is_digit(current))
- {
- add_error("Unexpected digits after a leading zero");
- return Value();
- }
- else
- {
- if (negative)
- {
- return Value::number(-0.0);
- }
- else
- {
- return Value::integer(0);
- }
- }
- }
-
- while (is_digit(current))
- {
- number_to_parse.push_back(static_cast<char>(current));
- current = next();
- }
- if (!floating && current == '.')
- {
- floating = true;
- number_to_parse.push_back('.');
- current = next();
- if (!is_digit(current))
- {
- add_error("Expected digits after the decimal point");
- return Value();
- }
- while (is_digit(current))
- {
- number_to_parse.push_back(static_cast<char>(current));
- current = next();
- }
- }
-
- if (floating)
- {
- auto opt = Strings::strto<double>(number_to_parse);
- if (auto res = opt.get())
- {
- if (std::abs(*res) < INFINITY)
- {
- return Value::number(*res);
- }
- else
- {
- add_error(Strings::format("Floating point constant too big: %s", number_to_parse));
- }
- }
- else
- {
- add_error(Strings::format("Invalid floating point constant: %s", number_to_parse));
- }
- }
- else
- {
- auto opt = Strings::strto<int64_t>(number_to_parse);
- if (auto res = opt.get())
- {
- return Value::integer(*res);
- }
- else
- {
- add_error(Strings::format("Invalid integer constant: %s", number_to_parse));
- }
- }
-
- return Value();
- }
-
- Value parse_keyword() noexcept
- {
- char32_t current = cur();
- const char32_t* rest;
- Value val;
- switch (current)
- {
- case 't': // parse true
- rest = U"rue";
- val = Value::boolean(true);
- break;
- case 'f': // parse false
- rest = U"alse";
- val = Value::boolean(false);
- break;
- case 'n': // parse null
- rest = U"ull";
- val = Value::null(nullptr);
- break;
- default: vcpkg::Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- for (const char32_t* rest_it = rest; *rest_it != '\0'; ++rest_it)
- {
- current = next();
-
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF in middle of keyword");
- return Value();
- }
- if (current != *rest_it)
- {
- add_error("Unexpected character in middle of keyword");
- }
- }
- next();
-
- return val;
- }
-
- Value parse_array() noexcept
- {
- Checks::check_exit(VCPKG_LINE_INFO, cur() == '[');
- next();
-
- Array arr;
- bool first = true;
- for (;;)
- {
- skip_whitespace();
-
- char32_t current = cur();
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF in middle of array");
- return Value();
- }
- if (current == ']')
- {
- next();
- return Value::array(std::move(arr));
- }
-
- if (first)
- {
- first = false;
- }
- else if (current == ',')
- {
- auto comma_loc = cur_loc();
- next();
- skip_whitespace();
- current = cur();
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF in middle of array");
- return Value();
- }
- if (current == ']')
- {
- add_error("Trailing comma in array", comma_loc);
- return Value::array(std::move(arr));
- }
- }
- else
- {
- add_error("Unexpected character in middle of array");
- return Value();
- }
-
- arr.push_back(parse_value());
- }
- }
-
- std::pair<std::string, Value> parse_kv_pair() noexcept
- {
- skip_whitespace();
-
- auto current = cur();
-
- std::pair<std::string, Value> res = {std::string(""), Value()};
-
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF; expected property name");
- return res;
- }
- if (current != '"')
- {
- add_error("Unexpected character; expected property name");
- return res;
- }
- res.first = parse_string();
-
- skip_whitespace();
- current = cur();
- if (current == ':')
- {
- next();
- }
- else if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF; expected colon");
- return res;
- }
- else
- {
- add_error("Unexpected character; expected colon");
- return res;
- }
-
- res.second = parse_value();
-
- return res;
- }
-
- Value parse_object() noexcept
- {
- char32_t current = cur();
-
- Checks::check_exit(VCPKG_LINE_INFO, current == '{');
- next();
-
- Object obj;
- bool first = true;
- for (;;)
- {
- skip_whitespace();
- current = cur();
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF; expected property or close brace");
- return Value();
- }
- else if (current == '}')
- {
- next();
- return Value::object(std::move(obj));
- }
-
- if (first)
- {
- first = false;
- }
- else if (current == ',')
- {
- auto comma_loc = cur_loc();
- next();
- skip_whitespace();
- current = cur();
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF; expected property");
- return Value();
- }
- else if (current == '}')
- {
- add_error("Trailing comma in an object", comma_loc);
- return Value();
- }
- }
- else
- {
- add_error("Unexpected character; expected comma or close brace");
- }
-
- auto val = parse_kv_pair();
- obj.insert(std::move(val.first), std::move(val.second));
- }
- }
-
- Value parse_value() noexcept
- {
- skip_whitespace();
- char32_t current = cur();
- if (current == Unicode::end_of_file)
- {
- add_error("Unexpected EOF; expected value");
- return Value();
- }
-
- switch (current)
- {
- case '{': return parse_object();
- case '[': return parse_array();
- case '"': return Value::string(parse_string());
- case 'n':
- case 't':
- case 'f': return parse_keyword();
- default:
- if (is_number_start(current))
- {
- return parse_number();
- }
- else
- {
- add_error("Unexpected character; expected value");
- return Value();
- }
- }
- }
-
- static ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<Parse::IParseError>> parse(
- StringView json, StringView origin) noexcept
- {
- auto parser = Parser(json, origin);
-
- auto val = parser.parse_value();
-
- parser.skip_whitespace();
- if (!parser.at_eof())
- {
- parser.add_error("Unexpected character; expected EOF");
- return std::move(parser).extract_error();
- }
- else if (parser.get_error())
- {
- return std::move(parser).extract_error();
- }
- else
- {
- return std::make_pair(std::move(val), parser.style());
- }
- }
-
- JsonStyle style() const noexcept { return style_; }
-
- private:
- JsonStyle style_;
- };
- }
-
- NaturalNumberDeserializer NaturalNumberDeserializer::instance;
- BooleanDeserializer BooleanDeserializer::instance;
- ParagraphDeserializer ParagraphDeserializer::instance;
- IdentifierDeserializer IdentifierDeserializer::instance;
- IdentifierArrayDeserializer IdentifierArrayDeserializer::instance;
- PackageNameDeserializer PackageNameDeserializer::instance;
- PathDeserializer PathDeserializer::instance;
-
- bool IdentifierDeserializer::is_ident(StringView sv)
- {
- static const std::regex BASIC_IDENTIFIER = std::regex(R"([a-z0-9]+(-[a-z0-9]+)*)");
-
- // we only check for lowercase in RESERVED since we already remove all
- // strings with uppercase letters from the basic check
- static const std::regex RESERVED = std::regex(R"(prn|aux|nul|con|(lpt|com)[1-9]|core|default)");
-
- // back-compat
- if (sv == "all_modules")
- {
- return true;
- }
-
- if (!std::regex_match(sv.begin(), sv.end(), BASIC_IDENTIFIER))
- {
- return false; // we're not even in the shape of an identifier
- }
-
- if (std::regex_match(sv.begin(), sv.end(), RESERVED))
- {
- return false; // we're a reserved identifier
- }
-
- return true;
- }
-
- ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<Parse::IParseError>> parse_file(const Files::Filesystem& fs,
- const fs::path& path,
- std::error_code& ec) noexcept
- {
- auto res = fs.read_contents(path);
- if (auto buf = res.get())
- {
- return parse(*buf, path);
- }
- else
- {
- ec = res.error();
- return std::unique_ptr<Parse::IParseError>();
- }
- }
-
- std::pair<Value, JsonStyle> parse_file(vcpkg::LineInfo linfo,
- const Files::Filesystem& fs,
- const fs::path& path) noexcept
- {
- std::error_code ec;
- auto ret = parse_file(fs, path, ec);
- if (ec)
- {
- System::print2(System::Color::error, "Failed to read ", fs::u8string(path), ": ", ec.message(), "\n");
- Checks::exit_fail(linfo);
- }
- else if (!ret)
- {
- System::print2(System::Color::error, "Failed to parse ", fs::u8string(path), ":\n");
- System::print2(ret.error()->format());
- Checks::exit_fail(linfo);
- }
- return ret.value_or_exit(linfo);
- }
-
- ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<Parse::IParseError>> parse(StringView json,
- const fs::path& filepath) noexcept
- {
- return Parser::parse(json, fs::u8string(filepath));
- }
- ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<Parse::IParseError>> parse(StringView json,
- StringView origin) noexcept
- {
- return Parser::parse(json, origin);
- }
- // } auto parse()
-
- namespace
- {
- struct Stringifier
- {
- JsonStyle style;
- std::string& buffer;
-
- void append_indent(int indent)
- {
- if (style.use_tabs())
- {
- buffer.append(indent, '\t');
- }
- else
- {
- buffer.append(indent * style.spaces(), ' ');
- }
- };
-
- void append_unicode_escape(char16_t code_unit)
- {
- buffer.append("\\u");
-
- // AFAIK, there's no standard way of doing this?
- constexpr const char hex_digit[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
- buffer.push_back(hex_digit[(code_unit >> 12) & 0x0F]);
- buffer.push_back(hex_digit[(code_unit >> 8) & 0x0F]);
- buffer.push_back(hex_digit[(code_unit >> 4) & 0x0F]);
- buffer.push_back(hex_digit[(code_unit >> 0) & 0x0F]);
- }
-
- // taken from the ECMAScript 2020 standard, 24.5.2.2: Runtime Semantics: QuoteJSONString
- void append_quoted_json_string(StringView sv)
- {
- // Table 66: JSON Single Character Escape Sequences
- constexpr static std::array<std::pair<char32_t, const char*>, 7> escape_sequences = {{
- {0x0008, R"(\b)"}, // BACKSPACE
- {0x0009, R"(\t)"}, // CHARACTER TABULATION
- {0x000A, R"(\n)"}, // LINE FEED (LF)
- {0x000C, R"(\f)"}, // FORM FEED (FF)
- {0x000D, R"(\r)"}, // CARRIAGE RETURN (CR)
- {0x0022, R"(\")"}, // QUOTATION MARK
- {0x005C, R"(\\)"} // REVERSE SOLIDUS
- }};
- // 1. Let product be the String value consisting solely of the code unit 0x0022 (QUOTATION MARK).
- buffer.push_back('"');
-
- // 2. For each code point C in ! UTF16DecodeString(value), do
- // (note that we use utf8 instead of utf16)
- for (auto code_point : Unicode::Utf8Decoder(sv.begin(), sv.end()))
- {
- // a. If C is listed in the "Code Point" column of Table 66, then
- const auto match = std::find_if(begin(escape_sequences),
- end(escape_sequences),
- [code_point](const std::pair<char32_t, const char*>& attempt) {
- return attempt.first == code_point;
- });
- // i. Set product to the string-concatenation of product and the escape sequence for C as
- // specified in the "Escape Sequence" column of the corresponding row.
- if (match != end(escape_sequences))
- {
- buffer.append(match->second);
- continue;
- }
-
- // b. Else if C has a numeric value less than 0x0020 (SPACE), or if C has the same numeric value as
- // a leading surrogate or trailing surrogate, then
- if (code_point < 0x0020 || Unicode::utf16_is_surrogate_code_point(code_point))
- {
- // i. Let unit be the code unit whose numeric value is that of C.
- // ii. Set product to the string-concatenation of product and UnicodeEscape(unit).
- append_unicode_escape(static_cast<char16_t>(code_point));
- break;
- }
-
- // c. Else,
- // i. Set product to the string-concatenation of product and the UTF16Encoding of C.
- // (again, we use utf-8 here instead)
- Unicode::utf8_append_code_point(buffer, code_point);
- }
-
- // 3. Set product to the string-concatenation of product and the code unit 0x0022 (QUOTATION MARK).
- buffer.push_back('"');
- }
-
- void stringify_object(const Object& obj, int current_indent)
- {
- buffer.push_back('{');
- if (obj.size() != 0)
- {
- bool first = true;
-
- for (const auto& el : obj)
- {
- if (!first)
- {
- buffer.push_back(',');
- }
- first = false;
-
- buffer.append(style.newline());
- append_indent(current_indent + 1);
-
- append_quoted_json_string(el.first);
- buffer.append(": ");
- stringify(el.second, current_indent + 1);
- }
- buffer.append(style.newline());
- append_indent(current_indent);
- }
- buffer.push_back('}');
- }
-
- void stringify_array(const Array& arr, int current_indent)
- {
- buffer.push_back('[');
- if (arr.size() == 0)
- {
- buffer.push_back(']');
- }
- else
- {
- bool first = true;
-
- for (const auto& el : arr)
- {
- if (!first)
- {
- buffer.push_back(',');
- }
- first = false;
-
- buffer.append(style.newline());
- append_indent(current_indent + 1);
-
- stringify(el, current_indent + 1);
- }
- buffer.append(style.newline());
- append_indent(current_indent);
- buffer.push_back(']');
- }
- }
-
- void stringify(const Value& value, int current_indent)
- {
- switch (value.kind())
- {
- case VK::Null: buffer.append("null"); break;
- case VK::Boolean:
- {
- auto v = value.boolean();
- buffer.append(v ? "true" : "false");
- break;
- }
- // TODO: switch to `to_chars` once we are able to remove support for old compilers
- case VK::Integer: buffer.append(std::to_string(value.integer())); break;
- case VK::Number: buffer.append(std::to_string(value.number())); break;
- case VK::String:
- {
- append_quoted_json_string(value.string());
- break;
- }
- case VK::Array:
- {
- stringify_array(value.array(), current_indent);
- break;
- }
- case VK::Object:
- {
- stringify_object(value.object(), current_indent);
- break;
- }
- }
- }
- };
- }
-
- std::string stringify(const Value& value, JsonStyle style)
- {
- std::string res;
- Stringifier{style, res}.stringify(value, 0);
- res.push_back('\n');
- return res;
- }
- std::string stringify(const Object& obj, JsonStyle style)
- {
- std::string res;
- Stringifier{style, res}.stringify_object(obj, 0);
- res.push_back('\n');
- return res;
- }
- std::string stringify(const Array& arr, JsonStyle style)
- {
- std::string res;
- Stringifier{style, res}.stringify_array(arr, 0);
- res.push_back('\n');
- return res;
- }
- // } auto stringify()
-
- static std::vector<std::string> invalid_json_fields(const Json::Object& obj,
- Span<const StringView> known_fields) noexcept
- {
- const auto field_is_unknown = [known_fields](StringView sv) {
- // allow directives
- if (sv.size() != 0 && *sv.begin() == '$')
- {
- return false;
- }
- return std::find(known_fields.begin(), known_fields.end(), sv) == known_fields.end();
- };
-
- std::vector<std::string> res;
- for (const auto& kv : obj)
- {
- if (field_is_unknown(kv.first))
- {
- res.push_back(kv.first.to_string());
- }
- }
-
- return res;
- }
-
- void Reader::add_missing_field_error(StringView type, StringView key, StringView key_type)
- {
- add_generic_error(type, "missing required field '", key, "' (", key_type, ")");
- }
- void Reader::add_expected_type_error(StringView expected_type)
- {
- m_errors.push_back(Strings::concat(path(), ": mismatched type: expected ", expected_type));
- }
- void Reader::add_extra_field_error(StringView type, StringView field, StringView suggestion)
- {
- if (suggestion.size() > 0)
- {
- add_generic_error(type, "unexpected field '", field, "\', did you mean \'", suggestion, "\'?");
- }
- else
- {
- add_generic_error(type, "unexpected field '", field, '\'');
- }
- }
-
- void Reader::check_for_unexpected_fields(const Object& obj, View<StringView> valid_fields, StringView type_name)
- {
- if (valid_fields.size() == 0)
- {
- return;
- }
-
- auto extra_fields = invalid_json_fields(obj, valid_fields);
- for (auto&& f : extra_fields)
- {
- auto best_it = valid_fields.begin();
- auto best_value = Strings::byte_edit_distance(f, *best_it);
- for (auto i = best_it + 1; i != valid_fields.end(); ++i)
- {
- auto v = Strings::byte_edit_distance(f, *i);
- if (v < best_value)
- {
- best_value = v;
- best_it = i;
- }
- }
- add_extra_field_error(type_name.to_string(), f, *best_it);
- }
- }
-
- std::string Reader::path() const noexcept
- {
- std::string p("$");
- for (auto&& s : m_path)
- {
- if (s.index < 0)
- Strings::append(p, '.', s.field);
- else
- Strings::append(p, '[', s.index, ']');
- }
- return p;
- }
-
- Optional<std::vector<std::string>> ParagraphDeserializer::visit_string(Reader&, StringView sv)
- {
- std::vector<std::string> out;
- out.push_back(sv.to_string());
- return out;
- }
-
- Optional<std::vector<std::string>> ParagraphDeserializer::visit_array(Reader& r, const Array& arr)
- {
- static StringDeserializer d{"a string"};
- return r.array_elements(arr, d);
- }
-
- Optional<std::string> IdentifierDeserializer::visit_string(Json::Reader& r, StringView sv)
- {
- if (!is_ident(sv))
- {
- r.add_generic_error(type_name(), "must be lowercase alphanumeric+hyphens and not reserved");
- }
- return sv.to_string();
- }
-
- Optional<std::vector<std::string>> IdentifierArrayDeserializer::visit_array(Reader& r, const Array& arr)
- {
- return r.array_elements(arr, IdentifierDeserializer::instance);
- }
-
- bool PackageNameDeserializer::is_package_name(StringView sv)
- {
- if (sv.size() == 0)
- {
- return false;
- }
-
- for (const auto& ident : Strings::split(sv, '.'))
- {
- if (!IdentifierDeserializer::is_ident(ident))
- {
- return false;
- }
- }
-
- return true;
- }
-
- Optional<std::string> PackageNameDeserializer::visit_string(Json::Reader&, StringView sv)
- {
- if (!is_package_name(sv))
- {
- return nullopt;
- }
- return sv.to_string();
- }
-}
diff --git a/toolsrc/src/vcpkg/base/machinetype.cpp b/toolsrc/src/vcpkg/base/machinetype.cpp
deleted file mode 100644
index 9b34d4b18..000000000
--- a/toolsrc/src/vcpkg/base/machinetype.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/machinetype.h>
-
-namespace vcpkg
-{
- MachineType to_machine_type(const uint16_t value)
- {
- const MachineType t = static_cast<MachineType>(value);
- switch (t)
- {
- case MachineType::UNKNOWN:
- case MachineType::AM33:
- case MachineType::AMD64:
- case MachineType::ARM:
- case MachineType::ARM64:
- case MachineType::ARMNT:
- case MachineType::EBC:
- case MachineType::I386:
- case MachineType::IA64:
- case MachineType::M32R:
- case MachineType::MIPS16:
- case MachineType::MIPSFPU:
- case MachineType::MIPSFPU16:
- case MachineType::POWERPC:
- case MachineType::POWERPCFP:
- case MachineType::R4000:
- case MachineType::RISCV32:
- case MachineType::RISCV64:
- case MachineType::RISCV128:
- case MachineType::SH3:
- case MachineType::SH3DSP:
- case MachineType::SH4:
- case MachineType::SH5:
- case MachineType::THUMB:
- case MachineType::WCEMIPSV2: return t;
- default: Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Unknown machine type code 0x%hx", value);
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/base/parse.cpp b/toolsrc/src/vcpkg/base/parse.cpp
deleted file mode 100644
index fb1b4c3bf..000000000
--- a/toolsrc/src/vcpkg/base/parse.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <vcpkg/base/parse.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <utility>
-
-using namespace vcpkg;
-
-namespace vcpkg::Parse
-{
- static void advance_rowcol(char32_t ch, int& row, int& column)
- {
- if (ch == '\t')
- column = (column + 7) / 8 * 8 + 1; // round to next 8-width tab stop
- else if (ch == '\n')
- {
- row++;
- column = 1;
- }
- else
- {
- ++column;
- }
- }
-
- std::string ParseError::format() const
- {
- auto caret_spacing = std::string(18, ' ');
- auto decoder = Unicode::Utf8Decoder(line.data(), line.data() + line.size());
- for (int i = 0; i < caret_col; ++i, ++decoder)
- {
- const char32_t cp = *decoder;
- // this may eventually want to check for full-width characters and grapheme clusters as well
- caret_spacing.push_back(cp == '\t' ? '\t' : ' ');
- }
-
- return Strings::concat(origin,
- ":",
- row,
- ":",
- column,
- ": error: ",
- message,
- "\n"
- " on expression: ", // 18 columns
- line,
- "\n",
- caret_spacing,
- "^\n");
- }
-
- const std::string& ParseError::get_message() const { return this->message; }
-
- ParserBase::ParserBase(StringView text, StringView origin, TextRowCol init_rowcol)
- : m_it(text.begin(), text.end())
- , m_start_of_line(m_it)
- , m_row(init_rowcol.row_or(1))
- , m_column(init_rowcol.column_or(1))
- , m_text(text)
- , m_origin(origin)
- {
- }
-
- char32_t ParserBase::next()
- {
- if (m_it == m_it.end())
- {
- return Unicode::end_of_file;
- }
- auto ch = *m_it;
- // See https://www.gnu.org/prep/standards/standards.html#Errors
- advance_rowcol(ch, m_row, m_column);
-
- ++m_it;
- if (ch == '\n')
- {
- m_start_of_line = m_it;
- }
- if (m_it != m_it.end() && Unicode::utf16_is_surrogate_code_point(*m_it))
- {
- m_it = m_it.end();
- }
-
- return cur();
- }
-
- void ParserBase::add_error(std::string message, const SourceLoc& loc)
- {
- // avoid cascading errors by only saving the first
- if (!m_err)
- {
- // find end of line
- auto line_end = loc.it;
- while (line_end != line_end.end() && *line_end != '\n' && *line_end != '\r')
- {
- ++line_end;
- }
- m_err = std::make_unique<ParseError>(
- m_origin.to_string(),
- loc.row,
- loc.column,
- static_cast<int>(std::distance(loc.start_of_line, loc.it)),
- std::string(loc.start_of_line.pointer_to_current(), line_end.pointer_to_current()),
- std::move(message));
- }
-
- // Avoid error loops by skipping to the end
- skip_to_eof();
- }
-}
diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp
deleted file mode 100644
index 89b3b46de..000000000
--- a/toolsrc/src/vcpkg/base/strings.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/util.h>
-
-#include <locale.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <algorithm>
-#include <locale>
-#include <string>
-#include <vector>
-
-namespace vcpkg::Strings::details
-{
- // To disambiguate between two overloads
- static bool is_space(const char c) { return std::isspace(static_cast<unsigned char>(c)) != 0; }
-
- // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower()
- static char toupper_char(const char c) { return (c < 'a' || c > 'z') ? c : c - 'a' + 'A'; }
-
- static bool icase_eq(char a, char b) { return tolower_char{}(a) == tolower_char{}(b); }
-
-#if defined(_WIN32)
- static _locale_t& c_locale()
- {
- static _locale_t c_locale_impl = _create_locale(LC_ALL, "C");
- return c_locale_impl;
- }
-#endif
-
- std::string format_internal(const char* fmtstr, ...)
- {
- va_list args;
- va_start(args, fmtstr);
-
-#if defined(_WIN32)
- const int sz = _vscprintf_l(fmtstr, c_locale(), args);
-#else
- const int sz = vsnprintf(nullptr, 0, fmtstr, args);
-#endif
- Checks::check_exit(VCPKG_LINE_INFO, sz > 0);
-
- std::string output(sz, '\0');
-
-#if defined(_WIN32)
- _vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args);
-#else
- va_start(args, fmtstr);
- vsnprintf(&output.at(0), output.size() + 1, fmtstr, args);
-#endif
- va_end(args);
-
- return output;
- }
-}
-
-using namespace vcpkg;
-
-#if defined(_WIN32)
-std::wstring Strings::to_utf16(StringView s)
-{
- std::wstring output;
- if (s.size() == 0) return output;
- Checks::check_exit(VCPKG_LINE_INFO, s.size() < size_t(INT_MAX));
- int size = MultiByteToWideChar(CP_UTF8, 0, s.data(), static_cast<int>(s.size()), nullptr, 0);
- output.resize(static_cast<size_t>(size));
- MultiByteToWideChar(CP_UTF8, 0, s.data(), static_cast<int>(s.size()), output.data(), size);
- return output;
-}
-#endif
-
-#if defined(_WIN32)
-std::string Strings::to_utf8(const wchar_t* w)
-{
- std::string output;
- const size_t size = WideCharToMultiByte(CP_UTF8, 0, w, -1, nullptr, 0, nullptr, nullptr);
- if (size == 0) return output;
- output.resize(size - 1);
- WideCharToMultiByte(CP_UTF8, 0, w, -1, output.data(), static_cast<int>(size) - 1, nullptr, nullptr);
- return output;
-}
-#endif
-
-std::string Strings::escape_string(std::string&& s, char char_to_escape, char escape_char)
-{
- // Replace '\' with '\\' or '`' with '``'
- auto ret = Strings::replace_all(std::move(s), {&escape_char, 1}, std::string{escape_char, escape_char});
- // Replace '"' with '\"' or '`"'
- ret = Strings::replace_all(std::move(ret), {&char_to_escape, 1}, std::string{escape_char, char_to_escape});
- return ret;
-}
-
-static const char* case_insensitive_ascii_find(StringView s, StringView pattern)
-{
- return std::search(s.begin(), s.end(), pattern.begin(), pattern.end(), &Strings::details::icase_eq);
-}
-
-bool Strings::case_insensitive_ascii_contains(StringView s, StringView pattern)
-{
- return case_insensitive_ascii_find(s, pattern) != s.end();
-}
-
-bool Strings::case_insensitive_ascii_equals(StringView left, StringView right)
-{
- return std::equal(left.begin(), left.end(), right.begin(), right.end(), &details::icase_eq);
-}
-
-std::string Strings::ascii_to_lowercase(std::string&& s)
-{
- Strings::ascii_to_lowercase(s.begin(), s.end());
- return std::move(s);
-}
-
-std::string Strings::ascii_to_uppercase(std::string&& s)
-{
- std::transform(s.begin(), s.end(), s.begin(), &details::toupper_char);
- return std::move(s);
-}
-
-bool Strings::case_insensitive_ascii_starts_with(StringView s, StringView pattern)
-{
- if (s.size() < pattern.size()) return false;
- return std::equal(s.begin(), s.begin() + pattern.size(), pattern.begin(), pattern.end(), &details::icase_eq);
-}
-
-bool Strings::ends_with(StringView s, StringView pattern)
-{
- if (s.size() < pattern.size()) return false;
- return std::equal(s.end() - pattern.size(), s.end(), pattern.begin(), pattern.end());
-}
-bool Strings::starts_with(StringView s, StringView pattern)
-{
- if (s.size() < pattern.size()) return false;
- return std::equal(s.begin(), s.begin() + pattern.size(), pattern.begin(), pattern.end());
-}
-
-std::string Strings::replace_all(std::string&& s, StringView search, StringView rep)
-{
- inplace_replace_all(s, search, rep);
- return std::move(s);
-}
-
-void Strings::inplace_replace_all(std::string& s, StringView search, StringView rep)
-{
- if (search.empty())
- {
- return;
- }
-
- size_t pos = 0;
- while ((pos = s.find(search.data(), pos, search.size())) != std::string::npos)
- {
- s.replace(pos, search.size(), rep.data(), rep.size());
- pos += rep.size();
- }
-}
-
-void Strings::inplace_replace_all(std::string& s, char search, char rep) noexcept
-{
- std::replace(s.begin(), s.end(), search, rep);
-}
-
-std::string Strings::trim(std::string&& s)
-{
- s.erase(std::find_if_not(s.rbegin(), s.rend(), details::is_space).base(), s.end());
- s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::is_space));
- return std::move(s);
-}
-
-StringView Strings::trim(StringView sv)
-{
- auto last = std::find_if_not(sv.rbegin(), sv.rend(), details::is_space).base();
- auto first = std::find_if_not(sv.begin(), sv.end(), details::is_space);
- return StringView(first, last);
-}
-
-void Strings::trim_all_and_remove_whitespace_strings(std::vector<std::string>* strings)
-{
- for (std::string& s : *strings)
- {
- s = trim(std::move(s));
- }
-
- Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); });
-}
-
-std::vector<std::string> Strings::split(StringView s, const char delimiter)
-{
- std::vector<std::string> output;
- auto first = s.begin();
- const auto last = s.end();
- for (;;)
- {
- first = std::find_if(first, last, [=](const char c) { return c != delimiter; });
- if (first == last)
- {
- return output;
- }
-
- auto next = std::find(first, last, delimiter);
- output.emplace_back(first, next);
- first = next;
- }
-}
-
-std::vector<std::string> Strings::split_paths(StringView s)
-{
-#if defined(_WIN32)
- return Strings::split(s, ';');
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- return Strings::split(s, ':');
-#endif
-}
-
-const char* Strings::find_first_of(StringView input, StringView chars)
-{
- return std::find_first_of(input.begin(), input.end(), chars.begin(), chars.end());
-}
-
-std::vector<StringView> Strings::find_all_enclosed(StringView input, StringView left_delim, StringView right_delim)
-{
- auto it_left = input.begin();
- auto it_right = input.begin();
-
- std::vector<StringView> output;
-
- for (;;)
- {
- it_left = std::search(it_right, input.end(), left_delim.begin(), left_delim.end());
- if (it_left == input.end()) break;
-
- it_left += left_delim.size();
-
- it_right = std::search(it_left, input.end(), right_delim.begin(), right_delim.end());
- if (it_right == input.end()) break;
-
- output.emplace_back(it_left, it_right);
-
- ++it_right;
- }
-
- return output;
-}
-
-StringView Strings::find_exactly_one_enclosed(StringView input, StringView left_tag, StringView right_tag)
-{
- std::vector<StringView> result = find_all_enclosed(input, left_tag, right_tag);
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- result.size() == 1,
- "Found %d sets of %s.*%s but expected exactly 1, in block:\n%s",
- result.size(),
- left_tag,
- right_tag,
- input);
- return result.front();
-}
-
-Optional<StringView> Strings::find_at_most_one_enclosed(StringView input, StringView left_tag, StringView right_tag)
-{
- std::vector<StringView> result = find_all_enclosed(input, left_tag, right_tag);
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- result.size() <= 1,
- "Found %d sets of %s.*%s but expected at most 1, in block:\n%s",
- result.size(),
- left_tag,
- right_tag,
- input);
-
- if (result.empty())
- {
- return nullopt;
- }
-
- return result.front();
-}
-
-bool Strings::equals(StringView a, StringView b)
-{
- if (a.size() != b.size()) return false;
- return std::equal(a.begin(), a.end(), b.begin(), b.end());
-}
-
-const char* Strings::search(StringView haystack, StringView needle)
-{
- return std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end());
-}
-
-bool Strings::contains(StringView haystack, StringView needle)
-{
- return Strings::search(haystack, needle) != haystack.end();
-}
-
-size_t Strings::byte_edit_distance(StringView a, StringView b)
-{
- static constexpr size_t max_string_size = 100;
- // For large strings, give up early to avoid performance problems
- if (a.size() > max_string_size || b.size() > max_string_size)
- {
- if (a == b)
- return 0;
- else
- return std::max(a.size(), b.size());
- }
- if (a.size() == 0 || b.size() == 0) return std::max(a.size(), b.size());
-
- auto pa = a.data();
- auto pb = b.data();
- size_t sa = a.size();
- size_t sb = b.size();
-
- // Levenshtein distance (https://en.wikipedia.org/wiki/Levenshtein_distance)
- // The first row of the edit distance matrix has been omitted because it's trivial (counting from 0)
- // Because each subsequent row only depends on the row above, we never need to store the entire matrix
- char d[max_string_size];
-
- // Useful invariants:
- // `sa` is sizeof `pa` using iterator `ia`
- // `sb` is sizeof `pb` using iterator `ib`
- // `sa` and `sb` are in (0, `max_string_size`]
-
- // To avoid dealing with edge effects, `ia` == 0 and `ib` == 0 have been unrolled.
- // Comparisons are used as the cost for the diagonal action (substitute/leave unchanged)
- d[0] = pa[0] != pb[0];
- for (size_t ia = 1; ia < sa; ++ia)
- d[ia] = std::min<char>(d[ia - 1] + 1, static_cast<char>(ia + (pa[ia] != pb[0])));
-
- for (size_t ib = 1; ib < sb; ++ib)
- {
- // The diagonal information (d[ib-1][ia-1]) is used to compute substitution cost and so must be preserved
- char diag = d[0];
- d[0] = std::min<char>(d[0] + 1, static_cast<char>(ib + (pa[0] != pb[ib])));
- for (size_t ia = 1; ia < sa; ++ia)
- {
- auto subst_or_add = std::min<char>(d[ia - 1] + 1, static_cast<char>(diag + (pa[ia] != pb[ib])));
- diag = d[ia];
- d[ia] = std::min<char>(d[ia] + 1, subst_or_add);
- }
- }
- return d[sa - 1];
-}
-
-namespace vcpkg::Strings
-{
- namespace
- {
- template<class Integral>
- std::string b32_encode_implementation(Integral x)
- {
- static_assert(std::is_integral<Integral>::value, "b64url_encode must take an integer type");
- using Unsigned = std::make_unsigned_t<Integral>;
- auto value = static_cast<Unsigned>(x);
-
- // 32 values, plus the implicit \0
- constexpr static char map[33] = "ABCDEFGHIJKLMNOP"
- "QRSTUVWXYZ234567";
-
- // log2(32)
- constexpr static int shift = 5;
- // 32 - 1
- constexpr static auto mask = 31;
-
- // ceiling(bitsize(Integral) / log2(32))
- constexpr static auto result_size = (sizeof(value) * 8 + shift - 1) / shift;
-
- std::string result;
- result.reserve(result_size);
-
- for (std::size_t i = 0; i < result_size; ++i)
- {
- result.push_back(map[value & mask]);
- value >>= shift;
- }
-
- return result;
- }
- }
-
- std::string b32_encode(std::uint64_t x) noexcept { return b32_encode_implementation(x); }
-
-}
diff --git a/toolsrc/src/vcpkg/base/stringview.cpp b/toolsrc/src/vcpkg/base/stringview.cpp
deleted file mode 100644
index fd7f787a1..000000000
--- a/toolsrc/src/vcpkg/base/stringview.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/lineinfo.h>
-#include <vcpkg/base/stringview.h>
-
-#include <algorithm>
-#include <cstring>
-
-namespace vcpkg
-{
- StringView::StringView(const std::string& s) noexcept : m_ptr(s.data()), m_size(s.size()) { }
-
- std::string StringView::to_string() const { return std::string(m_ptr, m_size); }
- void StringView::to_string(std::string& s) const { s.append(m_ptr, m_size); }
-
- StringView StringView::substr(size_t pos, size_t count) const noexcept
- {
- if (pos > m_size)
- {
- return StringView();
- }
-
- if (count > m_size - pos)
- {
- return StringView(m_ptr + pos, m_size - pos);
- }
-
- return StringView(m_ptr + pos, count);
- }
-
- bool operator==(StringView lhs, StringView rhs) noexcept
- {
- return lhs.size() == rhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
- }
-
- bool operator!=(StringView lhs, StringView rhs) noexcept { return !(lhs == rhs); }
-
- bool operator<(StringView lhs, StringView rhs) noexcept
- {
- return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
-
- bool operator>(StringView lhs, StringView rhs) noexcept { return rhs < lhs; }
- bool operator<=(StringView lhs, StringView rhs) noexcept { return !(rhs < lhs); }
- bool operator>=(StringView lhs, StringView rhs) noexcept { return !(lhs < rhs); }
-}
diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp
deleted file mode 100644
index b18a41e6d..000000000
--- a/toolsrc/src/vcpkg/base/system.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/chrono.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.h>
-#include <vcpkg/base/util.h>
-
-#include <ctime>
-
-using namespace vcpkg::System;
-
-namespace vcpkg
-{
- long System::get_process_id()
- {
-#ifdef _WIN32
- return ::_getpid();
-#else
- return ::getpid();
-#endif
- }
-
- Optional<CPUArchitecture> System::to_cpu_architecture(StringView arch)
- {
- if (Strings::case_insensitive_ascii_equals(arch, "x86")) return CPUArchitecture::X86;
- if (Strings::case_insensitive_ascii_equals(arch, "x64")) return CPUArchitecture::X64;
- if (Strings::case_insensitive_ascii_equals(arch, "amd64")) return CPUArchitecture::X64;
- if (Strings::case_insensitive_ascii_equals(arch, "arm")) return CPUArchitecture::ARM;
- if (Strings::case_insensitive_ascii_equals(arch, "arm64")) return CPUArchitecture::ARM64;
- if (Strings::case_insensitive_ascii_equals(arch, "s390x")) return CPUArchitecture::S390X;
- if (Strings::case_insensitive_ascii_equals(arch, "ppc64le")) return CPUArchitecture::PPC64LE;
- return nullopt;
- }
-
- ZStringView System::to_zstring_view(CPUArchitecture arch) noexcept
- {
- switch (arch)
- {
- case CPUArchitecture::X86: return "x86";
- case CPUArchitecture::X64: return "x64";
- case CPUArchitecture::ARM: return "arm";
- case CPUArchitecture::ARM64: return "arm64";
- case CPUArchitecture::S390X: return "s390x";
- case CPUArchitecture::PPC64LE: return "ppc64le";
- default: Checks::exit_with_message(VCPKG_LINE_INFO, "unexpected vcpkg::System::CPUArchitecture");
- }
- }
-
- CPUArchitecture System::get_host_processor()
- {
-#if defined(_WIN32)
- auto w6432 = get_environment_variable("PROCESSOR_ARCHITEW6432");
- if (const auto p = w6432.get()) return to_cpu_architecture(*p).value_or_exit(VCPKG_LINE_INFO);
-
- const auto procarch = get_environment_variable("PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO);
- return to_cpu_architecture(procarch).value_or_exit(VCPKG_LINE_INFO);
-#else // ^^^ defined(_WIN32) / !defined(_WIN32) vvv
-#if defined(__x86_64__) || defined(_M_X64)
- return CPUArchitecture::X64;
-#elif defined(__x86__) || defined(_M_X86) || defined(__i386__)
- return CPUArchitecture::X86;
-#elif defined(__arm__) || defined(_M_ARM)
- return CPUArchitecture::ARM;
-#elif defined(__aarch64__) || defined(_M_ARM64)
- return CPUArchitecture::ARM64;
-#elif defined(__s390x__)
- return CPUArchitecture::S390X;
-#elif (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) && \
- defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
- return CPUArchitecture::PPC64LE;
-#else // choose architecture
-#error "Unknown host architecture"
-#endif // choose architecture
-#endif // defined(_WIN32)
- }
-
- std::vector<CPUArchitecture> System::get_supported_host_architectures()
- {
- std::vector<CPUArchitecture> supported_architectures;
- supported_architectures.push_back(get_host_processor());
-
- // AMD64 machines support running x86 applications and ARM64 machines support running ARM applications
- if (supported_architectures.back() == CPUArchitecture::X64)
- {
- supported_architectures.push_back(CPUArchitecture::X86);
- }
- else if (supported_architectures.back() == CPUArchitecture::ARM64)
- {
- supported_architectures.push_back(CPUArchitecture::ARM);
- }
-
-#if defined(_WIN32)
- // On ARM32/64 Windows we can rely on x86 emulation
- if (supported_architectures.front() == CPUArchitecture::ARM ||
- supported_architectures.front() == CPUArchitecture::ARM64)
- {
- supported_architectures.push_back(CPUArchitecture::X86);
- }
-#endif // defined(_WIN32)
-
- return supported_architectures;
- }
-
- Optional<std::string> System::get_environment_variable(ZStringView varname) noexcept
- {
-#if defined(_WIN32)
- const auto w_varname = Strings::to_utf16(varname);
- const auto sz = GetEnvironmentVariableW(w_varname.c_str(), nullptr, 0);
- if (sz == 0) return nullopt;
-
- std::wstring ret(sz, L'\0');
-
- Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size());
- const auto sz2 = GetEnvironmentVariableW(w_varname.c_str(), ret.data(), static_cast<DWORD>(ret.size()));
- Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz);
- ret.pop_back();
- return Strings::to_utf8(ret.c_str());
-#else // ^^^ defined(_WIN32) / !defined(_WIN32) vvv
- auto v = getenv(varname.c_str());
- if (!v) return nullopt;
- return std::string(v);
-#endif // defined(_WIN32)
- }
-
- void System::set_environment_variable(ZStringView varname, Optional<ZStringView> value) noexcept
- {
-#if defined(_WIN32)
- const auto w_varname = Strings::to_utf16(varname);
- const auto w_varcstr = w_varname.c_str();
- BOOL exit_code;
- if (auto v = value.get())
- {
- exit_code = SetEnvironmentVariableW(w_varcstr, Strings::to_utf16(*v).c_str());
- }
- else
- {
- exit_code = SetEnvironmentVariableW(w_varcstr, nullptr);
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, exit_code != 0);
-#else // ^^^ defined(_WIN32) / !defined(_WIN32) vvv
- if (auto v = value.get())
- {
- Checks::check_exit(VCPKG_LINE_INFO, setenv(varname.c_str(), v->c_str(), 1) == 0);
- }
- else
- {
- Checks::check_exit(VCPKG_LINE_INFO, unsetenv(varname.c_str()) == 0);
- }
-#endif // defined(_WIN32)
- }
-
- const ExpectedS<fs::path>& System::get_home_dir() noexcept
- {
- static ExpectedS<fs::path> s_home = []() -> ExpectedS<fs::path> {
-#ifdef _WIN32
-#define HOMEVAR "%USERPROFILE%"
- auto maybe_home = System::get_environment_variable("USERPROFILE");
- if (!maybe_home.has_value() || maybe_home.get()->empty())
- return {"unable to read " HOMEVAR, ExpectedRightTag{}};
-#else
-#define HOMEVAR "$HOME"
- auto maybe_home = System::get_environment_variable("HOME");
- if (!maybe_home.has_value() || maybe_home.get()->empty())
- return {"unable to read " HOMEVAR, ExpectedRightTag{}};
-#endif
-
- auto p = fs::u8path(*maybe_home.get());
- if (!p.is_absolute()) return {HOMEVAR " was not an absolute path", ExpectedRightTag{}};
-
- return {std::move(p), ExpectedLeftTag{}};
- }();
- return s_home;
-#undef HOMEVAR
- }
-
-#ifdef _WIN32
- const ExpectedS<fs::path>& System::get_appdata_local() noexcept
- {
- static ExpectedS<fs::path> s_home = []() -> ExpectedS<fs::path> {
- auto maybe_home = System::get_environment_variable("LOCALAPPDATA");
- if (!maybe_home.has_value() || maybe_home.get()->empty())
- {
- // Consult %APPDATA% as a workaround for Service accounts
- // Microsoft/vcpkg#12285
- maybe_home = System::get_environment_variable("APPDATA");
- if (!maybe_home.has_value() || maybe_home.get()->empty())
- {
- return {"unable to read %LOCALAPPDATA% or %APPDATA%", ExpectedRightTag{}};
- }
-
- auto p = fs::u8path(*maybe_home.get()).parent_path();
- p /= "Local";
- if (!p.is_absolute()) return {"%APPDATA% was not an absolute path", ExpectedRightTag{}};
- return {std::move(p), ExpectedLeftTag{}};
- }
-
- auto p = fs::u8path(*maybe_home.get());
- if (!p.is_absolute()) return {"%LOCALAPPDATA% was not an absolute path", ExpectedRightTag{}};
-
- return {std::move(p), ExpectedLeftTag{}};
- }();
- return s_home;
- }
-#else
- static const ExpectedS<fs::path>& get_xdg_cache_home() noexcept
- {
- static ExpectedS<fs::path> s_home = [] {
- auto maybe_home = System::get_environment_variable("XDG_CACHE_HOME");
- if (auto p = maybe_home.get())
- {
- return ExpectedS<fs::path>(fs::u8path(*p));
- }
- else
- {
- return System::get_home_dir().map([](fs::path home) {
- home /= fs::u8path(".cache");
- return home;
- });
- }
- }();
- return s_home;
- }
-#endif
-
- const ExpectedS<fs::path>& System::get_platform_cache_home() noexcept
- {
-#ifdef _WIN32
- return System::get_appdata_local();
-#else
- return get_xdg_cache_home();
-#endif
- }
-
-#if defined(_WIN32)
- static bool is_string_keytype(const DWORD hkey_type)
- {
- return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ;
- }
-
- Optional<std::string> System::get_registry_string(void* base_hkey, StringView sub_key, StringView valuename)
- {
- HKEY k = nullptr;
- const LSTATUS ec =
- RegOpenKeyExW(reinterpret_cast<HKEY>(base_hkey), Strings::to_utf16(sub_key).c_str(), 0, KEY_READ, &k);
- if (ec != ERROR_SUCCESS) return nullopt;
-
- auto w_valuename = Strings::to_utf16(valuename);
-
- DWORD dw_buffer_size = 0;
- DWORD dw_type = 0;
- auto rc = RegQueryValueExW(k, w_valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size);
- if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 ||
- dw_buffer_size % sizeof(wchar_t) != 0)
- return nullopt;
- std::wstring ret;
- ret.resize(dw_buffer_size / sizeof(wchar_t));
-
- rc = RegQueryValueExW(
- k, w_valuename.c_str(), nullptr, &dw_type, reinterpret_cast<LPBYTE>(ret.data()), &dw_buffer_size);
- if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size())
- return nullopt;
-
- ret.pop_back(); // remove extra trailing null byte
- return Strings::to_utf8(ret);
- }
-#else // ^^^ defined(_WIN32) / !defined(_WIN32) vvv
- Optional<std::string> System::get_registry_string(void*, StringView, StringView) { return nullopt; }
-#endif // defined(_WIN32)
-
- static const Optional<fs::path>& get_program_files()
- {
- static const auto PROGRAMFILES = []() -> Optional<fs::path> {
- auto value = System::get_environment_variable("PROGRAMFILES");
- if (auto v = value.get())
- {
- return *v;
- }
-
- return nullopt;
- }();
-
- return PROGRAMFILES;
- }
-
- const Optional<fs::path>& System::get_program_files_32_bit()
- {
- static const auto PROGRAMFILES_x86 = []() -> Optional<fs::path> {
- auto value = System::get_environment_variable("ProgramFiles(x86)");
- if (auto v = value.get())
- {
- return *v;
- }
- return get_program_files();
- }();
- return PROGRAMFILES_x86;
- }
-
- const Optional<fs::path>& System::get_program_files_platform_bitness()
- {
- static const auto ProgramW6432 = []() -> Optional<fs::path> {
- auto value = System::get_environment_variable("ProgramW6432");
- if (auto v = value.get())
- {
- return *v;
- }
- return get_program_files();
- }();
- return ProgramW6432;
- }
-
- int System::get_num_logical_cores() { return std::thread::hardware_concurrency(); }
-
- Optional<CPUArchitecture> System::guess_visual_studio_prompt_target_architecture()
- {
- // Check for the "vsdevcmd" infrastructure used by Visual Studio 2017 and later
- const auto vscmd_arg_tgt_arch_env = System::get_environment_variable("VSCMD_ARG_TGT_ARCH");
- if (vscmd_arg_tgt_arch_env)
- {
- return to_cpu_architecture(vscmd_arg_tgt_arch_env.value_or_exit(VCPKG_LINE_INFO));
- }
-
- // Check for the "vcvarsall" infrastructure used by Visual Studio 2015
- if (System::get_environment_variable("VCINSTALLDIR"))
- {
- const auto Platform = System::get_environment_variable("Platform");
- if (Platform)
- {
- return to_cpu_architecture(Platform.value_or_exit(VCPKG_LINE_INFO));
- }
- else
- {
- return CPUArchitecture::X86;
- }
- }
-
- return nullopt;
- }
-}
-
-namespace vcpkg::Debug
-{
- std::atomic<bool> g_debugging(false);
-}
diff --git a/toolsrc/src/vcpkg/base/system.print.cpp b/toolsrc/src/vcpkg/base/system.print.cpp
deleted file mode 100644
index 458f53155..000000000
--- a/toolsrc/src/vcpkg/base/system.print.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-namespace vcpkg::System
-{
- namespace details
- {
- void print(StringView message) { fwrite(message.data(), 1, message.size(), stdout); }
-
- void print(const Color c, StringView message)
- {
-#if defined(_WIN32)
- const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
-
- CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{};
- GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info);
- const auto original_color = console_screen_buffer_info.wAttributes;
-
- SetConsoleTextAttribute(console_handle, static_cast<WORD>(c) | (original_color & 0xF0));
- System::print2(message);
- SetConsoleTextAttribute(console_handle, original_color);
-#else
- // TODO: add color handling code
- // it should probably use VT-220 codes
- (void)c;
- System::print2(message);
-#endif
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/base/system.process.cpp b/toolsrc/src/vcpkg/base/system.process.cpp
deleted file mode 100644
index 22726e42a..000000000
--- a/toolsrc/src/vcpkg/base/system.process.cpp
+++ /dev/null
@@ -1,793 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/chrono.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <ctime>
-
-#if defined(__APPLE__)
-#include <mach-o/dyld.h>
-#endif
-
-#if defined(__FreeBSD__)
-#include <sys/sysctl.h>
-#endif
-
-#if defined(_WIN32)
-#pragma comment(lib, "Advapi32")
-#endif
-
-using namespace vcpkg::System;
-
-namespace vcpkg
-{
-#if defined(_WIN32)
- namespace
- {
- struct CtrlCStateMachine
- {
- CtrlCStateMachine() : m_number_of_external_processes(0), m_global_job(NULL), m_in_interactive(0) { }
-
- void transition_to_spawn_process() noexcept
- {
- int cur = 0;
- while (!m_number_of_external_processes.compare_exchange_strong(cur, cur + 1))
- {
- if (cur < 0)
- {
- // Ctrl-C was hit and is asynchronously executing on another thread.
- // Some other processes are outstanding.
- // Sleep forever -- the other process will complete and exit the program
- while (true)
- {
- std::this_thread::sleep_for(std::chrono::seconds(10));
- System::print2("Waiting for child processes to exit...\n");
- }
- }
- }
- }
- void transition_from_spawn_process() noexcept
- {
- auto previous = m_number_of_external_processes.fetch_add(-1);
- if (previous == INT_MIN + 1)
- {
- // Ctrl-C was hit while blocked on the child process
- // This is the last external process to complete
- // Therefore, exit
- Checks::final_cleanup_and_exit(1);
- }
- else if (previous < 0)
- {
- // Ctrl-C was hit while blocked on the child process
- // Some other processes are outstanding.
- // Sleep forever -- the other process will complete and exit the program
- while (true)
- {
- std::this_thread::sleep_for(std::chrono::seconds(10));
- System::print2("Waiting for child processes to exit...\n");
- }
- }
- }
- void transition_handle_ctrl_c() noexcept
- {
- int old_value = 0;
- while (!m_number_of_external_processes.compare_exchange_strong(old_value, old_value + INT_MIN))
- {
- if (old_value < 0)
- {
- // Repeat calls to Ctrl-C -- a previous one succeeded.
- return;
- }
- }
-
- if (old_value == 0)
- {
- // Not currently blocked on a child process
- Checks::final_cleanup_and_exit(1);
- }
- else
- {
- // We are currently blocked on a child process.
- // If none of the child processes are interactive, use the Job Object to terminate the tree.
- if (m_in_interactive.load() == 0)
- {
- auto job = m_global_job.exchange(NULL);
- if (job != NULL)
- {
- ::CloseHandle(job);
- }
- }
- }
- }
-
- void initialize_job()
- {
- m_global_job = CreateJobObjectW(NULL, NULL);
- if (m_global_job != NULL)
- {
- JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = {};
- info.BasicLimitInformation.LimitFlags =
- JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
- ::SetInformationJobObject(m_global_job, JobObjectExtendedLimitInformation, &info, sizeof(info));
- ::AssignProcessToJobObject(m_global_job, ::GetCurrentProcess());
- }
- }
-
- void enter_interactive() { ++m_in_interactive; }
- void exit_interactive() { --m_in_interactive; }
-
- private:
- std::atomic<int> m_number_of_external_processes;
- std::atomic<HANDLE> m_global_job;
- std::atomic<int> m_in_interactive;
- };
-
- static CtrlCStateMachine g_ctrl_c_state;
- }
-
- void System::initialize_global_job_object() { g_ctrl_c_state.initialize_job(); }
- void System::enter_interactive_subprocess() { g_ctrl_c_state.enter_interactive(); }
- void System::exit_interactive_subprocess() { g_ctrl_c_state.exit_interactive(); }
-#endif
-
- fs::path System::get_exe_path_of_current_process()
- {
-#if defined(_WIN32)
- wchar_t buf[_MAX_PATH];
- const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
- if (bytes == 0) std::abort();
- return fs::path(buf, buf + bytes);
-#elif defined(__APPLE__)
- static constexpr const uint32_t buff_size = 1024 * 32;
- uint32_t size = buff_size;
- char buf[buff_size] = {};
- int result = _NSGetExecutablePath(buf, &size);
- Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path.");
- std::unique_ptr<char> canonicalPath(realpath(buf, NULL));
- Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path.");
- return fs::path(std::string(canonicalPath.get()));
-#elif defined(__FreeBSD__)
- int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
- char exePath[2048];
- size_t len = sizeof(exePath);
- auto rcode = sysctl(mib, 4, exePath, &len, NULL, 0);
- Checks::check_exit(VCPKG_LINE_INFO, rcode == 0, "Could not determine current executable path.");
- Checks::check_exit(VCPKG_LINE_INFO, len > 0, "Could not determine current executable path.");
- return fs::path(exePath, exePath + len - 1);
-#elif defined(__OpenBSD__)
- const char* progname = getprogname();
- char resolved_path[PATH_MAX];
- auto ret = realpath(progname, resolved_path);
- Checks::check_exit(VCPKG_LINE_INFO, ret != nullptr, "Could not determine current executable path.");
- return fs::u8path(resolved_path);
-#else /* LINUX */
- std::array<char, 1024 * 4> buf;
- auto written = readlink("/proc/self/exe", buf.data(), buf.size());
- Checks::check_exit(VCPKG_LINE_INFO, written != -1, "Could not determine current executable path.");
- return fs::path(buf.data(), buf.data() + written);
-#endif
- }
-
- System::CMakeVariable::CMakeVariable(const StringView varname, const char* varvalue)
- : s(Strings::format("-D%s=%s", varname, varvalue))
- {
- }
- System::CMakeVariable::CMakeVariable(const StringView varname, const std::string& varvalue)
- : CMakeVariable(varname, varvalue.c_str())
- {
- }
- System::CMakeVariable::CMakeVariable(const StringView varname, const fs::path& path)
- : CMakeVariable(varname, fs::generic_u8string(path))
- {
- }
- System::CMakeVariable::CMakeVariable(std::string var) : s(std::move(var)) { }
-
- System::Command System::make_basic_cmake_cmd(const fs::path& cmake_tool_path,
- const fs::path& cmake_script,
- const std::vector<CMakeVariable>& pass_variables)
- {
- System::Command cmd{cmake_tool_path};
- for (auto&& var : pass_variables)
- {
- cmd.string_arg(var.s);
- }
- cmd.string_arg("-P").path_arg(cmake_script);
- return cmd;
- }
-
- System::Command& System::Command::string_arg(StringView s) &
- {
- if (!buf.empty()) buf.push_back(' ');
- if (Strings::find_first_of(s, " \t\n\r\"\\,;&`^|'") != s.end())
- {
- // TODO: improve this to properly handle all escaping
-#if _WIN32
- // On Windows, `\`s before a double-quote must be doubled. Inner double-quotes must be escaped.
- buf.push_back('"');
- size_t n_slashes = 0;
- for (auto ch : s)
- {
- if (ch == '\\')
- {
- ++n_slashes;
- }
- else if (ch == '"')
- {
- buf.append(n_slashes + 1, '\\');
- n_slashes = 0;
- }
- else
- {
- n_slashes = 0;
- }
- buf.push_back(ch);
- }
- buf.append(n_slashes, '\\');
- buf.push_back('"');
-#else
- // On non-Windows, `\` is the escape character and always requires doubling. Inner double-quotes must be
- // escaped.
- buf.push_back('"');
- for (auto ch : s)
- {
- if (ch == '\\' || ch == '"') buf.push_back('\\');
- buf.push_back(ch);
- }
- buf.push_back('"');
-#endif
- }
- else
- {
- Strings::append(buf, s);
- }
- return *this;
- }
-
-#if defined(_WIN32)
- Environment System::get_modified_clean_environment(const std::unordered_map<std::string, std::string>& extra_env,
- const std::string& prepend_to_path)
- {
- static const std::string system_root_env =
- get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO);
- static const std::string system32_env = system_root_env + R"(\system32)";
- std::string new_path = Strings::format(R"(Path=%s%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)",
- prepend_to_path,
- system32_env,
- system_root_env,
- system32_env,
- system32_env);
-
- std::vector<std::wstring> env_wstrings = {
- L"ALLUSERSPROFILE",
- L"APPDATA",
- L"CommonProgramFiles",
- L"CommonProgramFiles(x86)",
- L"CommonProgramW6432",
- L"COMPUTERNAME",
- L"ComSpec",
- L"HOMEDRIVE",
- L"HOMEPATH",
- L"LOCALAPPDATA",
- L"LOGONSERVER",
- L"NUMBER_OF_PROCESSORS",
- L"OS",
- L"PATHEXT",
- L"PROCESSOR_ARCHITECTURE",
- L"PROCESSOR_ARCHITEW6432",
- L"PROCESSOR_IDENTIFIER",
- L"PROCESSOR_LEVEL",
- L"PROCESSOR_REVISION",
- L"ProgramData",
- L"ProgramFiles",
- L"ProgramFiles(x86)",
- L"ProgramW6432",
- L"PROMPT",
- L"PSModulePath",
- L"PUBLIC",
- L"SystemDrive",
- L"SystemRoot",
- L"TEMP",
- L"TMP",
- L"USERDNSDOMAIN",
- L"USERDOMAIN",
- L"USERDOMAIN_ROAMINGPROFILE",
- L"USERNAME",
- L"USERPROFILE",
- L"windir",
- // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe
- L"http_proxy",
- L"https_proxy",
- // Environment variables to tell git to use custom SSH executable or command
- L"GIT_SSH",
- L"GIT_SSH_COMMAND",
- // Environment variables needed for ssh-agent based authentication
- L"SSH_AUTH_SOCK",
- L"SSH_AGENT_PID",
- // Enables find_package(CUDA) and enable_language(CUDA) in CMake
- L"CUDA_PATH",
- L"CUDA_PATH_V9_0",
- L"CUDA_PATH_V9_1",
- L"CUDA_PATH_V10_0",
- L"CUDA_PATH_V10_1",
- L"CUDA_PATH_V10_2",
- L"CUDA_PATH_V11_0",
- L"CUDA_TOOLKIT_ROOT_DIR",
- // Environmental variable generated automatically by CUDA after installation
- L"NVCUDASAMPLES_ROOT",
- L"NVTOOLSEXT_PATH",
- // Enables find_package(Vulkan) in CMake. Environmental variable generated by Vulkan SDK installer
- L"VULKAN_SDK",
- // Enable targeted Android NDK
- L"ANDROID_NDK_HOME",
- };
-
- const Optional<std::string> keep_vars = System::get_environment_variable("VCPKG_KEEP_ENV_VARS");
- const auto k = keep_vars.get();
-
- if (k && !k->empty())
- {
- auto vars = Strings::split(*k, ';');
-
- for (auto&& var : vars)
- {
- env_wstrings.push_back(Strings::to_utf16(var));
- }
- }
-
- std::wstring env_cstr;
-
- for (auto&& env_wstring : env_wstrings)
- {
- const Optional<std::string> value = System::get_environment_variable(Strings::to_utf8(env_wstring.c_str()));
- const auto v = value.get();
- if (!v || v->empty()) continue;
-
- env_cstr.append(env_wstring);
- env_cstr.push_back(L'=');
- env_cstr.append(Strings::to_utf16(*v));
- env_cstr.push_back(L'\0');
- }
-
- if (extra_env.find("PATH") != extra_env.end())
- new_path += Strings::format(";%s", extra_env.find("PATH")->second);
- env_cstr.append(Strings::to_utf16(new_path));
- env_cstr.push_back(L'\0');
- env_cstr.append(L"VSLANG=1033");
- env_cstr.push_back(L'\0');
- env_cstr.append(L"VSCMD_SKIP_SENDTELEMETRY=1");
- env_cstr.push_back(L'\0');
-
- for (const auto& item : extra_env)
- {
- if (item.first == "PATH") continue;
- env_cstr.append(Strings::to_utf16(item.first));
- env_cstr.push_back(L'=');
- env_cstr.append(Strings::to_utf16(item.second));
- env_cstr.push_back(L'\0');
- }
-
- return {env_cstr};
- }
-#else
- Environment System::get_modified_clean_environment(const std::unordered_map<std::string, std::string>&,
- const std::string&)
- {
- return {};
- }
-#endif
- const Environment& System::get_clean_environment()
- {
- static const Environment clean_env = get_modified_clean_environment({});
- return clean_env;
- }
-
- int System::cmd_execute_clean(const Command& cmd_line, InWorkingDirectory wd)
- {
- return cmd_execute(cmd_line, wd, get_clean_environment());
- }
-
-#if defined(_WIN32)
- struct ProcessInfo
- {
- constexpr ProcessInfo() noexcept : proc_info{} { }
- ProcessInfo(ProcessInfo&& other) noexcept : proc_info(other.proc_info)
- {
- other.proc_info.hProcess = nullptr;
- other.proc_info.hThread = nullptr;
- }
- ~ProcessInfo()
- {
- if (proc_info.hThread)
- {
- CloseHandle(proc_info.hThread);
- }
- if (proc_info.hProcess)
- {
- CloseHandle(proc_info.hProcess);
- }
- }
-
- ProcessInfo& operator=(ProcessInfo&& other) noexcept
- {
- ProcessInfo{std::move(other)}.swap(*this);
- return *this;
- }
-
- void swap(ProcessInfo& other) noexcept
- {
- std::swap(proc_info.hProcess, other.proc_info.hProcess);
- std::swap(proc_info.hThread, other.proc_info.hThread);
- }
-
- friend void swap(ProcessInfo& lhs, ProcessInfo& rhs) noexcept { lhs.swap(rhs); }
-
- unsigned int wait()
- {
- const DWORD result = WaitForSingleObject(proc_info.hProcess, INFINITE);
- Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed");
- DWORD exit_code = 0;
- GetExitCodeProcess(proc_info.hProcess, &exit_code);
- return exit_code;
- }
-
- PROCESS_INFORMATION proc_info;
- };
-
- /// <param name="maybe_environment">If non-null, an environment block to use for the new process. If null, the
- /// new process will inherit the current environment.</param>
- static ExpectedT<ProcessInfo, unsigned long> windows_create_process(StringView cmd_line,
- InWorkingDirectory wd,
- const Environment& env,
- DWORD dwCreationFlags,
- STARTUPINFOW& startup_info) noexcept
- {
- ProcessInfo process_info;
- Debug::print("CreateProcessW(", cmd_line, ")\n");
-
- // Flush stdout before launching external process
- fflush(nullptr);
-
- std::wstring working_directory;
- if (!wd.working_directory.empty())
- {
- // this only fails if we can't get the current working directory of vcpkg, and we assume that we have that,
- // so it's fine anyways
- working_directory = Files::get_real_filesystem().absolute(VCPKG_LINE_INFO, wd.working_directory).native();
- }
-
- VCPKG_MSVC_WARNING(suppress : 6335) // Leaking process information handle 'process_info.proc_info.hProcess'
- // /analyze can't tell that we transferred ownership here
- bool succeeded =
- TRUE == CreateProcessW(nullptr,
- Strings::to_utf16(cmd_line).data(),
- nullptr,
- nullptr,
- TRUE,
- IDLE_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | dwCreationFlags,
- env.m_env_data.empty()
- ? nullptr
- : const_cast<void*>(static_cast<const void*>(env.m_env_data.data())),
- working_directory.empty() ? nullptr : working_directory.data(),
- &startup_info,
- &process_info.proc_info);
-
- if (succeeded)
- return process_info;
- else
- return GetLastError();
- }
-
- static ExpectedT<ProcessInfo, unsigned long> windows_create_windowless_process(StringView cmd_line,
- InWorkingDirectory wd,
- const Environment& env,
- DWORD dwCreationFlags) noexcept
- {
- STARTUPINFOW startup_info;
- memset(&startup_info, 0, sizeof(STARTUPINFOW));
- startup_info.cb = sizeof(STARTUPINFOW);
- startup_info.dwFlags = STARTF_USESHOWWINDOW;
- startup_info.wShowWindow = SW_HIDE;
-
- return windows_create_process(cmd_line, wd, env, dwCreationFlags, startup_info);
- }
-
- struct ProcessInfoAndPipes
- {
- ProcessInfo proc_info;
- HANDLE child_stdin = 0;
- HANDLE child_stdout = 0;
-
- template<class Function>
- int wait_and_stream_output(Function&& f)
- {
- CloseHandle(child_stdin);
-
- unsigned long bytes_read = 0;
- static constexpr int buffer_size = 1024 * 32;
- auto buf = std::make_unique<char[]>(buffer_size);
- while (ReadFile(child_stdout, (void*)buf.get(), buffer_size, &bytes_read, nullptr) && bytes_read > 0)
- {
- f(StringView{buf.get(), static_cast<size_t>(bytes_read)});
- }
-
- CloseHandle(child_stdout);
-
- return proc_info.wait();
- }
- };
-
- static ExpectedT<ProcessInfoAndPipes, unsigned long> windows_create_process_redirect(StringView cmd_line,
- InWorkingDirectory wd,
- const Environment& env,
- DWORD dwCreationFlags) noexcept
- {
- ProcessInfoAndPipes ret;
-
- STARTUPINFOW startup_info;
- memset(&startup_info, 0, sizeof(STARTUPINFOW));
- startup_info.cb = sizeof(STARTUPINFOW);
- startup_info.dwFlags |= STARTF_USESTDHANDLES;
-
- SECURITY_ATTRIBUTES saAttr;
- memset(&saAttr, 0, sizeof(SECURITY_ATTRIBUTES));
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- // Create a pipe for the child process's STDOUT.
- if (!CreatePipe(&ret.child_stdout, &startup_info.hStdOutput, &saAttr, 0)) Checks::exit_fail(VCPKG_LINE_INFO);
- // Ensure the read handle to the pipe for STDOUT is not inherited.
- if (!SetHandleInformation(ret.child_stdout, HANDLE_FLAG_INHERIT, 0)) Checks::exit_fail(VCPKG_LINE_INFO);
- // Create a pipe for the child process's STDIN.
- if (!CreatePipe(&startup_info.hStdInput, &ret.child_stdin, &saAttr, 0)) Checks::exit_fail(VCPKG_LINE_INFO);
- // Ensure the write handle to the pipe for STDIN is not inherited.
- if (!SetHandleInformation(ret.child_stdin, HANDLE_FLAG_INHERIT, 0)) Checks::exit_fail(VCPKG_LINE_INFO);
- startup_info.hStdError = startup_info.hStdOutput;
-
- auto maybe_proc_info = windows_create_process(cmd_line, wd, env, dwCreationFlags, startup_info);
-
- CloseHandle(startup_info.hStdInput);
- CloseHandle(startup_info.hStdOutput);
-
- if (auto proc_info = maybe_proc_info.get())
- {
- ret.proc_info = std::move(*proc_info);
- return std::move(ret);
- }
- else
- {
- return maybe_proc_info.error();
- }
- }
-#endif
-
-#if defined(_WIN32)
- void System::cmd_execute_background(const Command& cmd_line)
- {
- auto timer = Chrono::ElapsedTimer::create_started();
-
- auto process_info =
- windows_create_windowless_process(cmd_line.command_line(),
- InWorkingDirectory{fs::path()},
- {},
- CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB);
- if (!process_info.get())
- {
- Debug::print("cmd_execute_background() failed with error code ", process_info.error(), "\n");
- }
-
- Debug::print("cmd_execute_background() took ", static_cast<int>(timer.microseconds()), " us\n");
- }
-
- Environment System::cmd_execute_modify_env(const Command& cmd_line, const Environment& env)
- {
- static StringLiteral magic_string = "cdARN4xjKueKScMy9C6H";
-
- auto actual_cmd_line = cmd_line;
- actual_cmd_line.raw_arg(Strings::concat(" & echo ", magic_string, " & set"));
-
- auto rc_output = cmd_execute_and_capture_output(actual_cmd_line, env);
- Checks::check_exit(VCPKG_LINE_INFO, rc_output.exit_code == 0);
- Debug::print("command line: ", actual_cmd_line.command_line(), "\n");
- Debug::print(rc_output.output, "\n");
-
- auto it = Strings::search(rc_output.output, magic_string);
- const char* const last = rc_output.output.data() + rc_output.output.size();
-
- Checks::check_exit(VCPKG_LINE_INFO, it != last);
- // find the first non-whitespace character after the magic string
- it = std::find_if_not(it + magic_string.size(), last, ::isspace);
- Checks::check_exit(VCPKG_LINE_INFO, it != last);
-
- std::wstring out_env;
-
- for (;;)
- {
- auto equal_it = std::find(it, last, '=');
- if (equal_it == last) break;
- StringView variable_name(it, equal_it);
- auto newline_it = std::find(equal_it + 1, last, '\r');
- if (newline_it == last) break;
- StringView value(equal_it + 1, newline_it);
-
- out_env.append(Strings::to_utf16(Strings::concat(variable_name, '=', value)));
- out_env.push_back(L'\0');
-
- it = newline_it + 1;
- if (it != last && *it == '\n') ++it;
- }
-
- return {std::move(out_env)};
- }
-#endif
-
- int System::cmd_execute(const Command& cmd_line, System::InWorkingDirectory wd, const Environment& env)
- {
- auto timer = Chrono::ElapsedTimer::create_started();
-#if defined(_WIN32)
- using vcpkg::g_ctrl_c_state;
- g_ctrl_c_state.transition_to_spawn_process();
- auto proc_info = windows_create_windowless_process(cmd_line.command_line(), wd, env, 0);
- auto long_exit_code = [&]() -> unsigned long {
- if (auto p = proc_info.get())
- return p->wait();
- else
- return proc_info.error();
- }();
- if (long_exit_code > INT_MAX) long_exit_code = INT_MAX;
- int exit_code = static_cast<int>(long_exit_code);
- g_ctrl_c_state.transition_from_spawn_process();
-
- Debug::print(
- "cmd_execute() returned ", exit_code, " after ", static_cast<unsigned int>(timer.microseconds()), " us\n");
-#else
- (void)env;
- std::string real_command_line;
- if (wd.working_directory.empty())
- {
- real_command_line = cmd_line.command_line().to_string();
- }
- else
- {
- real_command_line = System::Command("cd")
- .path_arg(wd.working_directory)
- .raw_arg("&&")
- .raw_arg(cmd_line.command_line())
- .extract();
- }
- Debug::print("system(", real_command_line, ")\n");
- fflush(nullptr);
-
- int exit_code = system(real_command_line.c_str());
- Debug::print(
- "system() returned ", exit_code, " after ", static_cast<unsigned int>(timer.microseconds()), " us\n");
-#endif
- return exit_code;
- }
-
- int System::cmd_execute_and_stream_lines(const Command& cmd_line,
- System::InWorkingDirectory wd,
- std::function<void(StringView)> per_line_cb,
- const Environment& env)
- {
- std::string buf;
-
- auto rc = cmd_execute_and_stream_data(
- cmd_line,
- wd,
- [&](StringView sv) {
- auto prev_size = buf.size();
- Strings::append(buf, sv);
-
- auto it = std::find(buf.begin() + prev_size, buf.end(), '\n');
- while (it != buf.end())
- {
- std::string s(buf.begin(), it);
- per_line_cb(s);
- buf.erase(buf.begin(), it + 1);
- it = std::find(buf.begin(), buf.end(), '\n');
- }
- },
- env);
-
- per_line_cb(buf);
- return rc;
- }
-
- int System::cmd_execute_and_stream_data(const Command& cmd_line,
- System::InWorkingDirectory wd,
- std::function<void(StringView)> data_cb,
- const Environment& env)
- {
- auto timer = Chrono::ElapsedTimer::create_started();
-
-#if defined(_WIN32)
- using vcpkg::g_ctrl_c_state;
-
- g_ctrl_c_state.transition_to_spawn_process();
- auto maybe_proc_info = windows_create_process_redirect(cmd_line.command_line(), wd, env, 0);
- auto exit_code = [&]() -> unsigned long {
- if (auto p = maybe_proc_info.get())
- return p->wait_and_stream_output(data_cb);
- else
- return maybe_proc_info.error();
- }();
- g_ctrl_c_state.transition_from_spawn_process();
-#else
- (void)env;
- std::string actual_cmd_line;
- if (wd.working_directory.empty())
- {
- actual_cmd_line = Strings::format(R"(%s 2>&1)", cmd_line.command_line());
- }
- else
- {
- actual_cmd_line = System::Command("cd")
- .path_arg(wd.working_directory)
- .raw_arg("&&")
- .raw_arg(cmd_line.command_line())
- .raw_arg("2>&1")
- .extract();
- }
-
- Debug::print("popen(", actual_cmd_line, ")\n");
- // Flush stdout before launching external process
- fflush(stdout);
-
- const auto pipe = popen(actual_cmd_line.c_str(), "r");
- if (pipe == nullptr)
- {
- return 1;
- }
- char buf[1024];
- while (fgets(buf, 1024, pipe))
- {
- data_cb(StringView{buf, strlen(buf)});
- }
-
- if (!feof(pipe))
- {
- return 1;
- }
-
- const auto exit_code = pclose(pipe);
-#endif
- Debug::print("cmd_execute_and_stream_data() returned ",
- exit_code,
- " after ",
- Strings::format("%8d", static_cast<int>(timer.microseconds())),
- " us\n");
-
- return exit_code;
- }
-
- ExitCodeAndOutput System::cmd_execute_and_capture_output(const Command& cmd_line,
- System::InWorkingDirectory wd,
- const Environment& env)
- {
- std::string output;
- auto rc = cmd_execute_and_stream_data(
- cmd_line, wd, [&](StringView sv) { Strings::append(output, sv); }, env);
- return {rc, std::move(output)};
- }
-
-#if defined(_WIN32)
- static BOOL ctrl_handler(DWORD fdw_ctrl_type)
- {
- switch (fdw_ctrl_type)
- {
- case CTRL_C_EVENT: g_ctrl_c_state.transition_handle_ctrl_c(); return TRUE;
- default: return FALSE;
- }
- }
-
- void System::register_console_ctrl_handler()
- {
- SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(ctrl_handler), TRUE);
- }
-#else
- void System::register_console_ctrl_handler() { }
-#endif
-}
diff --git a/toolsrc/src/vcpkg/base/uint128.cpp b/toolsrc/src/vcpkg/base/uint128.cpp
deleted file mode 100644
index 900cbf9e6..000000000
--- a/toolsrc/src/vcpkg/base/uint128.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <vcpkg/base/uint128.h>
-
-#include <limits>
-
-namespace vcpkg
-{
- UInt128& UInt128::operator<<=(int by) noexcept
- {
- if (by == 0)
- {
- return *this;
- }
-
- if (by < 64)
- {
- top <<= by;
- const auto shift_up = bottom >> (64 - by);
- top |= shift_up;
- bottom <<= by;
- }
- else
- {
- top = bottom;
- top <<= (by - 64);
- bottom = 0;
- }
-
- return *this;
- }
-
- UInt128& UInt128::operator>>=(int by) noexcept
- {
- if (by == 0)
- {
- return *this;
- }
-
- if (by < 64)
- {
- bottom >>= by;
- const auto shift_down = top << (64 - by);
- bottom |= shift_down;
- top >>= by;
- }
- else
- {
- bottom = top;
- bottom >>= (by - 64);
- top = 0;
- }
-
- return *this;
- }
-
- UInt128& UInt128::operator+=(uint64_t rhs) noexcept
- {
- // bottom + lhs > uint64::max
- if (bottom > std::numeric_limits<uint64_t>::max() - rhs)
- {
- top += 1;
- }
- bottom += rhs;
- return *this;
- }
-
-}
diff --git a/toolsrc/src/vcpkg/base/unicode.cpp b/toolsrc/src/vcpkg/base/unicode.cpp
deleted file mode 100644
index 92b964ed8..000000000
--- a/toolsrc/src/vcpkg/base/unicode.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/unicode.h>
-
-namespace vcpkg::Unicode
-{
- Utf8CodeUnitKind utf8_code_unit_kind(unsigned char code_unit) noexcept
- {
- if (code_unit < 0b1000'0000)
- {
- return Utf8CodeUnitKind::StartOne;
- }
- else if (code_unit < 0b1100'0000)
- {
- return Utf8CodeUnitKind::Continue;
- }
- else if (code_unit < 0b1110'0000)
- {
- return Utf8CodeUnitKind::StartTwo;
- }
- else if (code_unit < 0b1111'0000)
- {
- return Utf8CodeUnitKind::StartThree;
- }
- else if (code_unit < 0b1111'1000)
- {
- return Utf8CodeUnitKind::StartFour;
- }
- else
- {
- return Utf8CodeUnitKind::Invalid;
- }
- }
-
- int utf8_code_unit_count(Utf8CodeUnitKind kind) noexcept { return static_cast<int>(kind); }
- int utf8_code_unit_count(char code_unit) noexcept { return utf8_code_unit_count(utf8_code_unit_kind(code_unit)); }
-
- static int utf8_encode_code_unit_count(char32_t code_point) noexcept
- {
- if (code_point < 0x80)
- {
- return 1;
- }
- else if (code_point < 0x800)
- {
- return 2;
- }
- else if (code_point < 0x10000)
- {
- return 3;
- }
- else if (code_point < 0x110000)
- {
- return 4;
- }
- else
- {
- vcpkg::Checks::exit_with_message(
- VCPKG_LINE_INFO, "Invalid code point passed to utf8_encoded_code_point_count (%x)", code_point);
- }
- }
-
- int utf8_encode_code_point(char (&array)[4], char32_t code_point) noexcept
- {
- // count \in {2, 3, 4}
- const auto start_code_point = [](char32_t code_point, int count) {
- const unsigned char and_mask = 0xFF >> (count + 1);
- const unsigned char or_mask = (0xFF << (8 - count)) & 0xFF;
- const int shift = 6 * (count - 1);
- return static_cast<char>(or_mask | ((code_point >> shift) & and_mask));
- };
- // count \in {2, 3, 4}, byte \in {1, 2, 3}
- const auto continue_code_point = [](char32_t code_point, int count, int byte) {
- constexpr unsigned char and_mask = 0xFF >> 2;
- constexpr unsigned char or_mask = (0xFF << 7) & 0xFF;
- const int shift = 6 * (count - byte - 1);
- return static_cast<char>(or_mask | ((code_point >> shift) & and_mask));
- };
-
- int count = utf8_encode_code_unit_count(code_point);
- if (count == 1)
- {
- array[0] = static_cast<char>(code_point);
- return 1;
- }
-
- array[0] = start_code_point(code_point, count);
- for (int i = 1; i < count; ++i)
- {
- array[i] = continue_code_point(code_point, count, i);
- }
-
- return count;
- }
-
- bool utf8_is_valid_string(const char* first, const char* last) noexcept
- {
- std::error_code ec;
- for (auto dec = Utf8Decoder(first, last); dec != dec.end(); dec.next(ec))
- {
- }
- return !ec;
- }
-
- char32_t utf16_surrogates_to_code_point(char32_t leading, char32_t trailing)
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, utf16_is_leading_surrogate_code_point(leading));
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, utf16_is_trailing_surrogate_code_point(trailing));
-
- char32_t res = (leading & 0b11'1111'1111) << 10;
- res |= trailing & 0b11'1111'1111;
- res += 0x0001'0000;
-
- return res;
- }
-
- const char* utf8_category::name() const noexcept { return "utf8"; }
- std::string utf8_category::message(int condition) const
- {
- switch (static_cast<utf8_errc>(condition))
- {
- case utf8_errc::NoError: return "no error";
- case utf8_errc::InvalidCodeUnit: return "invalid code unit";
- case utf8_errc::InvalidCodePoint: return "invalid code point (>0x10FFFF)";
- case utf8_errc::PairedSurrogates:
- return "trailing surrogate following leading surrogate (paired surrogates are invalid)";
- case utf8_errc::UnexpectedContinue: return "found continue code unit in start position";
- case utf8_errc::UnexpectedStart: return "found start code unit in continue position";
- case utf8_errc::UnexpectedEof: return "found end of string in middle of code point";
- default: return "error code out of range";
- }
- }
-
- Utf8Decoder::Utf8Decoder() noexcept : current_(end_of_file), next_(nullptr), last_(nullptr) { }
- Utf8Decoder::Utf8Decoder(const char* first, const char* last) noexcept : current_(0), next_(first), last_(last)
- {
- if (next_ != last_)
- {
- ++*this;
- }
- else
- {
- current_ = end_of_file;
- }
- }
-
- char const* Utf8Decoder::pointer_to_current() const noexcept
- {
- if (is_eof())
- {
- return last_;
- }
-
- auto count = utf8_encode_code_unit_count(current_);
- return next_ - count;
- }
-
- bool Utf8Decoder::is_eof() const noexcept { return current_ == end_of_file; }
- char32_t Utf8Decoder::operator*() const noexcept
- {
- if (is_eof())
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "Dereferenced Utf8Decoder on the end of a string");
- }
- return current_;
- }
-
- void Utf8Decoder::next(std::error_code& ec)
- {
- ec.clear();
-
- if (is_eof())
- {
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Incremented Utf8Decoder at the end of the string");
- }
-
- if (next_ == last_)
- {
- current_ = end_of_file;
- return;
- }
-
- auto set_error = [&ec, this](utf8_errc err) {
- ec = err;
- *this = sentinel();
- };
-
- unsigned char code_unit = static_cast<unsigned char>(*next_++);
-
- auto kind = utf8_code_unit_kind(code_unit);
- if (kind == Utf8CodeUnitKind::Invalid)
- {
- return set_error(utf8_errc::InvalidCodeUnit);
- }
- else if (kind == Utf8CodeUnitKind::Continue)
- {
- return set_error(utf8_errc::UnexpectedContinue);
- }
-
- const int count = utf8_code_unit_count(kind);
- if (count == 1)
- {
- current_ = static_cast<char32_t>(code_unit);
- }
- else
- {
- // 2 -> 0b0001'1111, 6
- // 3 -> 0b0000'1111, 12
- // 4 -> 0b0000'0111, 18
- const auto start_mask = static_cast<unsigned char>(0xFF >> (count + 1));
- const int start_shift = 6 * (count - 1);
- auto code_point = static_cast<char32_t>(code_unit & start_mask) << start_shift;
-
- constexpr unsigned char continue_mask = 0b0011'1111;
- for (int byte = 1; byte < count; ++byte)
- {
- if (next_ == last_)
- {
- return set_error(utf8_errc::UnexpectedContinue);
- }
- code_unit = static_cast<unsigned char>(*next_++);
-
- kind = utf8_code_unit_kind(code_unit);
- if (kind == Utf8CodeUnitKind::Invalid)
- {
- return set_error(utf8_errc::InvalidCodeUnit);
- }
- else if (kind != Utf8CodeUnitKind::Continue)
- {
- return set_error(utf8_errc::UnexpectedStart);
- }
-
- const int shift = 6 * (count - byte - 1);
- code_point |= (code_unit & continue_mask) << shift;
- }
-
- if (code_point > 0x10'FFFF)
- {
- return set_error(utf8_errc::InvalidCodePoint);
- }
- else if (utf16_is_trailing_surrogate_code_point(code_point) &&
- utf16_is_leading_surrogate_code_point(current_))
- {
- return set_error(utf8_errc::PairedSurrogates);
- }
- else
- {
- current_ = code_point;
- }
- }
- }
-
- Utf8Decoder& Utf8Decoder::operator++() noexcept
- {
- std::error_code ec;
- next(ec);
- if (ec)
- {
- vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, ec.message());
- }
-
- return *this;
- }
-
- Utf8Decoder& Utf8Decoder::operator=(sentinel) noexcept
- {
- next_ = last_;
- current_ = end_of_file;
- return *this;
- }
-
- bool operator==(const Utf8Decoder& lhs, const Utf8Decoder& rhs) noexcept
- {
- if (lhs.last_ != rhs.last_)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Comparing Utf8Decoders with different provenance; this is always an error");
- }
-
- return lhs.next_ == rhs.next_;
- }
-
-}
diff --git a/toolsrc/src/vcpkg/base/xmlserializer.cpp b/toolsrc/src/vcpkg/base/xmlserializer.cpp
deleted file mode 100644
index 535a0a92b..000000000
--- a/toolsrc/src/vcpkg/base/xmlserializer.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/xmlserializer.h>
-
-namespace vcpkg
-{
- XmlSerializer& XmlSerializer::emit_declaration()
- {
- buf.append(R"(<?xml version="1.0" encoding="utf-8"?>)");
- return *this;
- }
- XmlSerializer& XmlSerializer::open_tag(StringLiteral sl)
- {
- emit_pending_indent();
- Strings::append(buf, '<', sl, '>');
- m_indent += 2;
- return *this;
- }
- XmlSerializer& XmlSerializer::start_complex_open_tag(StringLiteral sl)
- {
- emit_pending_indent();
- Strings::append(buf, '<', sl);
- m_indent += 2;
- return *this;
- }
- XmlSerializer& XmlSerializer::text_attr(StringLiteral name, StringView content)
- {
- if (m_pending_indent)
- {
- m_pending_indent = false;
- buf.append(m_indent, ' ');
- }
- else
- {
- buf.push_back(' ');
- }
- Strings::append(buf, name, "=\"");
- text(content);
- Strings::append(buf, '"');
- return *this;
- }
- XmlSerializer& XmlSerializer::finish_complex_open_tag()
- {
- emit_pending_indent();
- Strings::append(buf, '>');
- return *this;
- }
- XmlSerializer& XmlSerializer::finish_self_closing_complex_tag()
- {
- emit_pending_indent();
- Strings::append(buf, "/>");
- m_indent -= 2;
- return *this;
- }
- XmlSerializer& XmlSerializer::close_tag(StringLiteral sl)
- {
- m_indent -= 2;
- emit_pending_indent();
- Strings::append(buf, "</", sl, '>');
- return *this;
- }
- XmlSerializer& XmlSerializer::text(StringView sv)
- {
- emit_pending_indent();
- for (auto ch : sv)
- {
- if (ch == '&')
- {
- buf.append("&amp;");
- }
- else if (ch == '<')
- {
- buf.append("&lt;");
- }
- else if (ch == '>')
- {
- buf.append("&gt;");
- }
- else if (ch == '"')
- {
- buf.append("&quot;");
- }
- else if (ch == '\'')
- {
- buf.append("&apos;");
- }
- else
- {
- buf.push_back(ch);
- }
- }
- return *this;
- }
- XmlSerializer& XmlSerializer::simple_tag(StringLiteral tag, StringView content)
- {
- return emit_pending_indent().open_tag(tag).text(content).close_tag(tag);
- }
- XmlSerializer& XmlSerializer::line_break()
- {
- buf.push_back('\n');
- m_pending_indent = true;
- return *this;
- }
- XmlSerializer& XmlSerializer::emit_pending_indent()
- {
- if (m_pending_indent)
- {
- m_pending_indent = false;
- buf.append(m_indent, ' ');
- }
- return *this;
- }
-
-}
diff --git a/toolsrc/src/vcpkg/binarycaching.cpp b/toolsrc/src/vcpkg/binarycaching.cpp
deleted file mode 100644
index 280a5be28..000000000
--- a/toolsrc/src/vcpkg/binarycaching.cpp
+++ /dev/null
@@ -1,1477 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/downloads.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/parse.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/xmlserializer.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/binarycaching.private.h>
-#include <vcpkg/build.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/tools.h>
-
-using namespace vcpkg;
-
-namespace
-{
- struct NullBinaryProvider : IBinaryProvider
- {
- void prefetch(const VcpkgPaths&, std::vector<const Dependencies::InstallPlanAction*>&) { }
-
- void push_success(const VcpkgPaths&, const Dependencies::InstallPlanAction&) { }
-
- RestoreResult try_restore(const VcpkgPaths&, const Dependencies::InstallPlanAction&)
- {
- return RestoreResult::missing;
- }
-
- void precheck(const VcpkgPaths&, std::unordered_map<const Dependencies::InstallPlanAction*, RestoreResult>&) { }
- };
-}
-
-std::unordered_map<const Dependencies::InstallPlanAction*, RestoreResult> vcpkg::binary_provider_precheck(
- const VcpkgPaths& paths, const Dependencies::ActionPlan& plan, IBinaryProvider& provider)
-{
- std::unordered_map<const Dependencies::InstallPlanAction*, RestoreResult> checked;
- for (auto&& action : plan.install_actions)
- {
- checked.emplace(&action, RestoreResult::missing);
- }
-
- provider.precheck(paths, checked);
- return checked;
-}
-
-namespace
-{
- static void clean_prepare_dir(Files::Filesystem& fs, const fs::path& dir)
- {
- fs.remove_all(dir, VCPKG_LINE_INFO);
- bool created_last = fs.create_directories(dir, VCPKG_LINE_INFO);
- Checks::check_exit(VCPKG_LINE_INFO, created_last, "unable to clear path: %s", fs::u8string(dir));
- }
-
- static System::ExitCodeAndOutput decompress_archive(const VcpkgPaths& paths,
- const fs::path& dst,
- const fs::path& archive_path)
- {
- System::Command cmd;
-#if defined(_WIN32)
- auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP);
- cmd.path_arg(seven_zip_exe)
- .string_arg("x")
- .path_arg(archive_path)
- .string_arg("-o" + fs::u8string(dst))
- .string_arg("-y");
-#else
- (void)paths;
- cmd.string_arg("unzip").string_arg("-qq").path_arg(archive_path).string_arg("-d" + fs::u8string(dst));
-#endif
- return System::cmd_execute_and_capture_output(cmd, System::get_clean_environment());
- }
-
- static System::ExitCodeAndOutput clean_decompress_archive(const VcpkgPaths& paths,
- const PackageSpec& spec,
- const fs::path& archive_path)
- {
- auto pkg_path = paths.package_dir(spec);
- clean_prepare_dir(paths.get_filesystem(), pkg_path);
- return decompress_archive(paths, pkg_path, archive_path);
- }
-
- // Compress the source directory into the destination file.
- static void compress_directory(const VcpkgPaths& paths, const fs::path& source, const fs::path& destination)
- {
- auto& fs = paths.get_filesystem();
-
- std::error_code ec;
-
- fs.remove(destination, ec);
- Checks::check_exit(
- VCPKG_LINE_INFO, !fs.exists(destination), "Could not remove file: %s", fs::u8string(destination));
-#if defined(_WIN32)
- auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP);
-
- System::cmd_execute_and_capture_output(
- System::Command{seven_zip_exe}.string_arg("a").path_arg(destination).path_arg(source / fs::u8path("*")),
- System::get_clean_environment());
-#else
- System::cmd_execute_clean(System::Command{"zip"}
- .string_arg("--quiet")
- .string_arg("-y")
- .string_arg("-r")
- .path_arg(destination)
- .string_arg("*"),
- System::InWorkingDirectory{source});
-#endif
- }
-
- struct ArchivesBinaryProvider : IBinaryProvider
- {
- ArchivesBinaryProvider(std::vector<fs::path>&& read_dirs,
- std::vector<fs::path>&& write_dirs,
- std::vector<std::string>&& put_url_templates,
- std::vector<std::string>&& secrets)
- : m_read_dirs(std::move(read_dirs))
- , m_write_dirs(std::move(write_dirs))
- , m_put_url_templates(std::move(put_url_templates))
- , m_secrets(std::move(secrets))
- {
- }
-
- void prefetch(const VcpkgPaths& paths, std::vector<const Dependencies::InstallPlanAction*>& actions) override
- {
- auto& fs = paths.get_filesystem();
- Util::erase_remove_if(actions, [this, &fs, &paths](const Dependencies::InstallPlanAction* action) {
- auto& spec = action->spec;
- const auto& abi_tag = action->abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi;
- const auto archive_name = fs::u8path(abi_tag + ".zip");
- for (const auto& archives_root_dir : m_read_dirs)
- {
- auto archive_path = archives_root_dir;
- archive_path /= fs::u8path(abi_tag.substr(0, 2));
- archive_path /= archive_name;
- if (fs.exists(archive_path))
- {
- System::print2("Using cached binary package: ", fs::u8string(archive_path), "\n");
-
- int archive_result = clean_decompress_archive(paths, spec, archive_path).exit_code;
-
- if (archive_result == 0)
- {
- m_restored.insert(spec);
- return true;
- }
- else
- {
- System::print2("Failed to decompress archive package\n");
- if (action->build_options.purge_decompress_failure == Build::PurgeDecompressFailure::YES)
- {
- System::print2("Purging bad archive\n");
- fs.remove(archive_path, ignore_errors);
- }
- }
- }
-
- System::printf("Could not locate cached archive: %s\n", fs::u8string(archive_path));
- }
- return false;
- });
- }
- RestoreResult try_restore(const VcpkgPaths&, const Dependencies::InstallPlanAction& action) override
- {
- if (Util::Sets::contains(m_restored, action.spec))
- return RestoreResult::success;
- else
- return RestoreResult::missing;
- }
- void push_success(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
- {
- if (m_write_dirs.empty() && m_put_url_templates.empty()) return;
- const auto& abi_tag = action.abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi;
- auto& spec = action.spec;
- auto& fs = paths.get_filesystem();
- const auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip");
- compress_directory(paths, paths.package_dir(spec), tmp_archive_path);
-
- size_t http_remotes_pushed = 0;
- 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)
- {
- http_remotes_pushed++;
- continue;
- }
-
- auto safe_url = url;
- if (!Debug::g_debugging.load(std::memory_order_relaxed))
- {
- for (const auto& secret : m_secrets)
- {
- Strings::inplace_replace_all(safe_url, secret, "*** SECRET ***");
- }
- }
-
- System::print2(System::Color::warning, "Failed to upload to ", safe_url, ": ", code, '\n');
- }
-
- if (!m_put_url_templates.empty())
- {
- System::print2("Uploaded binaries to ", http_remotes_pushed, " HTTP remotes.\n");
- }
-
- const auto archive_name = fs::u8path(abi_tag + ".zip");
- for (const auto& archives_root_dir : m_write_dirs)
- {
- auto archive_path = archives_root_dir;
- archive_path /= fs::u8path(abi_tag.substr(0, 2));
- archive_path /= archive_name;
- fs.create_directories(archive_path.parent_path(), ignore_errors);
- std::error_code ec;
- if (m_write_dirs.size() > 1)
- {
- fs.copy_file(tmp_archive_path, archive_path, fs::copy_options::overwrite_existing, ec);
- }
- else
- {
- fs.rename_or_copy(tmp_archive_path, archive_path, ".tmp", ec);
- }
-
- if (ec)
- {
- System::printf(System::Color::warning,
- "Failed to store binary cache %s: %s\n",
- fs::u8string(archive_path),
- ec.message());
- }
- else
- {
- System::printf("Stored binary cache: %s\n", fs::u8string(archive_path));
- }
- }
- // In the case of 1 write dir, the file will be moved instead of copied
- if (m_write_dirs.size() != 1)
- {
- fs.remove(tmp_archive_path, ignore_errors);
- }
- }
- void precheck(const VcpkgPaths& paths,
- std::unordered_map<const Dependencies::InstallPlanAction*, RestoreResult>& results_map) override
- {
- auto& fs = paths.get_filesystem();
-
- for (auto&& result_pair : results_map)
- {
- if (result_pair.second != RestoreResult::missing)
- {
- continue;
- }
-
- const auto& abi_tag = result_pair.first->abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi;
- std::error_code ec;
- for (auto&& archives_root_dir : m_read_dirs)
- {
- const std::string archive_name = abi_tag + ".zip";
- const fs::path archive_subpath = fs::u8path(abi_tag.substr(0, 2)) / archive_name;
- const fs::path archive_path = archives_root_dir / archive_subpath;
-
- if (fs.exists(archive_path))
- {
- result_pair.second = RestoreResult::success;
- break;
- }
- }
- }
- }
-
- private:
- std::vector<fs::path> m_read_dirs;
- std::vector<fs::path> m_write_dirs;
- std::vector<std::string> m_put_url_templates;
- std::vector<std::string> m_secrets;
-
- std::set<PackageSpec> m_restored;
- };
- struct HttpGetBinaryProvider : NullBinaryProvider
- {
- HttpGetBinaryProvider(std::vector<std::string>&& url_templates) : m_url_templates(std::move(url_templates)) { }
- void prefetch(const VcpkgPaths& paths, std::vector<const Dependencies::InstallPlanAction*>& actions) override
- {
- auto& fs = paths.get_filesystem();
-
- const size_t current_restored = m_restored.size();
-
- for (auto&& url_template : m_url_templates)
- {
- std::vector<std::pair<std::string, fs::path>> url_paths;
- std::vector<PackageSpec> specs;
-
- for (auto&& action : actions)
- {
- auto abi = action->package_abi();
- if (!abi)
- {
- continue;
- }
-
- specs.push_back(action->spec);
- auto pkgdir = paths.package_dir(action->spec);
- clean_prepare_dir(fs, pkgdir);
- pkgdir /= fs::u8path(Strings::concat(*abi.get(), ".zip"));
- url_paths.emplace_back(Strings::replace_all(std::string(url_template), "<SHA>", *abi.get()),
- pkgdir);
- }
-
- if (url_paths.empty()) break;
-
- System::print2("Attempting to fetch ", url_paths.size(), " packages from HTTP servers.\n");
-
- auto codes = Downloads::download_files(fs, url_paths);
- for (size_t i = 0; i < codes.size(); ++i)
- {
- if (codes[i] == 200)
- {
- int archive_result =
- decompress_archive(paths, paths.package_dir(specs[i]), url_paths[i].second).exit_code;
- if (archive_result == 0)
- {
- // decompression success
- fs.remove(url_paths[i].second, VCPKG_LINE_INFO);
- m_restored.insert(specs[i]);
- }
- else
- {
- Debug::print("Failed to decompress ", fs::u8string(url_paths[i].second), '\n');
- }
- }
- }
-
- Util::erase_remove_if(actions, [this](const Dependencies::InstallPlanAction* action) {
- return Util::Sets::contains(m_restored, action->spec);
- });
- }
- System::print2("Restored ",
- m_restored.size() - current_restored,
- " packages from HTTP servers. Use --debug for more information.\n");
- }
- RestoreResult try_restore(const VcpkgPaths&, const Dependencies::InstallPlanAction& action) override
- {
- if (Util::Sets::contains(m_restored, action.spec))
- {
- return RestoreResult::success;
- }
-
- return RestoreResult::missing;
- }
- void precheck(const VcpkgPaths&,
- std::unordered_map<const Dependencies::InstallPlanAction*, RestoreResult>& results_map) override
- {
- std::vector<std::string> urls;
- std::vector<const Dependencies::InstallPlanAction*> url_actions;
- for (auto&& url_template : m_url_templates)
- {
- urls.clear();
- url_actions.clear();
- for (auto&& result_pair : results_map)
- {
- if (result_pair.second != RestoreResult::missing) continue;
- auto abi = result_pair.first->package_abi();
- if (!abi) continue;
- urls.push_back(Strings::replace_all(std::string(url_template), "<SHA>", *abi.get()));
- url_actions.push_back(result_pair.first);
- }
-
- if (urls.empty())
- {
- break;
- }
-
- 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)
- {
- if (codes[i] == 200)
- {
- results_map[url_actions[i]] = RestoreResult::success;
- }
- }
- }
- }
-
- std::vector<std::string> m_url_templates;
- std::set<PackageSpec> m_restored;
- };
-
- static std::string trim_leading_zeroes(std::string v)
- {
- auto n = v.find_first_not_of('0');
- if (n == std::string::npos)
- {
- v = "0";
- }
- else if (n > 0)
- {
- v.erase(0, n);
- }
-
- return v;
- }
-
- struct NugetBinaryProvider : NullBinaryProvider
- {
- NugetBinaryProvider(std::vector<std::string>&& read_sources,
- std::vector<std::string>&& write_sources,
- std::vector<fs::path>&& read_configs,
- std::vector<fs::path>&& write_configs,
- bool interactive)
- : m_read_sources(std::move(read_sources))
- , m_write_sources(std::move(write_sources))
- , m_read_configs(std::move(read_configs))
- , m_write_configs(std::move(write_configs))
- , m_interactive(interactive)
- , m_use_nuget_cache(false)
- {
- const std::string use_nuget_cache = System::get_environment_variable("VCPKG_USE_NUGET_CACHE").value_or("");
- m_use_nuget_cache = Strings::case_insensitive_ascii_equals(use_nuget_cache, "true") ||
- Strings::case_insensitive_ascii_equals(use_nuget_cache, "1");
- }
-
- int run_nuget_commandline(const System::Command& cmdline)
- {
- if (m_interactive)
- {
- return System::cmd_execute(cmdline);
- }
-
- auto res = System::cmd_execute_and_capture_output(cmdline);
- if (Debug::g_debugging)
- {
- System::print2(res.output);
- }
-
- if (res.output.find("Authentication may require manual action.") != std::string::npos)
- {
- System::print2(System::Color::warning,
- "One or more NuGet credential providers requested manual action. Add the binary "
- "source 'interactive' to allow interactivity.\n");
- }
- else if (res.output.find("Response status code does not indicate success: 401 (Unauthorized)") !=
- std::string::npos &&
- res.exit_code != 0)
- {
- System::print2(System::Color::warning,
- "One or more NuGet credential providers failed to authenticate. See "
- "https://github.com/Microsoft/vcpkg/tree/master/docs/users/binarycaching.md for "
- "more details on how to provide credentials.\n");
- }
- else if (res.output.find("for example \"-ApiKey AzureDevOps\"") != std::string::npos)
- {
- auto real_cmdline = cmdline;
- real_cmdline.string_arg("-ApiKey").string_arg("AzureDevOps");
- auto res2 = System::cmd_execute_and_capture_output(real_cmdline);
- if (Debug::g_debugging)
- {
- System::print2(res2.output);
- }
-
- return res2.exit_code;
- }
-
- return res.exit_code;
- }
-
- void prefetch(const VcpkgPaths& paths, std::vector<const Dependencies::InstallPlanAction*>& actions) override
- {
- if (m_read_sources.empty() && m_read_configs.empty())
- {
- return;
- }
-
- auto& fs = paths.get_filesystem();
-
- std::vector<std::pair<PackageSpec, NugetReference>> nuget_refs;
-
- for (auto&& action : actions)
- {
- if (!action->has_package_abi())
- {
- continue;
- }
-
- auto& spec = action->spec;
- fs.remove_all(paths.package_dir(spec), VCPKG_LINE_INFO);
-
- nuget_refs.emplace_back(spec, NugetReference(*action));
- }
-
- if (nuget_refs.empty())
- {
- return;
- }
-
- System::print2("Attempting to fetch ", nuget_refs.size(), " packages from nuget.\n");
-
- auto packages_config = paths.buildtrees / fs::u8path("packages.config");
-
- auto generate_packages_config = [&] {
- XmlSerializer xml;
- xml.emit_declaration().line_break();
- xml.open_tag("packages").line_break();
-
- for (auto&& nuget_ref : nuget_refs)
- {
- xml.start_complex_open_tag("package")
- .text_attr("id", nuget_ref.second.id)
- .text_attr("version", nuget_ref.second.version)
- .finish_self_closing_complex_tag()
- .line_break();
- }
-
- xml.close_tag("packages").line_break();
- paths.get_filesystem().write_contents(packages_config, xml.buf, VCPKG_LINE_INFO);
- };
-
- const auto& nuget_exe = paths.get_tool_exe("nuget");
- std::vector<System::Command> cmdlines;
-
- if (!m_read_sources.empty())
- {
- // First check using all sources
- System::Command cmdline;
-#ifndef _WIN32
- cmdline.path_arg(paths.get_tool_exe(Tools::MONO));
-#endif
- cmdline.path_arg(nuget_exe)
- .string_arg("install")
- .path_arg(packages_config)
- .string_arg("-OutputDirectory")
- .path_arg(paths.packages)
- .string_arg("-Source")
- .string_arg(Strings::join(";", m_read_sources))
- .string_arg("-ExcludeVersion")
- .string_arg("-PreRelease")
- .string_arg("-PackageSaveMode")
- .string_arg("nupkg")
- .string_arg("-Verbosity")
- .string_arg("detailed")
- .string_arg("-ForceEnglishOutput");
- if (!m_interactive)
- {
- cmdline.string_arg("-NonInteractive");
- }
- if (!m_use_nuget_cache)
- {
- cmdline.string_arg("-DirectDownload").string_arg("-NoCache");
- }
-
- cmdlines.push_back(std::move(cmdline));
- }
- for (auto&& cfg : m_read_configs)
- {
- // Then check using each config
- System::Command cmdline;
-#ifndef _WIN32
- cmdline.path_arg(paths.get_tool_exe(Tools::MONO));
-#endif
- cmdline.path_arg(nuget_exe)
- .string_arg("install")
- .path_arg(packages_config)
- .string_arg("-OutputDirectory")
- .path_arg(paths.packages)
- .string_arg("-ConfigFile")
- .path_arg(cfg)
- .string_arg("-ExcludeVersion")
- .string_arg("-PreRelease")
- .string_arg("-PackageSaveMode")
- .string_arg("nupkg")
- .string_arg("-Verbosity")
- .string_arg("detailed")
- .string_arg("-ForceEnglishOutput");
- if (!m_interactive)
- {
- cmdline.string_arg("-NonInteractive");
- }
- if (!m_use_nuget_cache)
- {
- cmdline.string_arg("-DirectDownload").string_arg("-NoCache");
- }
-
- cmdlines.push_back(std::move(cmdline));
- }
-
- const size_t current_restored = m_restored.size();
-
- for (const auto& cmdline : cmdlines)
- {
- if (nuget_refs.empty())
- {
- break;
- }
-
- [&] {
- generate_packages_config();
- run_nuget_commandline(cmdline);
- }();
-
- Util::erase_remove_if(nuget_refs, [&](const std::pair<PackageSpec, NugetReference>& nuget_ref) -> bool {
- auto nupkg_path = paths.package_dir(nuget_ref.first) / fs::u8path(nuget_ref.second.id + ".nupkg");
- if (fs.exists(nupkg_path, ignore_errors))
- {
- fs.remove(nupkg_path, VCPKG_LINE_INFO);
- Checks::check_exit(VCPKG_LINE_INFO,
- !fs.exists(nupkg_path, ignore_errors),
- "Unable to remove nupkg after restoring: %s",
- fs::u8string(nupkg_path));
- m_restored.emplace(nuget_ref.first);
- return true;
- }
-
- return false;
- });
- }
-
- Util::erase_remove_if(actions, [this](const Dependencies::InstallPlanAction* action) {
- return Util::Sets::contains(m_restored, action->spec);
- });
-
- System::print2("Restored ",
- m_restored.size() - current_restored,
- " packages from NuGet. Use --debug for more information.\n");
- }
- RestoreResult try_restore(const VcpkgPaths&, const Dependencies::InstallPlanAction& action) override
- {
- if (Util::Sets::contains(m_restored, action.spec))
- {
- return RestoreResult::success;
- }
-
- return RestoreResult::missing;
- }
- void push_success(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
- {
- if (m_write_sources.empty() && m_write_configs.empty())
- {
- return;
- }
-
- auto& spec = action.spec;
-
- NugetReference nuget_ref(action);
- auto nuspec_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".nuspec");
- paths.get_filesystem().write_contents(
- nuspec_path, generate_nuspec(paths, action, nuget_ref), VCPKG_LINE_INFO);
-
- const auto& nuget_exe = paths.get_tool_exe("nuget");
- System::Command cmdline;
-#ifndef _WIN32
- cmdline.path_arg(paths.get_tool_exe(Tools::MONO));
-#endif
- cmdline.path_arg(nuget_exe)
- .string_arg("pack")
- .path_arg(nuspec_path)
- .string_arg("-OutputDirectory")
- .path_arg(paths.buildtrees)
- .string_arg("-NoDefaultExcludes")
- .string_arg("-ForceEnglishOutput");
- if (!m_interactive) cmdline.string_arg("-NonInteractive");
-
- auto pack_rc = run_nuget_commandline(cmdline);
-
- if (pack_rc != 0)
- {
- System::print2(System::Color::error, "Packing NuGet failed. Use --debug for more information.\n");
- }
- else
- {
- auto nupkg_path = paths.buildtrees / nuget_ref.nupkg_filename();
- for (auto&& write_src : m_write_sources)
- {
- System::Command cmd;
-#ifndef _WIN32
- cmd.path_arg(paths.get_tool_exe(Tools::MONO));
-#endif
- cmd.path_arg(nuget_exe)
- .string_arg("push")
- .path_arg(nupkg_path)
- .string_arg("-ForceEnglishOutput")
- .string_arg("-Source")
- .string_arg(write_src);
-
- if (!m_interactive)
- {
- cmd.string_arg("-NonInteractive");
- }
-
- System::print2("Uploading binaries for ", spec, " to NuGet source ", write_src, ".\n");
-
- auto rc = run_nuget_commandline(cmd);
- if (rc != 0)
- {
- System::print2(System::Color::error,
- "Pushing NuGet to ",
- write_src,
- " failed. Use --debug for more information.\n");
- }
- }
- for (auto&& write_cfg : m_write_configs)
- {
- System::Command cmd;
-#ifndef _WIN32
- cmd.path_arg(paths.get_tool_exe(Tools::MONO));
-#endif
- cmd.path_arg(nuget_exe)
- .string_arg("push")
- .path_arg(nupkg_path)
- .string_arg("-ForceEnglishOutput")
- .string_arg("-ConfigFile")
- .path_arg(write_cfg);
- if (!m_interactive)
- {
- cmd.string_arg("-NonInteractive");
- }
-
- System::print2(
- "Uploading binaries for ", spec, " using NuGet config ", fs::u8string(write_cfg), ".\n");
-
- auto rc = run_nuget_commandline(cmd);
-
- if (rc != 0)
- {
- System::print2(System::Color::error,
- "Pushing NuGet with ",
- fs::u8string(write_cfg),
- " failed. Use --debug for more information.\n");
- }
- }
-
- paths.get_filesystem().remove(nupkg_path, ignore_errors);
- }
- }
-
- private:
- std::vector<std::string> m_read_sources;
- std::vector<std::string> m_write_sources;
-
- std::vector<fs::path> m_read_configs;
- std::vector<fs::path> m_write_configs;
-
- std::set<PackageSpec> m_restored;
- bool m_interactive;
- bool m_use_nuget_cache;
- };
-}
-
-namespace vcpkg
-{
- struct MergeBinaryProviders : NullBinaryProvider
- {
- explicit MergeBinaryProviders(std::vector<std::unique_ptr<IBinaryProvider>>&& providers)
- : m_providers(std::move(providers))
- {
- }
-
- void prefetch(const VcpkgPaths& paths, std::vector<const Dependencies::InstallPlanAction*>& actions) override
- {
- for (auto&& provider : m_providers)
- {
- provider->prefetch(paths, actions);
- }
- }
- RestoreResult try_restore(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
- {
- for (auto&& provider : m_providers)
- {
- auto result = provider->try_restore(paths, action);
- switch (result)
- {
- case RestoreResult::build_failed:
- case RestoreResult::success: return result;
- case RestoreResult::missing: continue;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- return RestoreResult::missing;
- }
- void push_success(const VcpkgPaths& paths, const Dependencies::InstallPlanAction& action) override
- {
- for (auto&& provider : m_providers)
- {
- provider->push_success(paths, action);
- }
- }
- void precheck(const VcpkgPaths& paths,
- std::unordered_map<const Dependencies::InstallPlanAction*, RestoreResult>& results_map) override
- {
- for (auto&& provider : m_providers)
- {
- provider->precheck(paths, results_map);
- }
- }
-
- private:
- std::vector<std::unique_ptr<IBinaryProvider>> m_providers;
- };
-}
-
-IBinaryProvider& vcpkg::null_binary_provider()
-{
- static NullBinaryProvider p;
- return p;
-}
-
-namespace
-{
- const ExpectedS<fs::path>& default_cache_path()
- {
- static auto cachepath = System::get_platform_cache_home().then([](fs::path p) -> ExpectedS<fs::path> {
- auto maybe_cachepath = System::get_environment_variable("VCPKG_DEFAULT_BINARY_CACHE");
- if (auto p_str = maybe_cachepath.get())
- {
- Metrics::g_metrics.lock()->track_property("VCPKG_DEFAULT_BINARY_CACHE", "defined");
- auto path = fs::u8path(*p_str);
- path.make_preferred();
- const auto status = fs::stdfs::status(path);
- if (!fs::stdfs::exists(status))
- {
- return {"Path to VCPKG_DEFAULT_BINARY_CACHE does not exist: " + fs::u8string(path),
- expected_right_tag};
- }
-
- if (!fs::stdfs::is_directory(status))
- {
- return {"Value of environment variable VCPKG_DEFAULT_BINARY_CACHE is not a directory: " +
- fs::u8string(path),
- expected_right_tag};
- }
-
- if (!path.is_absolute())
- {
- return {"Value of environment variable VCPKG_DEFAULT_BINARY_CACHE is not absolute: " +
- fs::u8string(path),
- expected_right_tag};
- }
-
- return {std::move(path), expected_left_tag};
- }
- p /= fs::u8path("vcpkg/archives");
- p.make_preferred();
- if (p.is_absolute())
- {
- return {std::move(p), expected_left_tag};
- }
- else
- {
- return {"default path was not absolute: " + fs::u8string(p), expected_right_tag};
- }
- });
- return cachepath;
- }
-
- struct State
- {
- bool m_cleared = false;
- bool interactive = false;
-
- std::vector<fs::path> archives_to_read;
- std::vector<fs::path> archives_to_write;
-
- std::vector<std::string> url_templates_to_get;
- std::vector<std::string> azblob_templates_to_put;
-
- std::vector<std::string> sources_to_read;
- std::vector<std::string> sources_to_write;
-
- std::vector<fs::path> configs_to_read;
- std::vector<fs::path> configs_to_write;
-
- std::vector<std::string> secrets;
-
- void clear()
- {
- m_cleared = true;
- interactive = false;
- archives_to_read.clear();
- archives_to_write.clear();
- url_templates_to_get.clear();
- azblob_templates_to_put.clear();
- sources_to_read.clear();
- sources_to_write.clear();
- configs_to_read.clear();
- configs_to_write.clear();
- secrets.clear();
- }
- };
-
- struct BinaryConfigParser : Parse::ParserBase
- {
- BinaryConfigParser(StringView text, StringView origin, State* state)
- : Parse::ParserBase(text, origin), state(state)
- {
- }
-
- State* state;
-
- void parse()
- {
- while (!at_eof())
- {
- std::vector<std::pair<SourceLoc, std::string>> segments;
-
- for (;;)
- {
- SourceLoc loc = cur_loc();
- std::string segment;
- for (;;)
- {
- auto n = match_until([](char32_t ch) { return ch == ',' || ch == '`' || ch == ';'; });
- Strings::append(segment, n);
- auto ch = cur();
- if (ch == Unicode::end_of_file || ch == ',' || ch == ';')
- {
- break;
- }
-
- if (ch == '`')
- {
- ch = next();
- if (ch == Unicode::end_of_file)
- {
- add_error("unexpected eof: trailing unescaped backticks (`) are not allowed");
- }
- else
- {
- Unicode::utf8_append_code_point(segment, ch);
- }
-
- next();
- }
- else
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- segments.emplace_back(std::move(loc), std::move(segment));
-
- auto ch = cur();
- if (ch == Unicode::end_of_file || ch == ';')
- {
- break;
- }
-
- if (ch == ',')
- {
- next();
- continue;
- }
-
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- if (segments.size() != 1 || !segments[0].second.empty())
- {
- handle_segments(std::move(segments));
- }
-
- segments.clear();
- if (get_error())
- {
- return;
- }
-
- if (cur() == ';')
- {
- next();
- }
- }
- }
-
- template<class T>
- void handle_readwrite(std::vector<T>& read,
- std::vector<T>& write,
- T&& t,
- const std::vector<std::pair<SourceLoc, std::string>>& segments,
- size_t segment_idx)
- {
- if (segment_idx >= segments.size())
- {
- read.push_back(std::move(t));
- return;
- }
-
- auto& mode = segments[segment_idx].second;
-
- if (mode == "read")
- {
- read.push_back(std::move(t));
- }
- else if (mode == "write")
- {
- write.push_back(std::move(t));
- }
- else if (mode == "readwrite")
- {
- read.push_back(t);
- write.push_back(std::move(t));
- }
- else
- {
- return add_error("unexpected argument: expected 'read', readwrite', or 'write'",
- segments[segment_idx].first);
- }
- }
-
- void handle_segments(std::vector<std::pair<SourceLoc, std::string>>&& segments)
- {
- if (segments.empty()) return;
- if (segments[0].second == "clear")
- {
- if (segments.size() != 1)
- {
- return add_error("unexpected arguments: binary config 'clear' does not take arguments",
- segments[1].first);
- }
-
- state->clear();
- }
- else if (segments[0].second == "files")
- {
- if (segments.size() < 2)
- {
- return add_error("expected arguments: binary config 'files' requires at least a path argument",
- segments[0].first);
- }
-
- auto p = fs::u8path(segments[1].second);
- if (!p.is_absolute())
- {
- return add_error("expected arguments: path arguments for binary config strings must be absolute",
- segments[1].first);
- }
-
- handle_readwrite(state->archives_to_read, state->archives_to_write, std::move(p), segments, 2);
- if (segments.size() > 3)
- {
- return add_error("unexpected arguments: binary config 'files' requires 1 or 2 arguments",
- segments[3].first);
- }
- }
- else if (segments[0].second == "interactive")
- {
- if (segments.size() > 1)
- {
- return add_error("unexpected arguments: binary config 'interactive' does not accept any arguments",
- segments[1].first);
- }
-
- state->interactive = true;
- }
- else if (segments[0].second == "nugetconfig")
- {
- if (segments.size() < 2)
- {
- return add_error(
- "expected arguments: binary config 'nugetconfig' requires at least a source argument",
- segments[0].first);
- }
-
- auto p = fs::u8path(segments[1].second);
- if (!p.is_absolute())
- {
- return add_error("expected arguments: path arguments for binary config strings must be absolute",
- segments[1].first);
- }
-
- handle_readwrite(state->configs_to_read, state->configs_to_write, std::move(p), segments, 2);
- if (segments.size() > 3)
- {
- return add_error("unexpected arguments: binary config 'nugetconfig' requires 1 or 2 arguments",
- segments[3].first);
- }
- }
- else if (segments[0].second == "nuget")
- {
- if (segments.size() < 2)
- {
- return add_error("expected arguments: binary config 'nuget' requires at least a source argument",
- segments[0].first);
- }
-
- auto&& p = segments[1].second;
- if (p.empty())
- {
- return add_error("unexpected arguments: binary config 'nuget' requires non-empty source");
- }
-
- handle_readwrite(state->sources_to_read, state->sources_to_write, std::move(p), segments, 2);
- if (segments.size() > 3)
- {
- return add_error("unexpected arguments: binary config 'nuget' requires 1 or 2 arguments",
- segments[3].first);
- }
- }
- else if (segments[0].second == "default")
- {
- if (segments.size() > 2)
- {
- return add_error("unexpected arguments: binary config 'default' does not take more than 1 argument",
- segments[0].first);
- }
-
- const auto& maybe_home = default_cache_path();
- if (!maybe_home.has_value())
- {
- return add_error(maybe_home.error(), segments[0].first);
- }
-
- handle_readwrite(
- state->archives_to_read, state->archives_to_write, fs::path(*maybe_home.get()), segments, 1);
- }
- else if (segments[0].second == "x-azblob")
- {
- // Scheme: x-azblob,<baseurl>,<sas>[,<readwrite>]
- if (segments.size() < 3)
- {
- return add_error(
- "expected arguments: binary config 'azblob' requires at least a base-url and a SAS token",
- segments[0].first);
- }
-
- if (!Strings::starts_with(segments[1].second, "https://"))
- {
- return add_error(
- "invalid argument: binary config 'azblob' requires an https base url as the first argument",
- segments[1].first);
- }
-
- if (Strings::starts_with(segments[2].second, "?"))
- {
- return add_error("invalid argument: binary config 'azblob' requires a SAS token without a "
- "preceeding '?' as the second argument",
- segments[2].first);
- }
-
- if (segments.size() > 4)
- {
- return add_error("unexpected arguments: binary config 'azblob' requires 2 or 3 arguments",
- segments[4].first);
- }
-
- auto p = segments[1].second;
- if (p.back() != '/')
- {
- p.push_back('/');
- }
-
- p.append("<SHA>.zip");
- if (!Strings::starts_with(segments[2].second, "?"))
- {
- p.push_back('?');
- }
-
- p.append(segments[2].second);
- state->secrets.push_back(segments[2].second);
- handle_readwrite(
- state->url_templates_to_get, state->azblob_templates_to_put, std::move(p), segments, 3);
- }
- else
- {
- return add_error(
- "unknown binary provider type: valid providers are 'clear', 'default', 'nuget', 'nugetconfig', "
- "'interactive', and 'files'",
- segments[0].first);
- }
- }
- };
-}
-
-ExpectedS<std::unique_ptr<IBinaryProvider>> vcpkg::create_binary_provider_from_configs(View<std::string> args)
-{
- std::string env_string = System::get_environment_variable("VCPKG_BINARY_SOURCES").value_or("");
- if (Debug::g_debugging)
- {
- const auto& cachepath = default_cache_path();
- if (cachepath.has_value())
- {
- Debug::print("Default binary cache path is: ", fs::u8string(*cachepath.get()), '\n');
- }
- else
- {
- Debug::print("No binary cache path. Reason: ", cachepath.error(), '\n');
- }
- }
-
- return create_binary_provider_from_configs_pure(env_string, args);
-}
-
-ExpectedS<std::unique_ptr<IBinaryProvider>> vcpkg::create_binary_provider_from_configs_pure(
- const std::string& env_string, View<std::string> args)
-{
- {
- auto metrics = Metrics::g_metrics.lock();
- if (!env_string.empty())
- {
- metrics->track_property("VCPKG_BINARY_SOURCES", "defined");
- }
-
- if (args.size() != 0)
- {
- metrics->track_property("binarycaching-source", "defined");
- }
- }
-
- State s;
-
- BinaryConfigParser default_parser("default,readwrite", "<defaults>", &s);
- default_parser.parse();
- if (auto err = default_parser.get_error())
- {
- return err->get_message();
- }
-
- BinaryConfigParser env_parser(env_string, "VCPKG_BINARY_SOURCES", &s);
- env_parser.parse();
- if (auto err = env_parser.get_error())
- {
- return err->format();
- }
-
- for (auto&& arg : args)
- {
- BinaryConfigParser arg_parser(arg, "<command>", &s);
- arg_parser.parse();
- if (auto err = arg_parser.get_error())
- {
- return err->format();
- }
- }
-
- if (s.m_cleared)
- {
- Metrics::g_metrics.lock()->track_property("binarycaching-clear", "defined");
- }
-
- std::vector<std::unique_ptr<IBinaryProvider>> providers;
- if (!s.archives_to_read.empty() || !s.archives_to_write.empty() || !s.azblob_templates_to_put.empty())
- {
- providers.push_back(std::make_unique<ArchivesBinaryProvider>(std::move(s.archives_to_read),
- std::move(s.archives_to_write),
- std::move(s.azblob_templates_to_put),
- std::move(s.secrets)));
- }
-
- if (!s.url_templates_to_get.empty())
- {
- Metrics::g_metrics.lock()->track_property("binarycaching-url-get", "defined");
- providers.push_back(std::make_unique<HttpGetBinaryProvider>(std::move(s.url_templates_to_get)));
- }
-
- if (!s.sources_to_read.empty() || !s.sources_to_write.empty() || !s.configs_to_read.empty() ||
- !s.configs_to_write.empty())
- {
- Metrics::g_metrics.lock()->track_property("binarycaching-nuget", "defined");
- providers.push_back(std::make_unique<NugetBinaryProvider>(std::move(s.sources_to_read),
- std::move(s.sources_to_write),
- std::move(s.configs_to_read),
- std::move(s.configs_to_write),
- s.interactive));
- }
-
- return {std::make_unique<MergeBinaryProviders>(std::move(providers))};
-}
-
-std::string vcpkg::reformat_version(const std::string& version, const std::string& abi_tag)
-{
- static const std::regex semver_matcher(R"(v?(\d+)(\.\d+|$)(\.\d+)?.*)");
-
- std::smatch sm;
- if (std::regex_match(version.cbegin(), version.cend(), sm, semver_matcher))
- {
- auto major = trim_leading_zeroes(sm.str(1));
- auto minor = sm.size() > 2 && !sm.str(2).empty() ? trim_leading_zeroes(sm.str(2).substr(1)) : "0";
- auto patch = sm.size() > 3 && !sm.str(3).empty() ? trim_leading_zeroes(sm.str(3).substr(1)) : "0";
- return Strings::concat(major, '.', minor, '.', patch, "-vcpkg", abi_tag);
- }
-
- static const std::regex date_matcher(R"((\d\d\d\d)-(\d\d)-(\d\d).*)");
- if (std::regex_match(version.cbegin(), version.cend(), sm, date_matcher))
- {
- return Strings::concat(trim_leading_zeroes(sm.str(1)),
- '.',
- trim_leading_zeroes(sm.str(2)),
- '.',
- trim_leading_zeroes(sm.str(3)),
- "-vcpkg",
- abi_tag);
- }
-
- return Strings::concat("0.0.0-vcpkg", abi_tag);
-}
-
-details::NuGetRepoInfo details::get_nuget_repo_info_from_env()
-{
- auto vcpkg_nuget_repository = System::get_environment_variable("VCPKG_NUGET_REPOSITORY");
- if (auto p = vcpkg_nuget_repository.get())
- {
- Metrics::g_metrics.lock()->track_property("VCPKG_NUGET_REPOSITORY", "defined");
- return {std::move(*p)};
- }
-
- auto gh_repo = System::get_environment_variable("GITHUB_REPOSITORY").value_or("");
- if (gh_repo.empty())
- {
- return {};
- }
-
- auto gh_server = System::get_environment_variable("GITHUB_SERVER_URL").value_or("");
- if (gh_server.empty())
- {
- return {};
- }
-
- Metrics::g_metrics.lock()->track_property("GITHUB_REPOSITORY", "defined");
- return {Strings::concat(gh_server, '/', gh_repo, ".git"),
- System::get_environment_variable("GITHUB_REF").value_or(""),
- System::get_environment_variable("GITHUB_SHA").value_or("")};
-}
-
-std::string vcpkg::generate_nuspec(const VcpkgPaths& paths,
- const Dependencies::InstallPlanAction& action,
- const vcpkg::NugetReference& ref,
- details::NuGetRepoInfo rinfo)
-{
- auto& spec = action.spec;
- auto& scf = *action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO).source_control_file;
- auto& version = scf.core_paragraph->version;
- const auto& abi_info = action.abi_info.value_or_exit(VCPKG_LINE_INFO);
- const auto& compiler_info = abi_info.compiler_info.value_or_exit(VCPKG_LINE_INFO);
- std::string description =
- Strings::concat("NOT FOR DIRECT USE. Automatically generated cache package.\n\n",
- Strings::join("\n ", scf.core_paragraph->description),
- "\n\nVersion: ",
- version,
- "\nTriplet: ",
- spec.triplet().to_string(),
- "\nCXX Compiler id: ",
- compiler_info.id,
- "\nCXX Compiler version: ",
- compiler_info.version,
- "\nTriplet/Compiler hash: ",
- abi_info.triplet_abi.value_or_exit(VCPKG_LINE_INFO),
- "\nFeatures:",
- Strings::join(",", action.feature_list, [](const std::string& s) { return " " + s; }),
- "\nDependencies:\n");
-
- for (auto&& dep : action.package_dependencies)
- {
- Strings::append(description, " ", dep.name(), '\n');
- }
-
- XmlSerializer xml;
- xml.open_tag("package").line_break();
- xml.open_tag("metadata").line_break();
- xml.simple_tag("id", ref.id).line_break();
- xml.simple_tag("version", ref.version).line_break();
- if (!scf.core_paragraph->homepage.empty())
- {
- xml.simple_tag("projectUrl", scf.core_paragraph->homepage);
- }
-
- xml.simple_tag("authors", "vcpkg").line_break();
- xml.simple_tag("description", description).line_break();
- xml.open_tag("packageTypes");
- xml.start_complex_open_tag("packageType").text_attr("name", "vcpkg").finish_self_closing_complex_tag();
- xml.close_tag("packageTypes").line_break();
- if (!rinfo.repo.empty())
- {
- xml.start_complex_open_tag("repository").text_attr("type", "git").text_attr("url", rinfo.repo);
- if (!rinfo.branch.empty())
- {
- xml.text_attr("branch", rinfo.branch);
- }
-
- if (!rinfo.commit.empty())
- {
- xml.text_attr("commit", rinfo.commit);
- }
-
- xml.finish_self_closing_complex_tag().line_break();
- }
-
- xml.close_tag("metadata").line_break();
- xml.open_tag("files");
- xml.start_complex_open_tag("file")
- .text_attr("src", fs::u8string(paths.package_dir(spec) / fs::u8path("**")))
- .text_attr("target", "")
- .finish_self_closing_complex_tag();
- xml.close_tag("files").line_break();
- xml.close_tag("package").line_break();
- return std::move(xml.buf);
-}
-
-void vcpkg::help_topic_binary_caching(const VcpkgPaths&)
-{
- HelpTableFormatter tbl;
- tbl.text("Vcpkg can cache compiled packages to accelerate restoration on a single machine or across the network."
- " By default, vcpkg will save builds to a local machine cache. This can be disabled by passing "
- "`--binarysource=clear` as the last option on the command line.");
- tbl.blank();
- tbl.blank();
- tbl.text(
- "Binary caching can be further configured by either passing `--binarysource=<source>` options "
- "to every command line or setting the `VCPKG_BINARY_SOURCES` environment variable to a set of sources (Ex: "
- "\"<source>;<source>;...\"). Command line sources are interpreted after environment sources.");
- tbl.blank();
- tbl.blank();
- tbl.header("Valid source strings");
- tbl.format("clear", "Removes all previous sources");
- tbl.format("default[,<rw>]", "Adds the default file-based location.");
- tbl.format("files,<path>[,<rw>]", "Adds a custom file-based location.");
- tbl.format("nuget,<uri>[,<rw>]",
- "Adds a NuGet-based source; equivalent to the `-Source` parameter of the NuGet CLI.");
- tbl.format("nugetconfig,<path>[,<rw>]",
- "Adds a NuGet-config-file-based source; equivalent to the `-Config` parameter of the NuGet CLI. This "
- "config should specify `defaultPushSource` for uploads.");
- tbl.format("x-azblob,<url>,<sas>[,<rw>]",
- "**Experimental: will change or be removed without warning** Adds an Azure Blob Storage source. Uses "
- "Shared Access Signature validation. URL should include the container path.");
- tbl.format("interactive", "Enables interactive credential management for some source types");
- tbl.blank();
- tbl.text("The `<rw>` optional parameter for certain strings controls whether they will be consulted for "
- "downloading binaries and whether on-demand builds will be uploaded to that remote. It can be specified "
- "as 'read', 'write', or 'readwrite'.");
- tbl.blank();
- tbl.text("The `nuget` and `nugetconfig` source providers additionally respect certain environment variables while "
- "generating nuget packages. The `metadata.repository` field will be optionally generated like:\n"
- "\n"
- " <repository type=\"git\" url=\"$VCPKG_NUGET_REPOSITORY\"/>\n"
- "or\n"
- " <repository type=\"git\"\n"
- " url=\"${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git\"\n"
- " branch=\"${GITHUB_REF}\"\n"
- " commit=\"${GITHUB_SHA}\"/>\n"
- "\n"
- "if the appropriate environment variables are defined and non-empty.\n");
- tbl.blank();
- tbl.text("NuGet's cache is not used by default. To use it for every nuget-based source, set the environment "
- "variable `VCPKG_USE_NUGET_CACHE` to `true` (case-insensitive) or `1`.\n");
- tbl.blank();
- System::print2(tbl.m_str);
- const auto& maybe_cachepath = default_cache_path();
- if (auto p = maybe_cachepath.get())
- {
- System::print2(
- "\nBased on your system settings, the default path to store binaries is\n ",
- fs::u8string(*p),
- "\nThis consults %LOCALAPPDATA%/%APPDATA% on Windows and $XDG_CACHE_HOME or $HOME on other platforms.\n");
- }
-
- System::print2("\nExtended documentation is available at "
- "https://github.com/Microsoft/vcpkg/tree/master/docs/users/binarycaching.md \n");
-}
-
-std::string vcpkg::generate_nuget_packages_config(const Dependencies::ActionPlan& action)
-{
- auto refs = Util::fmap(action.install_actions,
- [&](const Dependencies::InstallPlanAction& ipa) { return NugetReference(ipa); });
- XmlSerializer xml;
- xml.emit_declaration().line_break();
- xml.open_tag("packages").line_break();
- for (auto&& ref : refs)
- {
- xml.start_complex_open_tag("package")
- .text_attr("id", ref.id)
- .text_attr("version", ref.version)
- .finish_self_closing_complex_tag()
- .line_break();
- }
-
- xml.close_tag("packages").line_break();
- return std::move(xml.buf);
-}
diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp
deleted file mode 100644
index f86081223..000000000
--- a/toolsrc/src/vcpkg/binaryparagraph.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binaryparagraph.h>
-#include <vcpkg/paragraphparser.h>
-#include <vcpkg/paragraphs.h>
-
-namespace vcpkg
-{
- namespace Fields
- {
- static const std::string PACKAGE = "Package";
- static const std::string VERSION = "Version";
- static const std::string PORT_VERSION = "Port-Version";
- static const std::string ARCHITECTURE = "Architecture";
- static const std::string MULTI_ARCH = "Multi-Arch";
- }
-
- namespace Fields
- {
- static const std::string ABI = "Abi";
- static const std::string FEATURE = "Feature";
- static const std::string DESCRIPTION = "Description";
- static const std::string MAINTAINER = "Maintainer";
- static const std::string DEPENDS = "Depends";
- static const std::string DEFAULT_FEATURES = "Default-Features";
- static const std::string TYPE = "Type";
- }
-
- BinaryParagraph::BinaryParagraph() = default;
-
- BinaryParagraph::BinaryParagraph(Parse::Paragraph fields)
- {
- using namespace vcpkg::Parse;
-
- ParagraphParser parser(std::move(fields));
-
- {
- std::string name;
- parser.required_field(Fields::PACKAGE, name);
- std::string architecture;
- parser.required_field(Fields::ARCHITECTURE, architecture);
- this->spec = PackageSpec(std::move(name), Triplet::from_canonical_name(std::move(architecture)));
- }
-
- // one or the other
- this->version = parser.optional_field(Fields::VERSION);
- this->feature = parser.optional_field(Fields::FEATURE);
-
- auto pv_str = parser.optional_field(Fields::PORT_VERSION);
- this->port_version = 0;
- if (!pv_str.empty())
- {
- auto pv_opt = Strings::strto<int>(pv_str);
- if (auto pv = pv_opt.get())
- {
- this->port_version = *pv;
- }
- else
- {
- parser.add_type_error(Fields::PORT_VERSION, "a non-negative integer");
- }
- }
-
- this->description = Strings::split(parser.optional_field(Fields::DESCRIPTION), '\n');
- for (auto& desc : this->description)
- {
- desc = Strings::trim(std::move(desc));
- }
- this->maintainers = Strings::split(parser.optional_field(Fields::MAINTAINER), '\n');
- for (auto& maintainer : this->maintainers)
- {
- maintainer = Strings::trim(std::move(maintainer));
- }
-
- this->abi = parser.optional_field(Fields::ABI);
-
- std::string multi_arch;
- parser.required_field(Fields::MULTI_ARCH, multi_arch);
-
- this->dependencies = Util::fmap(
- parse_qualified_specifier_list(parser.optional_field(Fields::DEPENDS)).value_or_exit(VCPKG_LINE_INFO),
- [](const ParsedQualifiedSpecifier& dep) {
- // for compatibility with previous vcpkg versions, we discard all irrelevant information
- return dep.name;
- });
- if (!this->is_feature())
- {
- this->default_features = parse_default_features_list(parser.optional_field(Fields::DEFAULT_FEATURES))
- .value_or_exit(VCPKG_LINE_INFO);
- }
-
- this->type = Type::from_string(parser.optional_field(Fields::TYPE));
-
- if (const auto err = parser.error_info(this->spec.to_string()))
- {
- System::print2(System::Color::error, "Error: while parsing the Binary Paragraph for ", this->spec, '\n');
- print_error_message(err);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- // prefer failing above when possible because it gives better information
- Checks::check_exit(VCPKG_LINE_INFO, multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch);
- }
-
- BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh,
- Triplet triplet,
- const std::string& abi_tag,
- const std::vector<FeatureSpec>& deps)
- : spec(spgh.name, triplet)
- , version(spgh.version)
- , port_version(spgh.port_version)
- , description(spgh.description)
- , maintainers(spgh.maintainers)
- , feature()
- , default_features(spgh.default_features)
- , dependencies()
- , abi(abi_tag)
- , type(spgh.type)
- {
- this->dependencies = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec().name(); });
- Util::sort_unique_erase(this->dependencies);
- }
-
- BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh,
- const FeatureParagraph& fpgh,
- Triplet triplet,
- const std ::vector<FeatureSpec>& deps)
- : spec(spgh.name, triplet)
- , version()
- , port_version()
- , description(fpgh.description)
- , maintainers()
- , feature(fpgh.name)
- , default_features()
- , dependencies()
- , abi()
- , type(spgh.type)
- {
- this->dependencies = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec().name(); });
- Util::sort_unique_erase(this->dependencies);
- }
-
- std::string BinaryParagraph::displayname() const
- {
- if (!this->is_feature() || this->feature == "core")
- return Strings::format("%s:%s", this->spec.name(), this->spec.triplet());
- return Strings::format("%s[%s]:%s", this->spec.name(), this->feature, this->spec.triplet());
- }
-
- std::string BinaryParagraph::dir() const { return this->spec.dir(); }
-
- std::string BinaryParagraph::fullstem() const
- {
- return Strings::format("%s_%s_%s", this->spec.name(), this->version, this->spec.triplet());
- }
-
- bool operator==(const BinaryParagraph& lhs, const BinaryParagraph& rhs)
- {
- if (lhs.spec != rhs.spec) return false;
- if (lhs.version != rhs.version) return false;
- if (lhs.port_version != rhs.port_version) return false;
- if (lhs.description != rhs.description) return false;
- if (lhs.maintainers != rhs.maintainers) return false;
- if (lhs.feature != rhs.feature) return false;
- if (lhs.default_features != rhs.default_features) return false;
- if (lhs.dependencies != rhs.dependencies) return false;
- if (lhs.abi != rhs.abi) return false;
- if (lhs.type != rhs.type) return false;
-
- return true;
- }
-
- bool operator!=(const BinaryParagraph& lhs, const BinaryParagraph& rhs) { return !(lhs == rhs); }
-
- static void serialize_string(StringView name, const std::string& field, std::string& out_str)
- {
- if (field.empty())
- {
- return;
- }
-
- out_str.append(name.begin(), name.end()).append(": ").append(field).push_back('\n');
- }
- static void serialize_array(StringView name,
- const std::vector<std::string>& array,
- std::string& out_str,
- const char* joiner = ", ")
- {
- if (array.empty())
- {
- return;
- }
-
- out_str.append(name.begin(), name.end()).append(": ");
- out_str.append(Strings::join(joiner, array));
- out_str.push_back('\n');
- }
- static void serialize_paragraph(StringView name, const std::vector<std::string>& array, std::string& out_str)
- {
- serialize_array(name, array, out_str, "\n ");
- }
-
- void serialize(const BinaryParagraph& pgh, std::string& out_str)
- {
- const size_t initial_end = out_str.size();
-
- serialize_string(Fields::PACKAGE, pgh.spec.name(), out_str);
-
- serialize_string(Fields::VERSION, pgh.version, out_str);
- if (pgh.port_version != 0)
- {
- out_str.append(Fields::PORT_VERSION).append(": ").append(std::to_string(pgh.port_version)).push_back('\n');
- }
-
- if (pgh.is_feature())
- {
- serialize_string(Fields::FEATURE, pgh.feature, out_str);
- }
-
- if (!pgh.dependencies.empty())
- {
- serialize_array(Fields::DEPENDS, pgh.dependencies, out_str);
- }
-
- serialize_string(Fields::ARCHITECTURE, pgh.spec.triplet().to_string(), out_str);
- serialize_string(Fields::MULTI_ARCH, "same", out_str);
-
- serialize_paragraph(Fields::MAINTAINER, pgh.maintainers, out_str);
-
- serialize_string(Fields::ABI, pgh.abi, out_str);
-
- serialize_paragraph(Fields::DESCRIPTION, pgh.description, out_str);
-
- serialize_string(Fields::TYPE, Type::to_string(pgh.type), out_str);
- serialize_array(Fields::DEFAULT_FEATURES, pgh.default_features, out_str);
-
- // sanity check the serialized data
- const auto my_paragraph = out_str.substr(initial_end);
- auto parsed_paragraph = Paragraphs::parse_single_paragraph(
- out_str.substr(initial_end), "vcpkg::serialize(const BinaryParagraph&, std::string&)");
- if (!parsed_paragraph.has_value())
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- R"([sanity check] Failed to parse a serialized binary paragraph.
-Please open an issue at https://github.com/microsoft/vcpkg, with the following output:
- Error: %s
-
-=== Serialized BinaryParagraph ===
-%s
- )",
- parsed_paragraph.error(),
- my_paragraph);
- }
-
- auto binary_paragraph = BinaryParagraph(*parsed_paragraph.get());
- if (binary_paragraph != pgh)
- {
- const auto& join_str = R"(", ")";
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- R"([sanity check] The serialized binary paragraph was different from the original binary paragraph.
-Please open an issue at https://github.com/microsoft/vcpkg, with the following output:
-
-=== Original BinaryParagraph ===
-spec: "%s"
-version: "%s"
-port_version: %d
-description: ["%s"]
-maintainers: ["%s"]
-feature: "%s"
-default_features: ["%s"]
-dependencies: ["%s"]
-abi: "%s"
-type: %s
-
-=== Serialized BinaryParagraph ===
-spec: "%s"
-version: "%s"
-port_version: %d
-description: ["%s"]
-maintainers: ["%s"]
-feature: "%s"
-default_features: ["%s"]
-dependencies: ["%s"]
-abi: "%s"
-type: %s
-)",
- pgh.spec.to_string(),
- pgh.version,
- pgh.port_version,
- Strings::join(join_str, pgh.description),
- Strings::join(join_str, pgh.maintainers),
- pgh.feature,
- Strings::join(join_str, pgh.default_features),
- Strings::join(join_str, pgh.dependencies),
- pgh.abi,
- Type::to_string(pgh.type),
- binary_paragraph.spec.to_string(),
- binary_paragraph.version,
- binary_paragraph.port_version,
- Strings::join(join_str, binary_paragraph.description),
- Strings::join(join_str, binary_paragraph.maintainers),
- binary_paragraph.feature,
- Strings::join(join_str, binary_paragraph.default_features),
- Strings::join(join_str, binary_paragraph.dependencies),
- binary_paragraph.abi,
- Type::to_string(binary_paragraph.type));
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
deleted file mode 100644
index b38062f0c..000000000
--- a/toolsrc/src/vcpkg/build.cpp
+++ /dev/null
@@ -1,1491 +0,0 @@
-#include <vcpkg/base/cache.h>
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/chrono.h>
-#include <vcpkg/base/enums.h>
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/optional.h>
-#include <vcpkg/base/stringliteral.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/build.h>
-#include <vcpkg/buildenvironment.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/commands.version.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/postbuildlint.h>
-#include <vcpkg/statusparagraphs.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkglib.h>
-
-using namespace vcpkg;
-using vcpkg::Build::BuildResult;
-using vcpkg::Parse::ParseControlErrorInfo;
-using vcpkg::Parse::ParseExpected;
-using vcpkg::PortFileProvider::PathsPortFileProvider;
-
-namespace
-{
- using vcpkg::PackageSpec;
- using vcpkg::VcpkgPaths;
- using vcpkg::Build::IBuildLogsRecorder;
- struct NullBuildLogsRecorder final : IBuildLogsRecorder
- {
- void record_build_result(const VcpkgPaths& paths, const PackageSpec& spec, BuildResult result) const override
- {
- (void)paths;
- (void)spec;
- (void)result;
- }
- };
-
- static const NullBuildLogsRecorder null_build_logs_recorder_instance;
-}
-
-namespace vcpkg::Build
-{
- using Dependencies::InstallPlanAction;
- using Dependencies::InstallPlanType;
-
- void Command::perform_and_exit_ex(const VcpkgCmdArguments& args,
- const FullPackageSpec& full_spec,
- const SourceControlFileLocation& scfl,
- const PathsPortFileProvider& provider,
- IBinaryProvider& binaryprovider,
- const IBuildLogsRecorder& build_logs_recorder,
- const VcpkgPaths& paths)
- {
- Checks::exit_with_code(VCPKG_LINE_INFO,
- perform_ex(args, full_spec, scfl, provider, binaryprovider, build_logs_recorder, paths));
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("build zlib:x64-windows"),
- 1,
- 1,
- {{}, {}},
- nullptr,
- };
-
- void Command::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- Checks::exit_with_code(VCPKG_LINE_INFO, perform(args, paths, default_triplet));
- }
-
- int Command::perform_ex(const VcpkgCmdArguments& args,
- const FullPackageSpec& full_spec,
- const SourceControlFileLocation& scfl,
- const PathsPortFileProvider& provider,
- IBinaryProvider& binaryprovider,
- const IBuildLogsRecorder& build_logs_recorder,
- const VcpkgPaths& paths)
- {
- auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
- auto& var_provider = *var_provider_storage;
- var_provider.load_dep_info_vars({{full_spec.package_spec}});
-
- StatusParagraphs status_db = database_load_check(paths);
-
- auto action_plan = Dependencies::create_feature_install_plan(
- provider, var_provider, std::vector<FullPackageSpec>{full_spec}, status_db);
-
- var_provider.load_tag_vars(action_plan, provider);
-
- const PackageSpec& spec = full_spec.package_spec;
- const SourceControlFile& scf = *scfl.source_control_file;
-
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO,
- spec.name() == scf.core_paragraph->name,
- Strings::format("The Source field inside the CONTROL file does not match the port directory: '%s' != '%s'",
- scf.core_paragraph->name,
- spec.name()));
-
- compute_all_abis(paths, action_plan, var_provider, status_db);
-
- InstallPlanAction* action = nullptr;
- for (auto& install_action : action_plan.already_installed)
- {
- if (install_action.spec == full_spec.package_spec)
- {
- action = &install_action;
- }
- }
- for (auto& install_action : action_plan.install_actions)
- {
- if (install_action.spec == full_spec.package_spec)
- {
- action = &install_action;
- }
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, action != nullptr);
- ASSUME(action != nullptr);
- action->build_options = default_build_package_options;
- action->build_options.editable = Editable::YES;
- action->build_options.clean_buildtrees = CleanBuildtrees::NO;
- action->build_options.clean_packages = CleanPackages::NO;
-
- const auto build_timer = Chrono::ElapsedTimer::create_started();
- const auto result = Build::build_package(args, paths, *action, binaryprovider, build_logs_recorder, status_db);
- System::print2("Elapsed time for package ", spec, ": ", build_timer, '\n');
-
- if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES)
- {
- System::print2(System::Color::error,
- "The build command requires all dependencies to be already installed.\n");
- System::print2("The following dependencies are missing:\n\n");
- for (const auto& p : result.unmet_dependencies)
- {
- System::print2(" ", p, '\n');
- }
- System::print2('\n');
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, result.code != BuildResult::EXCLUDED);
-
- if (result.code != BuildResult::SUCCEEDED)
- {
- System::print2(System::Color::error, Build::create_error_message(result.code, spec), '\n');
- System::print2(Build::create_user_troubleshooting_message(spec), '\n');
- return 1;
- }
-
- return 0;
- }
-
- int Command::perform(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- // Build only takes a single package and all dependencies must already be installed
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
- std::string first_arg = args.command_arguments.at(0);
-
- auto binaryprovider = create_binary_provider_from_configs(args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
-
- const FullPackageSpec spec = Input::check_and_get_full_package_spec(
- std::move(first_arg), default_triplet, COMMAND_STRUCTURE.example_text);
-
- Input::check_triplet(spec.package_spec.triplet(), paths);
-
- PathsPortFileProvider provider(paths, args.overlay_ports);
- const auto port_name = spec.package_spec.name();
- const auto* scfl = provider.get_control_file(port_name).get();
-
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO, scfl != nullptr, "Error: Couldn't find port '%s'", port_name);
- ASSUME(scfl != nullptr);
-
- return perform_ex(args,
- spec,
- *scfl,
- provider,
- args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(),
- Build::null_build_logs_recorder(),
- paths);
- }
-
- void BuildCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- Build::Command::perform_and_exit(args, paths, default_triplet);
- }
-}
-
-namespace vcpkg::Build
-{
- static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage";
- static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs";
- static const std::string NAME_DLLS_WITHOUT_EXPORTS = "PolicyDLLsWithoutExports";
- static const std::string NAME_DLLS_IN_STATIC_LIBRARY = "PolicyDLLsInStaticLibrary";
- static const std::string NAME_MISMATCHED_NUMBER_OF_BINARIES = "PolicyMismatchedNumberOfBinaries";
- static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT";
- static const std::string NAME_EMPTY_INCLUDE_FOLDER = "PolicyEmptyIncludeFolder";
- static const std::string NAME_ALLOW_OBSOLETE_MSVCRT = "PolicyAllowObsoleteMsvcrt";
- static const std::string NAME_ALLOW_RESTRICTED_HEADERS = "PolicyAllowRestrictedHeaders";
- static const std::string NAME_SKIP_DUMPBIN_CHECKS = "PolicySkipDumpbinChecks";
- static const std::string NAME_SKIP_ARCHITECTURE_CHECK = "PolicySkipArchitectureCheck";
-
- static std::remove_const_t<decltype(ALL_POLICIES)> generate_all_policies()
- {
- std::remove_const_t<decltype(ALL_POLICIES)> res{};
- for (size_t i = 0; i < res.size(); ++i)
- {
- res[i] = static_cast<BuildPolicy>(i);
- }
-
- return res;
- }
-
- decltype(ALL_POLICIES) ALL_POLICIES = generate_all_policies();
-
- const std::string& to_string(BuildPolicy policy)
- {
- switch (policy)
- {
- case BuildPolicy::EMPTY_PACKAGE: return NAME_EMPTY_PACKAGE;
- case BuildPolicy::DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS;
- case BuildPolicy::DLLS_WITHOUT_EXPORTS: return NAME_DLLS_WITHOUT_EXPORTS;
- case BuildPolicy::DLLS_IN_STATIC_LIBRARY: return NAME_DLLS_IN_STATIC_LIBRARY;
- case BuildPolicy::MISMATCHED_NUMBER_OF_BINARIES: return NAME_MISMATCHED_NUMBER_OF_BINARIES;
- case BuildPolicy::ONLY_RELEASE_CRT: return NAME_ONLY_RELEASE_CRT;
- case BuildPolicy::EMPTY_INCLUDE_FOLDER: return NAME_EMPTY_INCLUDE_FOLDER;
- case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return NAME_ALLOW_OBSOLETE_MSVCRT;
- case BuildPolicy::ALLOW_RESTRICTED_HEADERS: return NAME_ALLOW_RESTRICTED_HEADERS;
- case BuildPolicy::SKIP_DUMPBIN_CHECKS: return NAME_SKIP_DUMPBIN_CHECKS;
- case BuildPolicy::SKIP_ARCHITECTURE_CHECK: return NAME_SKIP_ARCHITECTURE_CHECK;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- CStringView to_cmake_variable(BuildPolicy policy)
- {
- switch (policy)
- {
- case BuildPolicy::EMPTY_PACKAGE: return "VCPKG_POLICY_EMPTY_PACKAGE";
- case BuildPolicy::DLLS_WITHOUT_LIBS: return "VCPKG_POLICY_DLLS_WITHOUT_LIBS";
- case BuildPolicy::DLLS_WITHOUT_EXPORTS: return "VCPKG_POLICY_DLLS_WITHOUT_EXPORTS";
- case BuildPolicy::DLLS_IN_STATIC_LIBRARY: return "VCPKG_POLICY_DLLS_IN_STATIC_LIBRARY";
- case BuildPolicy::MISMATCHED_NUMBER_OF_BINARIES: return "VCPKG_POLICY_MISMATCHED_NUMBER_OF_BINARIES";
- case BuildPolicy::ONLY_RELEASE_CRT: return "VCPKG_POLICY_ONLY_RELEASE_CRT";
- case BuildPolicy::EMPTY_INCLUDE_FOLDER: return "VCPKG_POLICY_EMPTY_INCLUDE_FOLDER";
- case BuildPolicy::ALLOW_OBSOLETE_MSVCRT: return "VCPKG_POLICY_ALLOW_OBSOLETE_MSVCRT";
- case BuildPolicy::ALLOW_RESTRICTED_HEADERS: return "VCPKG_POLICY_ALLOW_RESTRICTED_HEADERS";
- case BuildPolicy::SKIP_DUMPBIN_CHECKS: return "VCPKG_POLICY_SKIP_DUMPBIN_CHECKS";
- case BuildPolicy::SKIP_ARCHITECTURE_CHECK: return "VCPKG_POLICY_SKIP_ARCHITECTURE_CHECK";
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- static const std::string NAME_BUILD_IN_DOWNLOAD = "BUILT_IN";
- static const std::string NAME_ARIA2_DOWNLOAD = "ARIA2";
-
- const std::string& to_string(DownloadTool tool)
- {
- switch (tool)
- {
- case DownloadTool::BUILT_IN: return NAME_BUILD_IN_DOWNLOAD;
- case DownloadTool::ARIA2: return NAME_ARIA2_DOWNLOAD;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- Optional<LinkageType> to_linkage_type(const std::string& str)
- {
- if (str == "dynamic") return LinkageType::DYNAMIC;
- if (str == "static") return LinkageType::STATIC;
- return nullopt;
- }
-
- namespace BuildInfoRequiredField
- {
- static const std::string CRT_LINKAGE = "CRTLinkage";
- static const std::string LIBRARY_LINKAGE = "LibraryLinkage";
- }
-
- static CStringView to_vcvarsall_target(const std::string& cmake_system_name)
- {
- if (cmake_system_name.empty()) return "";
- if (cmake_system_name == "Windows") return "";
- if (cmake_system_name == "WindowsStore") return "store";
-
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Error: Could not map VCPKG_CMAKE_SYSTEM_NAME '%s' to a vcvarsall platform. "
- "Supported systems are '', 'Windows' and 'WindowsStore'.",
- cmake_system_name);
- }
-
- static CStringView to_vcvarsall_toolchain(const std::string& target_architecture,
- const Toolset& toolset,
- View<Toolset> all_toolsets)
- {
-#if defined(_WIN32)
- auto maybe_target_arch = System::to_cpu_architecture(target_architecture);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, maybe_target_arch.has_value(), "Invalid architecture string: %s", target_architecture);
- auto target_arch = maybe_target_arch.value_or_exit(VCPKG_LINE_INFO);
- auto host_architectures = System::get_supported_host_architectures();
-
- for (auto&& host : host_architectures)
- {
- const auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) {
- return host == opt.host_arch && target_arch == opt.target_arch;
- });
- if (it != toolset.supported_architectures.end()) return it->name;
- }
-
- System::print2("Error: Unsupported toolchain combination.\n");
- System::print2("Target was ",
- target_architecture,
- " but the chosen Visual Studio instance supports:\n ",
- Strings::join(", ",
- toolset.supported_architectures,
- [](const ToolsetArchOption& t) { return t.name.c_str(); }),
- "\nVcpkg selected ",
- fs::u8string(toolset.visual_studio_root_path),
- " as the Visual Studio instance.\nDetected instances:\n",
- Strings::join("",
- all_toolsets,
- [](const Toolset& t) {
- return Strings::concat(" ", fs::u8string(t.visual_studio_root_path), '\n');
- }),
- "\nSee "
- "https://github.com/microsoft/vcpkg/blob/master/docs/users/triplets.md#VCPKG_VISUAL_STUDIO_PATH "
- "for more information.\n");
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO);
-#else
- (void)target_architecture;
- (void)toolset;
- (void)all_toolsets;
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: vcvars-based toolchains are only usable on Windows platforms.");
-#endif
- }
-
-#if defined(_WIN32)
- const System::Environment& EnvCache::get_action_env(const VcpkgPaths& paths, const AbiInfo& abi_info)
- {
- auto build_env_cmd = make_build_env_cmd(
- *abi_info.pre_build_info, abi_info.toolset.value_or_exit(VCPKG_LINE_INFO), paths.get_all_toolsets());
-
- const auto& base_env = envs.get_lazy(abi_info.pre_build_info->passthrough_env_vars, [&]() -> EnvMapEntry {
- std::unordered_map<std::string, std::string> env;
-
- for (auto&& env_var : abi_info.pre_build_info->passthrough_env_vars)
- {
- auto env_val = System::get_environment_variable(env_var);
-
- if (env_val)
- {
- env[env_var] = env_val.value_or_exit(VCPKG_LINE_INFO);
- }
- }
- static constexpr StringLiteral s_extra_vars[] = {
- "VCPKG_COMMAND",
- "VCPKG_FORCE_SYSTEM_BINARIES",
- VcpkgCmdArguments::RECURSIVE_DATA_ENV,
- };
-
- for (auto var : s_extra_vars)
- {
- auto val = System::get_environment_variable(var);
- if (auto p_val = val.get()) env.emplace(var, *p_val);
- }
-
- return {env};
- });
-
- return base_env.cmd_cache.get_lazy(build_env_cmd, [&]() {
- const fs::path& powershell_exe_path = paths.get_tool_exe("powershell-core");
- auto clean_env = System::get_modified_clean_environment(
- base_env.env_map, fs::u8string(powershell_exe_path.parent_path()) + ";");
- if (build_env_cmd.empty())
- return clean_env;
- else
- return System::cmd_execute_modify_env(build_env_cmd, clean_env);
- });
- }
-#else
- const System::Environment& EnvCache::get_action_env(const VcpkgPaths&, const AbiInfo&)
- {
- return System::get_clean_environment();
- }
-#endif
-
- static CompilerInfo load_compiler_info(const VcpkgPaths& paths, const AbiInfo& abi_info);
-
- const CompilerInfo& EnvCache::get_compiler_info(const VcpkgPaths& paths, const AbiInfo& abi_info)
- {
- const auto& fs = paths.get_filesystem();
- Checks::check_exit(VCPKG_LINE_INFO, abi_info.pre_build_info != nullptr);
- const fs::path triplet_file_path = paths.get_triplet_file_path(abi_info.pre_build_info->triplet);
-
- auto tcfile = abi_info.pre_build_info->toolchain_file();
- auto&& toolchain_hash = m_toolchain_cache.get_lazy(
- tcfile, [&]() { return Hash::get_file_hash(VCPKG_LINE_INFO, fs, tcfile, Hash::Algorithm::Sha1); });
-
- auto&& triplet_entry = m_triplet_cache.get_lazy(triplet_file_path, [&]() -> TripletMapEntry {
- return TripletMapEntry{Hash::get_file_hash(VCPKG_LINE_INFO, fs, triplet_file_path, Hash::Algorithm::Sha1)};
- });
-
- return triplet_entry.compiler_info.get_lazy(toolchain_hash, [&]() -> CompilerInfo {
- if (m_compiler_tracking)
- {
- return load_compiler_info(paths, abi_info);
- }
- else
- {
- return CompilerInfo{};
- }
- });
- }
-
- const std::string& EnvCache::get_triplet_info(const VcpkgPaths& paths, const AbiInfo& abi_info)
- {
- const auto& fs = paths.get_filesystem();
- Checks::check_exit(VCPKG_LINE_INFO, abi_info.pre_build_info != nullptr);
- const fs::path triplet_file_path = paths.get_triplet_file_path(abi_info.pre_build_info->triplet);
-
- auto tcfile = abi_info.pre_build_info->toolchain_file();
- auto&& toolchain_hash = m_toolchain_cache.get_lazy(
- tcfile, [&]() { return Hash::get_file_hash(VCPKG_LINE_INFO, fs, tcfile, Hash::Algorithm::Sha1); });
-
- auto&& triplet_entry = m_triplet_cache.get_lazy(triplet_file_path, [&]() -> TripletMapEntry {
- return TripletMapEntry{Hash::get_file_hash(VCPKG_LINE_INFO, fs, triplet_file_path, Hash::Algorithm::Sha1)};
- });
-
- return triplet_entry.compiler_hashes.get_lazy(toolchain_hash, [&]() -> std::string {
- if (m_compiler_tracking)
- {
- auto& compiler_info = triplet_entry.compiler_info.get_lazy(toolchain_hash, [&]() -> CompilerInfo {
- if (m_compiler_tracking)
- {
- return load_compiler_info(paths, abi_info);
- }
- else
- {
- return CompilerInfo{};
- }
- });
- return Strings::concat(triplet_entry.hash, '-', toolchain_hash, '-', compiler_info.hash);
- }
- else
- {
- return triplet_entry.hash + "-" + toolchain_hash;
- }
- });
- }
-
- System::Command make_build_env_cmd(const PreBuildInfo& pre_build_info,
- const Toolset& toolset,
- View<Toolset> all_toolsets)
- {
- if (!pre_build_info.using_vcvars()) return {};
-
- const char* tonull = " >nul";
- if (Debug::g_debugging)
- {
- tonull = "";
- }
-
- const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset, all_toolsets);
- const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name);
-
- return System::Command{"cmd"}.string_arg("/c").raw_arg(
- Strings::format(R"("%s" %s %s %s %s 2>&1 <NUL)",
- fs::u8string(toolset.vcvarsall),
- Strings::join(" ", toolset.vcvarsall_options),
- arch,
- target,
- tonull));
- }
-
- static std::unique_ptr<BinaryControlFile> create_binary_control_file(
- const SourceParagraph& source_paragraph,
- Triplet triplet,
- const BuildInfo& build_info,
- const std::string& abi_tag,
- const std::vector<FeatureSpec>& core_dependencies)
- {
- auto bcf = std::make_unique<BinaryControlFile>();
- BinaryParagraph bpgh(source_paragraph, triplet, abi_tag, core_dependencies);
- if (const auto p_ver = build_info.version.get())
- {
- bpgh.version = *p_ver;
- }
-
- bcf->core_paragraph = std::move(bpgh);
- return bcf;
- }
-
- static void write_binary_control_file(const VcpkgPaths& paths, const BinaryControlFile& bcf)
- {
- std::string start = Strings::serialize(bcf.core_paragraph);
- for (auto&& feature : bcf.features)
- {
- start += "\n" + Strings::serialize(feature);
- }
- const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / fs::u8path("CONTROL");
- paths.get_filesystem().write_contents(binary_control_file, start, VCPKG_LINE_INFO);
- }
-
- static int get_concurrency()
- {
- static int concurrency = [] {
- auto user_defined_concurrency = System::get_environment_variable("VCPKG_MAX_CONCURRENCY");
- if (user_defined_concurrency)
- {
- return std::stoi(user_defined_concurrency.value_or_exit(VCPKG_LINE_INFO));
- }
- else
- {
- return System::get_num_logical_cores() + 1;
- }
- }();
-
- return concurrency;
- }
-
- static void get_generic_cmake_build_args(const VcpkgPaths& paths,
- Triplet triplet,
- const Toolset& toolset,
- std::vector<System::CMakeVariable>& out_vars)
- {
- Util::Vectors::append(&out_vars,
- std::initializer_list<System::CMakeVariable>{
- {"CMD", "BUILD"},
- {"DOWNLOADS", paths.downloads},
- {"TARGET_TRIPLET", triplet.canonical_name()},
- {"TARGET_TRIPLET_FILE", fs::u8string(paths.get_triplet_file_path(triplet))},
- {"VCPKG_BASE_VERSION", Commands::Version::base_version()},
- {"VCPKG_CONCURRENCY", std::to_string(get_concurrency())},
- {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
- });
- if (!System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
- {
- const fs::path& git_exe_path = paths.get_tool_exe(Tools::GIT);
- out_vars.push_back({"GIT", git_exe_path});
- }
- }
-
- static CompilerInfo load_compiler_info(const VcpkgPaths& paths, const AbiInfo& abi_info)
- {
- auto triplet = abi_info.pre_build_info->triplet;
- System::print2("Detecting compiler hash for triplet ", triplet, "...\n");
- auto buildpath = paths.buildtrees / "detect_compiler";
-
-#if !defined(_WIN32)
- // TODO: remove when vcpkg.exe is in charge for acquiring tools. Change introduced in vcpkg v0.0.107.
- // bootstrap should have already downloaded ninja, but making sure it is present in case it was deleted.
- (void)(paths.get_tool_exe(Tools::NINJA));
-#endif
- std::vector<System::CMakeVariable> cmake_args{
- {"CURRENT_PORT_DIR", paths.scripts / "detect_compiler"},
- {"CURRENT_BUILDTREES_DIR", buildpath},
- {"CURRENT_PACKAGES_DIR", paths.packages / ("detect_compiler_" + triplet.canonical_name())},
- };
- get_generic_cmake_build_args(paths, triplet, abi_info.toolset.value_or_exit(VCPKG_LINE_INFO), cmake_args);
-
- auto command = vcpkg::make_cmake_cmd(paths, paths.ports_cmake, std::move(cmake_args));
-
- const auto& env = paths.get_action_env(abi_info);
- auto& fs = paths.get_filesystem();
- if (!fs.exists(buildpath))
- {
- std::error_code err;
- fs.create_directory(buildpath, err);
- Checks::check_exit(VCPKG_LINE_INFO,
- !err.value(),
- "Failed to create directory '%s', code: %d",
- fs::u8string(buildpath),
- err.value());
- }
- auto stdoutlog = buildpath / ("stdout-" + triplet.canonical_name() + ".log");
- std::ofstream out_file(stdoutlog.native().c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
- Checks::check_exit(VCPKG_LINE_INFO, out_file, "Failed to open '%s' for writing", fs::u8string(stdoutlog));
- CompilerInfo compiler_info;
- std::string buf;
- int rc = System::cmd_execute_and_stream_lines(
- command,
- [&](StringView s) {
- static const StringLiteral s_hash_marker = "#COMPILER_HASH#";
- if (Strings::starts_with(s, s_hash_marker))
- {
- compiler_info.hash = s.data() + s_hash_marker.size();
- }
- static const StringLiteral s_version_marker = "#COMPILER_CXX_VERSION#";
- if (Strings::starts_with(s, s_version_marker))
- {
- compiler_info.version = s.data() + s_version_marker.size();
- }
- static const StringLiteral s_id_marker = "#COMPILER_CXX_ID#";
- if (Strings::starts_with(s, s_id_marker))
- {
- compiler_info.id = s.data() + s_id_marker.size();
- }
- Debug::print(s, '\n');
- Strings::append(buf, s, '\n');
- out_file.write(s.data(), s.size()).put('\n');
- Checks::check_exit(
- VCPKG_LINE_INFO, out_file, "Error occurred while writing '%s'", fs::u8string(stdoutlog));
- },
- env);
- out_file.close();
-
- if (compiler_info.hash.empty() || rc != 0)
- {
- Debug::print("Compiler information tracking can be disabled by passing --",
- VcpkgCmdArguments::FEATURE_FLAGS_ARG,
- "=-",
- VcpkgCmdArguments::COMPILER_TRACKING_FEATURE,
- "\n");
-
- System::print2("Error: while detecting compiler information:\nThe log content at ",
- fs::u8string(stdoutlog),
- " is:\n",
- buf);
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: vcpkg was unable to detect the active compiler's information. See above "
- "for the CMake failure output.");
- }
-
- Debug::print("Detected compiler hash for triplet ", triplet, ": ", compiler_info.hash, "\n");
- return compiler_info;
- }
-
- static std::vector<System::CMakeVariable> get_cmake_build_args(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- const Dependencies::InstallPlanAction& action,
- Triplet triplet)
- {
-#if !defined(_WIN32)
- // TODO: remove when vcpkg.exe is in charge for acquiring tools. Change introduced in vcpkg v0.0.107.
- // bootstrap should have already downloaded ninja, but making sure it is present in case it was deleted.
- (void)(paths.get_tool_exe(Tools::NINJA));
-#endif
- auto& scfl = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO);
- auto& scf = *scfl.source_control_file;
-
- std::string all_features;
- for (auto& feature : scf.feature_paragraphs)
- {
- all_features.append(feature->name + ";");
- }
-
- std::vector<System::CMakeVariable> variables{
- {"ALL_FEATURES", all_features},
- {"CURRENT_PORT_DIR", scfl.source_location},
- {"FEATURES", Strings::join(";", action.feature_list)},
- {"PORT", scf.core_paragraph->name},
- {"VCPKG_USE_HEAD_VERSION", Util::Enum::to_bool(action.build_options.use_head_version) ? "1" : "0"},
- {"_VCPKG_DOWNLOAD_TOOL", to_string(action.build_options.download_tool)},
- {"_VCPKG_EDITABLE", Util::Enum::to_bool(action.build_options.editable) ? "1" : "0"},
- {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(action.build_options.allow_downloads) ? "1" : "0"},
- };
-
- for (auto cmake_arg : args.cmake_args)
- {
- variables.push_back(System::CMakeVariable{cmake_arg});
- }
-
- if (action.build_options.backcompat_features == BackcompatFeatures::PROHIBIT)
- {
- variables.emplace_back("_VCPKG_PROHIBIT_BACKCOMPAT_FEATURES", "1");
- }
-
- get_generic_cmake_build_args(
- paths,
- triplet,
- action.abi_info.value_or_exit(VCPKG_LINE_INFO).toolset.value_or_exit(VCPKG_LINE_INFO),
- variables);
-
- if (Util::Enum::to_bool(action.build_options.only_downloads))
- {
- variables.push_back({"VCPKG_DOWNLOAD_MODE", "true"});
- }
-
- const Files::Filesystem& fs = paths.get_filesystem();
-
- std::vector<std::string> port_configs;
- for (const PackageSpec& dependency : action.package_dependencies)
- {
- const fs::path port_config_path = paths.installed / fs::u8path(dependency.triplet().canonical_name()) /
- fs::u8path("share") / fs::u8path(dependency.name()) /
- fs::u8path("vcpkg-port-config.cmake");
-
- if (fs.is_regular_file(port_config_path))
- {
- port_configs.emplace_back(fs::u8string(port_config_path));
- }
- }
-
- if (!port_configs.empty())
- {
- variables.emplace_back("VCPKG_PORT_CONFIGS", Strings::join(";", port_configs));
- }
-
- return variables;
- }
-
- bool PreBuildInfo::using_vcvars() const
- {
- return (!external_toolchain_file.has_value() || load_vcvars_env) &&
- (cmake_system_name.empty() || cmake_system_name == "WindowsStore");
- }
-
- fs::path PreBuildInfo::toolchain_file() const
- {
- if (auto p = external_toolchain_file.get())
- {
- return fs::u8path(*p);
- }
- else if (cmake_system_name == "Linux")
- {
- return m_paths.scripts / fs::u8path("toolchains/linux.cmake");
- }
- else if (cmake_system_name == "Darwin")
- {
- return m_paths.scripts / fs::u8path("toolchains/osx.cmake");
- }
- else if (cmake_system_name == "FreeBSD")
- {
- return m_paths.scripts / fs::u8path("toolchains/freebsd.cmake");
- }
- else if (cmake_system_name == "OpenBSD")
- {
- return m_paths.scripts / fs::u8path("toolchains/openbsd.cmake");
- }
- else if (cmake_system_name == "Android")
- {
- return m_paths.scripts / fs::u8path("toolchains/android.cmake");
- }
- else if (cmake_system_name == "iOS")
- {
- return m_paths.scripts / fs::u8path("toolchains/ios.cmake");
- }
- else if (cmake_system_name == "MinGW")
- {
- return m_paths.scripts / fs::u8path("toolchains/mingw.cmake");
- }
- else if (cmake_system_name.empty() || cmake_system_name == "Windows" || cmake_system_name == "WindowsStore")
- {
- return m_paths.scripts / fs::u8path("toolchains/windows.cmake");
- }
- else
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Unable to determine toolchain to use for triplet %s with CMAKE_SYSTEM_NAME %s; "
- "maybe you meant to use VCPKG_CHAINLOAD_TOOLCHAIN_FILE?",
- triplet,
- cmake_system_name);
- }
- }
-
- static ExtendedBuildResult do_build_package(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- const Dependencies::InstallPlanAction& action)
- {
- const auto& pre_build_info = action.pre_build_info(VCPKG_LINE_INFO);
-
- auto& fs = paths.get_filesystem();
- auto&& scfl = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO);
-
- Triplet triplet = action.spec.triplet();
- const auto& triplet_file_path = fs::u8string(paths.get_triplet_file_path(triplet));
-
- if (Strings::case_insensitive_ascii_starts_with(triplet_file_path, fs::u8string(paths.community_triplets)))
- {
- System::printf(vcpkg::System::Color::warning,
- "-- Using community triplet %s. This triplet configuration is not guaranteed to succeed.\n",
- triplet.canonical_name());
- System::printf("-- [COMMUNITY] Loading triplet configuration from: %s\n", triplet_file_path);
- }
- else if (!Strings::case_insensitive_ascii_starts_with(triplet_file_path, fs::u8string(paths.triplets)))
- {
- System::printf("-- [OVERLAY] Loading triplet configuration from: %s\n", triplet_file_path);
- }
-
- auto u8portdir = fs::u8string(scfl.source_location);
- if (!Strings::case_insensitive_ascii_starts_with(u8portdir, fs::u8string(paths.builtin_ports_directory())))
- {
- System::printf("-- Installing port from location: %s\n", u8portdir);
- }
-
- const auto timer = Chrono::ElapsedTimer::create_started();
-
- auto command =
- vcpkg::make_cmake_cmd(paths, paths.ports_cmake, get_cmake_build_args(args, paths, action, triplet));
-
- const auto& env = paths.get_action_env(action.abi_info.value_or_exit(VCPKG_LINE_INFO));
-
- auto buildpath = paths.buildtrees / action.spec.name();
- if (!fs.exists(buildpath))
- {
- std::error_code err;
- fs.create_directory(buildpath, err);
- Checks::check_exit(VCPKG_LINE_INFO,
- !err.value(),
- "Failed to create directory '%s', code: %d",
- fs::u8string(buildpath),
- err.value());
- }
- auto stdoutlog = buildpath / ("stdout-" + action.spec.triplet().canonical_name() + ".log");
- std::ofstream out_file(stdoutlog.native().c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
- Checks::check_exit(VCPKG_LINE_INFO, out_file, "Failed to open '%s' for writing", fs::u8string(stdoutlog));
- const int return_code = System::cmd_execute_and_stream_data(
- command,
- [&](StringView sv) {
- System::print2(sv);
- out_file.write(sv.data(), sv.size());
- Checks::check_exit(
- VCPKG_LINE_INFO, out_file, "Error occurred while writing '%s'", fs::u8string(stdoutlog));
- },
- env);
- out_file.close();
-
- // With the exception of empty packages, builds in "Download Mode" always result in failure.
- if (action.build_options.only_downloads == Build::OnlyDownloads::YES)
- {
- // TODO: Capture executed command output and evaluate whether the failure was intended.
- // If an unintended error occurs then return a BuildResult::DOWNLOAD_FAILURE status.
- return BuildResult::DOWNLOADED;
- }
-
- const auto buildtimeus = timer.microseconds();
- const auto spec_string = action.spec.to_string();
-
- {
- auto locked_metrics = Metrics::g_metrics.lock();
-
- locked_metrics->track_buildtime(Hash::get_string_hash(spec_string, Hash::Algorithm::Sha256) + ":[" +
- Strings::join(",",
- action.feature_list,
- [](const std::string& feature) {
- return Hash::get_string_hash(feature,
- Hash::Algorithm::Sha256);
- }) +
- "]",
- buildtimeus);
- if (return_code != 0)
- {
- locked_metrics->track_property("error", "build failed");
- locked_metrics->track_property("build_error", spec_string);
- return BuildResult::BUILD_FAILED;
- }
- }
-
- const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(action.spec));
- const size_t error_count =
- PostBuildLint::perform_all_checks(action.spec, paths, pre_build_info, build_info, scfl.source_location);
-
- auto find_itr = action.feature_dependencies.find("core");
- Checks::check_exit(VCPKG_LINE_INFO, find_itr != action.feature_dependencies.end());
-
- std::unique_ptr<BinaryControlFile> bcf = create_binary_control_file(*scfl.source_control_file->core_paragraph,
- triplet,
- build_info,
- action.public_abi(),
- std::move(find_itr->second));
-
- if (error_count != 0)
- {
- return BuildResult::POST_BUILD_CHECKS_FAILED;
- }
- for (auto&& feature : action.feature_list)
- {
- for (auto&& f_pgh : scfl.source_control_file->feature_paragraphs)
- {
- if (f_pgh->name == feature)
- {
- find_itr = action.feature_dependencies.find(feature);
- Checks::check_exit(VCPKG_LINE_INFO, find_itr != action.feature_dependencies.end());
-
- bcf->features.emplace_back(
- *scfl.source_control_file->core_paragraph, *f_pgh, triplet, std::move(find_itr->second));
- }
- }
- }
-
- write_binary_control_file(paths, *bcf);
- return {BuildResult::SUCCEEDED, std::move(bcf)};
- }
-
- static ExtendedBuildResult do_build_package_and_clean_buildtrees(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- const Dependencies::InstallPlanAction& action)
- {
- auto result = do_build_package(args, paths, action);
-
- if (action.build_options.clean_buildtrees == CleanBuildtrees::YES)
- {
- auto& fs = paths.get_filesystem();
- auto buildtree_files = fs.get_files_non_recursive(paths.build_dir(action.spec));
- for (auto&& file : buildtree_files)
- {
- if (fs.is_directory(file)) // Will only keep the logs
- {
- std::error_code ec;
- fs::path failure_point;
- fs.remove_all(file, ec, failure_point);
- }
- }
- }
-
- return result;
- }
-
- static void abi_entries_from_abi_info(const AbiInfo& abi_info, std::vector<AbiEntry>& abi_tag_entries)
- {
- const auto& pre_build_info = *abi_info.pre_build_info;
- if (pre_build_info.public_abi_override)
- {
- abi_tag_entries.emplace_back(
- "public_abi_override",
- Hash::get_string_hash(pre_build_info.public_abi_override.value_or_exit(VCPKG_LINE_INFO),
- Hash::Algorithm::Sha1));
- }
-
- for (const auto& env_var : pre_build_info.passthrough_env_vars_tracked)
- {
- if (auto e = System::get_environment_variable(env_var))
- {
- abi_tag_entries.emplace_back(
- "ENV:" + env_var, Hash::get_string_hash(e.value_or_exit(VCPKG_LINE_INFO), Hash::Algorithm::Sha1));
- }
- }
- }
-
- struct AbiTagAndFile
- {
- const std::string* triplet_abi;
- std::string tag;
- fs::path tag_file;
- };
-
- static Optional<AbiTagAndFile> compute_abi_tag(const VcpkgPaths& paths,
- const Dependencies::InstallPlanAction& action,
- Span<const AbiEntry> dependency_abis)
- {
- auto& fs = paths.get_filesystem();
- Triplet triplet = action.spec.triplet();
-
- if (action.build_options.use_head_version == UseHeadVersion::YES)
- {
- Debug::print("Binary caching for package ", action.spec, " is disabled due to --head\n");
- return nullopt;
- }
- if (action.build_options.editable == Editable::YES)
- {
- Debug::print("Binary caching for package ", action.spec, " is disabled due to --editable\n");
- return nullopt;
- }
- for (auto&& dep_abi : dependency_abis)
- {
- if (dep_abi.value.empty())
- {
- Debug::print("Binary caching for package ",
- action.spec,
- " is disabled due to missing abi info for ",
- dep_abi.key,
- '\n');
- return nullopt;
- }
- }
-
- std::vector<AbiEntry> abi_tag_entries(dependency_abis.begin(), dependency_abis.end());
-
- const auto& abi_info = action.abi_info.value_or_exit(VCPKG_LINE_INFO);
- const auto& triplet_abi = paths.get_triplet_info(abi_info);
- abi_tag_entries.emplace_back("triplet", triplet.canonical_name());
- abi_tag_entries.emplace_back("triplet_abi", triplet_abi);
- abi_entries_from_abi_info(abi_info, abi_tag_entries);
-
- // If there is an unusually large number of files in the port then
- // something suspicious is going on. Rather than hash all of them
- // just mark the port as no-hash
- const int max_port_file_count = 100;
-
- auto&& port_dir = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO).source_location;
- size_t port_file_count = 0;
- for (auto& port_file : fs::stdfs::recursive_directory_iterator(port_dir))
- {
- if (fs::is_regular_file(fs.status(VCPKG_LINE_INFO, port_file)))
- {
- abi_tag_entries.emplace_back(
- fs::u8string(port_file.path().filename()),
- vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO, fs, port_file, Hash::Algorithm::Sha1));
-
- ++port_file_count;
- if (port_file_count > max_port_file_count)
- {
- abi_tag_entries.emplace_back("no_hash_max_portfile", "");
- break;
- }
- }
- }
-
- abi_tag_entries.emplace_back("cmake", paths.get_tool_version(Tools::CMAKE));
-
-#if defined(_WIN32)
- abi_tag_entries.emplace_back("powershell", paths.get_tool_version("powershell-core"));
-#endif
-
- auto& helpers = paths.get_cmake_script_hashes();
- auto portfile_contents =
- fs.read_contents(port_dir / fs::u8path("portfile.cmake")).value_or_exit(VCPKG_LINE_INFO);
- for (auto&& helper : helpers)
- {
- if (Strings::case_insensitive_ascii_contains(portfile_contents, helper.first))
- {
- abi_tag_entries.emplace_back(helper.first, helper.second);
- }
- }
-
- abi_tag_entries.emplace_back("post_build_checks", "2");
- std::vector<std::string> sorted_feature_list = action.feature_list;
- Util::sort(sorted_feature_list);
- abi_tag_entries.emplace_back("features", Strings::join(";", sorted_feature_list));
-
- Util::sort(abi_tag_entries);
-
- const std::string full_abi_info =
- Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; });
-
- if (Debug::g_debugging)
- {
- std::string message = Strings::concat("[DEBUG] <abientries for ", action.spec, ">\n");
- for (auto&& entry : abi_tag_entries)
- {
- Strings::append(message, "[DEBUG] ", entry.key, "|", entry.value, "\n");
- }
- Strings::append(message, "[DEBUG] </abientries>\n");
- System::print2(message);
- }
-
- auto abi_tag_entries_missing = Util::filter(abi_tag_entries, [](const AbiEntry& p) { return p.value.empty(); });
-
- if (abi_tag_entries_missing.empty())
- {
- auto current_build_tree = paths.build_dir(action.spec);
- fs.create_directory(current_build_tree, VCPKG_LINE_INFO);
- const auto abi_file_path = current_build_tree / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
- fs.write_contents(abi_file_path, full_abi_info, VCPKG_LINE_INFO);
-
- return AbiTagAndFile{&triplet_abi,
- Hash::get_file_hash(VCPKG_LINE_INFO, fs, abi_file_path, Hash::Algorithm::Sha1),
- abi_file_path};
- }
-
- Debug::print(
- "Warning: abi keys are missing values:\n",
- Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { return " " + e.key + "\n"; }),
- "\n");
-
- return nullopt;
- }
-
- void compute_all_abis(const VcpkgPaths& paths,
- Dependencies::ActionPlan& action_plan,
- const CMakeVars::CMakeVarProvider& var_provider,
- const StatusParagraphs& status_db)
- {
- using Dependencies::InstallPlanAction;
- for (auto it = action_plan.install_actions.begin(); it != action_plan.install_actions.end(); ++it)
- {
- auto& action = *it;
- if (action.abi_info.has_value()) continue;
-
- std::vector<AbiEntry> dependency_abis;
- if (!Util::Enum::to_bool(action.build_options.only_downloads))
- {
- for (auto&& pspec : action.package_dependencies)
- {
- if (pspec == action.spec) continue;
-
- auto pred = [&](const InstallPlanAction& ipa) { return ipa.spec == pspec; };
- auto it2 = std::find_if(action_plan.install_actions.begin(), it, pred);
- if (it2 == it)
- {
- // Finally, look in current installed
- auto status_it = status_db.find(pspec);
- if (status_it == status_db.end())
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO, "Failed to find dependency abi for %s -> %s", action.spec, pspec);
- }
-
- dependency_abis.emplace_back(AbiEntry{pspec.name(), status_it->get()->package.abi});
- }
- else
- {
- dependency_abis.emplace_back(AbiEntry{pspec.name(), it2->public_abi()});
- }
- }
- }
-
- action.abi_info = AbiInfo();
- auto& abi_info = action.abi_info.value_or_exit(VCPKG_LINE_INFO);
-
- abi_info.pre_build_info = std::make_unique<PreBuildInfo>(
- paths, action.spec.triplet(), var_provider.get_tag_vars(action.spec).value_or_exit(VCPKG_LINE_INFO));
- abi_info.toolset = paths.get_toolset(*abi_info.pre_build_info);
-
- auto maybe_abi_tag_and_file = compute_abi_tag(paths, action, dependency_abis);
- if (auto p = maybe_abi_tag_and_file.get())
- {
- abi_info.compiler_info = paths.get_compiler_info(abi_info);
- abi_info.triplet_abi = *p->triplet_abi;
- abi_info.package_abi = std::move(p->tag);
- abi_info.abi_tag_file = std::move(p->tag_file);
- }
- }
- }
-
- ExtendedBuildResult build_package(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- const Dependencies::InstallPlanAction& action,
- IBinaryProvider& binaries_provider,
- const IBuildLogsRecorder& build_logs_recorder,
- const StatusParagraphs& status_db)
- {
- auto& filesystem = paths.get_filesystem();
- auto& spec = action.spec;
- const std::string& name = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO)
- .source_control_file->core_paragraph->name;
-
- std::vector<FeatureSpec> missing_fspecs;
- for (const auto& kv : action.feature_dependencies)
- {
- for (const FeatureSpec& fspec : kv.second)
- {
- if (!(status_db.is_installed(fspec) || fspec.name() == name))
- {
- missing_fspecs.emplace_back(fspec);
- }
- }
- }
-
- if (!missing_fspecs.empty() && !Util::Enum::to_bool(action.build_options.only_downloads))
- {
- return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(missing_fspecs)};
- }
-
- std::vector<AbiEntry> dependency_abis;
- for (auto&& pspec : action.package_dependencies)
- {
- if (pspec == spec || Util::Enum::to_bool(action.build_options.only_downloads))
- {
- continue;
- }
- const auto status_it = status_db.find_installed(pspec);
- Checks::check_exit(VCPKG_LINE_INFO, status_it != status_db.end());
- dependency_abis.emplace_back(
- AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi});
- }
-
- auto& abi_info = action.abi_info.value_or_exit(VCPKG_LINE_INFO);
- if (!abi_info.abi_tag_file)
- {
- return do_build_package_and_clean_buildtrees(args, paths, action);
- }
-
- auto& abi_file = *abi_info.abi_tag_file.get();
-
- const fs::path abi_package_dir = paths.package_dir(spec) / "share" / spec.name();
- const fs::path abi_file_in_package = paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt";
- if (action.has_package_abi())
- {
- auto restore = binaries_provider.try_restore(paths, action);
- if (restore == RestoreResult::build_failed)
- {
- return BuildResult::BUILD_FAILED;
- }
- else if (restore == RestoreResult::success)
- {
- auto maybe_bcf = Paragraphs::try_load_cached_package(paths, spec);
- auto bcf = std::make_unique<BinaryControlFile>(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO));
- return {BuildResult::SUCCEEDED, std::move(bcf)};
- }
- else
- {
- // missing package, proceed to build.
- }
- }
- if (action.build_options.build_missing == BuildMissing::NO)
- {
- return BuildResult::CACHE_MISSING;
- }
-
- ExtendedBuildResult result = do_build_package_and_clean_buildtrees(args, paths, action);
- build_logs_recorder.record_build_result(paths, spec, result.code);
-
- std::error_code ec;
- filesystem.create_directories(abi_package_dir, ec);
- if (ec)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO,
- Strings::format("Could not create %s: %s (%d)",
- fs::u8string(abi_package_dir).c_str(),
- ec.message().c_str(),
- ec.value()));
- }
-
- filesystem.copy_file(abi_file, abi_file_in_package, fs::copy_options::none, ec);
- if (ec)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO,
- Strings::format("Could not copy %s -> %s: %s (%d)",
- fs::u8string(abi_file).c_str(),
- fs::u8string(abi_file_in_package).c_str(),
- ec.message().c_str(),
- ec.value()));
- }
-
- if (action.has_package_abi() && result.code == BuildResult::SUCCEEDED)
- {
- binaries_provider.push_success(paths, action);
- }
-
- return result;
- }
-
- const std::string& to_string(const BuildResult build_result)
- {
- static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string("vcpkg::Commands::Build::BuildResult");
- static const std::string SUCCEEDED_STRING = "SUCCEEDED";
- static const std::string BUILD_FAILED_STRING = "BUILD_FAILED";
- static const std::string FILE_CONFLICTS_STRING = "FILE_CONFLICTS";
- static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED";
- static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES";
- static const std::string EXCLUDED_STRING = "EXCLUDED";
- static const std::string CACHE_MISSING_STRING = "CACHE_MISSING";
- static const std::string DOWNLOADED_STRING = "DOWNLOADED";
-
- switch (build_result)
- {
- case BuildResult::NULLVALUE: return NULLVALUE_STRING;
- case BuildResult::SUCCEEDED: return SUCCEEDED_STRING;
- case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING;
- case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING;
- case BuildResult::FILE_CONFLICTS: return FILE_CONFLICTS_STRING;
- case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING;
- case BuildResult::EXCLUDED: return EXCLUDED_STRING;
- case BuildResult::CACHE_MISSING: return CACHE_MISSING_STRING;
- case BuildResult::DOWNLOADED: return DOWNLOADED_STRING;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- std::string create_error_message(const BuildResult build_result, const PackageSpec& spec)
- {
- return Strings::format("Error: Building package %s failed with: %s", spec, Build::to_string(build_result));
- }
-
- std::string create_user_troubleshooting_message(const PackageSpec& spec)
- {
-#if defined(_WIN32)
- auto vcpkg_update_cmd = ".\\vcpkg";
-#else
- auto vcpkg_update_cmd = "./vcpkg";
-#endif
- return Strings::format("Please ensure you're using the latest portfiles with `%s update`, then\n"
- "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n"
- " Package: %s\n"
- " Vcpkg version: %s\n"
- "\n"
- "Additionally, attach any relevant sections from the log files above.",
- vcpkg_update_cmd,
- spec,
- Commands::Version::version());
- }
-
- static BuildInfo inner_create_buildinfo(Parse::Paragraph pgh)
- {
- Parse::ParagraphParser parser(std::move(pgh));
-
- BuildInfo build_info;
-
- {
- std::string crt_linkage_as_string;
- parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string);
-
- auto crtlinkage = to_linkage_type(crt_linkage_as_string);
- if (const auto p = crtlinkage.get())
- {
- build_info.crt_linkage = *p;
- }
- else
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string);
- }
- }
-
- {
- std::string library_linkage_as_string;
- parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string);
- auto liblinkage = to_linkage_type(library_linkage_as_string);
- if (const auto p = liblinkage.get())
- {
- build_info.library_linkage = *p;
- }
- else
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Invalid library linkage type: [%s]", library_linkage_as_string);
- }
- }
-
- std::string version = parser.optional_field("Version");
- if (!version.empty()) build_info.version = std::move(version);
-
- std::map<BuildPolicy, bool> policies;
- for (auto policy : ALL_POLICIES)
- {
- const auto setting = parser.optional_field(to_string(policy));
- if (setting.empty()) continue;
- if (setting == "enabled")
- policies.emplace(policy, true);
- else if (setting == "disabled")
- policies.emplace(policy, false);
- else
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting);
- }
-
- if (const auto err = parser.error_info("PostBuildInformation"))
- {
- print_error_message(err);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- build_info.policies = BuildPolicies(std::move(policies));
-
- return build_info;
- }
-
- BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath)
- {
- const ExpectedS<Parse::Paragraph> pghs = Paragraphs::get_single_paragraph(fs, filepath);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package: %s", pghs.error());
- return inner_create_buildinfo(*pghs.get());
- }
-
- PreBuildInfo::PreBuildInfo(const VcpkgPaths& paths,
- Triplet triplet,
- const std::unordered_map<std::string, std::string>& cmakevars)
- : triplet(triplet), m_paths(paths)
- {
- enum class VcpkgTripletVar
- {
- TARGET_ARCHITECTURE = 0,
- CMAKE_SYSTEM_NAME,
- CMAKE_SYSTEM_VERSION,
- PLATFORM_TOOLSET,
- VISUAL_STUDIO_PATH,
- CHAINLOAD_TOOLCHAIN_FILE,
- BUILD_TYPE,
- ENV_PASSTHROUGH,
- ENV_PASSTHROUGH_UNTRACKED,
- PUBLIC_ABI_OVERRIDE,
- LOAD_VCVARS_ENV,
- };
-
- static const std::vector<std::pair<std::string, VcpkgTripletVar>> VCPKG_OPTIONS = {
- {"VCPKG_TARGET_ARCHITECTURE", VcpkgTripletVar::TARGET_ARCHITECTURE},
- {"VCPKG_CMAKE_SYSTEM_NAME", VcpkgTripletVar::CMAKE_SYSTEM_NAME},
- {"VCPKG_CMAKE_SYSTEM_VERSION", VcpkgTripletVar::CMAKE_SYSTEM_VERSION},
- {"VCPKG_PLATFORM_TOOLSET", VcpkgTripletVar::PLATFORM_TOOLSET},
- {"VCPKG_VISUAL_STUDIO_PATH", VcpkgTripletVar::VISUAL_STUDIO_PATH},
- {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE},
- {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE},
- {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH},
- {"VCPKG_ENV_PASSTHROUGH_UNTRACKED", VcpkgTripletVar::ENV_PASSTHROUGH_UNTRACKED},
- {"VCPKG_PUBLIC_ABI_OVERRIDE", VcpkgTripletVar::PUBLIC_ABI_OVERRIDE},
- {"VCPKG_LOAD_VCVARS_ENV", VcpkgTripletVar::LOAD_VCVARS_ENV},
- };
-
- std::string empty;
- for (auto&& kv : VCPKG_OPTIONS)
- {
- const std::string& variable_value = [&]() -> const std::string& {
- auto find_itr = cmakevars.find(kv.first);
- if (find_itr == cmakevars.end())
- {
- return empty;
- }
- else
- {
- return find_itr->second;
- }
- }();
-
- switch (kv.second)
- {
- case VcpkgTripletVar::TARGET_ARCHITECTURE: target_architecture = variable_value; break;
- case VcpkgTripletVar::CMAKE_SYSTEM_NAME: cmake_system_name = variable_value; break;
- case VcpkgTripletVar::CMAKE_SYSTEM_VERSION: cmake_system_version = variable_value; break;
- case VcpkgTripletVar::PLATFORM_TOOLSET:
- platform_toolset = variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::VISUAL_STUDIO_PATH:
- visual_studio_path = variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
- break;
- case VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE:
- external_toolchain_file = variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::BUILD_TYPE:
- if (variable_value.empty())
- build_type = nullopt;
- else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
- build_type = ConfigurationType::DEBUG;
- else if (Strings::case_insensitive_ascii_equals(variable_value, "release"))
- build_type = ConfigurationType::RELEASE;
- else
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "Unknown setting for VCPKG_BUILD_TYPE: %s. Valid settings are '', 'debug' and 'release'.",
- variable_value);
- break;
- case VcpkgTripletVar::ENV_PASSTHROUGH:
- passthrough_env_vars_tracked = Strings::split(variable_value, ';');
- Util::Vectors::append(&passthrough_env_vars, passthrough_env_vars_tracked);
- break;
- case VcpkgTripletVar::ENV_PASSTHROUGH_UNTRACKED:
- Util::Vectors::append(&passthrough_env_vars, Strings::split(variable_value, ';'));
- break;
- case VcpkgTripletVar::PUBLIC_ABI_OVERRIDE:
- public_abi_override = variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::LOAD_VCVARS_ENV:
- if (variable_value.empty())
- {
- load_vcvars_env = true;
- if (external_toolchain_file) load_vcvars_env = false;
- }
- else if (Strings::case_insensitive_ascii_equals(variable_value, "1") ||
- Strings::case_insensitive_ascii_equals(variable_value, "on") ||
- Strings::case_insensitive_ascii_equals(variable_value, "true"))
- {
- load_vcvars_env = true;
- }
- else if (Strings::case_insensitive_ascii_equals(variable_value, "0") ||
- Strings::case_insensitive_ascii_equals(variable_value, "off") ||
- Strings::case_insensitive_ascii_equals(variable_value, "false"))
- {
- load_vcvars_env = false;
- }
- else
- {
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Unknown boolean setting for VCPKG_LOAD_VCVARS_ENV: %s. Valid "
- "settings are '', '1', '0', 'ON', 'OFF', 'TRUE', and 'FALSE'.",
- variable_value);
- }
- break;
- }
- }
- }
-
- ExtendedBuildResult::ExtendedBuildResult(BuildResult code) : code(code) { }
- ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::unique_ptr<BinaryControlFile>&& bcf)
- : code(code), binary_control_file(std::move(bcf))
- {
- }
- ExtendedBuildResult::ExtendedBuildResult(BuildResult code, std::vector<FeatureSpec>&& unmet_deps)
- : code(code), unmet_dependencies(std::move(unmet_deps))
- {
- }
-
- const IBuildLogsRecorder& null_build_logs_recorder() noexcept { return null_build_logs_recorder_instance; }
-}
diff --git a/toolsrc/src/vcpkg/buildenvironment.cpp b/toolsrc/src/vcpkg/buildenvironment.cpp
deleted file mode 100644
index bc116f4f3..000000000
--- a/toolsrc/src/vcpkg/buildenvironment.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <vcpkg/buildenvironment.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg
-{
- System::Command make_cmake_cmd(const VcpkgPaths& paths,
- const fs::path& cmake_script,
- std::vector<System::CMakeVariable>&& pass_variables)
- {
- auto local_variables = std::move(pass_variables);
- local_variables.emplace_back("VCPKG_ROOT_DIR", paths.root);
- local_variables.emplace_back("PACKAGES_DIR", paths.packages);
- local_variables.emplace_back("BUILDTREES_DIR", paths.buildtrees);
- local_variables.emplace_back("_VCPKG_INSTALLED_DIR", paths.installed);
- local_variables.emplace_back("DOWNLOADS", paths.downloads);
- local_variables.emplace_back("VCPKG_MANIFEST_INSTALL", "OFF");
- return System::make_basic_cmake_cmd(paths.get_tool_exe(Tools::CMAKE), cmake_script, local_variables);
- }
-}
diff --git a/toolsrc/src/vcpkg/cmakevars.cpp b/toolsrc/src/vcpkg/cmakevars.cpp
deleted file mode 100644
index 8a90e574b..000000000
--- a/toolsrc/src/vcpkg/cmakevars.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/optional.h>
-#include <vcpkg/base/span.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/buildenvironment.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/portfileprovider.h>
-
-using namespace vcpkg;
-using vcpkg::Optional;
-
-namespace vcpkg::CMakeVars
-{
- void CMakeVarProvider::load_tag_vars(const vcpkg::Dependencies::ActionPlan& action_plan,
- const PortFileProvider::PortFileProvider& port_provider) const
- {
- std::vector<FullPackageSpec> install_package_specs;
- for (auto&& action : action_plan.install_actions)
- {
- install_package_specs.emplace_back(FullPackageSpec{action.spec, action.feature_list});
- }
-
- load_tag_vars(install_package_specs, port_provider);
- }
-
- namespace
- {
- struct TripletCMakeVarProvider : Util::ResourceBase, CMakeVarProvider
- {
- explicit TripletCMakeVarProvider(const vcpkg::VcpkgPaths& paths) : paths(paths) { }
-
- void load_generic_triplet_vars(Triplet triplet) const override;
-
- void load_dep_info_vars(View<PackageSpec> specs) const override;
-
- void load_tag_vars(View<FullPackageSpec> specs,
- const PortFileProvider::PortFileProvider& port_provider) const override;
-
- Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars(
- Triplet triplet) const override;
-
- Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars(
- const PackageSpec& spec) const override;
-
- Optional<const std::unordered_map<std::string, std::string>&> get_tag_vars(
- const PackageSpec& spec) const override;
-
- public:
- fs::path create_tag_extraction_file(
- const View<std::pair<const FullPackageSpec*, std::string>> spec_abi_settings) const;
-
- fs::path create_dep_info_extraction_file(const View<PackageSpec> specs) const;
-
- void launch_and_split(const fs::path& script_path,
- std::vector<std::vector<std::pair<std::string, std::string>>>& vars) const;
-
- const VcpkgPaths& paths;
- const fs::path get_tags_path = paths.scripts / "vcpkg_get_tags.cmake";
- const fs::path get_dep_info_path = paths.scripts / "vcpkg_get_dep_info.cmake";
- mutable std::unordered_map<PackageSpec, std::unordered_map<std::string, std::string>> dep_resolution_vars;
- mutable std::unordered_map<PackageSpec, std::unordered_map<std::string, std::string>> tag_vars;
- mutable std::unordered_map<Triplet, std::unordered_map<std::string, std::string>> generic_triplet_vars;
- };
- }
-
- std::unique_ptr<CMakeVarProvider> make_triplet_cmake_var_provider(const vcpkg::VcpkgPaths& paths)
- {
- return std::make_unique<TripletCMakeVarProvider>(paths);
- }
-
- static std::string create_extraction_file_prelude(const VcpkgPaths& paths,
- const std::map<Triplet, int>& emitted_triplets)
- {
- const auto& fs = paths.get_filesystem();
- std::string extraction_file("macro(vcpkg_triplet_file VCPKG_TRIPLET_ID)\n");
-
- Strings::append(extraction_file,
- "set(_vcpkg_triplet_file_BACKUP_CURRENT_LIST_FILE \"${CMAKE_CURRENT_LIST_FILE}\")\n");
-
- for (auto&& p : emitted_triplets)
- {
- auto path_to_triplet = paths.get_triplet_file_path(p.first);
- Strings::append(extraction_file, "if(VCPKG_TRIPLET_ID EQUAL ", p.second, ")\n");
- Strings::append(
- extraction_file, "set(CMAKE_CURRENT_LIST_FILE \"", fs::generic_u8string(path_to_triplet), "\")\n");
- Strings::append(
- extraction_file,
- "get_filename_component(CMAKE_CURRENT_LIST_DIR \"${CMAKE_CURRENT_LIST_FILE}\" DIRECTORY)\n");
- Strings::append(extraction_file, fs.read_contents(path_to_triplet, VCPKG_LINE_INFO));
- Strings::append(extraction_file, "\nendif()\n");
- }
- Strings::append(extraction_file,
- R"(
-set(CMAKE_CURRENT_LIST_FILE "${_vcpkg_triplet_file_BACKUP_CURRENT_LIST_FILE}")
-get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
-endmacro()
-)");
- return extraction_file;
- }
-
- fs::path TripletCMakeVarProvider::create_tag_extraction_file(
- const View<std::pair<const FullPackageSpec*, std::string>> spec_abi_settings) const
- {
- Files::Filesystem& fs = paths.get_filesystem();
- static int tag_extract_id = 0;
-
- std::map<Triplet, int> emitted_triplets;
- int emitted_triplet_id = 0;
- for (const auto& spec_abi_setting : spec_abi_settings)
- {
- emitted_triplets[spec_abi_setting.first->package_spec.triplet()] = emitted_triplet_id++;
- }
- std::string extraction_file = create_extraction_file_prelude(paths, emitted_triplets);
-
- Strings::append(extraction_file, "\ninclude(\"" + fs::generic_u8string(get_tags_path) + "\")\n\n");
-
- for (const auto& spec_abi_setting : spec_abi_settings)
- {
- const FullPackageSpec& spec = *spec_abi_setting.first;
-
- Strings::append(extraction_file,
- "vcpkg_get_tags(\"",
- spec.package_spec.name(),
- "\" \"",
- Strings::join(";", spec.features),
- "\" \"",
- emitted_triplets[spec.package_spec.triplet()],
- "\" \"",
- spec_abi_setting.second,
- "\")\n");
- }
-
- fs::path path = paths.buildtrees / Strings::concat(tag_extract_id++, ".vcpkg_tags.cmake");
- fs.write_contents_and_dirs(path, extraction_file, VCPKG_LINE_INFO);
- return path;
- }
-
- fs::path TripletCMakeVarProvider::create_dep_info_extraction_file(const View<PackageSpec> specs) const
- {
- static int dep_info_id = 0;
- Files::Filesystem& fs = paths.get_filesystem();
-
- std::map<Triplet, int> emitted_triplets;
- int emitted_triplet_id = 0;
- for (const auto& spec : specs)
- {
- emitted_triplets[spec.triplet()] = emitted_triplet_id++;
- }
-
- std::string extraction_file = create_extraction_file_prelude(paths, emitted_triplets);
-
- Strings::append(extraction_file, "\ninclude(\"" + fs::generic_u8string(get_dep_info_path) + "\")\n\n");
-
- for (const PackageSpec& spec : specs)
- {
- Strings::append(
- extraction_file, "vcpkg_get_dep_info(", spec.name(), " ", emitted_triplets[spec.triplet()], ")\n");
- }
-
- fs::path path = paths.buildtrees / Strings::concat(dep_info_id++, ".vcpkg_dep_info.cmake");
- fs.write_contents_and_dirs(path, extraction_file, VCPKG_LINE_INFO);
- return path;
- }
-
- void TripletCMakeVarProvider::launch_and_split(
- const fs::path& script_path, std::vector<std::vector<std::pair<std::string, std::string>>>& vars) const
- {
- static constexpr CStringView PORT_START_GUID = "d8187afd-ea4a-4fc3-9aa4-a6782e1ed9af";
- static constexpr CStringView PORT_END_GUID = "8c504940-be29-4cba-9f8f-6cd83e9d87b7";
- static constexpr CStringView BLOCK_START_GUID = "c35112b6-d1ba-415b-aa5d-81de856ef8eb";
- static constexpr CStringView BLOCK_END_GUID = "e1e74b5c-18cb-4474-a6bd-5c1c8bc81f3f";
-
- const auto cmd_launch_cmake = vcpkg::make_cmake_cmd(paths, script_path, {});
- const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake);
- Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, ec_data.output);
-
- const std::vector<std::string> lines = Strings::split(ec_data.output, '\n');
-
- const auto end = lines.cend();
-
- auto port_start = std::find(lines.cbegin(), end, PORT_START_GUID);
- auto port_end = std::find(port_start, end, PORT_END_GUID);
-
- for (auto var_itr = vars.begin(); port_start != end && var_itr != vars.end(); ++var_itr)
- {
- auto block_start = std::find(port_start, port_end, BLOCK_START_GUID);
- auto block_end = std::find(++block_start, port_end, BLOCK_END_GUID);
-
- while (block_start != port_end)
- {
- while (block_start != block_end)
- {
- const std::string& line = *block_start;
-
- std::vector<std::string> s = Strings::split(line, '=');
- Checks::check_exit(VCPKG_LINE_INFO,
- s.size() == 1 || s.size() == 2,
- "Expected format is [VARIABLE_NAME=VARIABLE_VALUE], but was [%s]",
- line);
-
- var_itr->emplace_back(std::move(s[0]), s.size() == 1 ? "" : std::move(s[1]));
-
- ++block_start;
- }
-
- block_start = std::find(block_end, port_end, BLOCK_START_GUID);
- block_end = std::find(block_start, port_end, BLOCK_END_GUID);
- }
-
- port_start = std::find(port_end, end, PORT_START_GUID);
- port_end = std::find(port_start, end, PORT_END_GUID);
- }
- }
-
- void TripletCMakeVarProvider::load_generic_triplet_vars(Triplet triplet) const
- {
- std::vector<std::vector<std::pair<std::string, std::string>>> vars(1);
- // Hack: PackageSpecs should never have .name==""
- FullPackageSpec full_spec({"", triplet});
- const fs::path file_path =
- create_tag_extraction_file(std::array<std::pair<const FullPackageSpec*, std::string>, 1>{
- std::pair<const FullPackageSpec*, std::string>{&full_spec, ""}});
- launch_and_split(file_path, vars);
- paths.get_filesystem().remove(file_path, VCPKG_LINE_INFO);
-
- generic_triplet_vars[triplet].insert(std::make_move_iterator(vars.front().begin()),
- std::make_move_iterator(vars.front().end()));
- }
-
- void TripletCMakeVarProvider::load_dep_info_vars(View<PackageSpec> specs) const
- {
- if (specs.size() == 0) return;
- std::vector<std::vector<std::pair<std::string, std::string>>> vars(specs.size());
- const fs::path file_path = create_dep_info_extraction_file(specs);
- if (specs.size() > 100)
- {
- System::print2("Loading dependency information for ", specs.size(), " packages...\n");
- }
- launch_and_split(file_path, vars);
- paths.get_filesystem().remove(file_path, VCPKG_LINE_INFO);
-
- auto var_list_itr = vars.begin();
- for (const PackageSpec& spec : specs)
- {
- dep_resolution_vars.emplace(std::piecewise_construct,
- std::forward_as_tuple(spec),
- std::forward_as_tuple(std::make_move_iterator(var_list_itr->begin()),
- std::make_move_iterator(var_list_itr->end())));
- ++var_list_itr;
- }
- }
-
- void TripletCMakeVarProvider::load_tag_vars(View<FullPackageSpec> specs,
- const PortFileProvider::PortFileProvider& port_provider) const
- {
- if (specs.size() == 0) return;
- std::vector<std::pair<const FullPackageSpec*, std::string>> spec_abi_settings;
- spec_abi_settings.reserve(specs.size());
-
- for (const FullPackageSpec& spec : specs)
- {
- auto& scfl = port_provider.get_control_file(spec.package_spec.name()).value_or_exit(VCPKG_LINE_INFO);
- const fs::path override_path = scfl.source_location / "vcpkg-abi-settings.cmake";
- spec_abi_settings.emplace_back(&spec, fs::generic_u8string(override_path));
- }
-
- std::vector<std::vector<std::pair<std::string, std::string>>> vars(spec_abi_settings.size());
- const fs::path file_path = create_tag_extraction_file(spec_abi_settings);
- launch_and_split(file_path, vars);
- paths.get_filesystem().remove(file_path, VCPKG_LINE_INFO);
-
- auto var_list_itr = vars.begin();
- for (const auto& spec_abi_setting : spec_abi_settings)
- {
- const FullPackageSpec& spec = *spec_abi_setting.first;
-
- tag_vars.emplace(std::piecewise_construct,
- std::forward_as_tuple(spec.package_spec),
- std::forward_as_tuple(std::make_move_iterator(var_list_itr->begin()),
- std::make_move_iterator(var_list_itr->end())));
- ++var_list_itr;
- }
- }
-
- Optional<const std::unordered_map<std::string, std::string>&> TripletCMakeVarProvider::get_generic_triplet_vars(
- Triplet triplet) const
- {
- auto find_itr = generic_triplet_vars.find(triplet);
- if (find_itr != generic_triplet_vars.end())
- {
- return find_itr->second;
- }
-
- return nullopt;
- }
-
- Optional<const std::unordered_map<std::string, std::string>&> TripletCMakeVarProvider::get_dep_info_vars(
- const PackageSpec& spec) const
- {
- auto find_itr = dep_resolution_vars.find(spec);
- if (find_itr != dep_resolution_vars.end())
- {
- return find_itr->second;
- }
-
- return nullopt;
- }
-
- Optional<const std::unordered_map<std::string, std::string>&> TripletCMakeVarProvider::get_tag_vars(
- const PackageSpec& spec) const
- {
- auto find_itr = tag_vars.find(spec);
- if (find_itr != tag_vars.end())
- {
- return find_itr->second;
- }
-
- return nullopt;
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.add-version.cpp b/toolsrc/src/vcpkg/commands.add-version.cpp
deleted file mode 100644
index bb4cc213b..000000000
--- a/toolsrc/src/vcpkg/commands.add-version.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/json.h>
-
-#include <vcpkg/commands.add-version.h>
-#include <vcpkg/configuration.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/registries.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/versions.h>
-
-using namespace vcpkg;
-
-namespace
-{
- constexpr StringLiteral BASELINE = "baseline";
- constexpr StringLiteral VERSION_RELAXED = "version";
- constexpr StringLiteral VERSION_SEMVER = "version-semver";
- constexpr StringLiteral VERSION_DATE = "version-date";
- constexpr StringLiteral VERSION_STRING = "version-string";
-
- using VersionGitTree = std::pair<SchemedVersion, std::string>;
-
- void insert_version_to_json_object(Json::Object& obj, const VersionT& version, StringLiteral version_field)
- {
- obj.insert(version_field, Json::Value::string(version.text()));
- obj.insert("port-version", Json::Value::integer(version.port_version()));
- }
-
- void insert_schemed_version_to_json_object(Json::Object& obj, const SchemedVersion& version)
- {
- if (version.scheme == Versions::Scheme::Relaxed)
- {
- return insert_version_to_json_object(obj, version.versiont, VERSION_RELAXED);
- }
-
- if (version.scheme == Versions::Scheme::Semver)
- {
- return insert_version_to_json_object(obj, version.versiont, VERSION_SEMVER);
- }
-
- if (version.scheme == Versions::Scheme::Date)
- {
- return insert_version_to_json_object(obj, version.versiont, VERSION_DATE);
- }
-
- if (version.scheme == Versions::Scheme::String)
- {
- return insert_version_to_json_object(obj, version.versiont, VERSION_STRING);
- }
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- static Json::Object serialize_baseline(const std::map<std::string, VersionT, std::less<>>& baseline)
- {
- Json::Object port_entries_obj;
- for (auto&& kv_pair : baseline)
- {
- Json::Object baseline_version_obj;
- insert_version_to_json_object(baseline_version_obj, kv_pair.second, BASELINE);
- port_entries_obj.insert(kv_pair.first, baseline_version_obj);
- }
-
- Json::Object baseline_obj;
- baseline_obj.insert("default", port_entries_obj);
- return baseline_obj;
- }
-
- static Json::Object serialize_versions(const std::vector<VersionGitTree>& versions)
- {
- Json::Array versions_array;
- for (auto&& version : versions)
- {
- Json::Object version_obj;
- version_obj.insert("git-tree", Json::Value::string(version.second));
- insert_schemed_version_to_json_object(version_obj, version.first);
- versions_array.push_back(std::move(version_obj));
- }
-
- Json::Object output_object;
- output_object.insert("versions", versions_array);
- return output_object;
- }
-
- static void write_baseline_file(Files::Filesystem& fs,
- const std::map<std::string, VersionT, std::less<>>& baseline_map,
- const fs::path& output_path)
- {
- auto backup_path = fs::u8path(Strings::concat(fs::u8string(output_path), ".backup"));
- if (fs.exists(output_path))
- {
- fs.rename(output_path, backup_path, VCPKG_LINE_INFO);
- fs.remove(output_path, VCPKG_LINE_INFO);
- }
-
- std::error_code ec;
- fs.write_contents(
- output_path, Json::stringify(serialize_baseline(baseline_map), Json::JsonStyle::with_spaces(2)), ec);
- if (ec)
- {
- System::printf(
- System::Color::error, "Error: Couldn't write baseline file to %s.", fs::u8string(output_path));
- if (fs.exists(backup_path))
- {
- fs.rename(backup_path, output_path, VCPKG_LINE_INFO);
- }
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- if (fs.exists(backup_path))
- {
- fs.remove(backup_path, VCPKG_LINE_INFO);
- }
- }
-
- static void write_versions_file(Files::Filesystem& fs,
- const std::vector<VersionGitTree>& versions,
- const fs::path& output_path)
- {
- auto backup_path = fs::u8path(Strings::concat(fs::u8string(output_path), ".backup"));
- if (fs.exists(output_path))
- {
- fs.rename(output_path, backup_path, VCPKG_LINE_INFO);
- fs.remove(output_path, VCPKG_LINE_INFO);
- }
-
- std::error_code ec;
- fs.create_directories(output_path.parent_path(), VCPKG_LINE_INFO);
- fs.write_contents(
- output_path, Json::stringify(serialize_versions(versions), Json::JsonStyle::with_spaces(2)), ec);
- if (ec)
- {
- System::printf(
- System::Color::error, "Error: Couldn't write versions file to %s.", fs::u8string(output_path));
- if (fs.exists(backup_path))
- {
- fs.rename(backup_path, output_path, VCPKG_LINE_INFO);
- }
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- if (fs.exists(backup_path))
- {
- fs.remove(backup_path, VCPKG_LINE_INFO);
- }
- }
-
- static void update_baseline_version(const VcpkgPaths& paths,
- const std::string& port_name,
- const VersionT& version,
- const fs::path& baseline_path,
- bool print_success)
- {
- bool is_new_file = false;
- auto& fs = paths.get_filesystem();
- auto baseline_map = [&]() -> std::map<std::string, vcpkg::VersionT, std::less<>> {
- if (!fs.exists(VCPKG_LINE_INFO, baseline_path))
- {
- is_new_file = true;
- std::map<std::string, vcpkg::VersionT, std::less<>> ret;
- return ret;
- }
- auto maybe_baseline_map = vcpkg::get_builtin_baseline(paths);
- return maybe_baseline_map.value_or_exit(VCPKG_LINE_INFO);
- }();
-
- auto it = baseline_map.find(port_name);
- if (it != baseline_map.end())
- {
- auto& baseline_version = it->second;
- if (baseline_version == version)
- {
- if (print_success)
- {
- System::printf(System::Color::success,
- "Version `%s` is already in `%s`\n",
- version,
- fs::u8string(baseline_path));
- }
- return;
- }
- baseline_version = version;
- }
- else
- {
- baseline_map.emplace(port_name, version);
- }
-
- write_baseline_file(fs, baseline_map, baseline_path);
- if (print_success)
- {
- System::printf(System::Color::success,
- "Added version `%s` to `%s`%s.\n",
- version.to_string(),
- fs::u8string(baseline_path),
- is_new_file ? " (new file)" : "");
- }
- return;
- }
-
- static void update_version_db_file(const VcpkgPaths& paths,
- const std::string& port_name,
- const SchemedVersion& version,
- const std::string& git_tree,
- const fs::path& version_db_file_path,
- bool overwrite_version,
- bool print_success,
- bool keep_going)
- {
- auto& fs = paths.get_filesystem();
- if (!fs.exists(VCPKG_LINE_INFO, version_db_file_path))
- {
- std::vector<VersionGitTree> new_entry{{version, git_tree}};
- write_versions_file(fs, new_entry, version_db_file_path);
- if (print_success)
- {
- System::printf(System::Color::success,
- "Added version `%s` to `%s` (new file).\n",
- version.versiont,
- fs::u8string(version_db_file_path));
- }
- return;
- }
-
- auto maybe_versions = get_builtin_versions(paths, port_name);
- if (auto versions = maybe_versions.get())
- {
- const auto& versions_end = versions->end();
-
- auto found_same_sha = std::find_if(
- versions->begin(), versions_end, [&](auto&& entry) -> bool { return entry.second == git_tree; });
- if (found_same_sha != versions_end)
- {
- if (found_same_sha->first.versiont == version.versiont)
- {
- if (print_success)
- {
- System::printf(System::Color::success,
- "Version `%s` is already in `%s`\n",
- version.versiont,
- fs::u8string(version_db_file_path));
- }
- return;
- }
- System::printf(System::Color::warning,
- "Warning: Local port files SHA is the same as version `%s` in `%s`.\n"
- "-- SHA: %s\n"
- "-- Did you remember to commit your changes?\n"
- "***No files were updated.***\n",
- found_same_sha->first.versiont,
- fs::u8string(version_db_file_path),
- git_tree);
- if (keep_going) return;
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- auto it = std::find_if(versions->begin(), versions_end, [&](auto&& entry) -> bool {
- return entry.first.versiont == version.versiont;
- });
-
- if (it != versions_end)
- {
- if (!overwrite_version)
- {
- System::printf(System::Color::error,
- "Error: Local changes detected for %s but no changes to version or port version.\n"
- "-- Version: %s\n"
- "-- Old SHA: %s\n"
- "-- New SHA: %s\n"
- "-- Did you remember to update the version or port version?\n"
- "-- Pass `--overwrite-version` to bypass this check.\n"
- "***No files were updated.***\n",
- port_name,
- version.versiont,
- it->second,
- git_tree);
- if (keep_going) return;
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- it->first = version;
- it->second = git_tree;
- }
- else
- {
- versions->insert(versions->begin(), std::make_pair(version, git_tree));
- }
-
- write_versions_file(fs, *versions, version_db_file_path);
- if (print_success)
- {
- System::printf(System::Color::success,
- "Added version `%s` to `%s`.\n",
- version.versiont,
- fs::u8string(version_db_file_path));
- }
- return;
- }
-
- System::printf(System::Color::error,
- "Error: Unable to parse versions file %s.\n%s\n",
- fs::u8string(version_db_file_path),
- maybe_versions.error());
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-}
-
-namespace vcpkg::Commands::AddVersion
-{
- static constexpr StringLiteral OPTION_ALL = "all";
- static constexpr StringLiteral OPTION_OVERWRITE_VERSION = "overwrite-version";
- static constexpr StringLiteral OPTION_VERBOSE = "verbose";
-
- const CommandSwitch COMMAND_SWITCHES[] = {
- {OPTION_ALL, "Process versions for all ports."},
- {OPTION_OVERWRITE_VERSION, "Overwrite `git-tree` of an existing version."},
- {OPTION_VERBOSE, "Print success messages instead of just errors."},
- };
-
- const CommandStructure COMMAND_STRUCTURE{
- create_example_string(R"###(x-add-version <port name>)###"),
- 0,
- 1,
- {{COMMAND_SWITCHES}, {}, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- auto parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
- const bool add_all = Util::Sets::contains(parsed_args.switches, OPTION_ALL);
- const bool overwrite_version = Util::Sets::contains(parsed_args.switches, OPTION_OVERWRITE_VERSION);
- const bool verbose = Util::Sets::contains(parsed_args.switches, OPTION_VERBOSE);
-
- auto& fs = paths.get_filesystem();
- auto baseline_path = paths.builtin_registry_versions / fs::u8path("baseline.json");
- if (!fs.exists(VCPKG_LINE_INFO, baseline_path))
- {
- System::printf(
- System::Color::error, "Error: Couldn't find required file `%s`\n.", fs::u8string(baseline_path));
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- std::vector<std::string> port_names;
- if (!args.command_arguments.empty())
- {
- if (add_all)
- {
- System::printf(System::Color::warning,
- "Warning: Ignoring option `--%s` since a port name argument was provided.\n",
- OPTION_ALL);
- }
- port_names.emplace_back(args.command_arguments[0]);
- }
- else
- {
- if (!add_all)
- {
- System::printf(System::Color::error,
- "Error: Use option `--%s` to update version files for all ports at once.\n",
- OPTION_ALL);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- for (auto&& port_dir : fs::directory_iterator(paths.builtin_ports_directory()))
- {
- port_names.emplace_back(fs::u8string(port_dir.path().stem()));
- }
- }
-
- // Get tree-ish from local repository state.
- auto maybe_git_tree_map = paths.git_get_local_port_treeish_map();
- auto git_tree_map = maybe_git_tree_map.value_or_exit(VCPKG_LINE_INFO);
-
- for (auto&& port_name : port_names)
- {
- // Get version information of the local port
- auto maybe_scf = Paragraphs::try_load_port(fs, paths.builtin_ports_directory() / fs::u8path(port_name));
- if (!maybe_scf.has_value())
- {
- if (add_all) continue;
- System::printf(System::Color::error, "Error: Couldn't load port `%s`.", port_name);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- const auto& scf = maybe_scf.value_or_exit(VCPKG_LINE_INFO);
- const auto& schemed_version = scf->to_schemed_version();
-
- auto git_tree_it = git_tree_map.find(port_name);
- if (git_tree_it == git_tree_map.end())
- {
- System::printf(System::Color::warning,
- "Warning: No local Git SHA was found for port `%s`.\n"
- "-- Did you remember to commit your changes?\n"
- "***No files were updated.***\n",
- port_name);
- if (add_all) continue;
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- const auto& git_tree = git_tree_it->second;
-
- auto port_versions_path = paths.builtin_registry_versions / fs::u8path({port_name[0], '-'}) /
- fs::u8path(Strings::concat(port_name, ".json"));
- update_version_db_file(
- paths, port_name, schemed_version, git_tree, port_versions_path, overwrite_version, verbose, add_all);
- update_baseline_version(paths, port_name, schemed_version.versiont, baseline_path, verbose);
- }
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void AddVersionCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- AddVersion::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp
deleted file mode 100644
index d61e9119e..000000000
--- a/toolsrc/src/vcpkg/commands.autocomplete.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.autocomplete.h>
-#include <vcpkg/commands.edit.h>
-#include <vcpkg/commands.integrate.h>
-#include <vcpkg/commands.upgrade.h>
-#include <vcpkg/install.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/remove.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Commands::Autocomplete
-{
- [[noreturn]] static void output_sorted_results_and_exit(const LineInfo& line_info,
- std::vector<std::string>&& results)
- {
- const SortedVector<std::string> sorted_results(results);
- System::print2(Strings::join("\n", sorted_results), '\n');
-
- Checks::exit_success(line_info);
- }
-
- static std::vector<std::string> combine_port_with_triplets(const std::string& port,
- const std::vector<std::string>& triplets)
- {
- return Util::fmap(triplets,
- [&](const std::string& triplet) { return Strings::format("%s:%s", port, triplet); });
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- Metrics::g_metrics.lock()->set_send_metrics(false);
- const std::string to_autocomplete = Strings::join(" ", args.command_arguments);
- const std::vector<std::string> tokens = Strings::split(to_autocomplete, ' ');
-
- std::smatch match;
-
- // Handles vcpkg <command>
- if (std::regex_match(to_autocomplete, match, std::regex{R"###(^(\S*)$)###"}))
- {
- const std::string requested_command = match[1].str();
-
- // First try public commands
- std::vector<std::string> public_commands = {"install",
- "search",
- "remove",
- "list",
- "update",
- "hash",
- "help",
- "integrate",
- "export",
- "edit",
- "create",
- "owns",
- "cache",
- "version",
- "contact",
- "upgrade"};
-
- Util::erase_remove_if(public_commands, [&](const std::string& s) {
- return !Strings::case_insensitive_ascii_starts_with(s, requested_command);
- });
-
- if (!public_commands.empty())
- {
- output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(public_commands));
- }
-
- // If no public commands match, try private commands
- std::vector<std::string> private_commands = {
- "build",
- "buildexternal",
- "ci",
- "depend-info",
- "env",
- "portsdiff",
- };
-
- Util::erase_remove_if(private_commands, [&](const std::string& s) {
- return !Strings::case_insensitive_ascii_starts_with(s, requested_command);
- });
-
- output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(private_commands));
- }
-
- // Handles vcpkg install package:<triplet>
- if (std::regex_match(to_autocomplete, match, std::regex{R"###(^install(.*|)\s([^:]+):(\S*)$)###"}))
- {
- const auto port_name = match[2].str();
- const auto triplet_prefix = match[3].str();
-
- // TODO: Support autocomplete for ports in --overlay-ports
- auto maybe_port =
- Paragraphs::try_load_port(paths.get_filesystem(), paths.builtin_ports_directory() / port_name);
- if (maybe_port.error())
- {
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- std::vector<std::string> triplets = paths.get_available_triplets_names();
- Util::erase_remove_if(triplets, [&](const std::string& s) {
- return !Strings::case_insensitive_ascii_starts_with(s, triplet_prefix);
- });
-
- auto result = combine_port_with_triplets(port_name, triplets);
-
- output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(result));
- }
-
- struct CommandEntry
- {
- constexpr CommandEntry(const CStringView& name, const CStringView& regex, const CommandStructure& structure)
- : name(name), regex(regex), structure(structure)
- {
- }
-
- CStringView name;
- CStringView regex;
- const CommandStructure& structure;
- };
-
- static constexpr CommandEntry COMMANDS[] = {
- CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE},
- CommandEntry{"edit", R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE},
- CommandEntry{"remove", R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE},
- CommandEntry{"integrate", R"###(^integrate(\s+)(\S*)$)###", Integrate::COMMAND_STRUCTURE},
- CommandEntry{"upgrade", R"###(^upgrade(\s+)(\S*)$)###", Upgrade::COMMAND_STRUCTURE},
- };
-
- for (auto&& command : COMMANDS)
- {
- if (std::regex_match(to_autocomplete, match, std::regex{command.regex.c_str()}))
- {
- const auto prefix = match[2].str();
- std::vector<std::string> results;
-
- const bool is_option = Strings::case_insensitive_ascii_starts_with(prefix, "-");
- if (is_option)
- {
- results = Util::fmap(command.structure.options.switches, [](const CommandSwitch& s) -> std::string {
- return Strings::format("--%s", s.name.to_string());
- });
-
- auto settings = Util::fmap(command.structure.options.settings,
- [](auto&& s) { return Strings::format("--%s", s.name); });
- results.insert(results.end(), settings.begin(), settings.end());
-
- auto multisettings = Util::fmap(command.structure.options.multisettings,
- [](auto&& s) { return Strings::format("--%s", s.name); });
- results.insert(results.end(), multisettings.begin(), multisettings.end());
- }
- else
- {
- if (command.structure.valid_arguments != nullptr)
- {
- results = command.structure.valid_arguments(paths);
- }
- }
-
- Util::erase_remove_if(results, [&](const std::string& s) {
- return !Strings::case_insensitive_ascii_starts_with(s, prefix);
- });
-
- if (command.name == "install" && results.size() == 1 && !is_option)
- {
- const auto port_at_each_triplet =
- combine_port_with_triplets(results[0], paths.get_available_triplets_names());
- Util::Vectors::append(&results, port_at_each_triplet);
- }
-
- output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(results));
- }
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void AutocompleteCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Autocomplete::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp
deleted file mode 100644
index 65b1ec823..000000000
--- a/toolsrc/src/vcpkg/commands.buildexternal.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/build.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.buildexternal.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-namespace vcpkg::Commands::BuildExternal
-{
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"),
- 2,
- 2,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- auto binaryprovider = create_binary_provider_from_configs(args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
-
- const FullPackageSpec spec = Input::check_and_get_full_package_spec(
- std::string(args.command_arguments.at(0)), default_triplet, COMMAND_STRUCTURE.example_text);
- Input::check_triplet(spec.package_spec.triplet(), paths);
-
- auto overlays = args.overlay_ports;
- overlays.insert(overlays.begin(), args.command_arguments.at(1));
-
- PortFileProvider::PathsPortFileProvider provider(paths, overlays);
- auto maybe_scfl = provider.get_control_file(spec.package_spec.name());
-
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, maybe_scfl.has_value(), "could not load control file for %s", spec.package_spec.name());
-
- Build::Command::perform_and_exit_ex(args,
- spec,
- maybe_scfl.value_or_exit(VCPKG_LINE_INFO),
- provider,
- args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(),
- Build::null_build_logs_recorder(),
- paths);
- }
-
- void BuildExternalCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- BuildExternal::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp
deleted file mode 100644
index af851bc98..000000000
--- a/toolsrc/src/vcpkg/commands.cache.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/binaryparagraph.h>
-#include <vcpkg/commands.cache.h>
-#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg::Commands::Cache
-{
- static std::vector<BinaryParagraph> read_all_binary_paragraphs(const VcpkgPaths& paths)
- {
- std::vector<BinaryParagraph> output;
- for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages))
- {
- const auto pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), path / fs::u8path("CONTROL"));
- if (const auto p = pghs.get())
- {
- const BinaryParagraph binary_paragraph = BinaryParagraph(*p);
- output.push_back(binary_paragraph);
- }
- }
-
- return output;
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format(
- "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s",
- create_example_string("cache png")),
- 0,
- 1,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)(args.parse_arguments(COMMAND_STRUCTURE));
-
- const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths);
- if (binary_paragraphs.empty())
- {
- System::print2("No packages are cached.\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- if (args.command_arguments.empty())
- {
- for (const BinaryParagraph& binary_paragraph : binary_paragraphs)
- {
- System::print2(binary_paragraph.displayname(), '\n');
- }
- }
- else
- {
- // At this point there is 1 argument
- for (const BinaryParagraph& binary_paragraph : binary_paragraphs)
- {
- const std::string displayname = binary_paragraph.displayname();
- if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0]))
- {
- continue;
- }
-
- System::print2(displayname, '\n');
- }
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void CacheCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Cache::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp
deleted file mode 100644
index 26ae058ad..000000000
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ /dev/null
@@ -1,606 +0,0 @@
-#include <vcpkg/base/cache.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/graphs.h>
-#include <vcpkg/base/stringliteral.h>
-#include <vcpkg/base/system.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/build.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.ci.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/packagespec.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/platform-expression.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-
-using namespace vcpkg;
-
-namespace
-{
- using namespace vcpkg::Build;
-
- const fs::path dot_log = fs::u8path(".log");
- const fs::path readme_dot_log = fs::u8path("readme.log");
-
- class CiBuildLogsRecorder final : public IBuildLogsRecorder
- {
- fs::path base_path;
-
- public:
- CiBuildLogsRecorder(const fs::path& base_path_) : base_path(base_path_) { }
-
- virtual void record_build_result(const VcpkgPaths& paths,
- const PackageSpec& spec,
- BuildResult result) const override
- {
- if (result == BuildResult::SUCCEEDED)
- {
- return;
- }
-
- auto& filesystem = paths.get_filesystem();
- const auto source_path = paths.build_dir(spec);
- auto children = filesystem.get_files_non_recursive(source_path);
- Util::erase_remove_if(children, [](const fs::path& p) { return p.extension() != dot_log; });
- const auto target_path = base_path / fs::u8path(spec.name());
- (void)filesystem.create_directory(target_path, VCPKG_LINE_INFO);
- if (children.empty())
- {
- std::string message =
- "There are no build logs for " + spec.to_string() +
- " build.\n"
- "This is usually because the build failed early and outside of a task that is logged.\n"
- "See the console output logs from vcpkg for more information on the failure.\n";
- filesystem.write_contents(target_path / readme_dot_log, message, VCPKG_LINE_INFO);
- }
- else
- {
- for (const fs::path& p : children)
- {
- filesystem.copy_file(p, target_path / p.filename(), fs::copy_options::none, VCPKG_LINE_INFO);
- }
- }
- }
- };
-}
-
-namespace vcpkg::Commands::CI
-{
- using Build::BuildResult;
- using Dependencies::InstallPlanAction;
- using Dependencies::InstallPlanType;
-
- struct TripletAndSummary
- {
- Triplet triplet;
- Install::InstallSummary summary;
- };
-
- static constexpr StringLiteral OPTION_DRY_RUN = "dry-run";
- static constexpr StringLiteral OPTION_EXCLUDE = "exclude";
- static constexpr StringLiteral OPTION_FAILURE_LOGS = "failure-logs";
- static constexpr StringLiteral OPTION_XUNIT = "x-xunit";
- static constexpr StringLiteral OPTION_RANDOMIZE = "x-randomize";
-
- static constexpr std::array<CommandSetting, 3> CI_SETTINGS = {
- {{OPTION_EXCLUDE, "Comma separated list of ports to skip"},
- {OPTION_XUNIT, "File to output results in XUnit format (internal)"},
- {OPTION_FAILURE_LOGS, "Directory to which failure logs will be copied"}}};
-
- static constexpr std::array<CommandSwitch, 2> CI_SWITCHES = {{
- {OPTION_DRY_RUN, "Print out plan without execution"},
- {OPTION_RANDOMIZE, "Randomize the install order"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("ci x64-windows"),
- 1,
- SIZE_MAX,
- {CI_SWITCHES, CI_SETTINGS},
- nullptr,
- };
-
- struct XunitTestResults
- {
- public:
- XunitTestResults() { m_assembly_run_datetime = Chrono::CTime::get_current_date_time(); }
-
- void add_test_results(const std::string& spec,
- const Build::BuildResult& build_result,
- const Chrono::ElapsedTime& elapsed_time,
- const std::string& abi_tag,
- const std::vector<std::string>& features)
- {
- m_collections.back().tests.push_back({spec, build_result, elapsed_time, abi_tag, features});
- }
-
- // Starting a new test collection
- void push_collection(const std::string& name) { m_collections.push_back({name}); }
-
- void collection_time(const vcpkg::Chrono::ElapsedTime& time) { m_collections.back().time = time; }
-
- const std::string& build_xml()
- {
- m_xml.clear();
- xml_start_assembly();
-
- for (const auto& collection : m_collections)
- {
- xml_start_collection(collection);
- for (const auto& test : collection.tests)
- {
- xml_test(test);
- }
- xml_finish_collection();
- }
-
- xml_finish_assembly();
- return m_xml;
- }
-
- void assembly_time(const vcpkg::Chrono::ElapsedTime& assembly_time) { m_assembly_time = assembly_time; }
-
- private:
- struct XunitTest
- {
- std::string name;
- vcpkg::Build::BuildResult result;
- vcpkg::Chrono::ElapsedTime time;
- std::string abi_tag;
- std::vector<std::string> features;
- };
-
- struct XunitCollection
- {
- std::string name;
- vcpkg::Chrono::ElapsedTime time;
- std::vector<XunitTest> tests;
- };
-
- void xml_start_assembly()
- {
- std::string datetime;
- if (m_assembly_run_datetime)
- {
- auto rawDateTime = m_assembly_run_datetime.get()->to_string();
- // The expected format is "yyyy-mm-ddThh:mm:ss.0Z"
- // 0123456789012345678901
- datetime = Strings::format(
- R"(run-date="%s" run-time="%s")", rawDateTime.substr(0, 10), rawDateTime.substr(11, 8));
- }
-
- std::string time = Strings::format(R"(time="%lld")", m_assembly_time.as<std::chrono::seconds>().count());
-
- m_xml += Strings::format(R"(<assemblies>)"
- "\n"
- R"( <assembly name="vcpkg" %s %s>)"
- "\n",
- datetime,
- time);
- }
- void xml_finish_assembly()
- {
- m_xml += " </assembly>\n"
- "</assemblies>\n";
- }
-
- void xml_start_collection(const XunitCollection& collection)
- {
- m_xml += Strings::format(R"( <collection name="%s" time="%lld">)"
- "\n",
- collection.name,
- collection.time.as<std::chrono::seconds>().count());
- }
- void xml_finish_collection() { m_xml += " </collection>\n"; }
-
- void xml_test(const XunitTest& test)
- {
- std::string message_block;
- const char* result_string = "";
- switch (test.result)
- {
- case BuildResult::POST_BUILD_CHECKS_FAILED:
- case BuildResult::FILE_CONFLICTS:
- case BuildResult::BUILD_FAILED:
- result_string = "Fail";
- message_block =
- Strings::format("<failure><message><![CDATA[%s]]></message></failure>", to_string(test.result));
- break;
- case BuildResult::EXCLUDED:
- case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES:
- result_string = "Skip";
- message_block = Strings::format("<reason><![CDATA[%s]]></reason>", to_string(test.result));
- break;
- case BuildResult::SUCCEEDED: result_string = "Pass"; break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- std::string traits_block;
- if (!test.abi_tag.empty())
- {
- traits_block += Strings::format(R"(<trait name="abi_tag" value="%s" />)", test.abi_tag);
- }
-
- if (!test.features.empty())
- {
- std::string feature_list;
- for (const auto& feature : test.features)
- {
- if (!feature_list.empty())
- {
- feature_list += ", ";
- }
- feature_list += feature;
- }
-
- traits_block += Strings::format(R"(<trait name="features" value="%s" />)", feature_list);
- }
-
- if (!traits_block.empty())
- {
- traits_block = "<traits>" + traits_block + "</traits>";
- }
-
- m_xml += Strings::format(R"( <test name="%s" method="%s" time="%lld" result="%s">%s%s</test>)"
- "\n",
- test.name,
- test.name,
- test.time.as<std::chrono::seconds>().count(),
- result_string,
- traits_block,
- message_block);
- }
-
- Optional<vcpkg::Chrono::CTime> m_assembly_run_datetime;
- vcpkg::Chrono::ElapsedTime m_assembly_time;
- std::vector<XunitCollection> m_collections;
-
- std::string m_xml;
- };
-
- struct UnknownCIPortsResults
- {
- std::vector<FullPackageSpec> unknown;
- std::map<PackageSpec, Build::BuildResult> known;
- std::map<PackageSpec, std::vector<std::string>> features;
- Dependencies::ActionPlan plan;
- std::map<PackageSpec, std::string> abi_map;
- };
-
- static bool supported_for_triplet(const CMakeVars::CMakeVarProvider& var_provider,
- const InstallPlanAction* install_plan)
- {
- auto&& scfl = install_plan->source_control_file_location.value_or_exit(VCPKG_LINE_INFO);
- const auto& supports_expression = scfl.source_control_file->core_paragraph->supports_expression;
- PlatformExpression::Context context =
- var_provider.get_tag_vars(install_plan->spec).value_or_exit(VCPKG_LINE_INFO);
-
- return supports_expression.evaluate(context);
- }
-
- static std::unique_ptr<UnknownCIPortsResults> find_unknown_ports_for_ci(
- const VcpkgPaths& paths,
- const std::set<std::string>& exclusions,
- const PortFileProvider::PortFileProvider& provider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const std::vector<FullPackageSpec>& specs,
- IBinaryProvider& binaryprovider)
- {
- auto ret = std::make_unique<UnknownCIPortsResults>();
-
- std::set<PackageSpec> will_fail;
-
- std::vector<PackageSpec> packages_with_qualified_deps;
- auto has_qualifier = [](Dependency const& dep) { return !dep.platform.is_empty(); };
- for (auto&& spec : specs)
- {
- auto&& scfl = provider.get_control_file(spec.package_spec.name()).value_or_exit(VCPKG_LINE_INFO);
- if (Util::any_of(scfl.source_control_file->core_paragraph->dependencies, has_qualifier) ||
- Util::any_of(scfl.source_control_file->feature_paragraphs,
- [&](auto&& pgh) { return Util::any_of(pgh->dependencies, has_qualifier); }))
- {
- packages_with_qualified_deps.push_back(spec.package_spec);
- }
- }
-
- var_provider.load_dep_info_vars(packages_with_qualified_deps);
- auto action_plan = Dependencies::create_feature_install_plan(provider, var_provider, specs, {}, {});
-
- std::vector<FullPackageSpec> install_specs;
- for (auto&& install_action : action_plan.install_actions)
- {
- install_specs.emplace_back(install_action.spec, install_action.feature_list);
- }
-
- var_provider.load_tag_vars(install_specs, provider);
-
- auto timer = Chrono::ElapsedTimer::create_started();
-
- Checks::check_exit(VCPKG_LINE_INFO, action_plan.already_installed.empty());
- Checks::check_exit(VCPKG_LINE_INFO, action_plan.remove_actions.empty());
-
- Build::compute_all_abis(paths, action_plan, var_provider, {});
-
- auto precheck_results = binary_provider_precheck(paths, action_plan, binaryprovider);
- {
- vcpkg::System::BufferedPrint stdout_print;
-
- for (auto&& action : action_plan.install_actions)
- {
- auto p = &action;
- ret->abi_map.emplace(action.spec, action.abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi);
- ret->features.emplace(action.spec, action.feature_list);
-
- auto precheck_result = precheck_results.at(&action);
- bool b_will_build = false;
-
- std::string state;
-
- if (Util::Sets::contains(exclusions, p->spec.name()))
- {
- state = "skip";
- ret->known.emplace(p->spec, BuildResult::EXCLUDED);
- will_fail.emplace(p->spec);
- }
- else if (!supported_for_triplet(var_provider, p))
- {
- // This treats unsupported ports as if they are excluded
- // which means the ports dependent on it will be cascaded due to missing dependencies
- // Should this be changed so instead it is a failure to depend on a unsupported port?
- state = "n/a";
- ret->known.emplace(p->spec, BuildResult::EXCLUDED);
- will_fail.emplace(p->spec);
- }
- else if (Util::any_of(p->package_dependencies,
- [&](const PackageSpec& spec) { return Util::Sets::contains(will_fail, spec); }))
- {
- state = "cascade";
- ret->known.emplace(p->spec, BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES);
- will_fail.emplace(p->spec);
- }
- else if (precheck_result == RestoreResult::success)
- {
- state = "pass";
- ret->known.emplace(p->spec, BuildResult::SUCCEEDED);
- }
- else if (precheck_result == RestoreResult::build_failed)
- {
- state = "fail";
- ret->known.emplace(p->spec, BuildResult::BUILD_FAILED);
- will_fail.emplace(p->spec);
- }
- else
- {
- ret->unknown.emplace_back(p->spec, p->feature_list);
- b_will_build = true;
- }
-
- stdout_print.append(Strings::format("%40s: %1s %8s: %s\n",
- p->spec,
- (b_will_build ? "*" : " "),
- state,
- action.abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi));
- }
- } // flush stdout_print
-
- // This algorithm consumes the previous action plan to build and return a reduced one.
- std::vector<InstallPlanAction>&& input_install_actions = std::move(action_plan.install_actions);
- std::vector<InstallPlanAction*> rev_install_actions;
- rev_install_actions.reserve(input_install_actions.size());
- std::set<PackageSpec> to_keep;
- for (auto it = input_install_actions.rbegin(); it != input_install_actions.rend(); ++it)
- {
- if (!Util::Sets::contains(ret->known, it->spec))
- {
- to_keep.insert(it->spec);
- }
-
- if (Util::Sets::contains(to_keep, it->spec))
- {
- rev_install_actions.push_back(&*it);
- to_keep.insert(it->package_dependencies.begin(), it->package_dependencies.end());
- }
- }
-
- for (auto it = rev_install_actions.rbegin(); it != rev_install_actions.rend(); ++it)
- {
- ret->plan.install_actions.push_back(std::move(**it));
- }
-
- System::printf("Time to determine pass/fail: %s\n", timer.elapsed());
- return ret;
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- std::unique_ptr<IBinaryProvider> binaryproviderStorage;
- if (args.binary_caching_enabled())
- {
- binaryproviderStorage =
- create_binary_provider_from_configs(args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
- }
-
- IBinaryProvider& binaryprovider = binaryproviderStorage ? *binaryproviderStorage : null_binary_provider();
-
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
- auto& settings = options.settings;
-
- std::set<std::string> exclusions_set;
- auto it_exclusions = settings.find(OPTION_EXCLUDE);
- if (it_exclusions != settings.end())
- {
- auto exclusions = Strings::split(it_exclusions->second, ',');
- exclusions_set.insert(exclusions.begin(), exclusions.end());
- }
-
- const auto is_dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
-
- std::vector<Triplet> triplets = Util::fmap(
- args.command_arguments, [](std::string s) { return Triplet::from_canonical_name(std::move(s)); });
-
- if (triplets.empty())
- {
- triplets.push_back(default_triplet);
- }
-
- auto& filesystem = paths.get_filesystem();
- Optional<CiBuildLogsRecorder> build_logs_recorder_storage;
- {
- auto it_failure_logs = settings.find(OPTION_FAILURE_LOGS);
- if (it_failure_logs != settings.end())
- {
- auto raw_path = fs::u8path(it_failure_logs->second);
- System::printf("Creating failure logs output directory %s\n", it_failure_logs->second);
- filesystem.create_directories(raw_path, VCPKG_LINE_INFO);
- build_logs_recorder_storage = filesystem.canonical(VCPKG_LINE_INFO, raw_path);
- }
- }
-
- const IBuildLogsRecorder& build_logs_recorder =
- build_logs_recorder_storage ? *(build_logs_recorder_storage.get()) : null_build_logs_recorder();
-
- StatusParagraphs status_db = database_load_check(paths);
-
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
- auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
- auto& var_provider = *var_provider_storage;
-
- std::vector<std::map<PackageSpec, BuildResult>> all_known_results;
-
- XunitTestResults xunitTestResults;
-
- std::vector<std::string> all_ports =
- Util::fmap(provider.load_all_control_files(), Paragraphs::get_name_of_control_file);
- std::vector<TripletAndSummary> results;
- auto timer = Chrono::ElapsedTimer::create_started();
- for (Triplet triplet : triplets)
- {
- Input::check_triplet(triplet, paths);
-
- xunitTestResults.push_collection(triplet.canonical_name());
-
- std::vector<PackageSpec> specs = PackageSpec::to_package_specs(all_ports, triplet);
- // Install the default features for every package
- auto all_default_full_specs = Util::fmap(specs, [&](auto& spec) {
- std::vector<std::string> default_features =
- provider.get_control_file(spec.name()).get()->source_control_file->core_paragraph->default_features;
- default_features.emplace_back("core");
- return FullPackageSpec{spec, std::move(default_features)};
- });
-
- Dependencies::CreateInstallPlanOptions serialize_options;
-
- struct RandomizerInstance : Graphs::Randomizer
- {
- virtual int random(int i) override
- {
- if (i <= 1) return 0;
- std::uniform_int_distribution<int> d(0, i - 1);
- return d(e);
- }
-
- std::random_device e;
- } randomizer_instance;
-
- if (Util::Sets::contains(options.switches, OPTION_RANDOMIZE))
- {
- serialize_options.randomizer = &randomizer_instance;
- }
-
- auto split_specs = find_unknown_ports_for_ci(
- paths, exclusions_set, provider, var_provider, all_default_full_specs, binaryprovider);
-
- auto& action_plan = split_specs->plan;
-
- for (auto&& action : action_plan.install_actions)
- {
- if (Util::Sets::contains(exclusions_set, action.spec.name()))
- {
- action.plan_type = InstallPlanType::EXCLUDED;
- }
- else
- {
- action.build_options = vcpkg::Build::backcompat_prohibiting_package_options;
- }
- }
-
- if (is_dry_run)
- {
- Dependencies::print_plan(action_plan, true, paths.builtin_ports_directory());
- }
- else
- {
- auto collection_timer = Chrono::ElapsedTimer::create_started();
- auto summary = Install::perform(args,
- action_plan,
- Install::KeepGoing::YES,
- paths,
- status_db,
- binaryprovider,
- build_logs_recorder,
- var_provider);
- auto collection_time_elapsed = collection_timer.elapsed();
-
- // Adding results for ports that were built or pulled from an archive
- for (auto&& result : summary.results)
- {
- auto& port_features = split_specs->features.at(result.spec);
- split_specs->known.erase(result.spec);
- xunitTestResults.add_test_results(result.spec.to_string(),
- result.build_result.code,
- result.timing,
- split_specs->abi_map.at(result.spec),
- port_features);
- }
-
- // Adding results for ports that were not built because they have known states
- for (auto&& port : split_specs->known)
- {
- auto& port_features = split_specs->features.at(port.first);
- xunitTestResults.add_test_results(port.first.to_string(),
- port.second,
- Chrono::ElapsedTime{},
- split_specs->abi_map.at(port.first),
- port_features);
- }
-
- all_known_results.emplace_back(std::move(split_specs->known));
-
- results.push_back({triplet, std::move(summary)});
-
- xunitTestResults.collection_time(collection_time_elapsed);
- }
- }
- xunitTestResults.assembly_time(timer.elapsed());
-
- for (auto&& result : results)
- {
- System::print2("\nTriplet: ", result.triplet, "\n");
- System::print2("Total elapsed time: ", result.summary.total_elapsed_time, "\n");
- result.summary.print();
- }
-
- auto it_xunit = settings.find(OPTION_XUNIT);
- if (it_xunit != settings.end())
- {
- filesystem.write_contents(fs::u8path(it_xunit->second), xunitTestResults.build_xml(), VCPKG_LINE_INFO);
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void CICommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- CI::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.ciclean.cpp b/toolsrc/src/vcpkg/commands.ciclean.cpp
deleted file mode 100644
index a92b918c8..000000000
--- a/toolsrc/src/vcpkg/commands.ciclean.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.ciclean.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-using namespace vcpkg;
-
-namespace
-{
- void clear_directory(Files::Filesystem& fs, const fs::path& target)
- {
- using vcpkg::System::print2;
- if (fs.is_directory(target))
- {
- print2("Clearing contents of ", fs::u8string(target), "\n");
- fs.remove_all_inside(target, VCPKG_LINE_INFO);
- }
- else
- {
- print2("Skipping clearing contents of ", fs::u8string(target), " because it was not a directory\n");
- }
- }
-}
-
-namespace vcpkg::Commands::CIClean
-{
- void perform_and_exit(const VcpkgCmdArguments&, const VcpkgPaths& paths)
- {
- using vcpkg::System::print2;
- auto& fs = paths.get_filesystem();
- print2("Starting vcpkg CI clean\n");
- clear_directory(fs, paths.buildtrees);
- clear_directory(fs, paths.installed);
- clear_directory(fs, paths.packages);
- print2("Completed vcpkg CI clean\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void CICleanCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- CIClean::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.civerifyversions.cpp b/toolsrc/src/vcpkg/commands.civerifyversions.cpp
deleted file mode 100644
index 78269646c..000000000
--- a/toolsrc/src/vcpkg/commands.civerifyversions.cpp
+++ /dev/null
@@ -1,418 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/system.debug.h>
-
-#include <vcpkg/commands.civerifyversions.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/registries.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/versiondeserializers.h>
-
-namespace
-{
- using namespace vcpkg;
-
- std::string get_scheme_name(Versions::Scheme scheme)
- {
- switch (scheme)
- {
- case Versions::Scheme::Relaxed: return "version";
- case Versions::Scheme::Semver: return "version-semver";
- case Versions::Scheme::String: return "version-string";
- case Versions::Scheme::Date: return "version-date";
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-}
-
-namespace vcpkg::Commands::CIVerifyVersions
-{
- static constexpr StringLiteral OPTION_EXCLUDE = "exclude";
- static constexpr StringLiteral OPTION_VERBOSE = "verbose";
- static constexpr StringLiteral OPTION_VERIFY_GIT_TREES = "verify-git-trees";
-
- static constexpr CommandSwitch VERIFY_VERSIONS_SWITCHES[]{
- {OPTION_VERBOSE, "Print result for each port instead of just errors."},
- {OPTION_VERIFY_GIT_TREES, "Verify that each git tree object matches its declared version (this is very slow)"},
- };
-
- static constexpr CommandSetting VERIFY_VERSIONS_SETTINGS[] = {
- {OPTION_EXCLUDE, "Comma-separated list of ports to skip"},
- };
-
- const CommandStructure COMMAND_STRUCTURE{
- create_example_string(R"###(x-ci-verify-versions)###"),
- 0,
- SIZE_MAX,
- {{VERIFY_VERSIONS_SWITCHES}, {VERIFY_VERSIONS_SETTINGS}, {}},
- nullptr,
- };
-
- static ExpectedS<std::string> verify_version_in_db(const VcpkgPaths& paths,
- const std::map<std::string, VersionT, std::less<>> baseline,
- const std::string& port_name,
- const fs::path& port_path,
- const fs::path& versions_file_path,
- const std::string& local_git_tree,
- bool verify_git_trees)
- {
- auto maybe_versions = vcpkg::get_builtin_versions(paths, port_name);
- if (!maybe_versions.has_value())
- {
- return {
- Strings::format("Error: While attempting to parse versions for port %s from file: %s\n"
- " Found the following error(s):\n%s",
- port_name,
- fs::u8string(versions_file_path),
- maybe_versions.error()),
- expected_right_tag,
- };
- }
-
- const auto& versions = maybe_versions.value_or_exit(VCPKG_LINE_INFO);
- if (versions.empty())
- {
- return {
- Strings::format("Error: While reading versions for port %s from file: %s\n"
- " File contains no versions.",
- port_name,
- fs::u8string(versions_file_path)),
- expected_right_tag,
- };
- }
-
- if (verify_git_trees)
- {
- for (auto&& version_entry : versions)
- {
- bool version_ok = false;
- for (const std::string& control_file : {"CONTROL", "vcpkg.json"})
- {
- auto treeish = Strings::concat(version_entry.second, ':', control_file);
- auto maybe_file = paths.git_show(Strings::concat(treeish), paths.root / fs::u8path(".git"));
- if (!maybe_file.has_value()) continue;
-
- const auto& file = maybe_file.value_or_exit(VCPKG_LINE_INFO);
- auto maybe_scf = Paragraphs::try_load_port_text(file, treeish, control_file == "vcpkg.json");
- if (!maybe_scf.has_value())
- {
- return {
- Strings::format("Error: While reading versions for port %s from file: %s\n"
- " While validating version: %s.\n"
- " While trying to load port from: %s\n"
- " Found the following error(s):\n%s",
- port_name,
- fs::u8string(versions_file_path),
- version_entry.first.versiont,
- treeish,
- maybe_scf.error()->error),
- expected_right_tag,
- };
- }
-
- const auto& scf = maybe_scf.value_or_exit(VCPKG_LINE_INFO);
- auto&& git_tree_version = scf.get()->to_schemed_version();
- if (version_entry.first.versiont != git_tree_version.versiont)
- {
- return {
- Strings::format(
- "Error: While reading versions for port %s from file: %s\n"
- " While validating version: %s.\n"
- " The version declared in file does not match checked-out version: %s\n"
- " Checked out Git SHA: %s",
- port_name,
- fs::u8string(versions_file_path),
- version_entry.first.versiont,
- git_tree_version.versiont,
- version_entry.second),
- expected_right_tag,
- };
- }
- version_ok = true;
- break;
- }
-
- if (!version_ok)
- {
- return {
- Strings::format(
- "Error: While reading versions for port %s from file: %s\n"
- " While validating version: %s.\n"
- " The checked-out object does not contain a CONTROL file or vcpkg.json file.\n"
- " Checked out Git SHA: %s",
- port_name,
- fs::u8string(versions_file_path),
- version_entry.first.versiont,
- version_entry.second),
- expected_right_tag,
- };
- }
- }
- }
-
- const auto& top_entry = versions.front();
-
- auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), port_path);
- if (!maybe_scf.has_value())
- {
- return {
- Strings::format("Error: While attempting to load local port %s.\n"
- " Found the following error(s):\n%s",
- port_name,
- maybe_scf.error()->error),
- expected_right_tag,
- };
- }
-
- const auto local_port_version = maybe_scf.value_or_exit(VCPKG_LINE_INFO)->to_schemed_version();
-
- if (top_entry.first.versiont != local_port_version.versiont)
- {
- auto versions_end = versions.end();
- auto it = std::find_if(versions.begin(), versions_end, [&](auto&& entry) {
- return entry.first.versiont == local_port_version.versiont;
- });
- if (it != versions_end)
- {
- return {
- Strings::format("Error: While reading versions for port %s from file: %s\n"
- " Local port version `%s` exists in version file but it's not the first "
- "entry in the \"versions\" array.",
- port_name,
- fs::u8string(versions_file_path),
- local_port_version.versiont),
- expected_right_tag,
- };
- }
- else
- {
- return {
- Strings::format("Error: While reading versions for port %s from file: %s\n"
- " Version `%s` was not found in versions file.\n"
- " Run:\n\n"
- " vcpkg x-add-version %s\n\n"
- " to add the new port version.",
- port_name,
- fs::u8string(versions_file_path),
- local_port_version.versiont,
- port_name),
- expected_right_tag,
- };
- }
- }
-
- if (top_entry.first.scheme != local_port_version.scheme)
- {
- return {
- Strings::format("Error: While reading versions for port %s from file: %s\n"
- " File declares version `%s` with scheme: `%s`.\n"
- " But local port declares the same version with a different scheme: `%s`.\n"
- " Version must be unique even between different schemes.\n"
- " Run:\n\n"
- " vcpkg x-add-version %s --overwrite-version\n\n"
- " to overwrite the declared version's scheme.",
- port_name,
- fs::u8string(versions_file_path),
- top_entry.first.versiont,
- get_scheme_name(top_entry.first.scheme),
- get_scheme_name(local_port_version.scheme),
- port_name),
- expected_right_tag,
- };
- }
-
- if (local_git_tree != top_entry.second)
- {
- return {
- Strings::format("Error: While reading versions for port %s from file: %s\n"
- " File declares version `%s` with SHA: %s\n"
- " But local port with the same verion has a different SHA: %s\n"
- " Please update the port's version fields and then run:\n\n"
- " vcpkg x-add-version %s\n\n"
- " to add a new version.",
- port_name,
- fs::u8string(versions_file_path),
- top_entry.first.versiont,
- local_git_tree,
- top_entry.second,
- port_name),
- expected_right_tag,
- };
- }
-
- auto maybe_baseline = baseline.find(port_name);
- if (maybe_baseline == baseline.end())
- {
- return {
- Strings::format("Error: While reading baseline version for port %s.\n"
- " Baseline version not found.\n"
- " Run:\n\n"
- " vcpkg x-add-version %s\n\n"
- " to set version %s as the baseline version.",
- port_name,
- port_name,
- local_port_version.versiont),
- expected_right_tag,
- };
- }
-
- auto&& baseline_version = maybe_baseline->second;
- if (baseline_version != top_entry.first.versiont)
- {
- return {
- Strings::format("Error: While reading baseline version for port %s.\n"
- " While validating latest version from file: %s\n"
- " Baseline file declares version: %s.\n"
- " But the latest version in version files is: %s.\n"
- " Run:\n\n"
- " vcpkg x-add-version %s\n\n"
- " to update the baseline version.",
- port_name,
- fs::u8string(versions_file_path),
- baseline_version,
- top_entry.first.versiont,
- port_name),
- expected_right_tag,
- };
- }
-
- return {
- Strings::format("OK: %s\t%s -> %s\n", top_entry.second, port_name, top_entry.first.versiont),
- expected_left_tag,
- };
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- auto parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
-
- bool verbose = Util::Sets::contains(parsed_args.switches, OPTION_VERBOSE);
- bool verify_git_trees = Util::Sets::contains(parsed_args.switches, OPTION_VERIFY_GIT_TREES);
-
- std::set<std::string> exclusion_set;
- auto settings = parsed_args.settings;
- auto it_exclusions = settings.find(OPTION_EXCLUDE);
- if (it_exclusions != settings.end())
- {
- auto exclusions = Strings::split(it_exclusions->second, ',');
- exclusion_set.insert(exclusions.begin(), exclusions.end());
- }
-
- auto maybe_port_git_tree_map = paths.git_get_local_port_treeish_map();
- Checks::check_exit(VCPKG_LINE_INFO,
- maybe_port_git_tree_map.has_value(),
- "Fatal error: Failed to obtain git SHAs for local ports.\n%s",
- maybe_port_git_tree_map.error());
- auto port_git_tree_map = maybe_port_git_tree_map.value_or_exit(VCPKG_LINE_INFO);
-
- // Baseline is required.
- auto baseline = get_builtin_baseline(paths).value_or_exit(VCPKG_LINE_INFO);
- auto& fs = paths.get_filesystem();
- std::set<std::string> errors;
- for (const auto& dir : fs::directory_iterator(paths.builtin_ports_directory()))
- {
- const auto& port_path = dir.path();
-
- auto&& port_name = fs::u8string(port_path.stem());
- if (Util::Sets::contains(exclusion_set, port_name))
- {
- if (verbose) System::printf("SKIP: %s\n", port_name);
- continue;
- }
- auto git_tree_it = port_git_tree_map.find(port_name);
- if (git_tree_it == port_git_tree_map.end())
- {
- System::printf(System::Color::error, "FAIL: %s\n", port_name);
- errors.emplace(Strings::format("Error: While validating port %s.\n"
- " Missing Git SHA.\n"
- " Run:\n\n"
- " git add %s.\n"
- " git commit -m \"[%s] Add new port\"\n"
- " vcpkg x-add-version %s\n\n"
- " to commit the new port and create its version file.",
- port_name,
- fs::u8string(port_path),
- port_name,
- port_name));
- continue;
- }
- auto git_tree = git_tree_it->second;
-
- auto control_path = port_path / fs::u8path("CONTROL");
- auto manifest_path = port_path / fs::u8path("vcpkg.json");
- auto manifest_exists = fs.exists(manifest_path);
- auto control_exists = fs.exists(control_path);
-
- if (manifest_exists && control_exists)
- {
- System::printf(System::Color::error, "FAIL: %s\n", port_name);
- errors.emplace(
- Strings::format("Error: While validating port %s.\n"
- " Both a manifest file and a CONTROL file exist in port directory: %s",
- port_name,
- fs::u8string(port_path)));
- continue;
- }
-
- if (!manifest_exists && !control_exists)
- {
- System::printf(System::Color::error, "FAIL: %s\n", port_name);
- errors.emplace(Strings::format("Error: While validating port %s.\n"
- " No manifest file or CONTROL file exist in port directory: %s",
- port_name,
- fs::u8string(port_path)));
- continue;
- }
-
- auto versions_file_path = paths.builtin_registry_versions / fs::u8path({port_name[0], '-'}) /
- fs::u8path(Strings::concat(port_name, ".json"));
- if (!fs.exists(versions_file_path))
- {
- System::printf(System::Color::error, "FAIL: %s\n", port_name);
- errors.emplace(Strings::format("Error: While validating port %s.\n"
- " Missing expected versions file at: %s\n"
- " Run:\n\n"
- " vcpkg x-add-version %s\n\n"
- " to create the versions file.",
- port_name,
- fs::u8string(versions_file_path),
- port_name));
- continue;
- }
-
- auto maybe_ok = verify_version_in_db(
- paths, baseline, port_name, port_path, versions_file_path, git_tree, verify_git_trees);
-
- if (!maybe_ok.has_value())
- {
- System::printf(System::Color::error, "FAIL: %s\n", port_name);
- errors.emplace(maybe_ok.error());
- continue;
- }
-
- if (verbose) System::printf("%s", maybe_ok.value_or_exit(VCPKG_LINE_INFO));
- }
-
- if (!errors.empty())
- {
- System::print2(System::Color::error, "Found the following errors:\n");
- for (auto&& error : errors)
- {
- System::printf(System::Color::error, "%s\n", error);
- }
- System::print2(System::Color::error,
- "\nTo attempt to resolve all errors at once, run:\n\n"
- " vcpkg x-add-version --all\n\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void CIVerifyVersionsCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- CIVerifyVersions::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp
deleted file mode 100644
index 830dba908..000000000
--- a/toolsrc/src/vcpkg/commands.contact.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <vcpkg/base/chrono.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.contact.h>
-#include <vcpkg/help.h>
-#include <vcpkg/userconfig.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-namespace vcpkg::Commands::Contact
-{
- const std::string& email()
- {
- static const std::string S_EMAIL = R"(vcpkg@microsoft.com)";
- return S_EMAIL;
- }
-
- static constexpr StringLiteral OPTION_SURVEY = "survey";
-
- static constexpr std::array<CommandSwitch, 1> SWITCHES = {{
- {OPTION_SURVEY, "Launch default browser to the current vcpkg survey"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("contact"),
- 0,
- 0,
- {SWITCHES, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, Files::Filesystem& fs)
- {
- const ParsedArguments parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
-
- if (Util::Sets::contains(parsed_args.switches, SWITCHES[0].name))
- {
- auto maybe_now = Chrono::CTime::get_current_date_time();
- if (const auto p_now = maybe_now.get())
- {
- auto config = UserConfig::try_read_data(fs);
- config.last_completed_survey = p_now->to_string();
- config.try_write_data(fs);
- }
-
-#if defined(_WIN32)
- System::cmd_execute(System::Command("start").string_arg("https://aka.ms/NPS_vcpkg"));
- System::print2("Default browser launched to https://aka.ms/NPS_vcpkg; thank you for your feedback!\n");
-#else
- System::print2("Please navigate to https://aka.ms/NPS_vcpkg in your preferred browser. Thank you for your "
- "feedback!\n");
-#endif
- }
- else
- {
- System::print2("Send an email to ", email(), " with any feedback.\n");
- }
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void ContactCommand::perform_and_exit(const VcpkgCmdArguments& args, Files::Filesystem& fs) const
- {
- Contact::perform_and_exit(args, fs);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp
deleted file mode 100644
index 386aedf58..000000000
--- a/toolsrc/src/vcpkg/commands.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/build.h>
-#include <vcpkg/commands.add-version.h>
-#include <vcpkg/commands.autocomplete.h>
-#include <vcpkg/commands.buildexternal.h>
-#include <vcpkg/commands.cache.h>
-#include <vcpkg/commands.ci.h>
-#include <vcpkg/commands.ciclean.h>
-#include <vcpkg/commands.civerifyversions.h>
-#include <vcpkg/commands.contact.h>
-#include <vcpkg/commands.create.h>
-#include <vcpkg/commands.dependinfo.h>
-#include <vcpkg/commands.edit.h>
-#include <vcpkg/commands.env.h>
-#include <vcpkg/commands.fetch.h>
-#include <vcpkg/commands.format-manifest.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/commands.hash.h>
-#include <vcpkg/commands.info.h>
-#include <vcpkg/commands.integrate.h>
-#include <vcpkg/commands.list.h>
-#include <vcpkg/commands.owns.h>
-#include <vcpkg/commands.porthistory.h>
-#include <vcpkg/commands.portsdiff.h>
-#include <vcpkg/commands.search.h>
-#include <vcpkg/commands.setinstalled.h>
-#include <vcpkg/commands.upgrade.h>
-#include <vcpkg/commands.upload-metrics.h>
-#include <vcpkg/commands.version.h>
-#include <vcpkg/commands.xvsinstances.h>
-#include <vcpkg/export.h>
-#include <vcpkg/help.h>
-#include <vcpkg/install.h>
-#include <vcpkg/remove.h>
-#include <vcpkg/update.h>
-
-namespace vcpkg::Commands
-{
- Span<const PackageNameAndFunction<const BasicCommand*>> get_available_basic_commands()
- {
- static const Version::VersionCommand version{};
- static const Contact::ContactCommand contact{};
-#if defined(_WIN32)
- static const UploadMetrics::UploadMetricsCommand upload_metrics{};
-#endif // defined(_WIN32)
-
- static std::vector<PackageNameAndFunction<const BasicCommand*>> t = {
- {"version", &version},
- {"contact", &contact},
-#if defined(_WIN32)
- {"x-upload-metrics", &upload_metrics},
-#endif // defined(_WIN32)
- };
- return t;
- }
-
- Span<const PackageNameAndFunction<const PathsCommand*>> get_available_paths_commands()
- {
- static const Help::HelpCommand help{};
- static const Search::SearchCommand search{};
- static const List::ListCommand list{};
- static const Info::InfoCommand info{};
- static const Integrate::IntegrateCommand integrate{};
- static const Owns::OwnsCommand owns{};
- static const Update::UpdateCommand update{};
- static const Edit::EditCommand edit{};
- static const Create::CreateCommand create{};
- static const Cache::CacheCommand cache{};
- static const PortsDiff::PortsDiffCommand portsdiff{};
- static const Autocomplete::AutocompleteCommand autocomplete{};
- static const Hash::HashCommand hash{};
- static const Fetch::FetchCommand fetch{};
- static const CIClean::CICleanCommand ciclean{};
- static const PortHistory::PortHistoryCommand porthistory{};
- static const X_VSInstances::VSInstancesCommand vsinstances{};
- static const FormatManifest::FormatManifestCommand format_manifest{};
- static const CIVerifyVersions::CIVerifyVersionsCommand ci_verify_versions{};
- static const AddVersion::AddVersionCommand add_version{};
-
- static std::vector<PackageNameAndFunction<const PathsCommand*>> t = {
- {"/?", &help},
- {"help", &help},
- {"search", &search},
- {"list", &list},
- {"integrate", &integrate},
- {"owns", &owns},
- {"update", &update},
- {"edit", &edit},
- {"create", &create},
- {"cache", &cache},
- {"portsdiff", &portsdiff},
- {"autocomplete", &autocomplete},
- {"hash", &hash},
- {"fetch", &fetch},
- {"x-ci-clean", &ciclean},
- {"x-package-info", &info},
- {"x-history", &porthistory},
- {"x-vsinstances", &vsinstances},
- {"format-manifest", &format_manifest},
- {"x-ci-verify-versions", &ci_verify_versions},
- {"x-add-version", &add_version},
- };
- return t;
- }
-
- Span<const PackageNameAndFunction<const TripletCommand*>> get_available_triplet_commands()
- {
- static const Install::InstallCommand install{};
- static const SetInstalled::SetInstalledCommand set_installed{};
- static const CI::CICommand ci{};
- static const Remove::RemoveCommand remove{};
- static const Upgrade::UpgradeCommand upgrade{};
- static const Build::BuildCommand build{};
- static const Env::EnvCommand env{};
- static const BuildExternal::BuildExternalCommand build_external{};
- static const Export::ExportCommand export_command{};
- static const DependInfo::DependInfoCommand depend_info{};
-
- static std::vector<PackageNameAndFunction<const TripletCommand*>> t = {
- {"install", &install},
- {"x-set-installed", &set_installed},
- {"ci", &ci},
- {"remove", &remove},
- {"upgrade", &upgrade},
- {"build", &build},
- {"env", &env},
- {"build-external", &build_external},
- {"export", &export_command},
- {"depend-info", &depend_info},
- };
- return t;
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp
deleted file mode 100644
index 6ef5163cb..000000000
--- a/toolsrc/src/vcpkg/commands.create.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/buildenvironment.h>
-#include <vcpkg/commands.create.h>
-#include <vcpkg/commands.version.h>
-#include <vcpkg/help.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace
-{
- std::string remove_trailing_slashes(std::string argument)
- {
- using fs::is_slash;
- argument.erase(std::find_if_not(argument.rbegin(), argument.rend(), is_slash).base(), argument.end());
- return argument;
- }
-}
-
-namespace vcpkg::Commands::Create
-{
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string(R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"),
- 2,
- 3,
- {},
- nullptr,
- };
-
- int perform(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
- const std::string port_name = args.command_arguments.at(0);
- const std::string url = remove_trailing_slashes(args.command_arguments.at(1));
-
- std::vector<System::CMakeVariable> cmake_args{
- {"CMD", "CREATE"},
- {"PORT", port_name},
- {"PORT_PATH", fs::generic_u8string(paths.builtin_ports_directory() / fs::u8path(port_name))},
- {"URL", url},
- {"VCPKG_BASE_VERSION", Commands::Version::base_version()},
- };
-
- if (args.command_arguments.size() >= 3)
- {
- const std::string& zip_file_name = args.command_arguments.at(2);
- Checks::check_exit(VCPKG_LINE_INFO,
- !Files::has_invalid_chars_for_filesystem(zip_file_name),
- R"(Filename cannot contain invalid chars %s, but was %s)",
- Files::FILESYSTEM_INVALID_CHARACTERS,
- zip_file_name);
- cmake_args.emplace_back("FILENAME", zip_file_name);
- }
-
- auto cmd_launch_cmake = make_cmake_cmd(paths, paths.ports_cmake, std::move(cmake_args));
- return System::cmd_execute_clean(cmd_launch_cmake);
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- Checks::exit_with_code(VCPKG_LINE_INFO, perform(args, paths));
- }
-
- void CreateCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Create::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp
deleted file mode 100644
index bfd719df0..000000000
--- a/toolsrc/src/vcpkg/commands.dependinfo.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.dependinfo.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/packagespec.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-#include <vector>
-
-using vcpkg::Dependencies::ActionPlan;
-using vcpkg::Dependencies::InstallPlanAction;
-using vcpkg::PortFileProvider::PathsPortFileProvider;
-
-namespace vcpkg::Commands::DependInfo
-{
- namespace
- {
- constexpr StringLiteral OPTION_DOT = "dot";
- constexpr StringLiteral OPTION_DGML = "dgml";
- constexpr StringLiteral OPTION_SHOW_DEPTH = "show-depth";
- constexpr StringLiteral OPTION_MAX_RECURSE = "max-recurse";
- constexpr StringLiteral OPTION_SORT = "sort";
-
- constexpr int NO_RECURSE_LIMIT_VALUE = -1;
-
- constexpr std::array<CommandSwitch, 3> DEPEND_SWITCHES = {
- {{OPTION_DOT, "Creates graph on basis of dot"},
- {OPTION_DGML, "Creates graph on basis of dgml"},
- {OPTION_SHOW_DEPTH, "Show recursion depth in output"}}};
-
- constexpr std::array<CommandSetting, 2> DEPEND_SETTINGS = {
- {{OPTION_MAX_RECURSE, "Set max recursion depth, a value of -1 indicates no limit"},
- {OPTION_SORT,
- "Set sort order for the list of dependencies, accepted values are: lexicographical, topological "
- "(default), "
- "reverse"}}};
-
- struct PackageDependInfo
- {
- std::string package;
- int depth;
- std::unordered_set<std::string> features;
- std::vector<std::string> dependencies;
- };
-
- enum SortMode
- {
- Lexicographical = 0,
- Topological,
- ReverseTopological,
- Default = Topological
- };
-
- int get_max_depth(const ParsedArguments& options)
- {
- auto iter = options.settings.find(OPTION_MAX_RECURSE);
- if (iter != options.settings.end())
- {
- std::string value = iter->second;
- try
- {
- return std::stoi(value);
- }
- catch (std::exception&)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "Value of --max-depth must be an integer");
- }
- }
- // No --max-depth set, default to no limit.
- return NO_RECURSE_LIMIT_VALUE;
- }
-
- SortMode get_sort_mode(const ParsedArguments& options)
- {
- constexpr StringLiteral OPTION_SORT_LEXICOGRAPHICAL = "lexicographical";
- constexpr StringLiteral OPTION_SORT_TOPOLOGICAL = "topological";
- constexpr StringLiteral OPTION_SORT_REVERSE = "reverse";
-
- static const std::map<std::string, SortMode> sortModesMap{{OPTION_SORT_LEXICOGRAPHICAL, Lexicographical},
- {OPTION_SORT_TOPOLOGICAL, Topological},
- {OPTION_SORT_REVERSE, ReverseTopological}};
-
- auto iter = options.settings.find(OPTION_SORT);
- if (iter != options.settings.end())
- {
- const std::string value = Strings::ascii_to_lowercase(std::string{iter->second});
- auto it = sortModesMap.find(value);
- if (it != sortModesMap.end())
- {
- return it->second;
- }
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Value of --sort must be one of `%s`, `%s`, or `%s`",
- OPTION_SORT_LEXICOGRAPHICAL,
- OPTION_SORT_TOPOLOGICAL,
- OPTION_SORT_REVERSE);
- }
- return Default;
- }
-
- std::string create_dot_as_string(const std::vector<PackageDependInfo>& depend_info)
- {
- int empty_node_count = 0;
-
- std::string s;
- s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;");
-
- for (const auto& package : depend_info)
- {
- if (package.dependencies.empty())
- {
- empty_node_count++;
- continue;
- }
-
- const std::string name = Strings::replace_all(std::string{package.package}, "-", "_");
- s.append(Strings::format("%s;", name));
- for (const auto& d : package.dependencies)
- {
- const std::string dependency_name = Strings::replace_all(std::string{d}, "-", "_");
- s.append(Strings::format("%s -> %s;", name, dependency_name));
- }
- }
-
- s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count));
- return s;
- }
-
- std::string create_dgml_as_string(const std::vector<PackageDependInfo>& depend_info)
- {
- std::string s;
- s.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
- s.append("<DirectedGraph xmlns=\"http://schemas.microsoft.com/vs/2009/dgml\">");
-
- std::string nodes, links;
- for (const auto& package : depend_info)
- {
- const std::string name = package.package;
- nodes.append(Strings::format("<Node Id=\"%s\" />", name));
-
- // Iterate over dependencies.
- for (const auto& d : package.dependencies)
- {
- links.append(Strings::format("<Link Source=\"%s\" Target=\"%s\" />", name, d));
- }
- }
-
- s.append(Strings::format("<Nodes>%s</Nodes>", nodes));
-
- s.append(Strings::format("<Links>%s</Links>", links));
-
- s.append("</DirectedGraph>");
- return s;
- }
-
- std::string create_graph_as_string(const std::unordered_set<std::string>& switches,
- const std::vector<PackageDependInfo>& depend_info)
- {
- if (Util::Sets::contains(switches, OPTION_DOT))
- {
- return create_dot_as_string(depend_info);
- }
- else if (Util::Sets::contains(switches, OPTION_DGML))
- {
- return create_dgml_as_string(depend_info);
- }
- return "";
- }
-
- void assign_depth_to_dependencies(const std::string& package,
- const int depth,
- const int max_depth,
- std::map<std::string, PackageDependInfo>& dependencies_map)
- {
- auto iter = dependencies_map.find(package);
- Checks::check_exit(
- VCPKG_LINE_INFO, iter != dependencies_map.end(), "Package not found in dependency graph");
-
- PackageDependInfo& info = iter->second;
-
- if (depth > info.depth)
- {
- info.depth = depth;
- if (depth < max_depth || max_depth == NO_RECURSE_LIMIT_VALUE)
- {
- for (auto&& dependency : info.dependencies)
- {
- assign_depth_to_dependencies(dependency, depth + 1, max_depth, dependencies_map);
- }
- }
- }
- }
-
- std::vector<PackageDependInfo> extract_depend_info(const std::vector<const InstallPlanAction*>& install_actions,
- const int max_depth)
- {
- std::map<std::string, PackageDependInfo> package_dependencies;
- for (const InstallPlanAction* pia : install_actions)
- {
- const InstallPlanAction& install_action = *pia;
-
- const std::vector<std::string> dependencies = Util::fmap(
- install_action.package_dependencies, [](const PackageSpec& spec) { return spec.name(); });
-
- std::unordered_set<std::string> features{install_action.feature_list.begin(),
- install_action.feature_list.end()};
- features.erase("core");
-
- std::string port_name = install_action.spec.name();
-
- PackageDependInfo info{port_name, -1, features, dependencies};
- package_dependencies.emplace(port_name, std::move(info));
- }
-
- const InstallPlanAction& init = *install_actions.back();
- assign_depth_to_dependencies(init.spec.name(), 0, max_depth, package_dependencies);
-
- std::vector<PackageDependInfo> out =
- Util::fmap(package_dependencies, [](auto&& kvpair) -> PackageDependInfo { return kvpair.second; });
- Util::erase_remove_if(out, [](auto&& info) { return info.depth < 0; });
- return out;
- }
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("depend-info sqlite3"),
- 1,
- 1,
- {DEPEND_SWITCHES, DEPEND_SETTINGS},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
- const int max_depth = get_max_depth(options);
- const SortMode sort_mode = get_sort_mode(options);
- const bool show_depth = Util::Sets::contains(options.switches, OPTION_SHOW_DEPTH);
-
- const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_full_package_spec(
- std::string{arg}, default_triplet, COMMAND_STRUCTURE.example_text);
- });
-
- for (auto&& spec : specs)
- {
- Input::check_triplet(spec.package_spec.triplet(), paths);
- }
-
- PathsPortFileProvider provider(paths, args.overlay_ports);
- auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
- auto& var_provider = *var_provider_storage;
-
- // By passing an empty status_db, we should get a plan containing all dependencies.
- // All actions in the plan should be install actions, as there's no installed packages to remove.
- StatusParagraphs status_db;
- auto action_plan = Dependencies::create_feature_install_plan(provider, var_provider, specs, status_db);
- Checks::check_exit(
- VCPKG_LINE_INFO, action_plan.remove_actions.empty(), "Only install actions should exist in the plan");
- std::vector<const InstallPlanAction*> install_actions =
- Util::fmap(action_plan.already_installed, [&](const auto& action) { return &action; });
- for (auto&& action : action_plan.install_actions)
- install_actions.push_back(&action);
-
- std::vector<PackageDependInfo> depend_info = extract_depend_info(install_actions, max_depth);
-
- if (Util::Sets::contains(options.switches, OPTION_DOT) || Util::Sets::contains(options.switches, OPTION_DGML))
- {
- const std::vector<const SourceControlFile*> source_control_files =
- Util::fmap(install_actions, [](const InstallPlanAction* install_action) {
- const SourceControlFileLocation& scfl =
- install_action->source_control_file_location.value_or_exit(VCPKG_LINE_INFO);
- return const_cast<const SourceControlFile*>(scfl.source_control_file.get());
- });
-
- const std::string graph_as_string = create_graph_as_string(options.switches, depend_info);
- System::print2(graph_as_string, '\n');
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- // TODO: Improve this code
- auto lex = [](const PackageDependInfo& lhs, const PackageDependInfo& rhs) -> bool {
- return lhs.package < rhs.package;
- };
- auto topo = [](const PackageDependInfo& lhs, const PackageDependInfo& rhs) -> bool {
- return lhs.depth > rhs.depth;
- };
- auto reverse = [](const PackageDependInfo& lhs, const PackageDependInfo& rhs) -> bool {
- return lhs.depth < rhs.depth;
- };
-
- switch (sort_mode)
- {
- case SortMode::Lexicographical: std::sort(std::begin(depend_info), std::end(depend_info), lex); break;
- case SortMode::ReverseTopological:
- std::sort(std::begin(depend_info), std::end(depend_info), reverse);
- break;
- case SortMode::Topological: std::sort(std::begin(depend_info), std::end(depend_info), topo); break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- for (auto&& info : depend_info)
- {
- if (info.depth >= 0)
- {
- std::string features = Strings::join(", ", info.features);
- const std::string dependencies = Strings::join(", ", info.dependencies);
-
- if (show_depth)
- {
- System::print2(System::Color::error, "(", info.depth, ") ");
- }
- System::print2(System::Color::success, info.package);
- if (!features.empty())
- {
- System::print2("[");
- System::print2(System::Color::warning, features);
- System::print2("]");
- }
- System::print2(": ", dependencies, "\n");
- }
- }
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void DependInfoCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- DependInfo::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp
deleted file mode 100644
index e761b3cf4..000000000
--- a/toolsrc/src/vcpkg/commands.edit.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.edit.h>
-#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-#include <limits.h>
-
-#if defined(_WIN32)
-namespace
-{
- std::vector<fs::path> find_from_registry()
- {
- std::vector<fs::path> output;
-
- struct RegKey
- {
- HKEY root;
- vcpkg::StringLiteral subkey;
- } REGKEYS[] = {
- {HKEY_LOCAL_MACHINE,
- R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)"},
- {HKEY_LOCAL_MACHINE,
- R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)"},
- {HKEY_LOCAL_MACHINE,
- R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)"},
- {HKEY_CURRENT_USER,
- R"(Software\Microsoft\Windows\CurrentVersion\Uninstall\{771FD6B0-FA20-440A-A002-3B3BAC16DC50}_is1)"},
- {HKEY_LOCAL_MACHINE,
- R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EA457B21-F73E-494C-ACAB-524FDE069978}_is1)"},
- };
-
- for (auto&& keypath : REGKEYS)
- {
- const vcpkg::Optional<std::string> code_installpath =
- vcpkg::System::get_registry_string(keypath.root, keypath.subkey, "InstallLocation");
- if (const auto c = code_installpath.get())
- {
- const fs::path install_path = fs::u8path(*c);
- output.push_back(install_path / "Code - Insiders.exe");
- output.push_back(install_path / "Code.exe");
- }
- }
- return output;
- }
-
- std::string expand_environment_strings(const std::string& input)
- {
- const auto widened = vcpkg::Strings::to_utf16(input);
- std::wstring result;
- result.resize(result.capacity());
- bool done;
- do
- {
- if (result.size() == ULONG_MAX)
- {
- vcpkg::Checks::exit_fail(VCPKG_LINE_INFO); // integer overflow
- }
-
- const auto required_size =
- ExpandEnvironmentStringsW(widened.c_str(), &result[0], static_cast<unsigned long>(result.size() + 1));
- if (required_size == 0)
- {
- vcpkg::System::print2(vcpkg::System::Color::error, "Error: could not expand the environment string:\n");
- vcpkg::System::print2(vcpkg::System::Color::error, input);
- vcpkg::Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- done = required_size <= result.size() + 1;
- result.resize(required_size - 1);
- } while (!done);
- return vcpkg::Strings::to_utf8(result);
- }
-}
-#endif
-
-namespace vcpkg::Commands::Edit
-{
- static constexpr StringLiteral OPTION_BUILDTREES = "buildtrees";
-
- static constexpr StringLiteral OPTION_ALL = "all";
-
- static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
- {
- auto sources_and_errors = Paragraphs::try_load_all_registry_ports(paths);
-
- return Util::fmap(sources_and_errors.paragraphs, Paragraphs::get_name_of_control_file);
- }
-
- static constexpr std::array<CommandSwitch, 2> EDIT_SWITCHES = {
- {{OPTION_BUILDTREES, "Open editor into the port-specific buildtree subfolder"},
- {OPTION_ALL, "Open editor into the port as well as the port-specific buildtree subfolder"}}};
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("edit zlib"),
- 1,
- 10,
- {EDIT_SWITCHES, {}},
- &valid_arguments,
- };
-
- static std::vector<std::string> create_editor_arguments(const VcpkgPaths& paths,
- const ParsedArguments& options,
- const std::vector<std::string>& ports)
- {
- if (Util::Sets::contains(options.switches, OPTION_ALL))
- {
- const auto& fs = paths.get_filesystem();
- auto packages = fs.get_files_non_recursive(paths.packages);
-
- // TODO: Support edit for --overlay-ports
- return Util::fmap(ports, [&](const std::string& port_name) -> std::string {
- const auto portpath = paths.builtin_ports_directory() / port_name;
- const auto portfile = portpath / "portfile.cmake";
- const auto buildtrees_current_dir = paths.build_dir(port_name);
- const auto pattern = port_name + "_";
-
- std::string package_paths;
- for (auto&& package : packages)
- {
- if (Strings::case_insensitive_ascii_starts_with(fs::u8string(package.filename()), pattern))
- {
- package_paths.append(Strings::format(" \"%s\"", fs::u8string(package)));
- }
- }
-
- return Strings::format(R"###("%s" "%s" "%s"%s)###",
- fs::u8string(portpath),
- fs::u8string(portfile),
- fs::u8string(buildtrees_current_dir),
- package_paths);
- });
- }
-
- if (Util::Sets::contains(options.switches, OPTION_BUILDTREES))
- {
- return Util::fmap(ports, [&](const std::string& port_name) -> std::string {
- return Strings::format(R"###("%s")###", fs::u8string(paths.build_dir(port_name)));
- });
- }
-
- return Util::fmap(ports, [&](const std::string& port_name) -> std::string {
- const auto portpath = paths.builtin_ports_directory() / port_name;
- const auto portfile = portpath / "portfile.cmake";
- return Strings::format(R"###("%s" "%s")###", fs::u8string(portpath), fs::u8string(portfile));
- });
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- auto& fs = paths.get_filesystem();
-
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- const std::vector<std::string>& ports = args.command_arguments;
- for (auto&& port_name : ports)
- {
- const fs::path portpath = paths.builtin_ports_directory() / port_name;
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name);
- }
-
- std::vector<fs::path> candidate_paths;
- auto maybe_editor_path = System::get_environment_variable("EDITOR");
- if (const std::string* editor_path = maybe_editor_path.get())
- {
- candidate_paths.emplace_back(*editor_path);
- }
-
-#ifdef _WIN32
- static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe";
- static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe";
-
- const auto& program_files = System::get_program_files_platform_bitness();
- if (const fs::path* pf = program_files.get())
- {
- candidate_paths.push_back(*pf / VS_CODE_INSIDERS);
- candidate_paths.push_back(*pf / VS_CODE);
- }
-
- const auto& program_files_32_bit = System::get_program_files_32_bit();
- if (const fs::path* pf = program_files_32_bit.get())
- {
- candidate_paths.push_back(*pf / VS_CODE_INSIDERS);
- candidate_paths.push_back(*pf / VS_CODE);
- }
-
- const auto& app_data = System::get_environment_variable("APPDATA");
- if (const auto* ad = app_data.get())
- {
- const fs::path default_base = fs::path{*ad}.parent_path() / "Local" / "Programs";
- candidate_paths.push_back(default_base / VS_CODE_INSIDERS);
- candidate_paths.push_back(default_base / VS_CODE);
- }
-
- const std::vector<fs::path> from_registry = find_from_registry();
- candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend());
-
- const auto txt_default = System::get_registry_string(HKEY_CLASSES_ROOT, R"(.txt\ShellNew)", "ItemName");
- if (const auto entry = txt_default.get())
- {
- auto full_path = expand_environment_strings(*entry);
- auto first = full_path.begin();
- const auto last = full_path.end();
- first = std::find_if_not(first, last, [](const char c) { return c == '@'; });
- const auto comma = std::find(first, last, ',');
- candidate_paths.push_back(fs::u8path(first, comma));
- }
-#elif defined(__APPLE__)
- candidate_paths.push_back(
- fs::path{"/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"});
- candidate_paths.push_back(fs::path{"/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"});
-#elif defined(__linux__)
- candidate_paths.push_back(fs::path{"/usr/share/code/bin/code"});
- candidate_paths.push_back(fs::path{"/usr/bin/code"});
-
- if (System::cmd_execute(System::Command("command").string_arg("-v").string_arg("xdg-mime")) == 0)
- {
- auto mime_qry =
- System::Command("xdg-mime").string_arg("query").string_arg("default").string_arg("text/plain");
- auto execute_result = System::cmd_execute_and_capture_output(mime_qry);
- if (execute_result.exit_code == 0 && !execute_result.output.empty())
- {
- mime_qry = System::Command("command").string_arg("-v").string_arg(
- execute_result.output.substr(0, execute_result.output.find('.')));
- execute_result = System::cmd_execute_and_capture_output(mime_qry);
- if (execute_result.exit_code == 0 && !execute_result.output.empty())
- {
- execute_result.output.erase(
- std::remove(std::begin(execute_result.output), std::end(execute_result.output), '\n'),
- std::end(execute_result.output));
- candidate_paths.push_back(fs::path{execute_result.output});
- }
- }
- }
-#endif
-
- const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); });
- if (it == candidate_paths.cend())
- {
- System::print2(
- System::Color::error,
- "Error: Visual Studio Code was not found and the environment variable EDITOR is not set or invalid.\n");
- System::print2("The following paths were examined:\n");
- Files::print_paths(candidate_paths);
- System::print2("You can also set the environmental variable EDITOR to your editor of choice.\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- const fs::path env_editor = *it;
- const std::vector<std::string> arguments = create_editor_arguments(paths, options, ports);
- const auto args_as_string = Strings::join(" ", arguments);
- auto cmd_line = System::Command(env_editor).raw_arg(args_as_string).string_arg("-n");
-
- auto editor_exe = fs::u8string(env_editor.filename());
-
-#ifdef _WIN32
- if (editor_exe == "Code.exe" || editor_exe == "Code - Insiders.exe")
- {
- // note that we are invoking cmd silently but Code.exe is relaunched from there
- System::cmd_execute_background(System::Command("cmd").string_arg("/c").raw_arg(
- Strings::concat('"', cmd_line.command_line(), R"( <NUL")")));
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-#endif
- Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line));
- }
-
- void EditCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Edit::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp
deleted file mode 100644
index f129f0262..000000000
--- a/toolsrc/src/vcpkg/commands.env.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/build.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.env.h>
-#include <vcpkg/help.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-namespace vcpkg::Commands::Env
-{
- static constexpr StringLiteral OPTION_BIN = "bin";
- static constexpr StringLiteral OPTION_INCLUDE = "include";
- static constexpr StringLiteral OPTION_DEBUG_BIN = "debug-bin";
- static constexpr StringLiteral OPTION_TOOLS = "tools";
- static constexpr StringLiteral OPTION_PYTHON = "python";
-
- static constexpr std::array<CommandSwitch, 5> SWITCHES = {{
- {OPTION_BIN, "Add installed bin/ to PATH"},
- {OPTION_INCLUDE, "Add installed include/ to INCLUDE"},
- {OPTION_DEBUG_BIN, "Add installed debug/bin/ to PATH"},
- {OPTION_TOOLS, "Add installed tools/*/ to PATH"},
- {OPTION_PYTHON, "Add installed python/ to PYTHONPATH"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("env <optional command> --triplet x64-windows"),
- 0,
- 1,
- {SWITCHES, {}},
- nullptr,
- };
-
- // This command should probably optionally take a port
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet triplet)
- {
- const auto& fs = paths.get_filesystem();
-
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
- auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
- auto& var_provider = *var_provider_storage;
-
- var_provider.load_generic_triplet_vars(triplet);
-
- const Build::PreBuildInfo pre_build_info(
- paths, triplet, var_provider.get_generic_triplet_vars(triplet).value_or_exit(VCPKG_LINE_INFO));
- const Toolset& toolset = paths.get_toolset(pre_build_info);
- auto build_env_cmd = Build::make_build_env_cmd(pre_build_info, toolset, paths.get_all_toolsets());
-
- std::unordered_map<std::string, std::string> extra_env = {};
- const bool add_bin = Util::Sets::contains(options.switches, OPTION_BIN);
- const bool add_include = Util::Sets::contains(options.switches, OPTION_INCLUDE);
- const bool add_debug_bin = Util::Sets::contains(options.switches, OPTION_DEBUG_BIN);
- const bool add_tools = Util::Sets::contains(options.switches, OPTION_TOOLS);
- const bool add_python = Util::Sets::contains(options.switches, OPTION_PYTHON);
-
- std::vector<std::string> path_vars;
- if (add_bin) path_vars.push_back(fs::u8string(paths.installed / triplet.to_string() / "bin"));
- if (add_debug_bin) path_vars.push_back(fs::u8string(paths.installed / triplet.to_string() / "debug" / "bin"));
- if (add_include) extra_env.emplace("INCLUDE", fs::u8string(paths.installed / triplet.to_string() / "include"));
- if (add_tools)
- {
- auto tools_dir = paths.installed / triplet.to_string() / "tools";
- auto tool_files = fs.get_files_non_recursive(tools_dir);
- path_vars.push_back(fs::u8string(tools_dir));
- for (auto&& tool_dir : tool_files)
- {
- if (fs.is_directory(tool_dir)) path_vars.push_back(fs::u8string(tool_dir));
- }
- }
- if (add_python)
- extra_env.emplace("PYTHONPATH",
- fs::u8string(paths.installed / fs::u8path(triplet.to_string()) / fs::u8path("python")));
- if (path_vars.size() > 0) extra_env.emplace("PATH", Strings::join(";", path_vars));
- for (auto&& passthrough : pre_build_info.passthrough_env_vars)
- {
- if (auto e = System::get_environment_variable(passthrough))
- {
- extra_env.emplace(passthrough, e.value_or_exit(VCPKG_LINE_INFO));
- }
- }
-
- auto env = [&] {
- auto clean_env = System::get_modified_clean_environment(extra_env);
- if (build_env_cmd.empty())
- return clean_env;
- else
- {
-#ifdef _WIN32
- return System::cmd_execute_modify_env(build_env_cmd, clean_env);
-#else
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Build environment commands are not supported on this platform");
-#endif
- }
- }();
-
- System::Command cmd("cmd");
- if (!args.command_arguments.empty())
- {
- cmd.string_arg("/c").raw_arg(args.command_arguments.at(0));
- }
-#ifdef _WIN32
- System::enter_interactive_subprocess();
-#endif
- auto rc = System::cmd_execute(cmd, env);
-#ifdef _WIN32
- System::exit_interactive_subprocess();
-#endif
- Checks::exit_with_code(VCPKG_LINE_INFO, rc);
- }
-
- void EnvCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- Env::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp
deleted file mode 100644
index 68df98700..000000000
--- a/toolsrc/src/vcpkg/commands.fetch.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.fetch.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg::Commands::Fetch
-{
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format("The argument should be tool name\n%s", create_example_string("fetch cmake")),
- 1,
- 1,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
- const std::string tool = args.command_arguments[0];
- const fs::path tool_path = paths.get_tool_exe(tool);
- System::print2(fs::u8string(tool_path), '\n');
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void FetchCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Fetch::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.format-manifest.cpp b/toolsrc/src/vcpkg/commands.format-manifest.cpp
deleted file mode 100644
index 0e7394c25..000000000
--- a/toolsrc/src/vcpkg/commands.format-manifest.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/system.debug.h>
-
-#include <vcpkg/commands.format-manifest.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace
-{
- using namespace vcpkg;
-
- struct ToWrite
- {
- SourceControlFile scf;
- fs::path file_to_write;
- fs::path original_path;
- std::string original_source;
- };
-
- Optional<ToWrite> read_manifest(Files::Filesystem& fs, fs::path&& manifest_path)
- {
- auto path_string = fs::u8string(manifest_path);
- Debug::print("Reading ", path_string, "\n");
- auto contents = fs.read_contents(manifest_path, VCPKG_LINE_INFO);
- auto parsed_json_opt = Json::parse(contents, manifest_path);
- if (!parsed_json_opt.has_value())
- {
- System::printf(
- System::Color::error, "Failed to parse %s: %s\n", path_string, parsed_json_opt.error()->format());
- return nullopt;
- }
-
- const auto& parsed_json = parsed_json_opt.value_or_exit(VCPKG_LINE_INFO).first;
- if (!parsed_json.is_object())
- {
- System::printf(System::Color::error, "The file %s is not an object\n", path_string);
- return nullopt;
- }
-
- auto parsed_json_obj = parsed_json.object();
-
- auto scf = SourceControlFile::parse_manifest_file(manifest_path, parsed_json_obj);
- if (!scf.has_value())
- {
- System::printf(System::Color::error, "Failed to parse manifest file: %s\n", path_string);
- print_error_message(scf.error());
- return nullopt;
- }
-
- return ToWrite{
- std::move(*scf.value_or_exit(VCPKG_LINE_INFO)),
- manifest_path,
- manifest_path,
- std::move(contents),
- };
- }
-
- Optional<ToWrite> read_control_file(Files::Filesystem& fs, fs::path&& control_path)
- {
- std::error_code ec;
- auto control_path_string = fs::u8string(control_path);
- Debug::print("Reading ", control_path_string, "\n");
-
- auto manifest_path = control_path.parent_path();
- manifest_path /= fs::u8path("vcpkg.json");
-
- auto contents = fs.read_contents(control_path, VCPKG_LINE_INFO);
- auto paragraphs = Paragraphs::parse_paragraphs(contents, control_path_string);
-
- if (!paragraphs)
- {
- System::printf(System::Color::error,
- "Failed to read paragraphs from %s: %s\n",
- control_path_string,
- paragraphs.error());
- return {};
- }
- auto scf_res = SourceControlFile::parse_control_file(fs::u8string(control_path),
- std::move(paragraphs).value_or_exit(VCPKG_LINE_INFO));
- if (!scf_res)
- {
- System::printf(System::Color::error, "Failed to parse control file: %s\n", control_path_string);
- print_error_message(scf_res.error());
- return {};
- }
-
- return ToWrite{
- std::move(*scf_res.value_or_exit(VCPKG_LINE_INFO)),
- manifest_path,
- control_path,
- std::move(contents),
- };
- }
-
- void write_file(Files::Filesystem& fs, const ToWrite& data)
- {
- auto original_path_string = fs::u8string(data.original_path);
- auto file_to_write_string = fs::u8string(data.file_to_write);
- if (data.file_to_write == data.original_path)
- {
- Debug::print("Formatting ", file_to_write_string, "\n");
- }
- else
- {
- Debug::print("Converting ", file_to_write_string, " -> ", original_path_string, "\n");
- }
- auto res = serialize_manifest(data.scf);
-
- auto check = SourceControlFile::parse_manifest_file(fs::path{}, res);
- if (!check)
- {
- System::printf(System::Color::error,
- R"([correctness check] Failed to parse serialized manifest file of %s
-Please open an issue at https://github.com/microsoft/vcpkg, with the following output:
-Error:)",
- data.scf.core_paragraph->name);
- print_error_message(check.error());
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- R"(
-=== Serialized manifest file ===
-%s
-)",
- Json::stringify(res, {}));
- }
-
- auto check_scf = std::move(check).value_or_exit(VCPKG_LINE_INFO);
- if (*check_scf != data.scf)
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- R"([correctness check] The serialized manifest SCF was different from the original SCF.
-Please open an issue at https://github.com/microsoft/vcpkg, with the following output:
-
-=== Original File ===
-%s
-
-=== Serialized File ===
-%s
-
-=== Original SCF ===
-%s
-
-=== Serialized SCF ===
-%s
-)",
- data.original_source,
- Json::stringify(res, {}),
- Json::stringify(serialize_debug_manifest(data.scf), {}),
- Json::stringify(serialize_debug_manifest(*check_scf), {}));
- }
-
- // the manifest scf is correct
- std::error_code ec;
- fs.write_contents(data.file_to_write, Json::stringify(res, {}), ec);
- if (ec)
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Failed to write manifest file %s: %s\n", file_to_write_string, ec.message());
- }
- if (data.original_path != data.file_to_write)
- {
- fs.remove(data.original_path, ec);
- if (ec)
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Failed to remove control file %s: %s\n", original_path_string, ec.message());
- }
- }
- }
-}
-
-namespace vcpkg::Commands::FormatManifest
-{
- static constexpr StringLiteral OPTION_ALL = "all";
- static constexpr StringLiteral OPTION_CONVERT_CONTROL = "convert-control";
-
- const CommandSwitch FORMAT_SWITCHES[] = {
- {OPTION_ALL, "Format all ports' manifest files."},
- {OPTION_CONVERT_CONTROL, "Convert CONTROL files to manifest files."},
- };
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string(R"###(format-manifest --all)###"),
- 0,
- SIZE_MAX,
- {FORMAT_SWITCHES, {}, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- auto parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
-
- auto& fs = paths.get_filesystem();
- bool has_error = false;
-
- const bool format_all = Util::Sets::contains(parsed_args.switches, OPTION_ALL);
- const bool convert_control = Util::Sets::contains(parsed_args.switches, OPTION_CONVERT_CONTROL);
-
- if (!format_all && convert_control)
- {
- System::print2(System::Color::warning, R"(format-manifest was passed '--convert-control' without '--all'.
- This doesn't do anything:
- we will automatically convert all control files passed explicitly.)");
- }
-
- if (!format_all && args.command_arguments.empty())
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "No files to format; please pass either --all, or the explicit files to format or convert.");
- }
-
- std::vector<ToWrite> to_write;
-
- const auto add_file = [&to_write, &has_error](Optional<ToWrite>&& opt) {
- if (auto t = opt.get())
- to_write.push_back(std::move(*t));
- else
- has_error = true;
- };
-
- for (const auto& arg : args.command_arguments)
- {
- auto path = fs::u8path(arg);
- if (path.is_relative())
- {
- path = paths.original_cwd / path;
- }
-
- if (path.filename() == fs::u8path("CONTROL"))
- {
- add_file(read_control_file(fs, std::move(path)));
- }
- else
- {
- add_file(read_manifest(fs, std::move(path)));
- }
- }
-
- if (format_all)
- {
- for (const auto& dir : fs::directory_iterator(paths.builtin_ports_directory()))
- {
- auto control_path = dir.path() / fs::u8path("CONTROL");
- auto manifest_path = dir.path() / fs::u8path("vcpkg.json");
- auto manifest_exists = fs.exists(manifest_path);
- auto control_exists = fs.exists(control_path);
-
- Checks::check_exit(VCPKG_LINE_INFO,
- !manifest_exists || !control_exists,
- "Both a manifest file and a CONTROL file exist in port directory: %s",
- fs::u8string(dir.path()));
-
- if (manifest_exists)
- {
- add_file(read_manifest(fs, std::move(manifest_path)));
- }
- if (convert_control && control_exists)
- {
- add_file(read_control_file(fs, std::move(control_path)));
- }
- }
- }
-
- for (auto const& el : to_write)
- {
- write_file(fs, el);
- }
-
- if (has_error)
- {
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- else
- {
- System::print2("Succeeded in formatting the manifest files.\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
- }
-
- void FormatManifestCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- FormatManifest::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp
deleted file mode 100644
index 6b2e81c12..000000000
--- a/toolsrc/src/vcpkg/commands.hash.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.hash.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg::Commands::Hash
-{
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format("The argument should be a file path\n%s", create_example_string("hash boost_1_62_0.tar.bz2")),
- 1,
- 2,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
-
- const fs::path file_to_hash = args.command_arguments[0];
-
- auto algorithm = vcpkg::Hash::Algorithm::Sha512;
- if (args.command_arguments.size() == 2)
- {
- algorithm = vcpkg::Hash::algorithm_from_string(args.command_arguments[1]).value_or_exit(VCPKG_LINE_INFO);
- }
-
- const std::string hash =
- vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO, paths.get_filesystem(), file_to_hash, algorithm);
- System::print2(hash, '\n');
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void HashCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Hash::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.info.cpp b/toolsrc/src/vcpkg/commands.info.cpp
deleted file mode 100644
index dbf089534..000000000
--- a/toolsrc/src/vcpkg/commands.info.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-#include "pch.h"
-
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/parse.h>
-#include <vcpkg/base/stringliteral.h>
-
-#include <vcpkg/commands.info.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/statusparagraphs.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/versiont.h>
-
-namespace vcpkg::Commands::Info
-{
- static constexpr StringLiteral OPTION_TRANSITIVE = "x-transitive";
- static constexpr StringLiteral OPTION_INSTALLED = "x-installed";
-
- static constexpr CommandSwitch INFO_SWITCHES[] = {
- {OPTION_INSTALLED, "(experimental) Report on installed packages instead of available"},
- {OPTION_TRANSITIVE, "(experimental) Also report on dependencies of installed packages"},
- };
-
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format("Display detailed information on packages.\n%s",
- create_example_string("x-package-info zlib openssl:x64-windows")),
- 1,
- SIZE_MAX,
- {INFO_SWITCHES, {}},
- nullptr,
- };
-
- void InfoCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
- if (!args.output_json())
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO, "This command currently requires --%s", VcpkgCmdArguments::JSON_SWITCH);
- }
-
- const bool installed = Util::Sets::contains(options.switches, OPTION_INSTALLED);
- const bool transitive = Util::Sets::contains(options.switches, OPTION_TRANSITIVE);
-
- if (transitive && !installed)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "--%s requires --%s", OPTION_TRANSITIVE, OPTION_INSTALLED);
- }
-
- if (installed)
- {
- const StatusParagraphs status_paragraphs = database_load_check(paths);
- std::set<PackageSpec> specs_written;
- std::vector<PackageSpec> specs_to_write;
- for (auto&& arg : args.command_arguments)
- {
- Parse::ParserBase parser(arg, "<command>");
- auto maybe_qpkg = parse_qualified_specifier(parser);
- if (!parser.at_eof() || !maybe_qpkg)
- {
- parser.add_error("expected a package specifier");
- }
- else if (!maybe_qpkg.get()->triplet)
- {
- parser.add_error("expected an explicit triplet");
- }
- else if (maybe_qpkg.get()->features)
- {
- parser.add_error("unexpected list of features");
- }
- else if (maybe_qpkg.get()->platform)
- {
- parser.add_error("unexpected qualifier");
- }
- if (auto err = parser.get_error())
- {
- System::print2(err->format(), "\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- auto& qpkg = *maybe_qpkg.get();
- auto t = Triplet::from_canonical_name(std::string(*qpkg.triplet.get()));
- Input::check_triplet(t, paths);
- specs_to_write.emplace_back(qpkg.name, t);
- }
- Json::Object response;
- Json::Object results;
- while (!specs_to_write.empty())
- {
- auto spec = std::move(specs_to_write.back());
- specs_to_write.pop_back();
- if (!specs_written.insert(spec).second) continue;
- auto maybe_ipv = status_paragraphs.get_installed_package_view(spec);
- if (auto ipv = maybe_ipv.get())
- {
- results.insert(spec.to_string(), serialize_ipv(*ipv, paths));
- if (transitive)
- {
- auto deps = ipv->dependencies();
- specs_to_write.insert(specs_to_write.end(),
- std::make_move_iterator(deps.begin()),
- std::make_move_iterator(deps.end()));
- }
- }
- }
- response.insert("results", std::move(results));
- System::print2(Json::stringify(response, {}));
- }
- else
- {
- Json::Object response;
- Json::Object results;
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
-
- for (auto&& arg : args.command_arguments)
- {
- Parse::ParserBase parser(arg, "<command>");
- auto maybe_pkg = parse_package_name(parser);
- if (!parser.at_eof() || !maybe_pkg)
- {
- parser.add_error("expected only a package identifier");
- }
- if (auto err = parser.get_error())
- {
- System::print2(err->format(), "\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- auto& pkg = *maybe_pkg.get();
-
- if (results.contains(pkg)) continue;
-
- auto maybe_scfl = provider.get_control_file(pkg);
-
- Json::Object obj;
- if (auto pscfl = maybe_scfl.get())
- {
- results.insert(pkg, serialize_manifest(*pscfl->source_control_file));
- }
- }
- response.insert("results", std::move(results));
- System::print2(Json::stringify(response, {}));
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp
deleted file mode 100644
index 8258de1fe..000000000
--- a/toolsrc/src/vcpkg/commands.integrate.cpp
+++ /dev/null
@@ -1,607 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/expected.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.integrate.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/userconfig.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg::Commands::Integrate
-{
-#if defined(_WIN32)
- static std::string create_appdata_shortcut(const std::string& target_path) noexcept
- {
- return Strings::format(R"###(
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Condition="Exists('%s') and '$(VCPkgLocalAppDataDisabled)' == ''" Project="%s" />
-</Project>
-)###",
- target_path,
- target_path);
- }
-#endif
-
-#if defined(_WIN32)
- static std::string create_system_targets_shortcut() noexcept
- {
- return R"###(
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <!-- version 1 -->
- <PropertyGroup>
- <VCLibPackagePath Condition="'$(VCLibPackagePath)' == ''">$(LOCALAPPDATA)\vcpkg\vcpkg.user</VCLibPackagePath>
- </PropertyGroup>
- <Import Condition="'$(VCLibPackagePath)' != '' and Exists('$(VCLibPackagePath).props')" Project="$(VCLibPackagePath).props" />
- <Import Condition="'$(VCLibPackagePath)' != '' and Exists('$(VCLibPackagePath).targets')" Project="$(VCLibPackagePath).targets" />
-</Project>
-)###";
- }
-#endif
-
-#if defined(_WIN32)
- static std::string create_nuget_targets_file_contents(const fs::path& msbuild_vcpkg_targets_file) noexcept
- {
- const std::string as_string = msbuild_vcpkg_targets_file.string();
-
- return Strings::format(R"###(
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="%s" Condition="Exists('%s')" />
- <Target Name="CheckValidPlatform" BeforeTargets="Build">
- <Error Text="Unsupported architecture combination. Remove the 'vcpkg' nuget package." Condition="'$(VCPkgEnabled)' != 'true' and '$(VCPkgDisableError)' == ''"/>
- </Target>
-</Project>
-)###",
- as_string,
- as_string);
- }
-#endif
-
-#if defined(_WIN32)
- static std::string create_nuget_props_file_contents() noexcept
- {
- return R"###(
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <VCPkgLocalAppDataDisabled>true</VCPkgLocalAppDataDisabled>
- </PropertyGroup>
-</Project>
-)###";
- }
-#endif
-
-#if defined(_WIN32)
- static std::string get_nuget_id(const fs::path& vcpkg_root_dir)
- {
- std::string dir_id = fs::generic_u8string(vcpkg_root_dir);
- std::replace(dir_id.begin(), dir_id.end(), '/', '.');
- dir_id.erase(1, 1); // Erasing the ":"
-
- // NuGet id cannot have invalid characters. We will only use alphanumeric and dot.
- Util::erase_remove_if(dir_id, [](char c) { return !isalnum(static_cast<unsigned char>(c)) && (c != '.'); });
-
- const std::string nuget_id = "vcpkg." + dir_id;
- return nuget_id;
- }
-#endif
-
-#if defined(_WIN32)
- static std::string create_nuspec_file_contents(const fs::path& vcpkg_root_dir,
- const std::string& nuget_id,
- const std::string& nupkg_version)
- {
- static constexpr auto CONTENT_TEMPLATE = R"(
-<package>
- <metadata>
- <id>@NUGET_ID@</id>
- <version>@VERSION@</version>
- <authors>vcpkg</authors>
- <description>
- This package imports all libraries currently installed in @VCPKG_DIR@. This package does not contain any libraries and instead refers to the folder directly (like a symlink).
- </description>
- </metadata>
- <files>
- <file src="vcpkg.nuget.props" target="build\native\@NUGET_ID@.props" />
- <file src="vcpkg.nuget.targets" target="build\native\@NUGET_ID@.targets" />
- </files>
-</package>
-)";
-
- std::string content = Strings::replace_all(CONTENT_TEMPLATE, "@NUGET_ID@", nuget_id);
- Strings::inplace_replace_all(content, "@VCPKG_DIR@", vcpkg_root_dir.string());
- Strings::inplace_replace_all(content, "@VERSION@", nupkg_version);
- return content;
- }
-#endif
-
-#if defined(_WIN32)
- enum class ElevationPromptChoice
- {
- YES,
- NO
- };
-
- static ElevationPromptChoice elevated_cmd_execute(const std::string& param)
- {
- SHELLEXECUTEINFOW sh_ex_info{};
- sh_ex_info.cbSize = sizeof(sh_ex_info);
- sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS;
- sh_ex_info.hwnd = nullptr;
- sh_ex_info.lpVerb = L"runas";
- sh_ex_info.lpFile = L"cmd"; // Application to start
-
- auto wparam = Strings::to_utf16(param);
- sh_ex_info.lpParameters = wparam.c_str(); // Additional parameters
- sh_ex_info.lpDirectory = nullptr;
- sh_ex_info.nShow = SW_HIDE;
- sh_ex_info.hInstApp = nullptr;
-
- if (!ShellExecuteExW(&sh_ex_info))
- {
- return ElevationPromptChoice::NO;
- }
- if (sh_ex_info.hProcess == nullptr)
- {
- return ElevationPromptChoice::NO;
- }
- WaitForSingleObject(sh_ex_info.hProcess, INFINITE);
- CloseHandle(sh_ex_info.hProcess);
- return ElevationPromptChoice::YES;
- }
-#endif
-
-#if defined(_WIN32)
- static fs::path get_appdata_targets_path()
- {
- return System::get_appdata_local().value_or_exit(VCPKG_LINE_INFO) / fs::u8path("vcpkg/vcpkg.user.targets");
- }
-#endif
-#if defined(_WIN32)
- static fs::path get_appdata_props_path()
- {
- return System::get_appdata_local().value_or_exit(VCPKG_LINE_INFO) / fs::u8path("vcpkg/vcpkg.user.props");
- }
-#endif
-
- static fs::path get_path_txt_path() { return get_user_dir() / "vcpkg.path.txt"; }
-
-#if defined(_WIN32)
- static void integrate_install_msbuild14(Files::Filesystem& fs, const fs::path& tmp_dir)
- {
- static const std::array<fs::path, 2> OLD_SYSTEM_TARGET_FILES = {
- System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) /
- "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets",
- System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) /
- "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"};
- static const fs::path SYSTEM_WIDE_TARGETS_FILE =
- System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) /
- "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props";
-
- // TODO: This block of code should eventually be removed
- for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES)
- {
- if (fs.exists(old_system_wide_targets_file))
- {
- const std::string param =
- Strings::format(R"(/c "DEL "%s" /Q > nul")", old_system_wide_targets_file.string());
- const ElevationPromptChoice user_choice = elevated_cmd_execute(param);
- switch (user_choice)
- {
- case ElevationPromptChoice::YES: break;
- case ElevationPromptChoice::NO:
- System::print2(System::Color::warning, "Warning: Previous integration file was not removed\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- }
- bool should_install_system = true;
- const Expected<std::string> system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE);
- static const std::regex RE(R"###(<!-- version (\d+) -->)###");
- if (const auto contents_data = system_wide_file_contents.get())
- {
- std::match_results<std::string::const_iterator> match;
- const auto found = std::regex_search(*contents_data, match, RE);
- if (found)
- {
- const int ver = atoi(match[1].str().c_str());
- if (ver >= 1) should_install_system = false;
- }
- }
-
- if (should_install_system)
- {
- const fs::path sys_src_path = tmp_dir / "vcpkg.system.targets";
- fs.write_contents(sys_src_path, create_system_targets_shortcut(), VCPKG_LINE_INFO);
-
- const std::string param = Strings::format(R"(/c "mkdir "%s" & copy "%s" "%s" /Y > nul")",
- SYSTEM_WIDE_TARGETS_FILE.parent_path().string(),
- sys_src_path.string(),
- SYSTEM_WIDE_TARGETS_FILE.string());
- const ElevationPromptChoice user_choice = elevated_cmd_execute(param);
- switch (user_choice)
- {
- case ElevationPromptChoice::YES: break;
- case ElevationPromptChoice::NO:
- System::print2(System::Color::warning, "Warning: integration was not applied\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- Checks::check_exit(VCPKG_LINE_INFO,
- fs.exists(SYSTEM_WIDE_TARGETS_FILE),
- "Error: failed to copy targets file to %s",
- SYSTEM_WIDE_TARGETS_FILE.string());
- }
- }
-#endif
-
- static void integrate_install(const VcpkgPaths& paths)
- {
- auto& fs = paths.get_filesystem();
-
-#if defined(_WIN32)
- {
- std::error_code ec;
- const fs::path tmp_dir = paths.buildsystems / "tmp";
- fs.create_directory(paths.buildsystems, ec);
- fs.create_directory(tmp_dir, ec);
-
- integrate_install_msbuild14(fs, tmp_dir);
-
- const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets";
- fs.write_contents(appdata_src_path,
- create_appdata_shortcut(fs::u8string(paths.buildsystems_msbuild_targets)),
- VCPKG_LINE_INFO);
- auto appdata_dst_path = get_appdata_targets_path();
-
- const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec);
-
- if (!rc || ec)
- {
- System::print2(System::Color::error,
- "Error: Failed to copy file: ",
- fs::u8string(appdata_src_path),
- " -> ",
- fs::u8string(appdata_dst_path),
- "\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- const fs::path appdata_src_path2 = tmp_dir / "vcpkg.user.props";
- fs.write_contents(appdata_src_path2,
- create_appdata_shortcut(fs::u8string(paths.buildsystems_msbuild_props)),
- VCPKG_LINE_INFO);
- auto appdata_dst_path2 = get_appdata_props_path();
-
- const auto rc2 =
- fs.copy_file(appdata_src_path2, appdata_dst_path2, fs::copy_options::overwrite_existing, ec);
-
- if (!rc2 || ec)
- {
- System::print2(System::Color::error,
- "Error: Failed to copy file: ",
- fs::u8string(appdata_src_path2),
- " -> ",
- fs::u8string(appdata_dst_path2),
- "\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-#endif
-
- const auto pathtxt = get_path_txt_path();
- std::error_code ec;
- fs.write_contents(pathtxt, fs::generic_u8string(paths.root), VCPKG_LINE_INFO);
-
- System::print2(System::Color::success, "Applied user-wide integration for this vcpkg root.\n");
- const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake";
-#if defined(_WIN32)
- System::printf(
- R"(
-All MSBuild C++ projects can now #include any installed libraries.
-Linking will be handled automatically.
-Installing new libraries will make them instantly available.
-
-CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s"
-)",
- fs::generic_u8string(cmake_toolchain));
-#else
- System::printf(
- R"(
-CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s"
-)",
- fs::generic_u8string(cmake_toolchain));
-#endif
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- static void integrate_remove(Files::Filesystem& fs)
- {
- std::error_code ec;
- bool was_deleted = false;
-
-#if defined(_WIN32)
- const fs::path path = get_appdata_targets_path();
-
- was_deleted |= fs.remove(path, ec);
- Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message());
-
- const fs::path path2 = get_appdata_props_path();
-
- was_deleted |= fs.remove(path2, ec);
- Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message());
-#endif
-
- was_deleted |= fs.remove(get_path_txt_path(), ec);
- Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message());
-
- if (was_deleted)
- {
- System::print2(System::Color::success, "User-wide integration was removed\n");
- }
- else
- {
- System::print2(System::Color::success, "User-wide integration is not installed\n");
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
-#if defined(WIN32)
- static void integrate_project(const VcpkgPaths& paths)
- {
- auto& fs = paths.get_filesystem();
-
- const fs::path& nuget_exe = paths.get_tool_exe(Tools::NUGET);
-
- const fs::path& buildsystems_dir = paths.buildsystems;
- const fs::path tmp_dir = buildsystems_dir / "tmp";
- std::error_code ec;
- fs.create_directory(buildsystems_dir, ec);
- fs.create_directory(tmp_dir, ec);
-
- const fs::path targets_file_path = tmp_dir / "vcpkg.nuget.targets";
- const fs::path props_file_path = tmp_dir / "vcpkg.nuget.props";
- const fs::path nuspec_file_path = tmp_dir / "vcpkg.nuget.nuspec";
- const std::string nuget_id = get_nuget_id(paths.root);
- const std::string nupkg_version = "1.0.0";
-
- fs.write_contents(
- targets_file_path, create_nuget_targets_file_contents(paths.buildsystems_msbuild_targets), VCPKG_LINE_INFO);
- fs.write_contents(props_file_path, create_nuget_props_file_contents(), VCPKG_LINE_INFO);
- fs.write_contents(
- nuspec_file_path, create_nuspec_file_contents(paths.root, nuget_id, nupkg_version), VCPKG_LINE_INFO);
-
- // Using all forward slashes for the command line
- auto cmd_line = System::Command(nuget_exe)
- .string_arg("pack")
- .string_arg("-OutputDirectory")
- .path_arg(buildsystems_dir)
- .path_arg(nuspec_file_path);
-
- const int exit_code =
- System::cmd_execute_and_capture_output(cmd_line, System::get_clean_environment()).exit_code;
-
- const fs::path nuget_package = buildsystems_dir / Strings::format("%s.%s.nupkg", nuget_id, nupkg_version);
- Checks::check_exit(
- VCPKG_LINE_INFO, exit_code == 0 && fs.exists(nuget_package), "Error: NuGet package creation failed");
- System::print2(System::Color::success, "Created nupkg: ", fs::u8string(nuget_package), '\n');
-
- auto source_path = fs::u8string(buildsystems_dir);
- Strings::inplace_replace_all(source_path, "`", "``");
-
- System::printf(R"(
-With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste:
- Install-Package %s -Source "%s"
-
-)",
- nuget_id,
- source_path);
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-#endif
-
-#if defined(_WIN32)
- static void integrate_powershell(const VcpkgPaths& paths)
- {
- static constexpr StringLiteral TITLE = "PowerShell Tab-Completion";
- const fs::path script_path = paths.scripts / "addPoshVcpkgToPowershellProfile.ps1";
-
- const auto& ps = paths.get_tool_exe("powershell-core");
- auto cmd = System::Command(ps)
- .string_arg("-NoProfile")
- .string_arg("-ExecutionPolicy")
- .string_arg("Bypass")
- .string_arg("-Command")
- .string_arg(Strings::format("& {& '%s' }", fs::u8string(script_path)));
- const int rc = System::cmd_execute(cmd);
- if (rc)
- {
- System::printf(System::Color::error,
- "%s\n"
- "Could not run:\n"
- " '%s'\n",
- TITLE,
- fs::generic_u8string(script_path));
-
- {
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->track_property("error", "powershell script failed");
- locked_metrics->track_property("title", TITLE);
- }
- }
-
- Checks::exit_with_code(VCPKG_LINE_INFO, rc);
- }
-#else
- static void integrate_bash(const VcpkgPaths& paths)
- {
- const auto home_path = System::get_environment_variable("HOME").value_or_exit(VCPKG_LINE_INFO);
- const fs::path bashrc_path = fs::path{home_path} / ".bashrc";
-
- auto& fs = paths.get_filesystem();
- const fs::path completion_script_path = paths.scripts / "vcpkg_completion.bash";
-
- Expected<std::vector<std::string>> maybe_bashrc_content = fs.read_lines(bashrc_path);
- Checks::check_exit(
- VCPKG_LINE_INFO, maybe_bashrc_content.has_value(), "Unable to read %s", fs::u8string(bashrc_path));
-
- std::vector<std::string> bashrc_content = maybe_bashrc_content.value_or_exit(VCPKG_LINE_INFO);
-
- std::vector<std::string> matches;
- for (auto&& line : bashrc_content)
- {
- std::smatch match;
- if (std::regex_match(line, match, std::regex{R"###(^source.*scripts/vcpkg_completion.bash$)###"}))
- {
- matches.push_back(line);
- }
- }
-
- if (!matches.empty())
- {
- System::printf("vcpkg bash completion is already imported to your %s file.\n"
- "The following entries were found:\n"
- " %s\n"
- "Please make sure you have started a new bash shell for the changes to take effect.\n",
- fs::u8string(bashrc_path),
- Strings::join("\n ", matches));
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- System::printf("Adding vcpkg completion entry to %s\n", fs::u8string(bashrc_path));
- bashrc_content.push_back(Strings::format("source %s", fs::u8string(completion_script_path)));
- fs.write_contents(bashrc_path, Strings::join("\n", bashrc_content) + '\n', VCPKG_LINE_INFO);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- static void integrate_fish(const VcpkgPaths& paths)
- {
- fs::path fish_completions_path;
- const auto config_path = System::get_environment_variable("XDG_CONFIG_HOME");
- if (config_path.has_value())
- {
- fish_completions_path = fs::path{config_path.value_or_exit(VCPKG_LINE_INFO)};
- }
- else
- {
- const auto home_path = System::get_environment_variable("HOME").value_or_exit(VCPKG_LINE_INFO);
- fish_completions_path = fs::path{home_path} / ".config";
- }
- fish_completions_path = fish_completions_path / "fish" / "completions" / "vcpkg.fish";
-
- if (fs::stdfs::exists(fish_completions_path))
- {
- System::printf("vcpkg fish completion is already added at %s.\n", fs::u8string(fish_completions_path));
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- const fs::path completion_script_path = paths.scripts / "vcpkg_completion.fish";
-
- System::printf("Adding vcpkg completion entry at %s.\n", fs::u8string(fish_completions_path));
- fs::stdfs::create_symlink(completion_script_path, fish_completions_path);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-#endif
-
- void append_helpstring(HelpTableFormatter& table)
- {
-#if defined(_WIN32)
- table.format("vcpkg integrate install",
- "Make installed packages available user-wide. Requires admin privileges on first use");
- table.format("vcpkg integrate remove", "Remove user-wide integration");
- table.format("vcpkg integrate project", "Generate a referencing nuget package for individual VS project use");
- table.format("vcpkg integrate powershell", "Enable PowerShell tab-completion");
-#else // ^^^ defined(_WIN32) // !defined(_WIN32) vvv
- table.format("vcpkg integrate install", "Make installed packages available user-wide");
- table.format("vcpkg integrate remove", "Remove user-wide integration");
- table.format("vcpkg integrate bash", "Enable bash tab-completion");
- table.format("vcpkg integrate fish", "Enable fish tab-completion");
-#endif // ^^^ !defined(_WIN32)
- }
-
- std::string get_helpstring()
- {
- HelpTableFormatter table;
- append_helpstring(table);
- return std::move(table.m_str);
- }
-
- namespace Subcommand
- {
- static const std::string INSTALL = "install";
- static const std::string REMOVE = "remove";
- static const std::string PROJECT = "project";
- static const std::string POWERSHELL = "powershell";
- static const std::string BASH = "bash";
- static const std::string FISH = "x-fish";
- }
-
- static std::vector<std::string> valid_arguments(const VcpkgPaths&)
- {
- return
- {
- Subcommand::INSTALL, Subcommand::REMOVE,
-#if defined(_WIN32)
- Subcommand::PROJECT, Subcommand::POWERSHELL,
-#else
- Subcommand::BASH, Subcommand::FISH,
-#endif
- };
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- "Commands:\n" + get_helpstring(),
- 1,
- 1,
- {},
- &valid_arguments,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
-
- if (args.command_arguments[0] == Subcommand::INSTALL)
- {
- return integrate_install(paths);
- }
- if (args.command_arguments[0] == Subcommand::REMOVE)
- {
- return integrate_remove(paths.get_filesystem());
- }
-#if defined(_WIN32)
- if (args.command_arguments[0] == Subcommand::PROJECT)
- {
- return integrate_project(paths);
- }
- if (args.command_arguments[0] == Subcommand::POWERSHELL)
- {
- return integrate_powershell(paths);
- }
-#else
- if (args.command_arguments[0] == Subcommand::BASH)
- {
- return integrate_bash(paths);
- }
- if (args.command_arguments[0] == Subcommand::FISH)
- {
- return integrate_fish(paths);
- }
-#endif
-
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]);
- }
-
- void IntegrateCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Integrate::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp
deleted file mode 100644
index 0af7c1f6c..000000000
--- a/toolsrc/src/vcpkg/commands.list.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.list.h>
-#include <vcpkg/help.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/versiont.h>
-
-namespace vcpkg::Commands::List
-{
- static constexpr StringLiteral OPTION_FULLDESC = "x-full-desc"; // TODO: This should find a better home, eventually
-
- static void do_print_json(std::vector<const vcpkg::StatusParagraph*> installed_packages)
- {
- Json::Object obj;
- for (const StatusParagraph* status_paragraph : installed_packages)
- {
- auto current_spec = status_paragraph->package.spec;
- if (obj.contains(current_spec.to_string()))
- {
- if (status_paragraph->package.is_feature())
- {
- Json::Value* value_obj = obj.get(current_spec.to_string());
- auto& feature_list = value_obj->object()["features"].array();
- feature_list.push_back(Json::Value::string(status_paragraph->package.feature));
- }
- }
- else
- {
- Json::Object& library_obj = obj.insert(current_spec.to_string(), Json::Object());
- library_obj.insert("package_name", Json::Value::string(current_spec.name()));
- library_obj.insert("triplet", Json::Value::string(current_spec.triplet().to_string()));
- library_obj.insert("version", Json::Value::string(status_paragraph->package.version));
- library_obj.insert("port_version", Json::Value::integer(status_paragraph->package.port_version));
- Json::Array& features_array = library_obj.insert("features", Json::Array());
- if (status_paragraph->package.is_feature())
- {
- features_array.push_back(Json::Value::string(status_paragraph->package.feature));
- }
- Json::Array& desc = library_obj.insert("desc", Json::Array());
- for (const auto& line : status_paragraph->package.description)
- {
- desc.push_back(Json::Value::string(line));
- }
- }
- }
-
- System::print2(Json::stringify(obj, Json::JsonStyle{}));
- }
-
- static void do_print(const StatusParagraph& pgh, const bool full_desc)
- {
- auto full_version = VersionT(pgh.package.version, pgh.package.port_version).to_string();
- if (full_desc)
- {
- System::printf("%-50s %-16s %s\n",
- pgh.package.displayname(),
- full_version,
- Strings::join("\n ", pgh.package.description));
- }
- else
- {
- std::string description;
- if (!pgh.package.description.empty())
- {
- description = pgh.package.description[0];
- }
- System::printf("%-50s %-16s %s\n",
- vcpkg::shorten_text(pgh.package.displayname(), 50),
- vcpkg::shorten_text(full_version, 16),
- vcpkg::shorten_text(description, 51));
- }
- }
-
- static constexpr std::array<CommandSwitch, 1> LIST_SWITCHES = {{
- {OPTION_FULLDESC, "Do not truncate long text"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format(
- "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s",
- create_example_string("list png")),
- 0,
- 1,
- {LIST_SWITCHES, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- const StatusParagraphs status_paragraphs = database_load_check(paths);
- auto installed_ipv = get_installed_ports(status_paragraphs);
-
- if (installed_ipv.empty())
- {
- if (args.output_json())
- System::print2(Json::stringify(Json::Object(), {}));
- else
- System::print2("No packages are installed. Did you mean `search`?\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- auto installed_packages = Util::fmap(installed_ipv, [](const InstalledPackageView& ipv) { return ipv.core; });
- auto installed_features =
- Util::fmap_flatten(installed_ipv, [](const InstalledPackageView& ipv) { return ipv.features; });
- installed_packages.insert(installed_packages.end(), installed_features.begin(), installed_features.end());
-
- std::sort(installed_packages.begin(),
- installed_packages.end(),
- [](const StatusParagraph* lhs, const StatusParagraph* rhs) -> bool {
- return lhs->package.displayname() < rhs->package.displayname();
- });
-
- const auto enable_fulldesc = Util::Sets::contains(options.switches, OPTION_FULLDESC.to_string());
-
- if (!args.command_arguments.empty())
- {
- auto& query = args.command_arguments[0];
- auto pghs = Util::filter(installed_packages, [query](const StatusParagraph* status_paragraph) {
- return Strings::case_insensitive_ascii_contains(status_paragraph->package.displayname(), query);
- });
- installed_packages = pghs;
- }
-
- if (args.output_json())
- {
- do_print_json(installed_packages);
- }
- else
- {
- for (const StatusParagraph* status_paragraph : installed_packages)
- {
- do_print(*status_paragraph, enable_fulldesc);
- }
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void ListCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- List::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.owns.cpp b/toolsrc/src/vcpkg/commands.owns.cpp
deleted file mode 100644
index 8bd020108..000000000
--- a/toolsrc/src/vcpkg/commands.owns.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.owns.h>
-#include <vcpkg/help.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Commands::Owns
-{
- static void search_file(const VcpkgPaths& paths, const std::string& file_substr, const StatusParagraphs& status_db)
- {
- const std::vector<StatusParagraphAndAssociatedFiles> installed_files = get_installed_files(paths, status_db);
- for (const StatusParagraphAndAssociatedFiles& pgh_and_file : installed_files)
- {
- const StatusParagraph& pgh = pgh_and_file.pgh;
-
- for (const std::string& file : pgh_and_file.files)
- {
- if (file.find(file_substr) != std::string::npos)
- {
- System::print2(pgh.package.displayname(), ": ", file, '\n');
- }
- }
- }
- }
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format("The argument should be a pattern to search for. %s", create_example_string("owns zlib.dll")),
- 1,
- 1,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
-
- const StatusParagraphs status_db = database_load_check(paths);
- search_file(paths, args.command_arguments[0], status_db);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void OwnsCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Owns::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.porthistory.cpp b/toolsrc/src/vcpkg/commands.porthistory.cpp
deleted file mode 100644
index 7d7fcf3d5..000000000
--- a/toolsrc/src/vcpkg/commands.porthistory.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.porthistory.h>
-#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/versiondeserializers.h>
-#include <vcpkg/versions.h>
-
-namespace vcpkg::Commands::PortHistory
-{
- namespace
- {
- struct HistoryVersion
- {
- std::string port_name;
- std::string git_tree;
- std::string commit_id;
- std::string commit_date;
- std::string version_string;
- std::string version;
- int port_version;
- Versions::Scheme scheme;
- };
-
- const System::ExitCodeAndOutput run_git_command_inner(const VcpkgPaths& paths,
- const fs::path& dot_git_directory,
- const fs::path& working_directory,
- const System::Command& cmd)
- {
- const fs::path& git_exe = paths.get_tool_exe(Tools::GIT);
-
- auto full_cmd = System::Command(git_exe)
- .string_arg(Strings::concat("--git-dir=", fs::u8string(dot_git_directory)))
- .string_arg(Strings::concat("--work-tree=", fs::u8string(working_directory)))
- .raw_arg(cmd.command_line());
-
- auto output = System::cmd_execute_and_capture_output(full_cmd);
- return output;
- }
-
- const System::ExitCodeAndOutput run_git_command(const VcpkgPaths& paths, const System::Command& cmd)
- {
- const fs::path& work_dir = paths.root;
- const fs::path dot_git_dir = paths.root / ".git";
-
- return run_git_command_inner(paths, dot_git_dir, work_dir, cmd);
- }
-
- vcpkg::Optional<HistoryVersion> get_version_from_text(const std::string& text,
- const std::string& git_tree,
- const std::string& commit_id,
- const std::string& commit_date,
- const std::string& port_name,
- bool is_manifest)
- {
- auto res = Paragraphs::try_load_port_text(text, Strings::concat(commit_id, ":", port_name), is_manifest);
- if (const auto& maybe_scf = res.get())
- {
- if (const auto& scf = maybe_scf->get())
- {
- auto version = scf->core_paragraph->version;
- auto port_version = scf->core_paragraph->port_version;
- auto scheme = scf->core_paragraph->version_scheme;
- return HistoryVersion{
- port_name,
- git_tree,
- commit_id,
- commit_date,
- Strings::concat(version, "#", port_version),
- version,
- port_version,
- scheme,
- };
- }
- }
-
- return nullopt;
- }
-
- vcpkg::Optional<HistoryVersion> get_version_from_commit(const VcpkgPaths& paths,
- const std::string& commit_id,
- const std::string& commit_date,
- const std::string& port_name)
- {
- auto rev_parse_cmd =
- System::Command("rev-parse").string_arg(Strings::concat(commit_id, ":ports/", port_name));
- auto rev_parse_output = run_git_command(paths, rev_parse_cmd);
- if (rev_parse_output.exit_code == 0)
- {
- // Remove newline character
- const auto git_tree = Strings::trim(std::move(rev_parse_output.output));
-
- // Do we have a manifest file?
- auto manifest_cmd = System::Command("show").string_arg(Strings::concat(git_tree, ":vcpkg.json"));
- auto manifest_output = run_git_command(paths, manifest_cmd);
- if (manifest_output.exit_code == 0)
- {
- return get_version_from_text(
- manifest_output.output, git_tree, commit_id, commit_date, port_name, true);
- }
-
- auto cmd = System::Command("show").string_arg(Strings::concat(git_tree, ":CONTROL"));
- auto control_output = run_git_command(paths, cmd);
-
- if (control_output.exit_code == 0)
- {
- return get_version_from_text(
- control_output.output, git_tree, commit_id, commit_date, port_name, false);
- }
- }
-
- return nullopt;
- }
-
- std::vector<HistoryVersion> read_versions_from_log(const VcpkgPaths& paths, const std::string& port_name)
- {
- // log --format="%H %cd" --date=short --left-only -- ports/{port_name}/.
- System::Command builder;
- builder.string_arg("log");
- builder.string_arg("--format=%H %cd");
- builder.string_arg("--date=short");
- builder.string_arg("--left-only");
- builder.string_arg("--"); // Begin pathspec
- builder.string_arg(Strings::format("ports/%s/.", port_name));
- const auto output = run_git_command(paths, builder);
-
- auto commits = Util::fmap(
- Strings::split(output.output, '\n'), [](const std::string& line) -> auto {
- auto parts = Strings::split(line, ' ');
- return std::make_pair(parts[0], parts[1]);
- });
-
- std::vector<HistoryVersion> ret;
- std::string last_version;
- for (auto&& commit_date_pair : commits)
- {
- auto maybe_version =
- get_version_from_commit(paths, commit_date_pair.first, commit_date_pair.second, port_name);
- if (maybe_version.has_value())
- {
- const auto version = maybe_version.value_or_exit(VCPKG_LINE_INFO);
-
- // Keep latest port with the current version string
- if (last_version != version.version_string)
- {
- last_version = version.version_string;
- ret.emplace_back(version);
- }
- }
- }
- return ret;
- }
- }
-
- static constexpr StringLiteral OPTION_OUTPUT_FILE = "output";
-
- static const CommandSetting HISTORY_SETTINGS[] = {
- {OPTION_OUTPUT_FILE, "Write output to a file"},
- };
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("history <port>"),
- 1,
- 1,
- {{}, {HISTORY_SETTINGS}, {}},
- nullptr,
- };
-
- static Optional<std::string> maybe_lookup(std::unordered_map<std::string, std::string> const& m,
- std::string const& key)
- {
- const auto it = m.find(key);
- if (it != m.end()) return it->second;
- return nullopt;
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- const ParsedArguments parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
- auto maybe_output_file = maybe_lookup(parsed_args.settings, OPTION_OUTPUT_FILE);
-
- std::string port_name = args.command_arguments.at(0);
- std::vector<HistoryVersion> versions = read_versions_from_log(paths, port_name);
-
- if (args.output_json())
- {
- Json::Array versions_json;
- for (auto&& version : versions)
- {
- Json::Object object;
- object.insert("git-tree", Json::Value::string(version.git_tree));
-
- serialize_schemed_version(object, version.scheme, version.version, version.port_version, true);
- versions_json.push_back(std::move(object));
- }
-
- Json::Object root;
- root.insert("versions", versions_json);
-
- auto json_string = Json::stringify(root, vcpkg::Json::JsonStyle::with_spaces(2));
-
- if (maybe_output_file.has_value())
- {
- auto output_file_path = fs::u8path(maybe_output_file.value_or_exit(VCPKG_LINE_INFO));
- auto& fs = paths.get_filesystem();
- fs.write_contents(output_file_path, json_string, VCPKG_LINE_INFO);
- }
- else
- {
- System::printf("%s\n", json_string);
- }
- }
- else
- {
- if (maybe_output_file.has_value())
- {
- System::printf(
- System::Color::warning, "Warning: Option `--$s` requires `--x-json` switch.", OPTION_OUTPUT_FILE);
- }
-
- System::print2(" version date vcpkg commit\n");
- for (auto&& version : versions)
- {
- System::printf("%20.20s %s %s\n", version.version_string, version.commit_date, version.commit_id);
- }
- }
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void PortHistoryCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- PortHistory::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp
deleted file mode 100644
index 18e3a9d91..000000000
--- a/toolsrc/src/vcpkg/commands.portsdiff.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-#include <vcpkg/base/sortedvector.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.portsdiff.h>
-#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/versiont.h>
-
-namespace vcpkg::Commands::PortsDiff
-{
- struct UpdatedPort
- {
- static bool compare_by_name(const UpdatedPort& left, const UpdatedPort& right)
- {
- return left.port < right.port;
- }
-
- std::string port;
- VersionDiff version_diff;
- };
-
- template<class T>
- struct SetElementPresence
- {
- static SetElementPresence create(std::vector<T> left, std::vector<T> right)
- {
- // TODO: This can be done with one pass instead of three passes
- SetElementPresence output;
- std::set_difference(
- left.cbegin(), left.cend(), right.cbegin(), right.cend(), std::back_inserter(output.only_left));
- std::set_intersection(
- left.cbegin(), left.cend(), right.cbegin(), right.cend(), std::back_inserter(output.both));
- std::set_difference(
- right.cbegin(), right.cend(), left.cbegin(), left.cend(), std::back_inserter(output.only_right));
-
- return output;
- }
-
- std::vector<T> only_left;
- std::vector<T> both;
- std::vector<T> only_right;
- };
-
- static std::vector<UpdatedPort> find_updated_ports(
- const std::vector<std::string>& ports,
- const std::map<std::string, VersionT>& previous_names_and_versions,
- const std::map<std::string, VersionT>& current_names_and_versions)
- {
- std::vector<UpdatedPort> output;
- for (const std::string& name : ports)
- {
- const VersionT& previous_version = previous_names_and_versions.at(name);
- const VersionT& current_version = current_names_and_versions.at(name);
- if (previous_version == current_version)
- {
- continue;
- }
-
- output.push_back({name, VersionDiff(previous_version, current_version)});
- }
-
- return output;
- }
-
- static void do_print_name_and_version(const std::vector<std::string>& ports_to_print,
- const std::map<std::string, VersionT>& names_and_versions)
- {
- for (const std::string& name : ports_to_print)
- {
- const VersionT& version = names_and_versions.at(name);
- System::printf(" - %-14s %-16s\n", name, version);
- }
- }
-
- static std::map<std::string, VersionT> read_ports_from_commit(const VcpkgPaths& paths,
- const std::string& git_commit_id)
- {
- std::error_code ec;
- auto& fs = paths.get_filesystem();
- const fs::path& git_exe = paths.get_tool_exe(Tools::GIT);
- const fs::path dot_git_dir = paths.root / ".git";
- const std::string ports_dir_name_as_string = fs::u8string(paths.builtin_ports_directory().filename());
- const fs::path temp_checkout_path =
- paths.root / Strings::format("%s-%s", ports_dir_name_as_string, git_commit_id);
- fs.create_directory(temp_checkout_path, ec);
- const auto checkout_this_dir =
- Strings::format(R"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository
-
- auto cmd = System::Command(git_exe)
- .string_arg(Strings::format("--git-dir=%s", fs::u8string(dot_git_dir)))
- .string_arg(Strings::format("--work-tree=%s", fs::u8string(temp_checkout_path)))
- .string_arg("checkout")
- .string_arg(git_commit_id)
- .string_arg("-f")
- .string_arg("-q")
- .string_arg("--")
- .string_arg(checkout_this_dir)
- .string_arg(".vcpkg-root");
- System::cmd_execute_and_capture_output(cmd, System::get_clean_environment());
- System::cmd_execute_and_capture_output(System::Command(git_exe).string_arg("reset"),
- System::get_clean_environment());
- const auto ports_at_commit = Paragraphs::load_overlay_ports(fs, temp_checkout_path / ports_dir_name_as_string);
- std::map<std::string, VersionT> names_and_versions;
- for (auto&& port : ports_at_commit)
- {
- const auto& core_pgh = *port.source_control_file->core_paragraph;
- names_and_versions.emplace(core_pgh.name, VersionT(core_pgh.version, core_pgh.port_version));
- }
- fs.remove_all(temp_checkout_path, VCPKG_LINE_INFO);
- return names_and_versions;
- }
-
- static void check_commit_exists(const fs::path& git_exe, const std::string& git_commit_id)
- {
- static const std::string VALID_COMMIT_OUTPUT = "commit\n";
-
- auto cmd = System::Command(git_exe).string_arg("cat-file").string_arg("-t").string_arg(git_commit_id);
- const System::ExitCodeAndOutput output = System::cmd_execute_and_capture_output(cmd);
- Checks::check_exit(
- VCPKG_LINE_INFO, output.output == VALID_COMMIT_OUTPUT, "Invalid commit id %s", git_commit_id);
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format("The argument should be a branch/tag/hash to checkout.\n%s",
- create_example_string("portsdiff mybranchname")),
- 1,
- 2,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
- const fs::path& git_exe = paths.get_tool_exe(Tools::GIT);
-
- const std::string git_commit_id_for_previous_snapshot = args.command_arguments.at(0);
- const std::string git_commit_id_for_current_snapshot =
- args.command_arguments.size() < 2 ? "HEAD" : args.command_arguments.at(1);
-
- check_commit_exists(git_exe, git_commit_id_for_current_snapshot);
- check_commit_exists(git_exe, git_commit_id_for_previous_snapshot);
-
- const std::map<std::string, VersionT> current_names_and_versions =
- read_ports_from_commit(paths, git_commit_id_for_current_snapshot);
- const std::map<std::string, VersionT> previous_names_and_versions =
- read_ports_from_commit(paths, git_commit_id_for_previous_snapshot);
-
- // Already sorted, so set_difference can work on std::vector too
- const std::vector<std::string> current_ports = Util::extract_keys(current_names_and_versions);
- const std::vector<std::string> previous_ports = Util::extract_keys(previous_names_and_versions);
-
- const SetElementPresence<std::string> setp =
- SetElementPresence<std::string>::create(current_ports, previous_ports);
-
- const std::vector<std::string>& added_ports = setp.only_left;
- if (!added_ports.empty())
- {
- System::printf("\nThe following %zd ports were added:\n", added_ports.size());
- do_print_name_and_version(added_ports, current_names_and_versions);
- }
-
- const std::vector<std::string>& removed_ports = setp.only_right;
- if (!removed_ports.empty())
- {
- System::printf("\nThe following %zd ports were removed:\n", removed_ports.size());
- do_print_name_and_version(removed_ports, previous_names_and_versions);
- }
-
- const std::vector<std::string>& common_ports = setp.both;
- const std::vector<UpdatedPort> updated_ports =
- find_updated_ports(common_ports, previous_names_and_versions, current_names_and_versions);
-
- if (!updated_ports.empty())
- {
- System::printf("\nThe following %zd ports were updated:\n", updated_ports.size());
- for (const UpdatedPort& p : updated_ports)
- {
- System::printf(" - %-14s %-16s\n", p.port, p.version_diff.to_string());
- }
- }
-
- if (added_ports.empty() && removed_ports.empty() && updated_ports.empty())
- {
- System::print2("There were no changes in the ports between the two commits.\n");
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void PortsDiffCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- PortsDiff::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp
deleted file mode 100644
index 69d31a249..000000000
--- a/toolsrc/src/vcpkg/commands.search.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.search.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/versiont.h>
-
-using vcpkg::PortFileProvider::PathsPortFileProvider;
-
-namespace vcpkg::Commands::Search
-{
- static constexpr StringLiteral OPTION_FULLDESC = "x-full-desc"; // TODO: This should find a better home, eventually
- static constexpr StringLiteral OPTION_JSON = "x-json";
-
- static void do_print_json(std::vector<const vcpkg::SourceControlFile*> source_control_files)
- {
- Json::Object obj;
- for (const SourceControlFile* scf : source_control_files)
- {
- auto& source_paragraph = scf->core_paragraph;
- Json::Object& library_obj = obj.insert(source_paragraph->name, Json::Object());
- library_obj.insert("package_name", Json::Value::string(source_paragraph->name));
- library_obj.insert("version", Json::Value::string(source_paragraph->version));
- library_obj.insert("port_version", Json::Value::integer(source_paragraph->port_version));
- Json::Array& desc = library_obj.insert("description", Json::Array());
- for (const auto& line : source_paragraph->description)
- {
- desc.push_back(Json::Value::string(line));
- }
- }
-
- System::print2(Json::stringify(obj, Json::JsonStyle{}));
- }
- static void do_print(const SourceParagraph& source_paragraph, bool full_desc)
- {
- auto full_version = VersionT(source_paragraph.version, source_paragraph.port_version).to_string();
- if (full_desc)
- {
- System::printf("%-20s %-16s %s\n",
- source_paragraph.name,
- full_version,
- Strings::join("\n ", source_paragraph.description));
- }
- else
- {
- std::string description;
- if (!source_paragraph.description.empty())
- {
- description = source_paragraph.description[0];
- }
- System::printf("%-20s %-16s %s\n",
- vcpkg::shorten_text(source_paragraph.name, 20),
- vcpkg::shorten_text(full_version, 16),
- vcpkg::shorten_text(description, 81));
- }
- }
-
- static void do_print(const std::string& name, const FeatureParagraph& feature_paragraph, bool full_desc)
- {
- auto full_feature_name = Strings::concat(name, "[", feature_paragraph.name, "]");
- if (full_desc)
- {
- System::printf("%-37s %s\n", full_feature_name, Strings::join("\n ", feature_paragraph.description));
- }
- else
- {
- std::string description;
- if (!feature_paragraph.description.empty())
- {
- description = feature_paragraph.description[0];
- }
- System::printf(
- "%-37s %s\n", vcpkg::shorten_text(full_feature_name, 37), vcpkg::shorten_text(description, 81));
- }
- }
-
- static constexpr std::array<CommandSwitch, 2> SEARCH_SWITCHES = {{
- {OPTION_FULLDESC, "Do not truncate long text"},
- {OPTION_JSON, "(experimental) List libraries in JSON format"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- Strings::format(
- "The argument should be a substring to search for, or no argument to display all libraries.\n%s",
- create_example_string("search png")),
- 0,
- 1,
- {SEARCH_SWITCHES, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
- const bool full_description = Util::Sets::contains(options.switches, OPTION_FULLDESC);
- const bool enable_json = Util::Sets::contains(options.switches, OPTION_JSON);
-
- PathsPortFileProvider provider(paths, args.overlay_ports);
- auto source_paragraphs =
- Util::fmap(provider.load_all_control_files(),
- [](auto&& port) -> const SourceControlFile* { return port->source_control_file.get(); });
-
- if (args.command_arguments.empty())
- {
- if (enable_json)
- {
- do_print_json(source_paragraphs);
- }
- else
- {
- for (const auto& source_control_file : source_paragraphs)
- {
- do_print(*source_control_file->core_paragraph, full_description);
- for (auto&& feature_paragraph : source_control_file->feature_paragraphs)
- {
- do_print(source_control_file->core_paragraph->name, *feature_paragraph, full_description);
- }
- }
- }
- }
- else
- {
- // At this point there is 1 argument
- auto&& args_zero = args.command_arguments[0];
- const auto contained_in = [&args_zero](const auto& s) {
- return Strings::case_insensitive_ascii_contains(s, args_zero);
- };
- for (const auto& source_control_file : source_paragraphs)
- {
- auto&& sp = *source_control_file->core_paragraph;
-
- bool found_match = contained_in(sp.name);
- if (!found_match)
- {
- found_match = std::any_of(sp.description.begin(), sp.description.end(), contained_in);
- }
-
- if (found_match)
- {
- do_print(sp, full_description);
- }
-
- for (auto&& feature_paragraph : source_control_file->feature_paragraphs)
- {
- bool found_match_for_feature = found_match;
- if (!found_match_for_feature)
- {
- found_match_for_feature = contained_in(feature_paragraph->name);
- }
- if (!found_match_for_feature)
- {
- found_match_for_feature = std::any_of(
- feature_paragraph->description.begin(), feature_paragraph->description.end(), contained_in);
- }
-
- if (found_match_for_feature)
- {
- do_print(sp.name, *feature_paragraph, full_description);
- }
- }
- }
- }
-
- if (!enable_json)
- {
- System::print2(
- "\nIf your library is not listed, please open an issue at and/or consider making a pull request:\n"
- " https://github.com/Microsoft/vcpkg/issues\n");
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void SearchCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Search::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.setinstalled.cpp b/toolsrc/src/vcpkg/commands.setinstalled.cpp
deleted file mode 100644
index 28eee6992..000000000
--- a/toolsrc/src/vcpkg/commands.setinstalled.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/commands.setinstalled.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/remove.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Commands::SetInstalled
-{
- static constexpr StringLiteral OPTION_DRY_RUN = "dry-run";
- static constexpr StringLiteral OPTION_WRITE_PACKAGES_CONFIG = "x-write-nuget-packages-config";
-
- static constexpr CommandSwitch INSTALL_SWITCHES[] = {
- {OPTION_DRY_RUN, "Do not actually build or install"},
- };
- static constexpr CommandSetting INSTALL_SETTINGS[] = {
- {OPTION_WRITE_PACKAGES_CONFIG,
- "Writes out a NuGet packages.config-formatted file for use with external binary caching.\n"
- "See `vcpkg help binarycaching` for more information."},
- };
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string(R"(x-set-installed <package>...)"),
- 0,
- SIZE_MAX,
- {INSTALL_SWITCHES, INSTALL_SETTINGS},
- nullptr,
- };
-
- void perform_and_exit_ex(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- const PortFileProvider::PathsPortFileProvider& provider,
- IBinaryProvider& binary_provider,
- const CMakeVars::CMakeVarProvider& cmake_vars,
- Dependencies::ActionPlan action_plan,
- DryRun dry_run,
- const Optional<fs::path>& maybe_pkgsconfig)
- {
- cmake_vars.load_tag_vars(action_plan, provider);
- Build::compute_all_abis(paths, action_plan, cmake_vars, {});
-
- std::set<std::string> all_abis;
-
- for (const auto& action : action_plan.install_actions)
- {
- all_abis.insert(action.abi_info.value_or_exit(VCPKG_LINE_INFO).package_abi);
- }
-
- // currently (or once) installed specifications
- auto status_db = database_load_check(paths);
- std::vector<PackageSpec> specs_to_remove;
- std::set<PackageSpec> specs_installed;
- for (auto&& status_pgh : status_db)
- {
- if (!status_pgh->is_installed()) continue;
- if (status_pgh->package.is_feature()) continue;
-
- const auto& abi = status_pgh->package.abi;
- if (abi.empty() || !Util::Sets::contains(all_abis, abi))
- {
- specs_to_remove.push_back(status_pgh->package.spec);
- }
- else
- {
- specs_installed.emplace(status_pgh->package.spec);
- }
- }
-
- action_plan.remove_actions = Dependencies::create_remove_plan(specs_to_remove, status_db);
-
- for (const auto& action : action_plan.remove_actions)
- {
- // This should not technically be needed, however ensuring that all specs to be removed are not included in
- // `specs_installed` acts as a sanity check
- specs_installed.erase(action.spec);
- }
-
- Util::erase_remove_if(action_plan.install_actions, [&](const Dependencies::InstallPlanAction& ipa) {
- return Util::Sets::contains(specs_installed, ipa.spec);
- });
-
- Dependencies::print_plan(action_plan, true, paths.builtin_ports_directory());
-
- if (auto p_pkgsconfig = maybe_pkgsconfig.get())
- {
- Build::compute_all_abis(paths, action_plan, cmake_vars, status_db);
- auto& fs = paths.get_filesystem();
- auto pkgsconfig_path = Files::combine(paths.original_cwd, *p_pkgsconfig);
- auto pkgsconfig_contents = generate_nuget_packages_config(action_plan);
- fs.write_contents(pkgsconfig_path, pkgsconfig_contents, VCPKG_LINE_INFO);
- System::print2("Wrote NuGet packages config information to ", fs::u8string(pkgsconfig_path), "\n");
- }
-
- if (dry_run == DryRun::Yes)
- {
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- const auto summary = Install::perform(args,
- action_plan,
- Install::KeepGoing::NO,
- paths,
- status_db,
- args.binary_caching_enabled() ? binary_provider : null_binary_provider(),
- Build::null_build_logs_recorder(),
- cmake_vars);
-
- System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- // input sanitization
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_full_package_spec(
- std::string(arg), default_triplet, COMMAND_STRUCTURE.example_text);
- });
-
- for (auto&& spec : specs)
- {
- Input::check_triplet(spec.package_spec.triplet(), paths);
- }
-
- auto binary_provider = create_binary_provider_from_configs(args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
-
- const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
-
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
- auto cmake_vars = CMakeVars::make_triplet_cmake_var_provider(paths);
-
- Optional<fs::path> pkgsconfig;
- auto it_pkgsconfig = options.settings.find(OPTION_WRITE_PACKAGES_CONFIG);
- if (it_pkgsconfig != options.settings.end())
- {
- Metrics::g_metrics.lock()->track_property("x-write-nuget-packages-config", "defined");
- pkgsconfig = it_pkgsconfig->second;
- }
-
- // We have a set of user-requested specs.
- // We need to know all the specs which are required to fulfill dependencies for those specs.
- // Therefore, we see what we would install into an empty installed tree, so we can use the existing code.
- auto action_plan = Dependencies::create_feature_install_plan(provider, *cmake_vars, specs, {});
-
- for (auto&& action : action_plan.install_actions)
- {
- action.build_options = Build::default_build_package_options;
- }
-
- perform_and_exit_ex(args,
- paths,
- provider,
- *binary_provider,
- *cmake_vars,
- std::move(action_plan),
- dry_run ? DryRun::Yes : DryRun::No,
- pkgsconfig);
- }
-
- void SetInstalledCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- SetInstalled::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp
deleted file mode 100644
index 2d25be455..000000000
--- a/toolsrc/src/vcpkg/commands.upgrade.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.upgrade.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/statusparagraphs.h>
-#include <vcpkg/update.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Commands::Upgrade
-{
- using Install::KeepGoing;
- using Install::to_keep_going;
-
- static constexpr StringLiteral OPTION_NO_DRY_RUN = "no-dry-run";
- static constexpr StringLiteral OPTION_KEEP_GOING = "keep-going";
-
- static constexpr std::array<CommandSwitch, 2> INSTALL_SWITCHES = {{
- {OPTION_NO_DRY_RUN, "Actually upgrade"},
- {OPTION_KEEP_GOING, "Continue installing packages on failure"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("upgrade --no-dry-run"),
- 0,
- SIZE_MAX,
- {INSTALL_SWITCHES, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN);
- const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING));
-
- auto binaryprovider = create_binary_provider_from_configs(args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
-
- StatusParagraphs status_db = database_load_check(paths);
-
- // Load ports from ports dirs
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
- auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
- auto& var_provider = *var_provider_storage;
-
- // input sanitization
- const std::vector<PackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(std::string(arg), default_triplet, COMMAND_STRUCTURE.example_text);
- });
-
- for (auto&& spec : specs)
- {
- Input::check_triplet(spec.triplet(), paths);
- }
-
- Dependencies::ActionPlan action_plan;
- if (specs.empty())
- {
- // If no packages specified, upgrade all outdated packages.
- auto outdated_packages = Update::find_outdated_packages(provider, status_db);
-
- if (outdated_packages.empty())
- {
- System::print2("All installed packages are up-to-date with the local portfiles.\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- action_plan = Dependencies::create_upgrade_plan(
- provider,
- var_provider,
- Util::fmap(outdated_packages, [](const Update::OutdatedPackage& package) { return package.spec; }),
- status_db);
- }
- else
- {
- std::vector<PackageSpec> not_installed;
- std::vector<PackageSpec> no_control_file;
- std::vector<PackageSpec> to_upgrade;
- std::vector<PackageSpec> up_to_date;
-
- for (auto&& spec : specs)
- {
- bool skip_version_check = false;
- auto installed_status = status_db.find_installed(spec);
- if (installed_status == status_db.end())
- {
- not_installed.push_back(spec);
- skip_version_check = true;
- }
-
- auto maybe_control_file = provider.get_control_file(spec.name());
- if (!maybe_control_file.has_value())
- {
- no_control_file.push_back(spec);
- skip_version_check = true;
- }
-
- if (skip_version_check) continue;
-
- const auto& control_file = maybe_control_file.value_or_exit(VCPKG_LINE_INFO);
- const auto& control_paragraph = *control_file.source_control_file->core_paragraph;
- auto control_version = VersionT(control_paragraph.version, control_paragraph.port_version);
- const auto& installed_paragraph = (*installed_status)->package;
- auto installed_version = VersionT(installed_paragraph.version, installed_paragraph.port_version);
- if (control_version == installed_version)
- {
- up_to_date.push_back(spec);
- }
- else
- {
- to_upgrade.push_back(spec);
- }
- }
-
- Util::sort(not_installed);
- Util::sort(no_control_file);
- Util::sort(up_to_date);
- Util::sort(to_upgrade);
-
- if (!up_to_date.empty())
- {
- System::print2(System::Color::success, "The following packages are up-to-date:\n");
- System::print2(Strings::join("",
- up_to_date,
- [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; }),
- '\n');
- }
-
- if (!not_installed.empty())
- {
- System::print2(System::Color::error, "The following packages are not installed:\n");
- System::print2(Strings::join("",
- not_installed,
- [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; }),
- '\n');
- }
-
- if (!no_control_file.empty())
- {
- System::print2(System::Color::error,
- "The following packages do not have a valid CONTROL or vcpkg.json:\n");
- System::print2(Strings::join("",
- no_control_file,
- [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; }),
- '\n');
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_control_file.empty());
-
- if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO);
-
- action_plan = Dependencies::create_upgrade_plan(provider, var_provider, to_upgrade, status_db);
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty());
-
- // Set build settings for all install actions
- for (auto&& action : action_plan.install_actions)
- {
- action.build_options = vcpkg::Build::default_build_package_options;
- }
-
- Dependencies::print_plan(action_plan, true, paths.builtin_ports_directory());
-
- if (!no_dry_run)
- {
- System::print2(System::Color::warning,
- "If you are sure you want to rebuild the above packages, run this command with the "
- "--no-dry-run option.\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- var_provider.load_tag_vars(action_plan, provider);
-
- const Install::InstallSummary summary =
- Install::perform(args,
- action_plan,
- keep_going,
- paths,
- status_db,
- args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(),
- Build::null_build_logs_recorder(),
- var_provider);
-
- System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
-
- if (keep_going == KeepGoing::YES)
- {
- summary.print();
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void UpgradeCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- Upgrade::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.upload-metrics.cpp b/toolsrc/src/vcpkg/commands.upload-metrics.cpp
deleted file mode 100644
index acf5a5377..000000000
--- a/toolsrc/src/vcpkg/commands.upload-metrics.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <vcpkg/commands.upload-metrics.h>
-
-#if defined(_WIN32)
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-
-#include <vcpkg/metrics.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-using namespace vcpkg;
-
-namespace vcpkg::Commands::UploadMetrics
-{
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("x-upload-metrics metrics.txt"),
- 1,
- 1,
- };
-
- void UploadMetricsCommand::perform_and_exit(const VcpkgCmdArguments& args, Files::Filesystem& fs) const
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
- const auto& payload_path = args.command_arguments[0];
- auto payload = fs.read_contents(payload_path).value_or_exit(VCPKG_LINE_INFO);
- Metrics::g_metrics.lock()->upload(payload);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-}
-#endif // defined(_WIN32)
diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp
deleted file mode 100644
index 5ee8e270e..000000000
--- a/toolsrc/src/vcpkg/commands.version.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.version.h>
-#include <vcpkg/help.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-
-#define STRINGIFY(...) #__VA_ARGS__
-#define MACRO_TO_STRING(X) STRINGIFY(X)
-
-#if !defined(VCPKG_VERSION)
-#error VCPKG_VERSION must be defined
-#endif
-
-#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION)
-
-#if !defined(VCPKG_BASE_VERSION)
-#error VCPKG_BASE_VERSION must be defined
-#endif
-
-#define VCPKG_BASE_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_BASE_VERSION)
-
-namespace vcpkg::Commands::Version
-{
- const char* base_version() noexcept { return VCPKG_BASE_VERSION_AS_STRING; }
-
- const char* version() noexcept
- {
- return VCPKG_BASE_VERSION_AS_STRING "-" VCPKG_VERSION_AS_STRING
-#ifndef NDEBUG
- "-debug"
-#endif
- ;
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("version"),
- 0,
- 0,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, Files::Filesystem&)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
- System::print2("Vcpkg package management program version ",
- version(),
- "\n"
- "\n"
- "See LICENSE.txt for license information.\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void VersionCommand::perform_and_exit(const VcpkgCmdArguments& args, Files::Filesystem& fs) const
- {
- Version::perform_and_exit(args, fs);
- }
-}
diff --git a/toolsrc/src/vcpkg/commands.xvsinstances.cpp b/toolsrc/src/vcpkg/commands.xvsinstances.cpp
deleted file mode 100644
index 67f35f542..000000000
--- a/toolsrc/src/vcpkg/commands.xvsinstances.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.xvsinstances.h>
-#include <vcpkg/help.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/visualstudio.h>
-
-namespace vcpkg::Commands::X_VSInstances
-{
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("x-vsinstances"),
- 0,
- 0,
- {{}, {}},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
-#if defined(_WIN32)
- const ParsedArguments parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
-
- const auto instances = vcpkg::VisualStudio::get_visual_studio_instances(paths);
- for (const std::string& instance : instances)
- {
- System::print2(instance, '\n');
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
-#else
- (void)args;
- (void)paths;
- Checks::exit_with_message(VCPKG_LINE_INFO, "This command is not supported on non-windows platforms.");
-#endif
- }
-
- void VSInstancesCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- X_VSInstances::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/configuration.cpp b/toolsrc/src/vcpkg/configuration.cpp
deleted file mode 100644
index 3fa02876f..000000000
--- a/toolsrc/src/vcpkg/configuration.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <vcpkg/base/jsonreader.h>
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/configuration.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-namespace
-{
- using namespace vcpkg;
-
- struct ConfigurationDeserializer final : Json::IDeserializer<Configuration>
- {
- virtual StringView type_name() const override { return "a configuration object"; }
-
- constexpr static StringLiteral DEFAULT_REGISTRY = "default-registry";
- constexpr static StringLiteral REGISTRIES = "registries";
- virtual View<StringView> valid_fields() const override
- {
- constexpr static StringView t[] = {DEFAULT_REGISTRY, REGISTRIES};
- return t;
- }
-
- virtual Optional<Configuration> visit_object(Json::Reader& r, const Json::Object& obj) override;
-
- ConfigurationDeserializer(const fs::path& configuration_directory);
-
- private:
- fs::path configuration_directory;
- };
-
- constexpr StringLiteral ConfigurationDeserializer::DEFAULT_REGISTRY;
- constexpr StringLiteral ConfigurationDeserializer::REGISTRIES;
-
- Optional<Configuration> ConfigurationDeserializer::visit_object(Json::Reader& r, const Json::Object& obj)
- {
- RegistrySet registries;
-
- auto impl_des = get_registry_implementation_deserializer(configuration_directory);
-
- std::unique_ptr<RegistryImplementation> default_registry;
- if (r.optional_object_field(obj, DEFAULT_REGISTRY, default_registry, *impl_des))
- {
- registries.set_default_registry(std::move(default_registry));
- }
-
- auto reg_des = get_registry_array_deserializer(configuration_directory);
- std::vector<Registry> regs;
- r.optional_object_field(obj, REGISTRIES, regs, *reg_des);
-
- for (Registry& reg : regs)
- {
- registries.add_registry(std::move(reg));
- }
-
- return Configuration{std::move(registries)};
- }
-
- ConfigurationDeserializer::ConfigurationDeserializer(const fs::path& configuration_directory)
- : configuration_directory(configuration_directory)
- {
- }
-
-}
-
-std::unique_ptr<Json::IDeserializer<Configuration>> vcpkg::make_configuration_deserializer(
- const fs::path& config_directory)
-{
- return std::make_unique<ConfigurationDeserializer>(config_directory);
-}
-
-namespace vcpkg
-{
- void Configuration::validate_feature_flags(const FeatureFlagSettings& flags)
- {
- if (!flags.registries && registry_set.has_modifications())
- {
- System::printf(System::Color::warning,
- "Warning: configuration specified the \"registries\" or \"default-registries\" field, but "
- "the %s feature flag was not enabled.\n",
- VcpkgCmdArguments::REGISTRIES_FEATURE);
- registry_set = RegistrySet();
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp
deleted file mode 100644
index aafdec065..000000000
--- a/toolsrc/src/vcpkg/dependencies.cpp
+++ /dev/null
@@ -1,1896 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/graphs.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/packagespec.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/statusparagraphs.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/vcpkgpaths.h>
-
-using namespace vcpkg;
-
-namespace vcpkg::Dependencies
-{
- namespace
- {
- struct ClusterInstalled
- {
- ClusterInstalled(const InstalledPackageView& ipv) : ipv(ipv)
- {
- original_features.emplace("core");
- for (auto&& feature : ipv.features)
- {
- original_features.emplace(feature->package.feature);
- }
- }
-
- InstalledPackageView ipv;
- std::unordered_set<PackageSpec> remove_edges;
- std::unordered_set<std::string> original_features;
-
- // Tracks whether an incoming request has asked for the default features -- on reinstall, add them
- bool defaults_requested = false;
- };
-
- struct ClusterInstallInfo
- {
- std::map<std::string, std::vector<FeatureSpec>> build_edges;
- bool defaults_requested = false;
- };
-
- /// <summary>
- /// Representation of a package and its features in a ClusterGraph.
- /// </summary>
- struct Cluster : Util::MoveOnlyBase
- {
- Cluster(const InstalledPackageView& ipv, ExpectedS<const SourceControlFileLocation&>&& scfl)
- : m_spec(ipv.spec()), m_scfl(std::move(scfl)), m_installed(ipv)
- {
- }
-
- Cluster(const PackageSpec& spec, const SourceControlFileLocation& scfl) : m_spec(spec), m_scfl(scfl) { }
-
- bool has_feature_installed(const std::string& feature) const
- {
- if (const ClusterInstalled* inst = m_installed.get())
- {
- return inst->original_features.find(feature) != inst->original_features.end();
- }
- return false;
- }
-
- bool has_defaults_installed() const
- {
- if (const ClusterInstalled* inst = m_installed.get())
- {
- return std::all_of(inst->ipv.core->package.default_features.begin(),
- inst->ipv.core->package.default_features.end(),
- [&](const std::string& feature) {
- return inst->original_features.find(feature) !=
- inst->original_features.end();
- });
- }
- return false;
- }
-
- // Returns dependencies which were added as a result of this call.
- // Precondition: must have called "mark_for_reinstall()" or "create_install_info()" on this cluster
- void add_feature(const std::string& feature,
- const CMakeVars::CMakeVarProvider& var_provider,
- std::vector<FeatureSpec>& out_new_dependencies)
- {
- ClusterInstallInfo& info = m_install_info.value_or_exit(VCPKG_LINE_INFO);
- if (feature == "default")
- {
- if (!info.defaults_requested)
- {
- info.defaults_requested = true;
- for (auto&& f : get_scfl_or_exit().source_control_file->core_paragraph->default_features)
- out_new_dependencies.emplace_back(m_spec, f);
- }
- return;
- }
-
- if (Util::Sets::contains(info.build_edges, feature))
- {
- // This feature has already been completely handled
- return;
- }
- auto maybe_vars = var_provider.get_dep_info_vars(m_spec);
- const std::vector<Dependency>* qualified_deps =
- &get_scfl_or_exit().source_control_file->find_dependencies_for_feature(feature).value_or_exit(
- VCPKG_LINE_INFO);
-
- std::vector<FeatureSpec> dep_list;
- if (auto vars = maybe_vars.get())
- {
- // Qualified dependency resolution is available
- auto fullspec_list = filter_dependencies(*qualified_deps, m_spec.triplet(), *vars);
-
- for (auto&& fspec : fullspec_list)
- {
- Util::Vectors::append(&dep_list, fspec.to_feature_specs({"default"}, {"default"}));
- }
-
- Util::sort_unique_erase(dep_list);
- info.build_edges.emplace(feature, dep_list);
- }
- else
- {
- bool requires_qualified_resolution = false;
- for (const Dependency& dep : *qualified_deps)
- {
- if (dep.platform.is_empty())
- {
- Util::Vectors::append(&dep_list,
- FullPackageSpec({dep.name, m_spec.triplet()}, dep.features)
- .to_feature_specs({"default"}, {"default"}));
- }
- else
- {
- requires_qualified_resolution = true;
- }
- }
- Util::sort_unique_erase(dep_list);
- if (!requires_qualified_resolution)
- {
- info.build_edges.emplace(feature, dep_list);
- }
- }
- Util::Vectors::append(&out_new_dependencies, dep_list);
- }
-
- void create_install_info(std::vector<FeatureSpec>& out_reinstall_requirements)
- {
- bool defaults_requested = false;
- if (const ClusterInstalled* inst = m_installed.get())
- {
- for (const std::string& installed_feature : inst->original_features)
- {
- out_reinstall_requirements.emplace_back(m_spec, installed_feature);
- }
- defaults_requested = inst->defaults_requested;
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, !m_install_info.has_value());
- m_install_info = make_optional(ClusterInstallInfo{});
-
- if (defaults_requested)
- {
- for (auto&& def_feature : get_scfl_or_exit().source_control_file->core_paragraph->default_features)
- out_reinstall_requirements.emplace_back(m_spec, def_feature);
- }
- else if (request_type != RequestType::USER_REQUESTED)
- {
- // If the user did not explicitly request this installation, we need to add all new default features
- auto&& new_defaults = get_scfl_or_exit().source_control_file->core_paragraph->default_features;
- std::set<std::string> defaults_set{new_defaults.begin(), new_defaults.end()};
-
- // Install only features that were not previously available
- if (auto p_inst = m_installed.get())
- {
- for (auto&& prev_default : p_inst->ipv.core->package.default_features)
- {
- defaults_set.erase(prev_default);
- }
- }
-
- for (const std::string& feature : defaults_set)
- {
- // Instead of dealing with adding default features to each of our dependencies right
- // away we just defer to the next pass of the loop.
- out_reinstall_requirements.emplace_back(m_spec, feature);
- }
- }
- }
-
- const SourceControlFileLocation& get_scfl_or_exit() const
- {
-#if defined(_WIN32)
- static auto vcpkg_remove_cmd = ".\\vcpkg";
-#else
- static auto vcpkg_remove_cmd = "./vcpkg";
-#endif
- if (!m_scfl)
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- "Error: while loading control file for %s: %s.\nPlease run \"%s remove %s\" and re-attempt.",
- m_spec,
- m_scfl.error(),
- vcpkg_remove_cmd,
- m_spec);
- }
-
- return *m_scfl.get();
- }
-
- PackageSpec m_spec;
- ExpectedS<const SourceControlFileLocation&> m_scfl;
-
- Optional<ClusterInstalled> m_installed;
- Optional<ClusterInstallInfo> m_install_info;
-
- RequestType request_type = RequestType::AUTO_SELECTED;
- };
-
- struct PackageGraph
- {
- PackageGraph(const PortFileProvider::PortFileProvider& provider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const StatusParagraphs& status_db);
- ~PackageGraph();
-
- void install(Span<const FeatureSpec> specs);
- void upgrade(Span<const PackageSpec> specs);
- void mark_user_requested(const PackageSpec& spec);
-
- ActionPlan serialize(const CreateInstallPlanOptions& options = {}) const;
-
- void mark_for_reinstall(const PackageSpec& spec, std::vector<FeatureSpec>& out_reinstall_requirements);
- const CMakeVars::CMakeVarProvider& m_var_provider;
-
- std::unique_ptr<ClusterGraph> m_graph;
- };
-
- }
-
- /// <summary>
- /// Directional graph representing a collection of packages with their features connected by their dependencies.
- /// </summary>
- struct ClusterGraph : Util::MoveOnlyBase
- {
- explicit ClusterGraph(const PortFileProvider::PortFileProvider& port_provider) : m_port_provider(port_provider)
- {
- }
-
- /// <summary>
- /// Find the cluster associated with spec or if not found, create it from the PortFileProvider.
- /// </summary>
- /// <param name="spec">Package spec to get the cluster for.</param>
- /// <returns>The cluster found or created for spec.</returns>
- Cluster& get(const PackageSpec& spec)
- {
- auto it = m_graph.find(spec);
- if (it == m_graph.end())
- {
- const SourceControlFileLocation* scfl = m_port_provider.get_control_file(spec.name()).get();
-
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, scfl, "Error: Cannot find definition for package `%s`.", spec.name());
-
- return m_graph
- .emplace(std::piecewise_construct, std::forward_as_tuple(spec), std::forward_as_tuple(spec, *scfl))
- .first->second;
- }
-
- return it->second;
- }
-
- Cluster& get(const InstalledPackageView& ipv)
- {
- auto it = m_graph.find(ipv.spec());
-
- if (it == m_graph.end())
- {
- ExpectedS<const SourceControlFileLocation&> maybe_scfl =
- m_port_provider.get_control_file(ipv.spec().name());
-
- return m_graph
- .emplace(std::piecewise_construct,
- std::forward_as_tuple(ipv.spec()),
- std::forward_as_tuple(ipv, std::move(maybe_scfl)))
- .first->second;
- }
-
- if (!it->second.m_installed)
- {
- it->second.m_installed = {ipv};
- }
-
- return it->second;
- }
-
- const Cluster& find_or_exit(const PackageSpec& spec, LineInfo linfo) const
- {
- auto it = m_graph.find(spec);
- Checks::check_maybe_upgrade(linfo, it != m_graph.end(), "Failed to locate spec in graph");
- return it->second;
- }
-
- auto begin() const { return m_graph.begin(); }
- auto end() const { return m_graph.end(); }
-
- private:
- std::map<PackageSpec, Cluster> m_graph;
- const PortFileProvider::PortFileProvider& m_port_provider;
- };
-
- static std::string to_output_string(RequestType request_type,
- const CStringView s,
- const Build::BuildPackageOptions& options,
- const SourceControlFileLocation* scfl,
- const InstalledPackageView* ipv,
- const fs::path& builtin_ports_dir)
- {
- std::string ret;
- switch (request_type)
- {
- case RequestType::AUTO_SELECTED: Strings::append(ret, " * "); break;
- case RequestType::USER_REQUESTED: Strings::append(ret, " "); break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- Strings::append(ret, s);
- if (scfl)
- {
- Strings::append(ret, " -> ", scfl->to_versiont());
- }
- else if (ipv)
- {
- Strings::append(ret, " -> ", VersionT{ipv->core->package.version, ipv->core->package.port_version});
- }
- if (options.use_head_version == Build::UseHeadVersion::YES)
- {
- Strings::append(ret, " (+HEAD)");
- }
- if (scfl)
- {
- const auto s_install_port_path = fs::u8string(scfl->source_location);
- if (!builtin_ports_dir.empty() &&
- !Strings::case_insensitive_ascii_starts_with(s_install_port_path, fs::u8string(builtin_ports_dir)))
- {
- Strings::append(ret, " -- ", s_install_port_path);
- }
- }
- return ret;
- }
-
- std::string to_output_string(RequestType request_type,
- const CStringView s,
- const Build::BuildPackageOptions& options)
- {
- return to_output_string(request_type, s, options, {}, {}, {});
- }
-
- std::string to_output_string(RequestType request_type, const CStringView s)
- {
- return to_output_string(request_type, s, {}, {}, {}, {});
- }
-
- InstallPlanAction::InstallPlanAction() noexcept
- : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN), build_options{}
- {
- }
-
- InstallPlanAction::InstallPlanAction(const PackageSpec& spec,
- const SourceControlFileLocation& scfl,
- const RequestType& request_type,
- std::map<std::string, std::vector<FeatureSpec>>&& dependencies)
- : spec(spec)
- , source_control_file_location(scfl)
- , plan_type(InstallPlanType::BUILD_AND_INSTALL)
- , request_type(request_type)
- , build_options{}
- , feature_dependencies(std::move(dependencies))
- {
- for (const auto& kv : feature_dependencies)
- {
- feature_list.emplace_back(kv.first);
- for (const FeatureSpec& fspec : kv.second)
- {
- if (spec != fspec.spec())
- {
- package_dependencies.emplace_back(fspec.spec());
- }
- }
- }
-
- Util::sort_unique_erase(package_dependencies);
- Util::sort_unique_erase(feature_list);
- }
-
- InstallPlanAction::InstallPlanAction(InstalledPackageView&& ipv, const RequestType& request_type)
- : spec(ipv.spec())
- , installed_package(std::move(ipv))
- , plan_type(InstallPlanType::ALREADY_INSTALLED)
- , request_type(request_type)
- , build_options{}
- , feature_dependencies(installed_package.get()->feature_dependencies())
- , package_dependencies(installed_package.get()->dependencies())
- {
- for (const auto& kv : feature_dependencies)
- {
- feature_list.emplace_back(kv.first);
- }
- }
-
- std::string InstallPlanAction::displayname() const
- {
- if (this->feature_list.empty())
- {
- return this->spec.to_string();
- }
-
- const std::string features = Strings::join(",", feature_list);
- return Strings::format("%s[%s]:%s", this->spec.name(), features, this->spec.triplet());
- }
- const std::string& InstallPlanAction::public_abi() const
- {
- switch (plan_type)
- {
- case InstallPlanType::ALREADY_INSTALLED:
- return installed_package.value_or_exit(VCPKG_LINE_INFO).core->package.abi;
- case InstallPlanType::BUILD_AND_INSTALL:
- {
- auto&& i = abi_info.value_or_exit(VCPKG_LINE_INFO);
- if (auto o = i.pre_build_info->public_abi_override.get())
- return *o;
- else
- return i.package_abi;
- }
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- bool InstallPlanAction::has_package_abi() const
- {
- if (!abi_info) return false;
- return !abi_info.get()->package_abi.empty();
- }
- Optional<const std::string&> InstallPlanAction::package_abi() const
- {
- if (!abi_info) return nullopt;
- if (abi_info.get()->package_abi.empty()) return nullopt;
- return abi_info.get()->package_abi;
- }
- const Build::PreBuildInfo& InstallPlanAction::pre_build_info(LineInfo linfo) const
- {
- return *abi_info.value_or_exit(linfo).pre_build_info.get();
- }
-
- bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right)
- {
- return left->spec.name() < right->spec.name();
- }
-
- RemovePlanAction::RemovePlanAction() noexcept
- : plan_type(RemovePlanType::UNKNOWN), request_type(RequestType::UNKNOWN)
- {
- }
-
- RemovePlanAction::RemovePlanAction(const PackageSpec& spec,
- const RemovePlanType& plan_type,
- const RequestType& request_type)
- : spec(spec), plan_type(plan_type), request_type(request_type)
- {
- }
-
- bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right)
- {
- return left->spec.name() < right->spec.name();
- }
-
- ExportPlanAction::ExportPlanAction() noexcept
- : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN)
- {
- }
-
- ExportPlanAction::ExportPlanAction(const PackageSpec& spec,
- InstalledPackageView&& installed_package,
- const RequestType& request_type)
- : spec(spec)
- , plan_type(ExportPlanType::ALREADY_BUILT)
- , request_type(request_type)
- , m_installed_package(std::move(installed_package))
- {
- }
-
- ExportPlanAction::ExportPlanAction(const PackageSpec& spec, const RequestType& request_type)
- : spec(spec), plan_type(ExportPlanType::NOT_BUILT), request_type(request_type)
- {
- }
-
- Optional<const BinaryParagraph&> ExportPlanAction::core_paragraph() const
- {
- if (auto p_ip = m_installed_package.get())
- {
- return p_ip->core->package;
- }
- return nullopt;
- }
-
- std::vector<PackageSpec> ExportPlanAction::dependencies() const
- {
- if (auto p_ip = m_installed_package.get())
- return p_ip->dependencies();
- else
- return {};
- }
-
- bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right)
- {
- return left->spec.name() < right->spec.name();
- }
-
- std::vector<RemovePlanAction> create_remove_plan(const std::vector<PackageSpec>& specs,
- const StatusParagraphs& status_db)
- {
- struct RemoveAdjacencyProvider final : Graphs::AdjacencyProvider<PackageSpec, RemovePlanAction>
- {
- const StatusParagraphs& status_db;
- const std::vector<InstalledPackageView>& installed_ports;
- const std::unordered_set<PackageSpec>& specs_as_set;
-
- RemoveAdjacencyProvider(const StatusParagraphs& status_db,
- const std::vector<InstalledPackageView>& installed_ports,
- const std::unordered_set<PackageSpec>& specs_as_set)
- : status_db(status_db), installed_ports(installed_ports), specs_as_set(specs_as_set)
- {
- }
-
- std::vector<PackageSpec> adjacency_list(const RemovePlanAction& plan) const override
- {
- if (plan.plan_type == RemovePlanType::NOT_INSTALLED)
- {
- return {};
- }
-
- const PackageSpec& spec = plan.spec;
- std::vector<PackageSpec> dependents;
- for (auto&& ipv : installed_ports)
- {
- auto deps = ipv.dependencies();
-
- if (std::find(deps.begin(), deps.end(), spec) == deps.end()) continue;
-
- dependents.push_back(ipv.spec());
- }
-
- return dependents;
- }
-
- RemovePlanAction load_vertex_data(const PackageSpec& spec) const override
- {
- const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end()
- ? RequestType::USER_REQUESTED
- : RequestType::AUTO_SELECTED;
- const StatusParagraphs::const_iterator it = status_db.find_installed(spec);
- if (it == status_db.end())
- {
- return RemovePlanAction{spec, RemovePlanType::NOT_INSTALLED, request_type};
- }
- return RemovePlanAction{spec, RemovePlanType::REMOVE, request_type};
- }
-
- std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); }
- };
-
- auto installed_ports = get_installed_ports(status_db);
- const std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend());
- return Graphs::topological_sort(
- std::move(specs), RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set}, {});
- }
-
- std::vector<ExportPlanAction> create_export_plan(const std::vector<PackageSpec>& specs,
- const StatusParagraphs& status_db)
- {
- struct ExportAdjacencyProvider final : Graphs::AdjacencyProvider<PackageSpec, ExportPlanAction>
- {
- const StatusParagraphs& status_db;
- const std::unordered_set<PackageSpec>& specs_as_set;
-
- ExportAdjacencyProvider(const StatusParagraphs& s, const std::unordered_set<PackageSpec>& specs_as_set)
- : status_db(s), specs_as_set(specs_as_set)
- {
- }
-
- std::vector<PackageSpec> adjacency_list(const ExportPlanAction& plan) const override
- {
- return plan.dependencies();
- }
-
- ExportPlanAction load_vertex_data(const PackageSpec& spec) const override
- {
- const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end()
- ? RequestType::USER_REQUESTED
- : RequestType::AUTO_SELECTED;
-
- auto maybe_ipv = status_db.get_installed_package_view(spec);
-
- if (auto p_ipv = maybe_ipv.get())
- {
- return ExportPlanAction{spec, std::move(*p_ipv), request_type};
- }
-
- return ExportPlanAction{spec, request_type};
- }
-
- std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); }
- };
-
- const std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend());
- std::vector<ExportPlanAction> toposort =
- Graphs::topological_sort(specs, ExportAdjacencyProvider{status_db, specs_as_set}, {});
- return toposort;
- }
-
- void PackageGraph::mark_user_requested(const PackageSpec& spec)
- {
- m_graph->get(spec).request_type = RequestType::USER_REQUESTED;
- }
-
- // `features` should have "default" instead of missing "core"
- std::vector<FullPackageSpec> resolve_deps_as_top_level(const SourceControlFile& scf,
- Triplet triplet,
- std::vector<std::string> features,
- CMakeVars::CMakeVarProvider& var_provider)
- {
- PackageSpec spec{scf.core_paragraph->name, triplet};
- std::map<std::string, std::vector<std::string>> specs_to_features;
-
- Optional<const PlatformExpression::Context&> ctx_storage = var_provider.get_dep_info_vars(spec);
- auto ctx = [&]() -> const PlatformExpression::Context& {
- if (!ctx_storage)
- {
- var_provider.load_dep_info_vars({&spec, 1});
- ctx_storage = var_provider.get_dep_info_vars(spec);
- }
- return ctx_storage.value_or_exit(VCPKG_LINE_INFO);
- };
-
- auto handle_deps = [&](View<Dependency> deps) {
- for (auto&& dep : deps)
- {
- if (dep.platform.is_empty() || dep.platform.evaluate(ctx()))
- {
- if (dep.name == spec.name())
- Util::Vectors::append(&features, dep.features);
- else
- Util::Vectors::append(&specs_to_features[dep.name], dep.features);
- }
- }
- };
-
- handle_deps(scf.core_paragraph->dependencies);
- enum class State
- {
- NotVisited = 0,
- Visited,
- };
- std::map<std::string, State> feature_state;
- while (!features.empty())
- {
- auto feature = std::move(features.back());
- features.pop_back();
-
- if (feature_state[feature] == State::Visited) continue;
- feature_state[feature] = State::Visited;
- if (feature == "default")
- {
- Util::Vectors::append(&features, scf.core_paragraph->default_features);
- }
- else
- {
- auto it =
- Util::find_if(scf.feature_paragraphs, [&feature](const std::unique_ptr<FeatureParagraph>& ptr) {
- return ptr->name == feature;
- });
- if (it != scf.feature_paragraphs.end()) handle_deps(it->get()->dependencies);
- }
- }
- return Util::fmap(specs_to_features, [triplet](std::pair<const std::string, std::vector<std::string>>& p) {
- return FullPackageSpec({p.first, triplet}, Util::sort_unique_erase(std::move(p.second)));
- });
- }
-
- ActionPlan create_feature_install_plan(const PortFileProvider::PortFileProvider& port_provider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const std::vector<FullPackageSpec>& specs,
- const StatusParagraphs& status_db,
- const CreateInstallPlanOptions& options)
- {
- PackageGraph pgraph(port_provider, var_provider, status_db);
-
- std::vector<FeatureSpec> feature_specs;
- for (const FullPackageSpec& spec : specs)
- {
- auto maybe_scfl = port_provider.get_control_file(spec.package_spec.name());
-
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- maybe_scfl.has_value(),
- "Error: while loading port `%s`: %s",
- spec.package_spec.name(),
- maybe_scfl.error());
-
- const SourceControlFileLocation* scfl = maybe_scfl.get();
-
- const std::vector<std::string> all_features =
- Util::fmap(scfl->source_control_file->feature_paragraphs,
- [](auto&& feature_paragraph) { return feature_paragraph->name; });
-
- auto fspecs =
- spec.to_feature_specs(scfl->source_control_file->core_paragraph->default_features, all_features);
- feature_specs.insert(
- feature_specs.end(), std::make_move_iterator(fspecs.begin()), std::make_move_iterator(fspecs.end()));
- }
- Util::sort_unique_erase(feature_specs);
-
- for (const FeatureSpec& spec : feature_specs)
- {
- pgraph.mark_user_requested(spec.spec());
- }
- pgraph.install(feature_specs);
-
- auto res = pgraph.serialize(options);
-
- return res;
- }
-
- void PackageGraph::mark_for_reinstall(const PackageSpec& first_remove_spec,
- std::vector<FeatureSpec>& out_reinstall_requirements)
- {
- std::set<PackageSpec> removed;
- std::vector<PackageSpec> to_remove{first_remove_spec};
-
- while (!to_remove.empty())
- {
- PackageSpec remove_spec = std::move(to_remove.back());
- to_remove.pop_back();
-
- if (!removed.insert(remove_spec).second) continue;
-
- Cluster& clust = m_graph->get(remove_spec);
- ClusterInstalled& info = clust.m_installed.value_or_exit(VCPKG_LINE_INFO);
-
- if (!clust.m_install_info)
- {
- clust.create_install_info(out_reinstall_requirements);
- }
-
- to_remove.insert(to_remove.end(), info.remove_edges.begin(), info.remove_edges.end());
- }
- }
-
- /// The list of specs to install should already have default features expanded
- void PackageGraph::install(Span<const FeatureSpec> specs)
- {
- // We batch resolving qualified dependencies, because it's an invocation of CMake which
- // takes ~150ms per call.
- std::vector<FeatureSpec> qualified_dependencies;
- std::vector<FeatureSpec> next_dependencies{specs.begin(), specs.end()};
-
- // Keep running while there is any chance of finding more dependencies
- while (!next_dependencies.empty())
- {
- // Keep running until the only dependencies left are qualified
- while (!next_dependencies.empty())
- {
- // Extract the top of the stack
- FeatureSpec spec = std::move(next_dependencies.back());
- next_dependencies.pop_back();
-
- // Get the cluster for the PackageSpec of the FeatureSpec we are adding to the install graph
- Cluster& clust = m_graph->get(spec.spec());
-
- // If this spec hasn't already had its qualified dependencies resolved
- if (!m_var_provider.get_dep_info_vars(spec.spec()).has_value())
- {
- // TODO: There's always the chance that we don't find the feature we're looking for (probably a
- // malformed CONTROL file somewhere). We should probably output a better error.
- const std::vector<Dependency>* paragraph_depends = nullptr;
- if (spec.feature() == "core")
- {
- paragraph_depends = &clust.get_scfl_or_exit().source_control_file->core_paragraph->dependencies;
- }
- else if (spec.feature() == "default")
- {
- }
- else
- {
- auto maybe_paragraph =
- clust.get_scfl_or_exit().source_control_file->find_feature(spec.feature());
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- maybe_paragraph.has_value(),
- "Package %s does not have a %s feature",
- spec.name(),
- spec.feature());
- paragraph_depends = &maybe_paragraph.value_or_exit(VCPKG_LINE_INFO).dependencies;
- }
-
- // And it has at least one qualified dependency
- if (paragraph_depends &&
- Util::any_of(*paragraph_depends, [](auto&& dep) { return !dep.platform.is_empty(); }))
- {
- // Add it to the next batch run
- qualified_dependencies.emplace_back(spec);
- }
- }
-
- if (clust.m_install_info.has_value())
- {
- clust.add_feature(spec.feature(), m_var_provider, next_dependencies);
- }
- else
- {
- if (!clust.m_installed.has_value())
- {
- clust.create_install_info(next_dependencies);
- clust.add_feature(spec.feature(), m_var_provider, next_dependencies);
- }
- else
- {
- if (spec.feature() == "default")
- {
- if (!clust.m_installed.get()->defaults_requested)
- {
- clust.m_installed.get()->defaults_requested = true;
- if (!clust.has_defaults_installed())
- {
- mark_for_reinstall(spec.spec(), next_dependencies);
- }
- }
- }
- else if (!clust.has_feature_installed(spec.feature()))
- {
- // If install_info is not present and it is already installed, we have never added a feature
- // which hasn't already been installed to this cluster. In this case, we need to reinstall
- // the port if the feature isn't already present.
- mark_for_reinstall(spec.spec(), next_dependencies);
- clust.add_feature(spec.feature(), m_var_provider, next_dependencies);
- }
- }
- }
- }
-
- if (!qualified_dependencies.empty())
- {
- Util::sort_unique_erase(qualified_dependencies);
-
- // Extract the package specs we need to get dependency info from. We don't run the triplet on a per
- // feature basis. We run it once for the whole port.
- auto qualified_package_specs =
- Util::fmap(qualified_dependencies, [](const FeatureSpec& fspec) { return fspec.spec(); });
- Util::sort_unique_erase(qualified_package_specs);
- m_var_provider.load_dep_info_vars(qualified_package_specs);
-
- // Put all the FeatureSpecs for which we had qualified dependencies back on the dependencies stack.
- // We need to recheck if evaluating the triplet revealed any new dependencies.
- next_dependencies.insert(next_dependencies.end(),
- std::make_move_iterator(qualified_dependencies.begin()),
- std::make_move_iterator(qualified_dependencies.end()));
- qualified_dependencies.clear();
- }
- }
- }
-
- void PackageGraph::upgrade(Span<const PackageSpec> specs)
- {
- std::vector<FeatureSpec> reinstall_reqs;
-
- for (const PackageSpec& spec : specs)
- mark_for_reinstall(spec, reinstall_reqs);
-
- Util::sort_unique_erase(reinstall_reqs);
-
- install(reinstall_reqs);
- }
-
- ActionPlan create_upgrade_plan(const PortFileProvider::PortFileProvider& port_provider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const std::vector<PackageSpec>& specs,
- const StatusParagraphs& status_db,
- const CreateInstallPlanOptions& options)
- {
- PackageGraph pgraph(port_provider, var_provider, status_db);
-
- pgraph.upgrade(specs);
-
- return pgraph.serialize(options);
- }
-
- ActionPlan PackageGraph::serialize(const CreateInstallPlanOptions& options) const
- {
- struct BaseEdgeProvider : Graphs::AdjacencyProvider<PackageSpec, const Cluster*>
- {
- BaseEdgeProvider(const ClusterGraph& parent) : m_parent(parent) { }
-
- std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); }
- const Cluster* load_vertex_data(const PackageSpec& spec) const override
- {
- return &m_parent.find_or_exit(spec, VCPKG_LINE_INFO);
- }
-
- const ClusterGraph& m_parent;
- };
-
- struct RemoveEdgeProvider final : BaseEdgeProvider
- {
- using BaseEdgeProvider::BaseEdgeProvider;
-
- std::vector<PackageSpec> adjacency_list(const Cluster* const& vertex) const override
- {
- auto&& set = vertex->m_installed.value_or_exit(VCPKG_LINE_INFO).remove_edges;
- return {set.begin(), set.end()};
- }
- } removeedgeprovider(*m_graph);
-
- struct InstallEdgeProvider final : BaseEdgeProvider
- {
- using BaseEdgeProvider::BaseEdgeProvider;
-
- std::vector<PackageSpec> adjacency_list(const Cluster* const& vertex) const override
- {
- if (!vertex->m_install_info.has_value()) return {};
-
- auto& info = vertex->m_install_info.value_or_exit(VCPKG_LINE_INFO);
- std::vector<PackageSpec> deps;
- for (auto&& kv : info.build_edges)
- for (auto&& e : kv.second)
- {
- auto spec = e.spec();
- if (spec != vertex->m_spec) deps.push_back(std::move(spec));
- }
- Util::sort_unique_erase(deps);
- return deps;
- }
- } installedgeprovider(*m_graph);
-
- std::vector<PackageSpec> removed_vertices;
- std::vector<PackageSpec> installed_vertices;
- for (auto&& kv : *m_graph)
- {
- if (kv.second.m_install_info.has_value() && kv.second.m_installed.has_value())
- {
- removed_vertices.push_back(kv.first);
- }
- if (kv.second.m_install_info.has_value() || kv.second.request_type == RequestType::USER_REQUESTED)
- {
- installed_vertices.push_back(kv.first);
- }
- }
- auto remove_toposort = Graphs::topological_sort(removed_vertices, removeedgeprovider, options.randomizer);
- auto insert_toposort = Graphs::topological_sort(installed_vertices, installedgeprovider, options.randomizer);
-
- ActionPlan plan;
-
- for (auto&& p_cluster : remove_toposort)
- {
- plan.remove_actions.emplace_back(p_cluster->m_spec, RemovePlanType::REMOVE, p_cluster->request_type);
- }
-
- for (auto&& p_cluster : insert_toposort)
- {
- // Every cluster that has an install_info needs to be built
- // If a cluster only has an installed object and is marked as user requested we should still report it.
- if (auto info_ptr = p_cluster->m_install_info.get())
- {
- std::map<std::string, std::vector<FeatureSpec>> computed_edges;
- for (auto&& kv : info_ptr->build_edges)
- {
- std::set<FeatureSpec> fspecs;
- for (auto&& fspec : kv.second)
- {
- if (fspec.feature() != "default")
- {
- fspecs.insert(fspec);
- continue;
- }
- auto&& dep_clust = m_graph->get(fspec.spec());
- const auto& default_features = [&] {
- if (dep_clust.m_install_info.has_value())
- return dep_clust.get_scfl_or_exit()
- .source_control_file->core_paragraph->default_features;
- if (auto p = dep_clust.m_installed.get()) return p->ipv.core->package.default_features;
- Checks::unreachable(VCPKG_LINE_INFO);
- }();
- for (auto&& default_feature : default_features)
- fspecs.emplace(fspec.spec(), default_feature);
- }
- computed_edges[kv.first].assign(fspecs.begin(), fspecs.end());
- }
- plan.install_actions.emplace_back(p_cluster->m_spec,
- p_cluster->get_scfl_or_exit(),
- p_cluster->request_type,
- std::move(computed_edges));
- }
- else if (p_cluster->request_type == RequestType::USER_REQUESTED && p_cluster->m_installed.has_value())
- {
- auto&& installed = p_cluster->m_installed.value_or_exit(VCPKG_LINE_INFO);
- plan.already_installed.emplace_back(InstalledPackageView(installed.ipv), p_cluster->request_type);
- }
- }
-
- return plan;
- }
-
- static std::unique_ptr<ClusterGraph> create_feature_install_graph(
- const PortFileProvider::PortFileProvider& port_provider, const StatusParagraphs& status_db)
- {
- std::unique_ptr<ClusterGraph> graph = std::make_unique<ClusterGraph>(port_provider);
-
- auto installed_ports = get_installed_ports(status_db);
-
- for (auto&& ipv : installed_ports)
- {
- graph->get(ipv);
- }
-
- // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges.
- for (auto&& ipv : installed_ports)
- {
- auto deps = ipv.dependencies();
-
- for (auto&& dep : deps)
- {
- auto p_installed = graph->get(dep).m_installed.get();
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO,
- p_installed,
- "Error: database corrupted. Package %s is installed but dependency %s is not.",
- ipv.spec(),
- dep);
- p_installed->remove_edges.emplace(ipv.spec());
- }
- }
- return graph;
- }
-
- PackageGraph::PackageGraph(const PortFileProvider::PortFileProvider& port_provider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const StatusParagraphs& status_db)
- : m_var_provider(var_provider), m_graph(create_feature_install_graph(port_provider, status_db))
- {
- }
-
- PackageGraph::~PackageGraph() = default;
-
- void print_plan(const ActionPlan& action_plan, const bool is_recursive, const fs::path& builtin_ports_dir)
- {
- if (action_plan.remove_actions.empty() && action_plan.already_installed.empty() &&
- action_plan.install_actions.empty())
- {
- System::print2("All requested packages are currently installed.\n");
- return;
- }
-
- std::set<PackageSpec> remove_specs;
- std::vector<const InstallPlanAction*> rebuilt_plans;
- std::vector<const InstallPlanAction*> only_install_plans;
- std::vector<const InstallPlanAction*> new_plans;
- std::vector<const InstallPlanAction*> already_installed_plans;
- std::vector<const InstallPlanAction*> excluded;
-
- const bool has_non_user_requested_packages =
- Util::find_if(action_plan.install_actions, [](const InstallPlanAction& action) -> bool {
- return action.request_type != RequestType::USER_REQUESTED;
- }) != action_plan.install_actions.cend();
-
- for (auto&& remove_action : action_plan.remove_actions)
- {
- remove_specs.emplace(remove_action.spec);
- }
- for (auto&& install_action : action_plan.install_actions)
- {
- // remove plans are guaranteed to come before install plans, so we know the plan will be contained
- // if at all.
- auto it = remove_specs.find(install_action.spec);
- if (it != remove_specs.end())
- {
- remove_specs.erase(it);
- rebuilt_plans.push_back(&install_action);
- }
- else
- {
- if (install_action.plan_type == InstallPlanType::EXCLUDED)
- excluded.push_back(&install_action);
- else
- new_plans.push_back(&install_action);
- }
- }
- for (auto&& action : action_plan.already_installed)
- {
- if (action.request_type == RequestType::USER_REQUESTED) already_installed_plans.emplace_back(&action);
- }
- already_installed_plans = Util::fmap(action_plan.already_installed, [](auto&& action) { return &action; });
-
- std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name);
-
- static auto actions_to_output_string = [&](const std::vector<const InstallPlanAction*>& v) {
- return Strings::join("\n", v, [&](const InstallPlanAction* p) {
- return to_output_string(p->request_type,
- p->displayname(),
- p->build_options,
- p->source_control_file_location.get(),
- p->installed_package.get(),
- builtin_ports_dir);
- });
- };
-
- if (!excluded.empty())
- {
- System::print2("The following packages are excluded:\n", actions_to_output_string(excluded), '\n');
- }
-
- if (!already_installed_plans.empty())
- {
- System::print2("The following packages are already installed:\n",
- actions_to_output_string(already_installed_plans),
- '\n');
- }
-
- if (!remove_specs.empty())
- {
- std::string msg = "The following packages will be removed:\n";
- for (auto spec : remove_specs)
- {
- Strings::append(msg, to_output_string(RequestType::USER_REQUESTED, spec.to_string()), '\n');
- }
- System::print2(msg);
- }
-
- if (!rebuilt_plans.empty())
- {
- System::print2("The following packages will be rebuilt:\n", actions_to_output_string(rebuilt_plans), '\n');
- }
-
- if (!new_plans.empty())
- {
- System::print2(
- "The following packages will be built and installed:\n", actions_to_output_string(new_plans), '\n');
- }
-
- if (!only_install_plans.empty())
- {
- System::print2("The following packages will be directly installed:\n",
- actions_to_output_string(only_install_plans),
- '\n');
- }
-
- if (has_non_user_requested_packages)
- System::print2("Additional packages (*) will be modified to complete this operation.\n");
- bool have_removals = !remove_specs.empty() || !rebuilt_plans.empty();
- if (have_removals && !is_recursive)
- {
- System::print2(System::Color::warning,
- "If you are sure you want to rebuild the above packages, run the command with the "
- "--recurse option\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- namespace
- {
- struct VersionedPackageGraph
- {
- private:
- using IVersionedPortfileProvider = PortFileProvider::IVersionedPortfileProvider;
- using IBaselineProvider = PortFileProvider::IBaselineProvider;
-
- public:
- VersionedPackageGraph(const IVersionedPortfileProvider& ver_provider,
- const IBaselineProvider& base_provider,
- const PortFileProvider::IOverlayProvider& oprovider,
- const CMakeVars::CMakeVarProvider& var_provider)
- : m_ver_provider(ver_provider)
- , m_base_provider(base_provider)
- , m_o_provider(oprovider)
- , m_var_provider(var_provider)
- {
- }
-
- void add_override(const std::string& name, const Versions::Version& v);
-
- void add_roots(View<Dependency> dep, const PackageSpec& toplevel);
-
- ExpectedS<ActionPlan> finalize_extract_plan();
-
- private:
- const IVersionedPortfileProvider& m_ver_provider;
- const IBaselineProvider& m_base_provider;
- const PortFileProvider::IOverlayProvider& m_o_provider;
- const CMakeVars::CMakeVarProvider& m_var_provider;
-
- struct DepSpec
- {
- PackageSpec spec;
- Versions::Version ver;
- std::vector<std::string> features;
- };
-
- // This object contains the current version within a given column.
- // Each "string" scheme text is treated as a separate column
- // "relaxed" versions all share the same column
- struct VersionSchemeInfo
- {
- const SourceControlFileLocation* scfl = nullptr;
- Versions::Version version;
- // This tracks a list of constraint sources for debugging purposes
- std::vector<std::string> origins;
- std::map<std::string, std::vector<FeatureSpec>> deps;
-
- bool is_less_than(const Versions::Version& new_ver) const;
- };
-
- struct PackageNode : Util::MoveOnlyBase
- {
- std::map<Versions::Version, VersionSchemeInfo*, VersionTMapLess> vermap;
- std::map<std::string, VersionSchemeInfo> exacts;
- Optional<std::unique_ptr<VersionSchemeInfo>> relaxed;
- Optional<std::unique_ptr<VersionSchemeInfo>> semver;
- Optional<std::unique_ptr<VersionSchemeInfo>> date;
- std::set<std::string> features;
- bool default_features = true;
-
- VersionSchemeInfo* get_node(const Versions::Version& ver);
- VersionSchemeInfo& emplace_node(Versions::Scheme scheme, const Versions::Version& ver);
- };
-
- std::vector<DepSpec> m_roots;
- std::map<std::string, Versions::Version> m_overrides;
- std::map<PackageSpec, PackageNode> m_graph;
-
- std::pair<const PackageSpec, PackageNode>& emplace_package(const PackageSpec& spec);
-
- void add_constraint(std::pair<const PackageSpec, PackageNode>& ref,
- const Dependency& dep,
- const std::string& origin);
- void add_constraint(std::pair<const PackageSpec, PackageNode>& ref,
- const Versions::Version& ver,
- const std::string& origin);
- void add_constraint(std::pair<const PackageSpec, PackageNode>& ref,
- const std::string& feature,
- const std::string& origin);
-
- void add_constraint_default_features(std::pair<const PackageSpec, PackageNode>& ref,
- const std::string& origin);
-
- void add_feature_to(std::pair<const PackageSpec, PackageNode>& ref,
- VersionSchemeInfo& vsi,
- const std::string& feature);
-
- Optional<Versions::Version> dep_to_version(const std::string& name, const DependencyConstraint& dc);
-
- std::vector<std::string> m_errors;
- };
-
- VersionedPackageGraph::VersionSchemeInfo& VersionedPackageGraph::PackageNode::emplace_node(
- Versions::Scheme scheme, const Versions::Version& ver)
- {
- auto it = vermap.find(ver);
- if (it != vermap.end()) return *it->second;
-
- VersionSchemeInfo* vsi = nullptr;
- if (scheme == Versions::Scheme::String)
- {
- vsi = &exacts[ver.text()];
- }
- else if (scheme == Versions::Scheme::Relaxed)
- {
- if (auto p = relaxed.get())
- {
- vsi = p->get();
- }
- else
- {
- relaxed = std::make_unique<VersionSchemeInfo>();
- vsi = relaxed.get()->get();
- }
- }
- else if (scheme == Versions::Scheme::Semver)
- {
- if (auto p = semver.get())
- {
- vsi = p->get();
- }
- else
- {
- semver = std::make_unique<VersionSchemeInfo>();
- vsi = semver.get()->get();
- }
- }
- else if (scheme == Versions::Scheme::Date)
- {
- if (auto p = date.get())
- {
- vsi = p->get();
- }
- else
- {
- date = std::make_unique<VersionSchemeInfo>();
- vsi = date.get()->get();
- }
- }
- else
- {
- // not implemented
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- vermap.emplace(ver, vsi);
- return *vsi;
- }
-
- VersionedPackageGraph::VersionSchemeInfo* VersionedPackageGraph::PackageNode::get_node(
- const Versions::Version& ver)
- {
- auto it = vermap.find(ver);
- return it == vermap.end() ? nullptr : it->second;
- }
-
- using Versions::VerComp;
-
- static VerComp compare_versions(Versions::Scheme sa,
- const Versions::Version& a,
- Versions::Scheme sb,
- const Versions::Version& b)
- {
- if (sa != sb) return VerComp::unk;
-
- if (a.text() != b.text())
- {
- auto result = Versions::compare(a.text(), b.text(), sa);
- if (result != VerComp::eq) return result;
- }
-
- if (a.port_version() < b.port_version()) return VerComp::lt;
- if (a.port_version() > b.port_version()) return VerComp::gt;
- return VerComp::eq;
- }
-
- bool VersionedPackageGraph::VersionSchemeInfo::is_less_than(const Versions::Version& new_ver) const
- {
- Checks::check_exit(VCPKG_LINE_INFO, scfl);
- ASSUME(scfl != nullptr);
- auto scheme = scfl->source_control_file->core_paragraph->version_scheme;
- auto r = compare_versions(scheme, version, scheme, new_ver);
- Checks::check_exit(VCPKG_LINE_INFO, r != VerComp::unk);
- return r == VerComp::lt;
- }
-
- Versions::Version to_version(const SourceControlFile& scf)
- {
- return {
- scf.core_paragraph->version,
- scf.core_paragraph->port_version,
- };
- }
- Optional<Versions::Version> to_version(const DependencyConstraint& dc)
- {
- if (dc.type == Versions::Constraint::Type::None)
- {
- return nullopt;
- }
- else
- {
- return Versions::Version{
- dc.value,
- dc.port_version,
- };
- }
- }
-
- void VersionedPackageGraph::add_feature_to(std::pair<const PackageSpec, PackageNode>& ref,
- VersionSchemeInfo& vsi,
- const std::string& feature)
- {
- auto deps = vsi.scfl->source_control_file->find_dependencies_for_feature(feature);
- if (!deps)
- {
- // This version doesn't have this feature. This may result in an error during finalize if the
- // constraint is not removed via upgrades.
- return;
- }
- auto p = vsi.deps.emplace(feature, std::vector<FeatureSpec>{});
- if (!p.second)
- {
- // This feature has already been handled
- return;
- }
-
- for (auto&& dep : *deps.get())
- {
- PackageSpec dep_spec(dep.name, ref.first.triplet());
-
- if (!dep.platform.is_empty())
- {
- auto maybe_vars = m_var_provider.get_dep_info_vars(ref.first);
- if (!maybe_vars)
- {
- m_var_provider.load_dep_info_vars({&ref.first, 1});
- maybe_vars = m_var_provider.get_dep_info_vars(ref.first);
- }
-
- if (!dep.platform.evaluate(maybe_vars.value_or_exit(VCPKG_LINE_INFO)))
- {
- continue;
- }
- }
-
- auto& dep_node = emplace_package(dep_spec);
- // Todo: cycle detection
- add_constraint(dep_node, dep, ref.first.name());
-
- p.first->second.emplace_back(dep_spec, "core");
- for (auto&& f : dep.features)
- {
- p.first->second.emplace_back(dep_spec, f);
- }
- }
- }
-
- void VersionedPackageGraph::add_constraint_default_features(std::pair<const PackageSpec, PackageNode>& ref,
- const std::string& origin)
- {
- (void)origin;
- if (!ref.second.default_features)
- {
- ref.second.default_features = true;
-
- if (auto relaxed = ref.second.relaxed.get())
- {
- for (auto&& f : relaxed->get()->scfl->source_control_file->core_paragraph->default_features)
- {
- add_feature_to(ref, **relaxed, f);
- }
- }
- for (auto&& vsi : ref.second.exacts)
- {
- for (auto&& f : vsi.second.scfl->source_control_file->core_paragraph->default_features)
- {
- add_feature_to(ref, vsi.second, f);
- }
- }
- }
- }
-
- void VersionedPackageGraph::add_constraint(std::pair<const PackageSpec, PackageNode>& ref,
- const Dependency& dep,
- const std::string& origin)
- {
- auto maybe_overlay = m_o_provider.get_control_file(ref.first.name());
- auto over_it = m_overrides.find(ref.first.name());
- if (auto p_overlay = maybe_overlay.get())
- {
- auto overlay_version = to_version(*p_overlay->source_control_file);
- add_constraint(ref, overlay_version, origin);
- }
- else if (over_it != m_overrides.end())
- {
- add_constraint(ref, over_it->second, origin);
- }
- else
- {
- auto base_ver = m_base_provider.get_baseline_version(dep.name);
- auto dep_ver = to_version(dep.constraint);
-
- if (auto dv = dep_ver.get())
- {
- add_constraint(ref, *dv, origin);
- }
-
- if (auto bv = base_ver.get())
- {
- add_constraint(ref, *bv, origin);
- }
- }
-
- for (auto&& f : dep.features)
- {
- add_constraint(ref, f, origin);
- }
- }
- void VersionedPackageGraph::add_constraint(std::pair<const PackageSpec, PackageNode>& ref,
- const Versions::Version& version,
- const std::string& origin)
- {
- ExpectedS<const vcpkg::SourceControlFileLocation&> maybe_scfl;
-
- auto maybe_overlay = m_o_provider.get_control_file(ref.first.name());
- if (auto p_overlay = maybe_overlay.get())
- {
- auto overlay_version = to_version(*p_overlay->source_control_file);
- if (version != overlay_version)
- {
- return add_constraint(ref, overlay_version, origin);
- }
- maybe_scfl = *p_overlay;
- }
- else
- {
- auto over_it = m_overrides.find(ref.first.name());
- if (over_it != m_overrides.end() && over_it->second != version)
- {
- return add_constraint(ref, over_it->second, origin);
- }
- maybe_scfl = m_ver_provider.get_control_file({ref.first.name(), version});
- }
-
- if (auto p_scfl = maybe_scfl.get())
- {
- auto& exact_ref =
- ref.second.emplace_node(p_scfl->source_control_file->core_paragraph->version_scheme, version);
- exact_ref.origins.push_back(origin);
-
- bool replace;
- if (exact_ref.scfl == nullptr)
- {
- replace = true;
- }
- else if (exact_ref.scfl == p_scfl)
- {
- replace = false;
- }
- else
- {
- replace = exact_ref.is_less_than(version);
- }
-
- if (replace)
- {
- exact_ref.scfl = p_scfl;
- exact_ref.version = to_version(*p_scfl->source_control_file);
- exact_ref.deps.clear();
-
- add_feature_to(ref, exact_ref, "core");
-
- for (auto&& f : ref.second.features)
- {
- add_feature_to(ref, exact_ref, f);
- }
-
- if (ref.second.default_features)
- {
- for (auto&& f : p_scfl->source_control_file->core_paragraph->default_features)
- {
- add_feature_to(ref, exact_ref, f);
- }
- }
- }
- }
- else
- {
- m_errors.push_back(maybe_scfl.error());
- }
- }
-
- void VersionedPackageGraph::add_constraint(std::pair<const PackageSpec, PackageNode>& ref,
- const std::string& feature,
- const std::string& origin)
- {
- auto inserted = ref.second.features.emplace(feature).second;
- if (inserted)
- {
- if (auto relaxed = ref.second.relaxed.get())
- {
- add_feature_to(ref, **relaxed, feature);
- }
- for (auto&& vsi : ref.second.exacts)
- {
- add_feature_to(ref, vsi.second, feature);
- }
- }
- (void)origin;
- }
-
- std::pair<const PackageSpec, VersionedPackageGraph::PackageNode>& VersionedPackageGraph::emplace_package(
- const PackageSpec& spec)
- {
- return *m_graph.emplace(spec, PackageNode{}).first;
- }
-
- Optional<Versions::Version> VersionedPackageGraph::dep_to_version(const std::string& name,
- const DependencyConstraint& dc)
- {
- auto maybe_overlay = m_o_provider.get_control_file(name);
- if (auto p_overlay = maybe_overlay.get())
- {
- return to_version(*p_overlay->source_control_file);
- }
-
- auto over_it = m_overrides.find(name);
- if (over_it != m_overrides.end())
- {
- return over_it->second;
- }
-
- auto maybe_cons = to_version(dc);
- if (maybe_cons)
- {
- return maybe_cons;
- }
- else
- {
- return m_base_provider.get_baseline_version(name);
- }
- }
-
- void VersionedPackageGraph::add_override(const std::string& name, const Versions::Version& v)
- {
- m_overrides.emplace(name, v);
- }
-
- void VersionedPackageGraph::add_roots(View<Dependency> deps, const PackageSpec& toplevel)
- {
- auto specs = Util::fmap(deps, [&toplevel](const Dependency& d) {
- return PackageSpec{d.name, toplevel.triplet()};
- });
- specs.push_back(toplevel);
- Util::sort_unique_erase(specs);
- m_var_provider.load_dep_info_vars(specs);
- const auto& vars = m_var_provider.get_dep_info_vars(toplevel).value_or_exit(VCPKG_LINE_INFO);
- std::vector<const Dependency*> active_deps;
-
- for (auto&& dep : deps)
- {
- PackageSpec spec(dep.name, toplevel.triplet());
- if (!dep.platform.evaluate(vars)) continue;
-
- active_deps.push_back(&dep);
-
- // Disable default features for deps with [core] as a dependency
- // Note: x[core], x[y] will still eventually depend on defaults due to the second x[y]
- if (Util::find(dep.features, "core") != dep.features.end())
- {
- auto& node = emplace_package(spec);
- node.second.default_features = false;
- }
- }
-
- for (auto pdep : active_deps)
- {
- const auto& dep = *pdep;
- PackageSpec spec(dep.name, toplevel.triplet());
-
- auto& node = emplace_package(spec);
-
- auto maybe_overlay = m_o_provider.get_control_file(dep.name);
- if (auto p_overlay = maybe_overlay.get())
- {
- auto ver = to_version(*p_overlay->source_control_file);
- m_roots.push_back(DepSpec{spec, ver, dep.features});
- add_constraint(node, ver, toplevel.name());
- continue;
- }
-
- auto over_it = m_overrides.find(dep.name);
- if (over_it != m_overrides.end())
- {
- m_roots.push_back(DepSpec{spec, over_it->second, dep.features});
- add_constraint(node, over_it->second, toplevel.name());
- continue;
- }
-
- auto dep_ver = to_version(dep.constraint);
- auto base_ver = m_base_provider.get_baseline_version(dep.name);
- if (auto p_dep_ver = dep_ver.get())
- {
- m_roots.push_back(DepSpec{spec, *p_dep_ver, dep.features});
- if (auto p_base_ver = base_ver.get())
- {
- // Compare version constraint with baseline to only evaluate the "tighter" constraint
- auto dep_scfl = m_ver_provider.get_control_file({dep.name, *p_dep_ver});
- auto base_scfl = m_ver_provider.get_control_file({dep.name, *p_base_ver});
- if (dep_scfl && base_scfl)
- {
- auto r =
- compare_versions(dep_scfl.get()->source_control_file->core_paragraph->version_scheme,
- *p_dep_ver,
- base_scfl.get()->source_control_file->core_paragraph->version_scheme,
- *p_base_ver);
- if (r == VerComp::lt)
- {
- add_constraint(node, *p_base_ver, "baseline");
- add_constraint(node, *p_dep_ver, toplevel.name());
- }
- else
- {
- add_constraint(node, *p_dep_ver, toplevel.name());
- add_constraint(node, *p_base_ver, "baseline");
- }
- }
- else
- {
- if (!dep_scfl) m_errors.push_back(dep_scfl.error());
- if (!base_scfl) m_errors.push_back(base_scfl.error());
- }
- }
- else
- {
- add_constraint(node, *p_dep_ver, toplevel.name());
- }
- }
- else if (auto p_base_ver = base_ver.get())
- {
- m_roots.push_back(DepSpec{spec, *p_base_ver, dep.features});
- add_constraint(node, *p_base_ver, toplevel.name());
- }
- else
- {
- m_errors.push_back(Strings::concat("Cannot resolve unversioned dependency from top-level to ",
- dep.name,
- " without a baseline entry or override."));
- }
-
- for (auto&& f : dep.features)
- {
- add_constraint(node, f, toplevel.name());
- }
- if (Util::find(dep.features, "core") == dep.features.end())
- {
- add_constraint_default_features(node, toplevel.name());
- }
- }
- }
-
- ExpectedS<ActionPlan> VersionedPackageGraph::finalize_extract_plan()
- {
- if (m_errors.size() > 0)
- {
- return Strings::join("\n", m_errors);
- }
-
- ActionPlan ret;
-
- // second == nullptr means "in progress"
- std::map<PackageSpec, VersionSchemeInfo*> emitted;
- struct Frame
- {
- InstallPlanAction ipa;
- std::vector<DepSpec> deps;
- };
- std::vector<Frame> stack;
-
- auto push = [&emitted, this, &stack](const PackageSpec& spec,
- const Versions::Version& new_ver) -> Optional<std::string> {
- auto&& node = m_graph[spec];
- auto overlay = m_o_provider.get_control_file(spec.name());
- auto over_it = m_overrides.find(spec.name());
-
- VersionedPackageGraph::VersionSchemeInfo* p_vnode;
- if (auto p_overlay = overlay.get())
- p_vnode = node.get_node(to_version(*p_overlay->source_control_file));
- else if (over_it != m_overrides.end())
- p_vnode = node.get_node(over_it->second);
- else
- p_vnode = node.get_node(new_ver);
-
- if (!p_vnode) return Strings::concat("Version was not found during discovery: ", spec, "@", new_ver);
-
- auto p = emitted.emplace(spec, nullptr);
- if (p.second)
- {
- // Newly inserted
- if (!overlay && over_it == m_overrides.end())
- {
- // Not overridden -- Compare against baseline
- if (auto baseline = m_base_provider.get_baseline_version(spec.name()))
- {
- if (auto base_node = node.get_node(*baseline.get()))
- {
- if (base_node != p_vnode)
- {
- return Strings::concat("Version conflict on ",
- spec.name(),
- "@",
- new_ver,
- ": baseline required ",
- *baseline.get());
- }
- }
- }
- }
-
- // -> Add stack frame
- auto maybe_vars = m_var_provider.get_dep_info_vars(spec);
-
- InstallPlanAction ipa(spec, *p_vnode->scfl, RequestType::USER_REQUESTED, std::move(p_vnode->deps));
- std::vector<DepSpec> deps;
- for (auto&& f : ipa.feature_list)
- {
- if (auto maybe_deps =
- p_vnode->scfl->source_control_file->find_dependencies_for_feature(f).get())
- {
- for (auto&& dep : *maybe_deps)
- {
- if (dep.name == spec.name()) continue;
-
- if (!dep.platform.is_empty() &&
- !dep.platform.evaluate(maybe_vars.value_or_exit(VCPKG_LINE_INFO)))
- {
- continue;
- }
- auto maybe_cons = dep_to_version(dep.name, dep.constraint);
-
- if (auto cons = maybe_cons.get())
- {
- deps.emplace_back(DepSpec{{dep.name, spec.triplet()}, std::move(*cons)});
- }
- else
- {
- return Strings::concat("Cannot resolve unconstrained dependency from ",
- spec.name(),
- " to ",
- dep.name,
- " without a baseline entry or override.");
- }
- }
- }
- }
- stack.push_back(Frame{std::move(ipa), std::move(deps)});
- return nullopt;
- }
- else
- {
- // spec already present in map
- if (p.first->second == nullptr)
- {
- return Strings::concat(
- "Cycle detected during ",
- spec,
- ":\n",
- Strings::join("\n", stack, [](const auto& p) -> const PackageSpec& { return p.ipa.spec; }));
- }
- else if (p.first->second != p_vnode)
- {
- // comparable versions should retrieve the same info node
- return Strings::concat(
- "Version conflict on ", spec.name(), "@", p.first->second->version, ": required ", new_ver);
- }
- return nullopt;
- }
- };
-
- for (auto&& root : m_roots)
- {
- if (auto err = push(root.spec, root.ver))
- {
- return std::move(*err.get());
- }
-
- while (stack.size() > 0)
- {
- auto& back = stack.back();
- if (back.deps.empty())
- {
- emitted[back.ipa.spec] = m_graph[back.ipa.spec].get_node(
- to_version(*back.ipa.source_control_file_location.get()->source_control_file));
- ret.install_actions.push_back(std::move(back.ipa));
- stack.pop_back();
- }
- else
- {
- auto dep = std::move(back.deps.back());
- back.deps.pop_back();
- if (auto err = push(dep.spec, dep.ver))
- {
- return std::move(*err.get());
- }
- }
- }
- }
- return ret;
- }
- }
-
- ExpectedS<ActionPlan> create_versioned_install_plan(const PortFileProvider::IVersionedPortfileProvider& provider,
- const PortFileProvider::IBaselineProvider& bprovider,
- const PortFileProvider::IOverlayProvider& oprovider,
- const CMakeVars::CMakeVarProvider& var_provider,
- const std::vector<Dependency>& deps,
- const std::vector<DependencyOverride>& overrides,
- const PackageSpec& toplevel)
- {
- VersionedPackageGraph vpg(provider, bprovider, oprovider, var_provider);
- for (auto&& o : overrides)
- vpg.add_override(o.name, {o.version, o.port_version});
- vpg.add_roots(deps, toplevel);
- return vpg.finalize_extract_plan();
- }
-}
diff --git a/toolsrc/src/vcpkg/export.chocolatey.cpp b/toolsrc/src/vcpkg/export.chocolatey.cpp
deleted file mode 100644
index 875982ed6..000000000
--- a/toolsrc/src/vcpkg/export.chocolatey.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/export.chocolatey.h>
-#include <vcpkg/export.h>
-#include <vcpkg/install.h>
-#include <vcpkg/tools.h>
-
-namespace vcpkg::Export::Chocolatey
-{
- using Dependencies::ExportPlanAction;
- using Dependencies::ExportPlanType;
- using Install::InstallDir;
-
- static std::string create_nuspec_dependencies(const BinaryParagraph& binary_paragraph,
- const std::map<std::string, std::string>& packages_version)
- {
- static constexpr auto CONTENT_TEMPLATE = R"(<dependency id="@PACKAGE_ID@" version="[@PACKAGE_VERSION@]" />)";
-
- std::string nuspec_dependencies;
- for (const std::string& depend : binary_paragraph.dependencies)
- {
- auto found = packages_version.find(depend);
- if (found == packages_version.end())
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot find desired dependency version.");
- }
-
- std::string nuspec_dependency = Strings::replace_all(CONTENT_TEMPLATE, "@PACKAGE_ID@", depend);
- Strings::inplace_replace_all(nuspec_dependency, "@PACKAGE_VERSION@", found->second);
- nuspec_dependencies += nuspec_dependency;
- }
- return nuspec_dependencies;
- }
-
- static std::string create_nuspec_file_contents(const std::string& exported_root_dir,
- const BinaryParagraph& binary_paragraph,
- const std::map<std::string, std::string>& packages_version,
- const Options& chocolatey_options)
- {
- static constexpr auto CONTENT_TEMPLATE = R"(<?xml version="1.0" encoding="utf-8"?>
-<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
- <metadata>
- <id>@PACKAGE_ID@</id>
- <version>@PACKAGE_VERSION@</version>
- <authors>@PACKAGE_MAINTAINER@</authors>
- <description><![CDATA[
- @PACKAGE_DESCRIPTION@
- ]]></description>
- <dependencies>
- @PACKAGE_DEPENDENCIES@
- </dependencies>
- </metadata>
- <files>
- <file src="@EXPORTED_ROOT_DIR@\installed\**" target="installed" />
- <file src="@EXPORTED_ROOT_DIR@\tools\**" target="tools" />
- </files>
-</package>
-)";
- auto package_version = packages_version.find(binary_paragraph.spec.name());
- if (package_version == packages_version.end())
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot find desired package version.");
- }
-
- std::string nuspec_file_content =
- Strings::replace_all(CONTENT_TEMPLATE, "@PACKAGE_ID@", binary_paragraph.spec.name());
- Strings::inplace_replace_all(nuspec_file_content, "@PACKAGE_VERSION@", package_version->second);
- Strings::inplace_replace_all(
- nuspec_file_content, "@PACKAGE_MAINTAINER@", chocolatey_options.maybe_maintainer.value_or(""));
- Strings::inplace_replace_all(
- nuspec_file_content, "@PACKAGE_DESCRIPTION@", Strings::join("\n", binary_paragraph.description));
- Strings::inplace_replace_all(nuspec_file_content, "@EXPORTED_ROOT_DIR@", exported_root_dir);
- Strings::inplace_replace_all(nuspec_file_content,
- "@PACKAGE_DEPENDENCIES@",
- create_nuspec_dependencies(binary_paragraph, packages_version));
- return nuspec_file_content;
- }
-
- static std::string create_chocolatey_install_contents()
- {
- static constexpr auto CONTENT_TEMPLATE = R"###(
-$ErrorActionPreference = 'Stop';
-
-$packageName= $env:ChocolateyPackageName
-$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
-$rootDir = "$(Split-Path -parent $toolsDir)"
-$installedDir = Join-Path $rootDir 'installed'
-
-$whereToInstall = (pwd).path
-$whereToInstallCache = Join-Path $rootDir 'install.txt'
-Set-Content -Path $whereToInstallCache -Value $whereToInstall
-Copy-Item $installedDir -destination $whereToInstall -recurse -force
-)###";
- return CONTENT_TEMPLATE;
- }
-
- static std::string create_chocolatey_uninstall_contents(const BinaryParagraph& binary_paragraph)
- {
- static constexpr auto CONTENT_TEMPLATE = R"###(
-$ErrorActionPreference = 'Stop';
-
-$packageName= $env:ChocolateyPackageName
-$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
-$rootDir = "$(Split-Path -parent $toolsDir)"
-$listFile = Join-Path $rootDir 'installed\vcpkg\info\@PACKAGE_FULLSTEM@.list'
-
-$whereToInstall = $null
-$whereToInstallCache = Join-Path $rootDir 'install.txt'
-Get-Content $whereToInstallCache | Foreach-Object {
- $whereToInstall = $_
-}
-
-$installedDir = Join-Path $whereToInstall 'installed'
-Get-Content $listFile | Foreach-Object {
- $fileToRemove = Join-Path $installedDir $_
- if (Test-Path $fileToRemove -PathType Leaf) {
- Remove-Item $fileToRemove
- }
-}
-
-Get-Content $listFile | Foreach-Object {
- $fileToRemove = Join-Path $installedDir $_
- if (Test-Path $fileToRemove -PathType Container) {
- $folderToDelete = Join-Path $fileToRemove *
- if (-Not (Test-Path $folderToDelete))
- {
- Remove-Item $fileToRemove
- }
- }
-}
-
-$listFileToRemove = Join-Path $whereToInstall 'installed\vcpkg\info\@PACKAGE_FULLSTEM@.list'
-Remove-Item $listFileToRemove
-
-if (Test-Path $installedDir)
-{
- while (
- $empties = Get-ChildItem $installedDir -recurse -Directory | Where-Object {
- $_.GetFiles().Count -eq 0 -and $_.GetDirectories().Count -eq 0
- }
- ) { $empties | Remove-Item }
-}
-)###";
- std::string chocolatey_uninstall_content =
- Strings::replace_all(CONTENT_TEMPLATE, "@PACKAGE_FULLSTEM@", binary_paragraph.fullstem());
- return chocolatey_uninstall_content;
- }
-
- void do_export(const std::vector<ExportPlanAction>& export_plan,
- const VcpkgPaths& paths,
- const Options& chocolatey_options)
- {
- Checks::check_exit(
- VCPKG_LINE_INFO, chocolatey_options.maybe_maintainer.has_value(), "--x-maintainer option is required.");
-
- Files::Filesystem& fs = paths.get_filesystem();
- const fs::path vcpkg_root_path = paths.root;
- const fs::path raw_exported_dir_path = vcpkg_root_path / "chocolatey";
- const fs::path exported_dir_path = vcpkg_root_path / "chocolatey_exports";
- const fs::path& nuget_exe = paths.get_tool_exe(Tools::NUGET);
-
- std::error_code ec;
- fs.remove_all(raw_exported_dir_path, VCPKG_LINE_INFO);
- fs.create_directory(raw_exported_dir_path, ec);
- fs.remove_all(exported_dir_path, VCPKG_LINE_INFO);
- fs.create_directory(exported_dir_path, ec);
-
- // execute the plan
- std::map<std::string, std::string> packages_version;
- for (const ExportPlanAction& action : export_plan)
- {
- if (action.plan_type != ExportPlanType::ALREADY_BUILT)
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
- auto norm_version = binary_paragraph.version;
-
- // normalize the version string to be separated by dots to be compliant with Nuspec.
- Strings::inplace_replace_all(norm_version, '-', '.');
- Strings::inplace_replace_all(norm_version, '_', '.');
- norm_version += chocolatey_options.maybe_version_suffix.value_or("");
- packages_version.insert(std::make_pair(binary_paragraph.spec.name(), norm_version));
- }
-
- for (const ExportPlanAction& action : export_plan)
- {
- const std::string display_name = action.spec.to_string();
- System::print2("Exporting package ", display_name, "...\n");
-
- const fs::path per_package_dir_path = raw_exported_dir_path / action.spec.name();
-
- const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
-
- const InstallDir dirs = InstallDir::from_destination_root(
- per_package_dir_path / "installed",
- action.spec.triplet().to_string(),
- per_package_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list"));
-
- Install::install_package_and_write_listfile(paths, action.spec, dirs);
-
- const std::string nuspec_file_content = create_nuspec_file_contents(
- per_package_dir_path.string(), binary_paragraph, packages_version, chocolatey_options);
- const fs::path nuspec_file_path =
- per_package_dir_path / Strings::concat(binary_paragraph.spec.name(), ".nuspec");
- fs.write_contents(nuspec_file_path, nuspec_file_content, VCPKG_LINE_INFO);
-
- fs.create_directory(per_package_dir_path / "tools", ec);
-
- const std::string chocolatey_install_content = create_chocolatey_install_contents();
- const fs::path chocolatey_install_file_path = per_package_dir_path / "tools" / "chocolateyInstall.ps1";
- fs.write_contents(chocolatey_install_file_path, chocolatey_install_content, VCPKG_LINE_INFO);
-
- const std::string chocolatey_uninstall_content = create_chocolatey_uninstall_contents(binary_paragraph);
- const fs::path chocolatey_uninstall_file_path = per_package_dir_path / "tools" / "chocolateyUninstall.ps1";
- fs.write_contents(chocolatey_uninstall_file_path, chocolatey_uninstall_content, VCPKG_LINE_INFO);
-
- auto cmd_line = System::Command(nuget_exe)
- .string_arg("pack")
- .string_arg("-OutputDirectory")
- .path_arg(exported_dir_path)
- .path_arg(nuspec_file_path)
- .string_arg("-NoDefaultExcludes");
-
- const int exit_code =
- System::cmd_execute_and_capture_output(cmd_line, System::get_clean_environment()).exit_code;
- Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed");
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
deleted file mode 100644
index 1f202a9d5..000000000
--- a/toolsrc/src/vcpkg/export.cpp
+++ /dev/null
@@ -1,707 +0,0 @@
-#include <vcpkg/base/stringliteral.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-#include <vcpkg/base/xmlserializer.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/export.chocolatey.h>
-#include <vcpkg/export.h>
-#include <vcpkg/export.ifw.h>
-#include <vcpkg/export.prefab.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Export
-{
- using Dependencies::ExportPlanAction;
- using Dependencies::ExportPlanType;
- using Dependencies::RequestType;
- using Install::InstallDir;
-
- static std::string create_nuspec_file_contents(const std::string& raw_exported_dir,
- const fs::path& targets_redirect_path,
- const fs::path& props_redirect_path,
- const std::string& nuget_id,
- const std::string& nupkg_version,
- const std::string& nuget_description)
- {
- XmlSerializer xml;
- xml.open_tag("package").line_break();
- xml.open_tag("metadata").line_break();
- xml.simple_tag("id", nuget_id).line_break();
- xml.simple_tag("version", nupkg_version).line_break();
- xml.simple_tag("authors", "vcpkg").line_break();
- xml.simple_tag("description", nuget_description).line_break();
- xml.close_tag("metadata").line_break();
- xml.open_tag("files").line_break();
- xml.start_complex_open_tag("file")
- .text_attr("src", raw_exported_dir + "\\installed\\**")
- .text_attr("target", "installed")
- .finish_self_closing_complex_tag();
-
- xml.start_complex_open_tag("file")
- .text_attr("src", raw_exported_dir + "\\scripts\\**")
- .text_attr("target", "scripts")
- .finish_self_closing_complex_tag();
-
- xml.start_complex_open_tag("file")
- .text_attr("src", raw_exported_dir + "\\.vcpkg-root")
- .text_attr("target", "")
- .finish_self_closing_complex_tag();
-
- xml.start_complex_open_tag("file")
- .text_attr("src", fs::u8string(targets_redirect_path))
- .text_attr("target", Strings::concat("build\\native\\", nuget_id, ".targets"))
- .finish_self_closing_complex_tag();
-
- xml.start_complex_open_tag("file")
- .text_attr("src", fs::u8string(props_redirect_path))
- .text_attr("target", Strings::concat("build\\native\\", nuget_id, ".props"))
- .finish_self_closing_complex_tag();
-
- xml.close_tag("files").line_break();
- xml.close_tag("package").line_break();
-
- return std::move(xml.buf);
- }
-
- static std::string create_targets_redirect(const std::string& target_path) noexcept
- {
- return Strings::format(R"###(
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Condition="Exists('%s')" Project="%s" />
-</Project>
-)###",
- target_path,
- target_path);
- }
-
- static void print_plan(const std::map<ExportPlanType, std::vector<const ExportPlanAction*>>& group_by_plan_type)
- {
- static constexpr std::array<ExportPlanType, 2> ORDER = {ExportPlanType::ALREADY_BUILT,
- ExportPlanType::NOT_BUILT};
- for (const ExportPlanType plan_type : ORDER)
- {
- const auto it = group_by_plan_type.find(plan_type);
- if (it == group_by_plan_type.cend())
- {
- continue;
- }
-
- std::vector<const ExportPlanAction*> cont = it->second;
- std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name);
- const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) {
- return Dependencies::to_output_string(
- p->request_type, p->spec.to_string(), vcpkg::Build::default_build_package_options);
- });
-
- switch (plan_type)
- {
- case ExportPlanType::ALREADY_BUILT:
- System::print2("The following packages are already built and will be exported:\n", as_string, '\n');
- continue;
- case ExportPlanType::NOT_BUILT:
- System::print2("The following packages need to be built:\n", as_string, '\n');
- continue;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- }
-
- static std::string create_export_id()
- {
- const tm date_time = Chrono::get_current_date_time_local();
-
- // Format is: YYYYmmdd-HHMMSS
- // 15 characters + 1 null terminating character will be written for a total of 16 chars
- char mbstr[16];
- const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y%m%d-%H%M%S", &date_time);
- Checks::check_exit(VCPKG_LINE_INFO,
- bytes_written == 15,
- "Expected 15 bytes to be written, but %u were written",
- bytes_written);
- const std::string date_time_as_string(mbstr);
- return ("vcpkg-export-" + date_time_as_string);
- }
-
- static fs::path do_nuget_export(const VcpkgPaths& paths,
- const std::string& nuget_id,
- const std::string& nuget_version,
- const std::string& nuget_description,
- const fs::path& raw_exported_dir,
- const fs::path& output_dir)
- {
- Files::Filesystem& fs = paths.get_filesystem();
- const fs::path& nuget_exe = paths.get_tool_exe(Tools::NUGET);
-
- std::error_code ec;
- fs.create_directories(paths.buildsystems / "tmp", ec);
-
- // This file will be placed in "build\native" in the nuget package. Therefore, go up two dirs.
- const std::string targets_redirect_content =
- create_targets_redirect("$(MSBuildThisFileDirectory)../../scripts/buildsystems/msbuild/vcpkg.targets");
- const fs::path targets_redirect = paths.buildsystems / "tmp" / "vcpkg.export.nuget.targets";
- fs.write_contents(targets_redirect, targets_redirect_content, VCPKG_LINE_INFO);
-
- // This file will be placed in "build\native" in the nuget package. Therefore, go up two dirs.
- const std::string props_redirect_content =
- create_targets_redirect("$(MSBuildThisFileDirectory)../../scripts/buildsystems/msbuild/vcpkg.props");
- const fs::path props_redirect = paths.buildsystems / "tmp" / "vcpkg.export.nuget.props";
- fs.write_contents(props_redirect, props_redirect_content, VCPKG_LINE_INFO);
-
- const std::string nuspec_file_content = create_nuspec_file_contents(
- raw_exported_dir.string(), targets_redirect, props_redirect, nuget_id, nuget_version, nuget_description);
- const fs::path nuspec_file_path = paths.buildsystems / "tmp" / "vcpkg.export.nuspec";
- fs.write_contents(nuspec_file_path, nuspec_file_content, VCPKG_LINE_INFO);
-
- // -NoDefaultExcludes is needed for ".vcpkg-root"
- System::Command cmd;
-#ifndef _WIN32
- cmd.path_arg(paths.get_tool_exe(Tools::MONO));
-#endif
- cmd.path_arg(nuget_exe)
- .string_arg("pack")
- .path_arg(nuspec_file_path)
- .string_arg("-OutputDirectory")
- .path_arg(output_dir)
- .string_arg("-NoDefaultExcludes");
-
- const int exit_code = System::cmd_execute_and_capture_output(cmd, System::get_clean_environment()).exit_code;
- Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed");
-
- const fs::path output_path = output_dir / (nuget_id + "." + nuget_version + ".nupkg");
- return output_path;
- }
-
- struct ArchiveFormat final
- {
- enum class BackingEnum
- {
- ZIP = 1,
- SEVEN_ZIP,
- };
-
- constexpr ArchiveFormat() = delete;
-
- constexpr ArchiveFormat(BackingEnum backing_enum, const char* extension, const char* cmake_option)
- : backing_enum(backing_enum), m_extension(extension), m_cmake_option(cmake_option)
- {
- }
-
- constexpr operator BackingEnum() const { return backing_enum; }
- constexpr CStringView extension() const { return this->m_extension; }
- constexpr CStringView cmake_option() const { return this->m_cmake_option; }
-
- private:
- BackingEnum backing_enum;
- const char* m_extension;
- const char* m_cmake_option;
- };
-
- namespace ArchiveFormatC
- {
- constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, "zip", "zip");
- constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, "7z", "7zip");
- }
-
- static fs::path do_archive_export(const VcpkgPaths& paths,
- const fs::path& raw_exported_dir,
- const fs::path& output_dir,
- const ArchiveFormat& format)
- {
- const fs::path& cmake_exe = paths.get_tool_exe(Tools::CMAKE);
-
- const std::string exported_dir_filename = fs::u8string(raw_exported_dir.filename());
- const std::string exported_archive_filename =
- Strings::format("%s.%s", exported_dir_filename, format.extension());
- const fs::path exported_archive_path = (output_dir / exported_archive_filename);
-
- System::Command cmd;
- cmd.path_arg(cmake_exe)
- .string_arg("-E")
- .string_arg("tar")
- .string_arg("cf")
- .path_arg(exported_archive_path)
- .string_arg(Strings::concat("--format=", format.cmake_option()))
- .string_arg("--")
- .path_arg(raw_exported_dir);
-
- const int exit_code =
- System::cmd_execute_clean(cmd, System::InWorkingDirectory{raw_exported_dir.parent_path()});
- Checks::check_exit(
- VCPKG_LINE_INFO, exit_code == 0, "Error: %s creation failed", exported_archive_path.generic_string());
- return exported_archive_path;
- }
-
- static Optional<std::string> maybe_lookup(std::unordered_map<std::string, std::string> const& m,
- std::string const& key)
- {
- const auto it = m.find(key);
- if (it != m.end()) return it->second;
- return nullopt;
- }
-
- void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths)
- {
- const std::vector<fs::path> integration_files_relative_to_root = {
- {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"},
- {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"},
- {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.props"},
- {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg-general.xml"},
- {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"},
- {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"},
- };
-
- Files::Filesystem& fs = paths.get_filesystem();
- for (const fs::path& file : integration_files_relative_to_root)
- {
- const fs::path source = paths.root / file;
- fs::path destination = raw_exported_dir_path / file;
- fs.create_directories(destination.parent_path(), ignore_errors);
- fs.copy_file(source, destination, fs::copy_options::overwrite_existing, VCPKG_LINE_INFO);
- }
- fs.write_contents(raw_exported_dir_path / fs::u8path(".vcpkg-root"), "", VCPKG_LINE_INFO);
- }
-
- struct ExportArguments
- {
- bool dry_run = false;
- bool raw = false;
- bool nuget = false;
- bool ifw = false;
- bool zip = false;
- bool seven_zip = false;
- bool chocolatey = false;
- bool prefab = false;
- bool all_installed = false;
-
- Optional<std::string> maybe_output;
- fs::path output_dir;
-
- Optional<std::string> maybe_nuget_id;
- Optional<std::string> maybe_nuget_version;
- Optional<std::string> maybe_nuget_description;
-
- IFW::Options ifw_options;
- Prefab::Options prefab_options;
- Chocolatey::Options chocolatey_options;
- std::vector<PackageSpec> specs;
- };
-
- static constexpr StringLiteral OPTION_OUTPUT = "output";
- static constexpr StringLiteral OPTION_OUTPUT_DIR = "output-dir";
- static constexpr StringLiteral OPTION_DRY_RUN = "dry-run";
- static constexpr StringLiteral OPTION_RAW = "raw";
- static constexpr StringLiteral OPTION_NUGET = "nuget";
- static constexpr StringLiteral OPTION_IFW = "ifw";
- static constexpr StringLiteral OPTION_ZIP = "zip";
- static constexpr StringLiteral OPTION_SEVEN_ZIP = "7zip";
- static constexpr StringLiteral OPTION_NUGET_ID = "nuget-id";
- static constexpr StringLiteral OPTION_NUGET_DESCRIPTION = "nuget-description";
- static constexpr StringLiteral OPTION_NUGET_VERSION = "nuget-version";
- static constexpr StringLiteral OPTION_IFW_REPOSITORY_URL = "ifw-repository-url";
- static constexpr StringLiteral OPTION_IFW_PACKAGES_DIR_PATH = "ifw-packages-directory-path";
- static constexpr StringLiteral OPTION_IFW_REPOSITORY_DIR_PATH = "ifw-repository-directory-path";
- static constexpr StringLiteral OPTION_IFW_CONFIG_FILE_PATH = "ifw-configuration-file-path";
- static constexpr StringLiteral OPTION_IFW_INSTALLER_FILE_PATH = "ifw-installer-file-path";
- static constexpr StringLiteral OPTION_CHOCOLATEY = "x-chocolatey";
- static constexpr StringLiteral OPTION_CHOCOLATEY_MAINTAINER = "x-maintainer";
- static constexpr StringLiteral OPTION_CHOCOLATEY_VERSION_SUFFIX = "x-version-suffix";
- static constexpr StringLiteral OPTION_ALL_INSTALLED = "x-all-installed";
-
- static constexpr StringLiteral OPTION_PREFAB = "prefab";
- static constexpr StringLiteral OPTION_PREFAB_GROUP_ID = "prefab-group-id";
- static constexpr StringLiteral OPTION_PREFAB_ARTIFACT_ID = "prefab-artifact-id";
- static constexpr StringLiteral OPTION_PREFAB_VERSION = "prefab-version";
- static constexpr StringLiteral OPTION_PREFAB_SDK_MIN_VERSION = "prefab-min-sdk";
- static constexpr StringLiteral OPTION_PREFAB_SDK_TARGET_VERSION = "prefab-target-sdk";
- static constexpr StringLiteral OPTION_PREFAB_ENABLE_MAVEN = "prefab-maven";
- static constexpr StringLiteral OPTION_PREFAB_ENABLE_DEBUG = "prefab-debug";
-
- static constexpr std::array<CommandSwitch, 11> EXPORT_SWITCHES = {{
- {OPTION_DRY_RUN, "Do not actually export"},
- {OPTION_RAW, "Export to an uncompressed directory"},
- {OPTION_NUGET, "Export a NuGet package"},
- {OPTION_IFW, "Export to an IFW-based installer"},
- {OPTION_ZIP, "Export to a zip file"},
- {OPTION_SEVEN_ZIP, "Export to a 7zip (.7z) file"},
- {OPTION_CHOCOLATEY, "Export a Chocolatey package (experimental feature)"},
- {OPTION_PREFAB, "Export to Prefab format"},
- {OPTION_PREFAB_ENABLE_MAVEN, "Enable maven"},
- {OPTION_PREFAB_ENABLE_DEBUG, "Enable prefab debug"},
- {OPTION_ALL_INSTALLED, "Export all installed packages"},
- }};
-
- static constexpr std::array<CommandSetting, 17> EXPORT_SETTINGS = {{
- {OPTION_OUTPUT, "Specify the output name (used to construct filename)"},
- {OPTION_OUTPUT_DIR, "Specify the output directory for produced artifacts"},
- {OPTION_NUGET_ID, "Specify the id for the exported NuGet package (overrides --output)"},
- {OPTION_NUGET_DESCRIPTION, "Specify a description for the exported NuGet package"},
- {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"},
- {OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"},
- {OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"},
- {OPTION_IFW_REPOSITORY_DIR_PATH, "Specify the directory path for the exported repository"},
- {OPTION_IFW_CONFIG_FILE_PATH, "Specify the temporary file path for the installer configuration"},
- {OPTION_IFW_INSTALLER_FILE_PATH, "Specify the file path for the exported installer"},
- {OPTION_CHOCOLATEY_MAINTAINER,
- "Specify the maintainer for the exported Chocolatey package (experimental feature)"},
- {OPTION_CHOCOLATEY_VERSION_SUFFIX,
- "Specify the version suffix to add for the exported Chocolatey package (experimental feature)"},
- {OPTION_PREFAB_GROUP_ID, "GroupId uniquely identifies your project according maven specifications"},
- {OPTION_PREFAB_ARTIFACT_ID, "Artifact Id is the name of the project according maven specifications"},
- {OPTION_PREFAB_VERSION, "Version is the name of the project according maven specifications"},
- {OPTION_PREFAB_SDK_MIN_VERSION, "Android minimum supported sdk version"},
- {OPTION_PREFAB_SDK_TARGET_VERSION, "Android target sdk version"},
- }};
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("export zlib zlib:x64-windows boost --nuget"),
- 0,
- SIZE_MAX,
- {EXPORT_SWITCHES, EXPORT_SETTINGS},
- nullptr,
- };
-
- static ExportArguments handle_export_command_arguments(const VcpkgPaths& paths,
- const VcpkgCmdArguments& args,
- Triplet default_triplet,
- const StatusParagraphs& status_db)
- {
- ExportArguments ret;
-
- const auto options = args.parse_arguments(COMMAND_STRUCTURE);
-
- ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend();
- ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend();
- ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend();
- ret.ifw = options.switches.find(OPTION_IFW) != options.switches.cend();
- ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend();
- ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend();
- ret.chocolatey = options.switches.find(OPTION_CHOCOLATEY) != options.switches.cend();
- ret.prefab = options.switches.find(OPTION_PREFAB) != options.switches.cend();
- ret.prefab_options.enable_maven = options.switches.find(OPTION_PREFAB_ENABLE_MAVEN) != options.switches.cend();
- ret.prefab_options.enable_debug = options.switches.find(OPTION_PREFAB_ENABLE_DEBUG) != options.switches.cend();
- ret.maybe_output = maybe_lookup(options.settings, OPTION_OUTPUT);
- auto maybe_output_dir = maybe_lookup(options.settings, OPTION_OUTPUT_DIR);
- if (auto output_dir = maybe_output_dir.get())
- {
- ret.output_dir = Files::combine(paths.original_cwd, fs::u8path(*output_dir));
- }
- else
- {
- ret.output_dir = paths.root;
- }
- ret.all_installed = options.switches.find(OPTION_ALL_INSTALLED) != options.switches.end();
-
- if (ret.all_installed)
- {
- auto installed_ipv = get_installed_ports(status_db);
- std::transform(installed_ipv.begin(),
- installed_ipv.end(),
- std::back_inserter(ret.specs),
- [](const auto& ipv) { return ipv.spec(); });
- }
- else
- {
- // input sanitization
- ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(
- std::string(arg), default_triplet, COMMAND_STRUCTURE.example_text);
- });
- }
-
- if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run && !ret.chocolatey &&
- !ret.prefab)
- {
- System::print2(
- System::Color::error,
- "Must provide at least one export type: --raw --nuget --ifw --zip --7zip --chocolatey --prefab\n");
- System::print2(COMMAND_STRUCTURE.example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- struct OptionPair
- {
- const StringLiteral& name;
- Optional<std::string>& out_opt;
- };
- const auto options_implies = [&](const StringLiteral& main_opt_name,
- bool is_main_opt,
- const std::initializer_list<OptionPair>& implying_opts) {
- if (is_main_opt)
- {
- for (auto&& opt : implying_opts)
- opt.out_opt = maybe_lookup(options.settings, opt.name);
- }
- else
- {
- for (auto&& opt : implying_opts)
- Checks::check_exit(VCPKG_LINE_INFO,
- !maybe_lookup(options.settings, opt.name),
- "%s is only valid with %s",
- opt.name,
- main_opt_name);
- }
- };
-
-#if defined(_MSC_VER) && _MSC_VER <= 1900
-// there's a bug in VS 2015 that causes a bunch of "unreferenced local variable" warnings
-#pragma warning(push)
-#pragma warning(disable : 4189)
-#endif
-
- options_implies(OPTION_NUGET,
- ret.nuget,
- {
- {OPTION_NUGET_ID, ret.maybe_nuget_id},
- {OPTION_NUGET_VERSION, ret.maybe_nuget_version},
- {OPTION_NUGET_DESCRIPTION, ret.maybe_nuget_description},
- });
-
- options_implies(OPTION_IFW,
- ret.ifw,
- {
- {OPTION_IFW_REPOSITORY_URL, ret.ifw_options.maybe_repository_url},
- {OPTION_IFW_PACKAGES_DIR_PATH, ret.ifw_options.maybe_packages_dir_path},
- {OPTION_IFW_REPOSITORY_DIR_PATH, ret.ifw_options.maybe_repository_dir_path},
- {OPTION_IFW_CONFIG_FILE_PATH, ret.ifw_options.maybe_config_file_path},
- {OPTION_IFW_INSTALLER_FILE_PATH, ret.ifw_options.maybe_installer_file_path},
- });
-
- options_implies(OPTION_PREFAB,
- ret.prefab,
- {
- {OPTION_PREFAB_ARTIFACT_ID, ret.prefab_options.maybe_artifact_id},
- {OPTION_PREFAB_GROUP_ID, ret.prefab_options.maybe_group_id},
- {OPTION_PREFAB_SDK_MIN_VERSION, ret.prefab_options.maybe_min_sdk},
- {OPTION_PREFAB_SDK_TARGET_VERSION, ret.prefab_options.maybe_target_sdk},
- {OPTION_PREFAB_VERSION, ret.prefab_options.maybe_version},
- });
-
- options_implies(OPTION_CHOCOLATEY,
- ret.chocolatey,
- {
- {OPTION_CHOCOLATEY_MAINTAINER, ret.chocolatey_options.maybe_maintainer},
- {OPTION_CHOCOLATEY_VERSION_SUFFIX, ret.chocolatey_options.maybe_version_suffix},
- });
-
-#if defined(_MSC_VER) && _MSC_VER <= 1900
-#pragma warning(pop)
-#endif
- return ret;
- }
-
- static void print_next_step_info(const fs::path& prefix)
- {
- const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake";
- const System::CMakeVariable cmake_variable =
- System::CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string());
- System::print2("\n"
- "To use the exported libraries in CMake projects use:"
- "\n"
- " ",
- cmake_variable.s,
- "\n\n");
- }
-
- static void handle_raw_based_export(Span<const ExportPlanAction> export_plan,
- const ExportArguments& opts,
- const std::string& export_id,
- const VcpkgPaths& paths)
- {
- Files::Filesystem& fs = paths.get_filesystem();
- const fs::path raw_exported_dir_path = opts.output_dir / export_id;
- fs.remove_all(raw_exported_dir_path, VCPKG_LINE_INFO);
-
- // TODO: error handling
- std::error_code ec;
- fs.create_directory(raw_exported_dir_path, ec);
-
- // execute the plan
- for (const ExportPlanAction& action : export_plan)
- {
- if (action.plan_type != ExportPlanType::ALREADY_BUILT)
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- const std::string display_name = action.spec.to_string();
- System::print2("Exporting package ", display_name, "...\n");
-
- const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
-
- const InstallDir dirs = InstallDir::from_destination_root(
- raw_exported_dir_path / "installed",
- action.spec.triplet().to_string(),
- raw_exported_dir_path / "installed" / "vcpkg" / "info" / (binary_paragraph.fullstem() + ".list"));
-
- auto lines = fs.read_lines(paths.listfile_path(binary_paragraph)).value_or_exit(VCPKG_LINE_INFO);
- std::vector<fs::path> files;
- for (auto&& suffix : lines)
- {
- if (suffix.empty()) continue;
- if (suffix.back() == '/') suffix.pop_back();
- if (suffix == action.spec.triplet().to_string()) continue;
- files.push_back(paths.installed / fs::u8path(suffix));
- }
-
- Install::install_files_and_write_listfile(
- fs, paths.installed / action.spec.triplet().to_string(), files, dirs);
- }
-
- // Copy files needed for integration
- export_integration_files(raw_exported_dir_path, paths);
-
- if (opts.raw)
- {
- System::printf(System::Color::success,
- R"(Files exported at: "%s")"
- "\n",
- fs::u8string(raw_exported_dir_path));
- print_next_step_info(raw_exported_dir_path);
- }
-
- if (opts.nuget)
- {
- System::print2("Packing nuget package...\n");
-
- const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string());
- const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0");
- const std::string nuget_description = opts.maybe_nuget_description.value_or("Vcpkg NuGet export");
- const fs::path output_path = do_nuget_export(
- paths, nuget_id, nuget_version, nuget_description, raw_exported_dir_path, opts.output_dir);
- System::print2(System::Color::success, "NuGet package exported at: ", fs::u8string(output_path), "\n");
-
- System::printf(R"(
-With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste:
- Install-Package %s -Source "%s"
-)"
- "\n\n",
- nuget_id,
- fs::u8string(output_path.parent_path()));
- }
-
- if (opts.zip)
- {
- System::print2("Creating zip archive...\n");
- const fs::path output_path =
- do_archive_export(paths, raw_exported_dir_path, opts.output_dir, ArchiveFormatC::ZIP);
- System::print2(System::Color::success, "Zip archive exported at: ", fs::u8string(output_path), "\n");
- print_next_step_info("[...]");
- }
-
- if (opts.seven_zip)
- {
- System::print2("Creating 7zip archive...\n");
- const fs::path output_path =
- do_archive_export(paths, raw_exported_dir_path, opts.output_dir, ArchiveFormatC::SEVEN_ZIP);
- System::print2(System::Color::success, "7zip archive exported at: ", fs::u8string(output_path), "\n");
- print_next_step_info("[...]");
- }
-
- if (!opts.raw)
- {
- fs.remove_all(raw_exported_dir_path, VCPKG_LINE_INFO);
- }
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- if (paths.manifest_mode_enabled())
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- "vcpkg export does not support manifest mode, in order to allow for future design considerations. You "
- "may use export in classic mode by running vcpkg outside of a manifest-based project.");
- }
- const StatusParagraphs status_db = database_load_check(paths);
- const auto opts = handle_export_command_arguments(paths, args, default_triplet, status_db);
- for (auto&& spec : opts.specs)
- Input::check_triplet(spec.triplet(), paths);
-
- // Load ports from ports dirs
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
-
- // create the plan
- std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(opts.specs, status_db);
- Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty");
-
- std::map<ExportPlanType, std::vector<const ExportPlanAction*>> group_by_plan_type;
- Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; });
- print_plan(group_by_plan_type);
-
- const bool has_non_user_requested_packages =
- Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool {
- return package.request_type != RequestType::USER_REQUESTED;
- }) != export_plan.cend();
-
- if (has_non_user_requested_packages)
- {
- System::print2(System::Color::warning,
- "Additional packages (*) need to be exported to complete this operation.\n");
- }
-
- const auto it = group_by_plan_type.find(ExportPlanType::NOT_BUILT);
- if (it != group_by_plan_type.cend() && !it->second.empty())
- {
- System::print2(System::Color::error, "There are packages that have not been built.\n");
-
- // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest.
- std::vector<const ExportPlanAction*> unbuilt = it->second;
- Util::erase_remove_if(
- unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; });
-
- const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); });
- System::print2("To build them, run:\n"
- " vcpkg install ",
- s,
- "\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- if (opts.dry_run)
- {
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- std::string export_id = opts.maybe_output.value_or(create_export_id());
-
- if (opts.raw || opts.nuget || opts.zip || opts.seven_zip)
- {
- handle_raw_based_export(export_plan, opts, export_id, paths);
- }
-
- if (opts.ifw)
- {
- IFW::do_export(export_plan, export_id, opts.ifw_options, paths);
-
- print_next_step_info("@RootDir@/src/vcpkg");
- }
-
- if (opts.chocolatey)
- {
- Chocolatey::do_export(export_plan, paths, opts.chocolatey_options);
- }
-
- if (opts.prefab)
- {
- Prefab::do_export(export_plan, paths, opts.prefab_options, default_triplet);
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void ExportCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- Export::perform_and_exit(args, paths, default_triplet);
- }
-}
diff --git a/toolsrc/src/vcpkg/export.ifw.cpp b/toolsrc/src/vcpkg/export.ifw.cpp
deleted file mode 100644
index 74b06f524..000000000
--- a/toolsrc/src/vcpkg/export.ifw.cpp
+++ /dev/null
@@ -1,517 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/export.h>
-#include <vcpkg/export.ifw.h>
-#include <vcpkg/install.h>
-#include <vcpkg/tools.h>
-
-namespace vcpkg::Export::IFW
-{
- using Dependencies::ExportPlanAction;
- using Dependencies::ExportPlanType;
- using Install::InstallDir;
-
- namespace
- {
- std::string create_release_date()
- {
- const tm date_time = Chrono::get_current_date_time_local();
-
- // Format is: YYYY-mm-dd
- // 10 characters + 1 null terminating character will be written for a total of 11 chars
- char mbstr[11];
- const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time);
- Checks::check_exit(VCPKG_LINE_INFO,
- bytes_written == 10,
- "Expected 10 bytes to be written, but %u were written",
- bytes_written);
- const std::string date_time_as_string(mbstr);
- return date_time_as_string;
- }
-
- std::string safe_rich_from_plain_text(const std::string& text)
- {
- // match standalone ampersand, no HTML number or name
- std::regex standalone_ampersand(R"###(&(?!(#[0-9]+|\w+);))###");
-
- return std::regex_replace(text, standalone_ampersand, "&amp;");
- }
-
- fs::path get_packages_dir_path(const std::string& export_id,
- const Options& ifw_options,
- const VcpkgPaths& paths)
- {
- return ifw_options.maybe_packages_dir_path.has_value()
- ? fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO))
- : paths.root / (export_id + "-ifw-packages");
- }
-
- fs::path get_repository_dir_path(const std::string& export_id,
- const Options& ifw_options,
- const VcpkgPaths& paths)
- {
- return ifw_options.maybe_repository_dir_path.has_value()
- ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO))
- : paths.root / (export_id + "-ifw-repository");
- }
-
- fs::path get_config_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths)
- {
- return ifw_options.maybe_config_file_path.has_value()
- ? fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO))
- : paths.root / (export_id + "-ifw-configuration.xml");
- }
-
- fs::path get_installer_file_path(const std::string& export_id,
- const Options& ifw_options,
- const VcpkgPaths& paths)
- {
- return ifw_options.maybe_installer_file_path.has_value()
- ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO))
- : paths.root / (export_id + "-ifw-installer.exe");
- }
-
- fs::path export_real_package(const fs::path& ifw_packages_dir_path,
- const ExportPlanAction& action,
- Files::Filesystem& fs)
- {
- std::error_code ec;
-
- const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
-
- // Prepare meta dir
- const fs::path package_xml_file_path =
- ifw_packages_dir_path /
- Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" /
- "package.xml";
- const fs::path package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
-
- auto deps = Strings::join(
- ",", binary_paragraph.dependencies, [](const std::string& dep) { return "packages." + dep + ":"; });
-
- if (!deps.empty()) deps = "\n <Dependencies>" + deps + "</Dependencies>";
-
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>%s</DisplayName>
- <Version>%s</Version>
- <ReleaseDate>%s</ReleaseDate>
- <AutoDependOn>packages.%s:,triplets.%s:</AutoDependOn>%s
- <Virtual>true</Virtual>
-</Package>
-)###",
- action.spec.to_string(),
- binary_paragraph.version,
- create_release_date(),
- action.spec.name(),
- action.spec.triplet().canonical_name(),
- deps),
- VCPKG_LINE_INFO);
-
- // Return dir path for export package data
- return ifw_packages_dir_path /
- Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) /
- "data" / "installed";
- }
-
- void export_unique_packages(const fs::path& raw_exported_dir_path,
- std::map<std::string, const ExportPlanAction*> unique_packages,
- Files::Filesystem& fs)
- {
- std::error_code ec;
-
- // packages
-
- fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml";
- fs::path package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>Packages</DisplayName>
- <Version>1.0.0</Version>
- <ReleaseDate>%s</ReleaseDate>
-</Package>
-)###",
- create_release_date()),
- VCPKG_LINE_INFO);
-
- for (const auto& unique_package : unique_packages)
- {
- const ExportPlanAction& action = *(unique_package.second);
- const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
-
- package_xml_file_path = raw_exported_dir_path / Strings::format("packages.%s", unique_package.first) /
- "meta" / "package.xml";
- package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
-
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>%s</DisplayName>
- <Description>%s</Description>
- <Version>%s</Version>
- <ReleaseDate>%s</ReleaseDate>
-</Package>
-)###",
- action.spec.name(),
- safe_rich_from_plain_text(Strings::join("\n", binary_paragraph.description)),
- binary_paragraph.version,
- create_release_date()),
- VCPKG_LINE_INFO);
- }
- }
-
- void export_unique_triplets(const fs::path& raw_exported_dir_path,
- std::set<std::string> unique_triplets,
- Files::Filesystem& fs)
- {
- std::error_code ec;
-
- // triplets
-
- fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml";
- fs::path package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>Triplets</DisplayName>
- <Version>1.0.0</Version>
- <ReleaseDate>%s</ReleaseDate>
-</Package>
-)###",
- create_release_date()),
- VCPKG_LINE_INFO);
-
- for (const std::string& triplet : unique_triplets)
- {
- package_xml_file_path =
- raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml";
- package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>%s</DisplayName>
- <Version>1.0.0</Version>
- <ReleaseDate>%s</ReleaseDate>
-</Package>
-)###",
- triplet,
- create_release_date()),
- VCPKG_LINE_INFO);
- }
- }
-
- void export_integration(const fs::path& raw_exported_dir_path, Files::Filesystem& fs)
- {
- std::error_code ec;
-
- // integration
- fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml";
- fs::path package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
-
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>Integration</DisplayName>
- <Version>1.0.0</Version>
- <ReleaseDate>%s</ReleaseDate>
-</Package>
-)###",
- create_release_date()),
- VCPKG_LINE_INFO);
- }
-
- void export_config(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths)
- {
- std::error_code ec;
- Files::Filesystem& fs = paths.get_filesystem();
-
- const fs::path config_xml_file_path = get_config_file_path(export_id, ifw_options, paths);
-
- fs::path config_xml_dir_path = config_xml_file_path.parent_path();
- fs.create_directories(config_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for configuration file %s",
- fs::generic_u8string(config_xml_file_path));
-
- std::string formatted_repo_url;
- std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or("");
- if (!ifw_repo_url.empty())
- {
- formatted_repo_url = Strings::format(R"###(
- <RemoteRepositories>
- <Repository>
- <Url>%s</Url>
- </Repository>
- </RemoteRepositories>)###",
- ifw_repo_url);
- }
-
- fs.write_contents(config_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Installer>
- <Name>vcpkg</Name>
- <Version>1.0.0</Version>
- <StartMenuDir>vcpkg</StartMenuDir>
- <TargetDir>@RootDir@/src/vcpkg</TargetDir>%s
-</Installer>
-)###",
- formatted_repo_url),
- VCPKG_LINE_INFO);
- }
-
- void export_maintenance_tool(const fs::path& ifw_packages_dir_path, const VcpkgPaths& paths)
- {
- System::print2("Exporting maintenance tool...\n");
-
- std::error_code ec;
- Files::Filesystem& fs = paths.get_filesystem();
-
- const fs::path& installerbase_exe = paths.get_tool_exe(Tools::IFW_INSTALLER_BASE);
- fs::path tempmaintenancetool = ifw_packages_dir_path / "maintenance" / "data" / "tempmaintenancetool.exe";
- fs.create_directories(tempmaintenancetool.parent_path(), ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(tempmaintenancetool));
- fs.copy_file(installerbase_exe, tempmaintenancetool, fs::copy_options::overwrite_existing, ec);
- Checks::check_exit(
- VCPKG_LINE_INFO, !ec, "Could not write package file %s", fs::generic_u8string(tempmaintenancetool));
-
- fs::path package_xml_file_path = ifw_packages_dir_path / "maintenance" / "meta" / "package.xml";
- fs::path package_xml_dir_path = package_xml_file_path.parent_path();
- fs.create_directories(package_xml_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create directory for package file %s",
- fs::generic_u8string(package_xml_file_path));
- fs.write_contents(package_xml_file_path,
- Strings::format(
- R"###(<?xml version="1.0"?>
-<Package>
- <DisplayName>Maintenance Tool</DisplayName>
- <Description>Maintenance Tool</Description>
- <Version>1.0.0</Version>
- <ReleaseDate>%s</ReleaseDate>
- <Script>maintenance.qs</Script>
- <Essential>true</Essential>
- <Virtual>true</Virtual>
- <ForcedInstallation>true</ForcedInstallation>
-</Package>
-)###",
- create_release_date()),
- VCPKG_LINE_INFO);
- const fs::path script_source = paths.root / "scripts" / "ifw" / "maintenance.qs";
- const fs::path script_destination = ifw_packages_dir_path / "maintenance" / "meta" / "maintenance.qs";
- fs.copy_file(script_source, script_destination, fs::copy_options::overwrite_existing, ec);
- Checks::check_exit(
- VCPKG_LINE_INFO, !ec, "Could not write package file %s", fs::generic_u8string(script_destination));
-
- System::print2("Exporting maintenance tool... done\n");
- }
-
- void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths)
- {
- const fs::path& repogen_exe = paths.get_tool_exe(Tools::IFW_REPOGEN);
- const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths);
- const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths);
-
- System::print2("Generating repository ", fs::generic_u8string(repository_dir), "...\n");
-
- std::error_code ec;
- fs::path failure_point;
- Files::Filesystem& fs = paths.get_filesystem();
-
- fs.remove_all(repository_dir, ec, failure_point);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not remove outdated repository directory %s due to file %s",
- fs::generic_u8string(repository_dir),
- failure_point.string());
-
- auto cmd_line =
- System::Command(repogen_exe).string_arg("--packages").path_arg(packages_dir).path_arg(repository_dir);
-
- const int exit_code =
- System::cmd_execute_and_capture_output(cmd_line, System::get_clean_environment()).exit_code;
- Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed");
-
- System::printf(
- System::Color::success, "Generating repository %s... done.\n", fs::generic_u8string(repository_dir));
- }
-
- void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths)
- {
- const fs::path& binarycreator_exe = paths.get_tool_exe(Tools::IFW_BINARYCREATOR);
- const fs::path config_file = get_config_file_path(export_id, ifw_options, paths);
- const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths);
- const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths);
- const fs::path installer_file = get_installer_file_path(export_id, ifw_options, paths);
-
- System::printf("Generating installer %s...\n", fs::generic_u8string(installer_file));
-
- System::Command cmd_line;
-
- std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or("");
- if (!ifw_repo_url.empty())
- {
- cmd_line = System::Command(binarycreator_exe)
- .string_arg("--online-only")
- .string_arg("--config")
- .path_arg(config_file)
- .string_arg("--repository")
- .path_arg(repository_dir)
- .path_arg(installer_file);
- }
- else
- {
- cmd_line = System::Command(binarycreator_exe)
- .string_arg("--config")
- .path_arg(config_file)
- .string_arg("--packages")
- .path_arg(packages_dir)
- .path_arg(installer_file);
- }
-
- const int exit_code =
- System::cmd_execute_and_capture_output(cmd_line, System::get_clean_environment()).exit_code;
- Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW installer generating failed");
-
- System::printf(
- System::Color::success, "Generating installer %s... done.\n", fs::generic_u8string(installer_file));
- }
- }
-
- void do_export(const std::vector<ExportPlanAction>& export_plan,
- const std::string& export_id,
- const Options& ifw_options,
- const VcpkgPaths& paths)
- {
- std::error_code ec;
- fs::path failure_point;
- Files::Filesystem& fs = paths.get_filesystem();
-
- // Prepare packages directory
- const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths);
-
- fs.remove_all(ifw_packages_dir_path, ec, failure_point);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not remove outdated packages directory %s due to file %s",
- fs::generic_u8string(ifw_packages_dir_path),
- failure_point.string());
-
- fs.create_directory(ifw_packages_dir_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Could not create packages directory %s",
- fs::generic_u8string(ifw_packages_dir_path));
-
- // Export maintenance tool
- export_maintenance_tool(ifw_packages_dir_path, paths);
-
- System::printf("Exporting packages %s...\n", fs::generic_u8string(ifw_packages_dir_path));
-
- // execute the plan
- std::map<std::string, const ExportPlanAction*> unique_packages;
- std::set<std::string> unique_triplets;
- for (const ExportPlanAction& action : export_plan)
- {
- if (action.plan_type != ExportPlanType::ALREADY_BUILT)
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- System::print2("Exporting package ", action.spec, "...\n");
-
- const BinaryParagraph& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
-
- unique_packages[action.spec.name()] = &action;
- unique_triplets.insert(action.spec.triplet().canonical_name());
-
- // Export real package and return data dir for installation
- fs::path ifw_package_dir_path = export_real_package(ifw_packages_dir_path, action, fs);
-
- // Copy package data
- const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path,
- action.spec.triplet().to_string(),
- ifw_package_dir_path / "vcpkg" / "info" /
- (binary_paragraph.fullstem() + ".list"));
-
- Install::install_package_and_write_listfile(paths, action.spec, dirs);
- }
-
- System::printf("Exporting packages %s... done\n", fs::generic_u8string(ifw_packages_dir_path));
-
- const fs::path config_file = get_config_file_path(export_id, ifw_options, paths);
-
- System::printf("Generating configuration %s...\n", fs::generic_u8string(config_file));
-
- // Unique packages
- export_unique_packages(ifw_packages_dir_path, unique_packages, fs);
-
- // Unique triplets
- export_unique_triplets(ifw_packages_dir_path, unique_triplets, fs);
-
- // Copy files needed for integration
- export_integration_files(ifw_packages_dir_path / "integration" / "data", paths);
- // Integration
- export_integration(ifw_packages_dir_path, fs);
-
- // Configuration
- export_config(export_id, ifw_options, paths);
-
- System::printf("Generating configuration %s... done.\n", fs::generic_u8string(config_file));
-
- // Do repository (optional)
- std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or("");
- if (!ifw_repo_url.empty())
- {
- do_repository(export_id, ifw_options, paths);
- }
-
- // Do installer
- do_installer(export_id, ifw_options, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/export.prefab.cpp b/toolsrc/src/vcpkg/export.prefab.cpp
deleted file mode 100644
index 2ca8e87f7..000000000
--- a/toolsrc/src/vcpkg/export.prefab.cpp
+++ /dev/null
@@ -1,719 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/build.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/export.h>
-#include <vcpkg/export.prefab.h>
-#include <vcpkg/install.h>
-#include <vcpkg/tools.h>
-
-namespace vcpkg::Export::Prefab
-{
- using Dependencies::ExportPlanAction;
- using Dependencies::ExportPlanType;
- using Install::InstallDir;
- using System::CPUArchitecture;
-
- static std::vector<fs::path> find_modules(const VcpkgPaths& system, const fs::path& root, const std::string& ext)
- {
- std::vector<fs::path> paths;
- Files::Filesystem& utils = system.get_filesystem();
- std::error_code error_code;
- if (!utils.exists(root, error_code) || !utils.is_directory(root)) return paths;
-
- fs::stdfs::recursive_directory_iterator it(root);
- fs::stdfs::recursive_directory_iterator endit;
-
- while (it != endit)
- {
- if (utils.is_regular_file(*it) && it->path().extension() == ext)
- {
- paths.push_back(it->path().filename());
- }
- ++it;
- }
- return paths;
- }
-
- std::string NdkVersion::to_string()
- {
- std::string ret;
- this->to_string(ret);
- return ret;
- }
- void NdkVersion::to_string(std::string& out)
- {
- out.append("NdkVersion{major=")
- .append(std::to_string(major()))
- .append(",minor=")
- .append(std::to_string(minor()))
- .append(",patch=")
- .append(std::to_string(patch()))
- .append("}");
- }
-
- static std::string jsonify(const std::vector<std::string>& dependencies)
- {
- std::vector<std::string> deps;
- for (const auto& dep : dependencies)
- {
- deps.push_back("\"" + dep + "\"");
- }
- return Strings::join(",", deps);
- }
-
- static std::string null_if_empty(const std::string& str)
- {
- std::string copy = str;
- if (copy.size() == 0)
- {
- copy = "null";
- }
- else
- {
- copy = "\"" + copy + "\"";
- }
- return copy;
- }
-
- static std::string null_if_empty_array(const std::string& str)
- {
- std::string copy = str;
- if (copy.size() == 0)
- {
- copy = "null";
- }
- else
- {
- copy = "[" + copy + "]";
- }
- return copy;
- }
-
- std::string ABIMetadata::to_string()
- {
- std::string TEMPLATE = R"({
- "abi":"@ABI@",
- "api":@API@,
- "ndk":@NDK@,
- "stl":"@STL@"
-})";
- std::string json = Strings::replace_all(std::move(TEMPLATE), "@ABI@", abi);
- Strings::inplace_replace_all(json, "@API@", std::to_string(api));
- Strings::inplace_replace_all(json, "@NDK@", std::to_string(ndk));
- Strings::inplace_replace_all(json, "@STL@", stl);
- return json;
- }
-
- std::string PlatformModuleMetadata::to_json()
- {
- std::string TEMPLATE = R"({
- "export_libraries": @LIBRARIES@,
- "library_name": @LIBRARY_NAME@
-})";
-
- std::string json = Strings::replace_all(std::move(TEMPLATE), "@LIBRARY_NAME@", null_if_empty(library_name));
- Strings::inplace_replace_all(json, "@LIBRARIES@", null_if_empty_array(jsonify(export_libraries)));
- return json;
- }
-
- std::string ModuleMetadata::to_json()
- {
- std::string TEMPLATE = R"({
- "export_libraries": [@LIBRARIES@],
- "library_name":@LIBRARY_NAME@,
- "android": @ANDROID_METADATA@
-})";
-
- std::string json = Strings::replace_all(std::move(TEMPLATE), "@LIBRARY_NAME@", null_if_empty(library_name));
- Strings::inplace_replace_all(json, "@LIBRARIES@", jsonify(export_libraries));
- Strings::inplace_replace_all(json, "@ANDROID_METADATA@", android.to_json());
- return json;
- }
-
- std::string PackageMetadata::to_json()
- {
- std::string deps = jsonify(dependencies);
-
- std::string TEMPLATE = R"({
- "name":"@PACKAGE_NAME@",
- "schema_version": @PACKAGE_SCHEMA@,
- "dependencies":[@PACKAGE_DEPS@],
- "version":"@PACKAGE_VERSION@"
-})";
- std::string json = Strings::replace_all(std::move(TEMPLATE), "@PACKAGE_NAME@", name);
- Strings::inplace_replace_all(json, "@PACKAGE_SCHEMA@", std::to_string(schema));
- Strings::inplace_replace_all(json, "@PACKAGE_DEPS@", deps);
- Strings::inplace_replace_all(json, "@PACKAGE_VERSION@", version);
- return json;
- }
-
- Optional<std::string> find_ndk_version(const std::string& content)
- {
- std::smatch pkg_match;
- std::regex pkg_regex(R"(Pkg\.Revision\s*=\s*(\d+)(\.\d+)(\.\d+)\s*)");
-
- if (std::regex_search(content, pkg_match, pkg_regex))
- {
- for (const auto& p : pkg_match)
- {
- std::string delimiter = "=";
- std::string s = p.str();
- auto it = s.find(delimiter);
- if (it != std::string::npos)
- {
- std::string token = (s.substr(s.find(delimiter) + 1, s.size()));
- return Strings::trim(std::move(token));
- }
- }
- }
- return {};
- }
-
- Optional<NdkVersion> to_version(const std::string& version)
- {
- if (version.size() > 100) return {};
- size_t last = 0;
- size_t next = 0;
- std::vector<int> fragments(0);
-
- while ((next = version.find(".", last)) != std::string::npos)
- {
- fragments.push_back(std::stoi(version.substr(last, next - last)));
- last = next + 1;
- }
- fragments.push_back(std::stoi(version.substr(last)));
- if (fragments.size() == kFragmentSize)
- {
- return NdkVersion(fragments[0], fragments[1], fragments[2]);
- }
- return {};
- }
-
- static void compress_directory(const VcpkgPaths& paths, const fs::path& source, const fs::path& destination)
- {
- auto& fs = paths.get_filesystem();
-
- std::error_code ec;
-
- fs.remove(destination, ec);
- Checks::check_exit(
- VCPKG_LINE_INFO, !fs.exists(destination), "Could not remove file: %s", fs::u8string(destination));
-#if defined(_WIN32)
- auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP);
-
- System::cmd_execute_and_capture_output(
- System::Command(seven_zip_exe).string_arg("a").path_arg(destination).path_arg(source / fs::u8path("*")),
- System::get_clean_environment());
-#else
- System::cmd_execute_clean(
- System::Command{"zip"}.string_arg("--quiet").string_arg("-r").path_arg(destination).string_arg("*"),
- System::InWorkingDirectory{source});
-#endif
- }
-
- static void maven_install(const fs::path& aar, const fs::path& pom, const Options& prefab_options)
- {
- if (prefab_options.enable_debug)
- {
- System::print2("\n[DEBUG] Installing POM and AAR file to ~/.m2\n\n");
- }
- auto cmd_line = System::Command(Tools::MAVEN);
- if (!prefab_options.enable_debug)
- {
- cmd_line.string_arg("-q");
- }
- cmd_line.string_arg("install:install-file")
- .string_arg(Strings::concat("-Dfile=", fs::u8string(aar)))
- .string_arg(Strings::concat("-DpomFile=", fs::u8string(pom)));
- const int exit_code = System::cmd_execute_clean(cmd_line);
- Checks::check_exit(
- VCPKG_LINE_INFO, exit_code == 0, "Error: %s installing maven file", fs::generic_u8string(aar));
- }
-
- static std::unique_ptr<Build::PreBuildInfo> build_info_from_triplet(
- const VcpkgPaths& paths, const std::unique_ptr<CMakeVars::CMakeVarProvider>& provider, const Triplet& triplet)
- {
- provider->load_generic_triplet_vars(triplet);
- return std::make_unique<Build::PreBuildInfo>(
- paths, triplet, provider->get_generic_triplet_vars(triplet).value_or_exit(VCPKG_LINE_INFO));
- }
-
- static bool is_supported(const Build::PreBuildInfo& info)
- {
- return Strings::case_insensitive_ascii_equals(info.cmake_system_name, "android");
- }
-
- void do_export(const std::vector<ExportPlanAction>& export_plan,
- const VcpkgPaths& paths,
- const Options& prefab_options,
- const Triplet& default_triplet)
- {
- auto provider = CMakeVars::make_triplet_cmake_var_provider(paths);
-
- {
- auto build_info = build_info_from_triplet(paths, provider, default_triplet);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, is_supported(*build_info), "Currenty supported on android triplets");
- }
-
- std::vector<VcpkgPaths::TripletFile> available_triplets = paths.get_available_triplets();
-
- std::unordered_map<CPUArchitecture, std::string> required_archs = {{CPUArchitecture::ARM, "armeabi-v7a"},
- {CPUArchitecture::ARM64, "arm64-v8a"},
- {CPUArchitecture::X86, "x86"},
- {CPUArchitecture::X64, "x86_64"}};
-
- std::unordered_map<CPUArchitecture, int> cpu_architecture_api_map = {{CPUArchitecture::ARM64, 21},
- {CPUArchitecture::ARM, 16},
- {CPUArchitecture::X64, 21},
- {CPUArchitecture::X86, 16}};
-
- std::vector<Triplet> triplets;
- std::unordered_map<Triplet, std::string> triplet_abi_map;
- std::unordered_map<Triplet, int> triplet_api_map;
-
- for (auto& triplet_file : available_triplets)
- {
- if (triplet_file.name.size() > 0)
- {
- Triplet triplet = Triplet::from_canonical_name(std::move(triplet_file.name));
- auto triplet_build_info = build_info_from_triplet(paths, provider, triplet);
- if (is_supported(*triplet_build_info))
- {
- auto cpu_architecture = System::to_cpu_architecture(triplet_build_info->target_architecture)
- .value_or_exit(VCPKG_LINE_INFO);
- auto required_arch = required_archs.find(cpu_architecture);
- if (required_arch != required_archs.end())
- {
- triplets.push_back(triplet);
- triplet_abi_map[triplet] = required_archs[cpu_architecture];
- triplet_api_map[triplet] = cpu_architecture_api_map[cpu_architecture];
- required_archs.erase(required_arch);
- }
- }
- }
- }
-
- Checks::check_exit(
- VCPKG_LINE_INFO,
- required_archs.empty(),
- "Export requires the following architectures arm64-v8a, armeabi-v7a, x86_64, x86 to be present");
-
- Optional<std::string> android_ndk_home = System::get_environment_variable("ANDROID_NDK_HOME");
-
- Checks::check_exit(
- VCPKG_LINE_INFO, android_ndk_home.has_value(), "Error: ANDROID_NDK_HOME environment missing");
-
- Files::Filesystem& utils = paths.get_filesystem();
-
- const fs::path ndk_location = android_ndk_home.value_or_exit(VCPKG_LINE_INFO);
-
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- utils.exists(ndk_location),
- "Error: ANDROID_NDK_HOME Directory does not exists %s",
- fs::generic_u8string(ndk_location));
- const fs::path source_properties_location = ndk_location / "source.properties";
-
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- utils.exists(ndk_location),
- "Error: source.properties missing in ANDROID_NDK_HOME directory %s",
- fs::generic_u8string(source_properties_location));
-
- std::string content = utils.read_contents(source_properties_location, VCPKG_LINE_INFO);
-
- Optional<std::string> version_opt = find_ndk_version(content);
-
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- version_opt.has_value(),
- "Error: NDK version missing %s",
- fs::generic_u8string(source_properties_location));
-
- NdkVersion version = to_version(version_opt.value_or_exit(VCPKG_LINE_INFO)).value_or_exit(VCPKG_LINE_INFO);
-
- utils.remove_all(paths.prefab, VCPKG_LINE_INFO);
-
- /*
- prefab
- +-- <name>
- +-- aar
- | +-- AndroidManifest.xml
- | +-- META-INF
- | | +-- LICENCE
- | +-- prefab
- | +-- modules
- | | +-- <module>
- | | +-- include
- | | +-- libs
- | | | +-- android.arm64-v8a
- | | | | +-- abi.json
- | | | | +-- lib<module>.so
- | | | +-- android.armeabi-v7a
- | | | | +-- abi.json
- | | | | +-- lib<module>.so
- | | | +-- android.x86
- | | | | +-- abi.json
- | | | | +-- lib<module>.so
- | | | +-- android.x86_64
- | | | +-- abi.json
- | | | +-- lib<module>.so
- | | +-- module.json
- | +-- prefab.json
- +-- <name>-<version>.aar
- +-- pom.xml
- */
-
- std::unordered_map<std::string, std::string> version_map;
-
- std::error_code error_code;
-
- std::unordered_map<std::string, std::set<PackageSpec>> empty_package_dependencies;
-
- //
-
- for (const auto& action : export_plan)
- {
- const std::string name = action.spec.name();
- auto dependencies = action.dependencies();
-
- const auto action_build_info = Build::read_build_info(utils, paths.build_info_file_path(action.spec));
- const bool is_empty_package = action_build_info.policies.is_enabled(Build::BuildPolicy::EMPTY_PACKAGE);
-
- if (is_empty_package)
- {
- empty_package_dependencies[name] = std::set<PackageSpec>();
- for (auto dependency : dependencies)
- {
- if (empty_package_dependencies.find(dependency.name()) != empty_package_dependencies.end())
- {
- auto& child_deps = empty_package_dependencies[name];
- auto& parent_deps = empty_package_dependencies[dependency.name()];
- for (auto parent_dep : parent_deps)
- {
- child_deps.insert(parent_dep);
- }
- }
- else
- {
- empty_package_dependencies[name].insert(dependency);
- }
- }
- continue;
- }
-
- const fs::path per_package_dir_path = paths.prefab / fs::u8path(name);
-
- const auto& binary_paragraph = action.core_paragraph().value_or_exit(VCPKG_LINE_INFO);
- const std::string norm_version = binary_paragraph.version;
-
- version_map[name] = norm_version;
-
- System::print2("\nExporting package ", name, "...\n");
-
- fs::path package_directory = per_package_dir_path / "aar";
- fs::path prefab_directory = package_directory / "prefab";
- fs::path modules_directory = prefab_directory / "modules";
-
- utils.create_directories(modules_directory, error_code);
-
- std::string artifact_id = prefab_options.maybe_artifact_id.value_or(name);
- std::string group_id = prefab_options.maybe_group_id.value_or("com.vcpkg.ndk.support");
- std::string sdk_min_version = prefab_options.maybe_min_sdk.value_or("16");
- std::string sdk_target_version = prefab_options.maybe_target_sdk.value_or("29");
-
- std::string MANIFEST_TEMPLATE =
- R"(<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="@GROUP_ID@.@ARTIFACT_ID@" android:versionCode="1" android:versionName="1.0">
- <uses-sdk android:minSdkVersion="@MIN_SDK_VERSION@" android:targetSdkVersion="@SDK_TARGET_VERSION@" />
-</manifest>)";
- std::string manifest = Strings::replace_all(std::move(MANIFEST_TEMPLATE), "@GROUP_ID@", group_id);
- Strings::inplace_replace_all(manifest, "@ARTIFACT_ID@", artifact_id);
- Strings::inplace_replace_all(manifest, "@MIN_SDK_VERSION@", sdk_min_version);
- Strings::inplace_replace_all(manifest, "@SDK_TARGET_VERSION@", sdk_target_version);
-
- fs::path manifest_path = package_directory / "AndroidManifest.xml";
- fs::path prefab_path = prefab_directory / "prefab.json";
-
- fs::path meta_dir = package_directory / "META-INF";
-
- utils.create_directories(meta_dir, error_code);
-
- const fs::path share_root =
- paths.packages / fs::u8path(Strings::format("%s_%s", name, action.spec.triplet()));
-
- utils.copy_file(share_root / "share" / name / "copyright",
- meta_dir / "LICENSE",
- fs::copy_options::overwrite_existing,
- error_code);
-
- PackageMetadata pm;
- pm.name = artifact_id;
- pm.schema = 1;
- pm.version = norm_version;
-
- std::set<PackageSpec> dependencies_minus_empty_packages;
-
- for (auto dependency : dependencies)
- {
- if (empty_package_dependencies.find(dependency.name()) != empty_package_dependencies.end())
- {
- for (auto& empty_package_dep : empty_package_dependencies[dependency.name()])
- {
- dependencies_minus_empty_packages.insert(empty_package_dep);
- }
- }
- else
- {
- dependencies_minus_empty_packages.insert(dependency);
- }
- }
-
- std::vector<std::string> pom_dependencies;
-
- if (dependencies_minus_empty_packages.size() > 0)
- {
- pom_dependencies.push_back("\n<dependencies>");
- }
-
- for (const auto& it : dependencies_minus_empty_packages)
- {
- std::string maven_pom = R"( <dependency>
- <groupId>@GROUP_ID@</groupId>
- <artifactId>@ARTIFACT_ID@</artifactId>
- <version>@VERSION@</version>
- <type>aar</type>
- <scope>runtime</scope>
- </dependency>)";
- std::string pom = Strings::replace_all(std::move(maven_pom), "@GROUP_ID@", group_id);
- Strings::inplace_replace_all(pom, "@ARTIFACT_ID@", it.name());
- Strings::inplace_replace_all(pom, "@VERSION@", version_map[it.name()]);
- pom_dependencies.push_back(pom);
- pm.dependencies.push_back(it.name());
- }
-
- if (dependencies_minus_empty_packages.size() > 0)
- {
- pom_dependencies.push_back("</dependencies>\n");
- }
-
- if (prefab_options.enable_debug)
- {
- System::print2(
- Strings::format("[DEBUG]\n\tWriting manifest\n\tTo %s\n\tWriting prefab meta data\n\tTo %s\n\n",
- fs::generic_u8string(manifest_path),
- fs::generic_u8string(prefab_path)));
- }
-
- utils.write_contents(manifest_path, manifest, VCPKG_LINE_INFO);
- utils.write_contents(prefab_path, pm.to_json(), VCPKG_LINE_INFO);
-
- if (prefab_options.enable_debug)
- {
- std::vector<std::string> triplet_names;
- for (auto triplet : triplets)
- {
- triplet_names.push_back(triplet.canonical_name());
- }
- System::print2(Strings::format(
- "[DEBUG] Found %d triplets\n\t%s\n\n", triplets.size(), Strings::join("\n\t", triplet_names)));
- }
-
- for (const auto& triplet : triplets)
- {
- const fs::path listfile =
- paths.vcpkg_dir_info /
- fs::u8path(Strings::format("%s_%s_%s", name, norm_version, triplet) + ".list");
- const fs::path installed_dir = paths.packages / fs::u8path(Strings::format("%s_%s", name, triplet));
- Checks::check_exit(VCPKG_LINE_INFO,
- utils.exists(listfile),
- "Error: Packages not installed %s:%s %s",
- name,
- triplet,
- fs::generic_u8string(listfile));
-
- fs::path libs = installed_dir / fs::u8path("lib");
-
- std::vector<fs::path> modules;
-
- std::vector<fs::path> modules_shared = find_modules(paths, libs, ".so");
-
- for (const auto& module : modules_shared)
- {
- modules.push_back(module);
- }
-
- std::vector<fs::path> modules_static = find_modules(paths, libs, ".a");
- for (const auto& module : modules_static)
- {
- modules.push_back(module);
- }
-
- // header only libs
- if (modules.empty())
- {
- fs::path module_dir = modules_directory / name;
- fs::path module_libs_dir = module_dir / fs::u8path("libs");
- utils.create_directories(module_libs_dir, error_code);
- fs::path installed_headers_dir = installed_dir / fs::u8path("include");
- fs::path exported_headers_dir = module_dir / fs::u8path("include");
-
- ModuleMetadata meta;
- fs::path module_meta_path = module_dir / fs::u8path("module.json");
- utils.write_contents(module_meta_path, meta.to_json(), VCPKG_LINE_INFO);
-
- utils.copy(installed_headers_dir, exported_headers_dir, fs::copy_options::recursive);
- break;
- }
- else
- {
- for (const auto& module : modules)
- {
- std::string module_name = fs::generic_u8string(module.stem());
- std::string extension = fs::generic_u8string(module.extension());
-
- ABIMetadata ab;
- ab.abi = triplet_abi_map[triplet];
- ab.api = triplet_api_map[triplet];
-
- ab.stl = Strings::contains(extension, "a") ? "c++_static" : "c++_shared";
- ab.ndk = version.major();
-
- if (prefab_options.enable_debug)
- {
- System::print2(Strings::format("[DEBUG] Found module %s:%s\n", module_name, ab.abi));
- }
-
- module_name = Strings::trim(std::move(module_name));
-
- if (Strings::starts_with(module_name, "lib"))
- {
- module_name = module_name.substr(3);
- }
- fs::path module_dir = (modules_directory / module_name);
- fs::path module_libs_dir = module_dir / "libs" / Strings::format("android.%s", ab.abi);
- utils.create_directories(module_libs_dir, error_code);
-
- fs::path abi_path = module_libs_dir / "abi.json";
-
- if (prefab_options.enable_debug)
- {
- System::print2(
- Strings::format("\tWriting abi metadata\n\tTo %s\n", fs::generic_u8string(abi_path)));
- }
- utils.write_contents(abi_path, ab.to_string(), VCPKG_LINE_INFO);
-
- fs::path installed_module_path = libs / module.filename();
- fs::path exported_module_path = module_libs_dir / module.filename();
-
- utils.copy_file(installed_module_path,
- exported_module_path,
- fs::copy_options::overwrite_existing,
- error_code);
- if (prefab_options.enable_debug)
- {
- System::print2(Strings::format("\tCopying libs\n\tFrom %s\n\tTo %s\n",
- fs::generic_u8string(installed_module_path),
- fs::generic_u8string(exported_module_path)));
- }
- fs::path installed_headers_dir = installed_dir / "include";
- fs::path exported_headers_dir = module_libs_dir / "include";
-
- if (prefab_options.enable_debug)
- {
- System::print2(Strings::format("\tCopying headers\n\tFrom %s\n\tTo %s\n",
- fs::generic_u8string(installed_headers_dir),
- fs::generic_u8string(exported_headers_dir)));
- }
-
- utils.copy(installed_headers_dir, exported_headers_dir, fs::copy_options::recursive);
-
- ModuleMetadata meta;
-
- fs::path module_meta_path = module_dir / "module.json";
-
- if (prefab_options.enable_debug)
- {
- System::print2(Strings::format("\tWriting module metadata\n\tTo %s\n\n",
- fs::generic_u8string(module_meta_path)));
- }
-
- utils.write_contents(module_meta_path, meta.to_json(), VCPKG_LINE_INFO);
- }
- }
- }
-
- fs::path exported_archive_path = per_package_dir_path / Strings::format("%s-%s.aar", name, norm_version);
- fs::path pom_path = per_package_dir_path / "pom.xml";
-
- if (prefab_options.enable_debug)
- {
- System::print2(Strings::format("[DEBUG] Exporting AAR And POM\n\tAAR Path %s\n\tPOM Path %s\n",
- fs::generic_u8string(exported_archive_path),
- fs::generic_u8string(pom_path)));
- }
-
- compress_directory(paths, package_directory, exported_archive_path);
-
- std::string POM = R"(<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
-
- <groupId>@GROUP_ID@</groupId>
- <artifactId>@ARTIFACT_ID@</artifactId>
- <version>@VERSION@</version>
- <packaging>aar</packaging>
- <description>The Vcpkg AAR for @ARTIFACT_ID@</description>
- <url>https://github.com/microsoft/vcpkg.git</url>
- @DEPENDENCIES@
-</project>)";
-
- std::string pom = Strings::replace_all(std::move(POM), "@GROUP_ID@", group_id);
- Strings::inplace_replace_all(pom, "@ARTIFACT_ID@", artifact_id);
- Strings::inplace_replace_all(pom, "@DEPENDENCIES@", Strings::join("\n", pom_dependencies));
- Strings::inplace_replace_all(pom, "@VERSION@", norm_version);
-
- utils.write_contents(pom_path, pom, VCPKG_LINE_INFO);
-
- if (prefab_options.enable_maven)
- {
- maven_install(exported_archive_path, pom_path, prefab_options);
- if (prefab_options.enable_debug)
- {
- System::print2(Strings::format(
- "\n\n[DEBUG] Configuration properties in Android Studio\nIn app/build.gradle\n\n\t%s:%s:%s\n\n",
- group_id,
- artifact_id,
- norm_version));
-
- System::print2(R"(And cmake flags
-
- externalNativeBuild {
- cmake {
- arguments '-DANDROID_STL=c++_shared'
- cppFlags "-std=c++17"
- }
- }
-
-)");
-
- System::print2(R"(In gradle.properties
-
- android.enablePrefab=true
- android.enableParallelJsonGen=false
- android.prefabVersion=${prefab.version}
-
-)");
- }
- }
- System::print2(
- System::Color::success,
- Strings::format("Successfuly exported %s. Checkout %s \n", name, fs::generic_u8string(paths.prefab)));
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp
deleted file mode 100644
index 896e96c81..000000000
--- a/toolsrc/src/vcpkg/globalstate.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <vcpkg/base/lockguarded.h>
-
-#include <vcpkg/globalstate.h>
-
-namespace vcpkg
-{
- Util::LockGuarded<Chrono::ElapsedTimer> GlobalState::timer;
- Util::LockGuarded<std::string> GlobalState::g_surveydate;
-
- std::atomic<int> GlobalState::g_init_console_cp(0);
- std::atomic<int> GlobalState::g_init_console_output_cp(0);
- std::atomic<bool> GlobalState::g_init_console_initialized(false);
-}
diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp
deleted file mode 100644
index 0556b4fa0..000000000
--- a/toolsrc/src/vcpkg/help.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/commands.create.h>
-#include <vcpkg/commands.dependinfo.h>
-#include <vcpkg/commands.edit.h>
-#include <vcpkg/commands.env.h>
-#include <vcpkg/commands.integrate.h>
-#include <vcpkg/commands.list.h>
-#include <vcpkg/commands.owns.h>
-#include <vcpkg/commands.search.h>
-#include <vcpkg/export.h>
-#include <vcpkg/help.h>
-#include <vcpkg/install.h>
-#include <vcpkg/remove.h>
-
-namespace vcpkg::Help
-{
- struct Topic
- {
- using topic_function = void (*)(const VcpkgPaths& paths);
-
- constexpr Topic(CStringView n, topic_function fn) : name(n), print(fn) { }
-
- CStringView name;
- topic_function print;
- };
-
- template<const CommandStructure& S>
- static void command_topic_fn(const VcpkgPaths&)
- {
- print_usage(S);
- }
-
- static void integrate_topic_fn(const VcpkgPaths&)
- {
- System::print2("Commands:\n", Commands::Integrate::get_helpstring());
- }
-
- static void help_topics(const VcpkgPaths&);
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("help"),
- 0,
- 1,
- {},
- nullptr,
- };
-
- static void help_topic_versioning(const VcpkgPaths&)
- {
- HelpTableFormatter tbl;
- tbl.text("Versioning allows you to deterministically control the precise revisions of dependencies used by "
- "your project from within your manifest file.");
- tbl.blank();
- tbl.blank();
- tbl.text("** This feature is experimental and requires `--feature-flags=versions` **");
- tbl.blank();
- tbl.blank();
- tbl.header("Versions in vcpkg come in four primary flavors");
- tbl.format("version", "A dot-separated sequence of numbers (1.2.3.4)");
- tbl.format("version-date", "A date (2021-01-01.5)");
- tbl.format("version-semver", "A Semantic Version 2.0 (2.1.0-rc2)");
- tbl.format("version-string", "An exact, incomparable version (Vista)");
- tbl.blank();
- tbl.text("Each version additionally has a \"port-version\" which is a nonnegative integer. When rendered as "
- "text, the port version (if nonzero) is added as a suffix to the primary version text separated by a "
- "hash (#). Port-versions are sorted lexographically after the primary version text, for example:");
- tbl.blank();
- tbl.blank();
- tbl.text(" 1.0.0 < 1.0.0#1 < 1.0.1 < 1.0.1#5 < 2.0.0");
- tbl.blank();
- tbl.blank();
- tbl.header("Manifests can place three kinds of constraints upon the versions used");
- tbl.format("builtin-baseline",
- "The baseline references a commit within the vcpkg repository that establishes a minimum version on "
- "every dependency in the graph. If no other constraints are specified (directly or transitively), "
- "then the version from the baseline of the top level manifest will be used. Baselines of transitive "
- "dependencies are ignored.");
- tbl.blank();
- tbl.format("version>=",
- "Within the \"dependencies\" field, each dependency can have a minimum constraint listed. These "
- "minimum constraints will be used when transitively depending upon this library. A minimum "
- "port-version can additionally be specified with a '#' suffix.");
- tbl.blank();
- tbl.format(
- "overrides",
- "When used as the top-level manifest (such as when running `vcpkg install` in the directory), overrides "
- "allow a manifest to short-circuit dependency resolution and specify exactly the version to use. These can "
- "be used to handle version conflicts, such as with `version-string` dependencies. They will not be "
- "considered when transitively depended upon.");
- tbl.blank();
- tbl.text("Example manifest:");
- tbl.blank();
- tbl.text(R"({
- "name": "example",
- "version": "1.0",
- "builtin-baseline": "a14a6bcb27287e3ec138dba1b948a0cdbc337a3a",
- "dependencies": [
- { "name": "zlib", "version>=": "1.2.11#8" },
- "rapidjson"
- ],
- "overrides": [
- { "name": "rapidjson", "version": "2020-09-14" }
- ]
-})");
- System::print2(tbl.m_str,
- "\nExtended documentation is available at "
- "https://github.com/Microsoft/vcpkg/tree/master/docs/users/versioning.md\n");
- }
-
- static constexpr std::array<Topic, 16> topics = {{
- {"binarycaching", help_topic_binary_caching},
- {"create", command_topic_fn<Commands::Create::COMMAND_STRUCTURE>},
- {"depend-info", command_topic_fn<Commands::DependInfo::COMMAND_STRUCTURE>},
- {"edit", command_topic_fn<Commands::Edit::COMMAND_STRUCTURE>},
- {"env", command_topic_fn<Commands::Env::COMMAND_STRUCTURE>},
- {"export", command_topic_fn<Export::COMMAND_STRUCTURE>},
- {"help", command_topic_fn<Help::COMMAND_STRUCTURE>},
- {"install", command_topic_fn<Install::COMMAND_STRUCTURE>},
- {"integrate", integrate_topic_fn},
- {"list", command_topic_fn<Commands::List::COMMAND_STRUCTURE>},
- {"owns", command_topic_fn<Commands::Owns::COMMAND_STRUCTURE>},
- {"remove", command_topic_fn<Remove::COMMAND_STRUCTURE>},
- {"search", command_topic_fn<Commands::Search::COMMAND_STRUCTURE>},
- {"topics", help_topics},
- {"triplet", help_topic_valid_triplet},
- {"versioning", help_topic_versioning},
- }};
-
- static void help_topics(const VcpkgPaths&)
- {
- System::print2("Available help topics:",
- Strings::join("", topics, [](const Topic& topic) { return std::string("\n ") + topic.name; }),
- "\n");
- }
-
- void help_topic_valid_triplet(const VcpkgPaths& paths)
- {
- std::map<std::string, std::vector<const VcpkgPaths::TripletFile*>> triplets_per_location;
- vcpkg::Util::group_by(paths.get_available_triplets(),
- &triplets_per_location,
- [](const VcpkgPaths::TripletFile& triplet_file) -> std::string {
- return fs::u8string(triplet_file.location);
- });
-
- System::print2("Available architecture triplets\n");
-
- System::print2("VCPKG built-in triplets:\n");
- for (auto* triplet : triplets_per_location[fs::u8string(paths.triplets)])
- {
- System::print2(" ", triplet->name, '\n');
- }
- triplets_per_location.erase(fs::u8string(paths.triplets));
-
- System::print2("\nVCPKG community triplets:\n");
- for (auto* triplet : triplets_per_location[fs::u8string(paths.community_triplets)])
- {
- System::print2(" ", triplet->name, '\n');
- }
- triplets_per_location.erase(fs::u8string(paths.community_triplets));
-
- for (auto&& kv_pair : triplets_per_location)
- {
- System::print2("\nOverlay triplets from ", kv_pair.first, ":\n");
- for (auto* triplet : kv_pair.second)
- {
- System::print2(" ", triplet->name, '\n');
- }
- }
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
-
- if (args.command_arguments.empty())
- {
- print_usage();
- Checks::exit_success(VCPKG_LINE_INFO);
- }
- const auto& topic = args.command_arguments[0];
- if (topic == "triplets" || topic == "triple")
- {
- help_topic_valid_triplet(paths);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- auto it_topic = Util::find_if(topics, [&](const Topic& t) { return t.name == topic; });
- if (it_topic != topics.end())
- {
- it_topic->print(paths);
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- System::print2(System::Color::error, "Error: unknown topic ", topic, '\n');
- help_topics(paths);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- void HelpCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Help::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/input.cpp b/toolsrc/src/vcpkg/input.cpp
deleted file mode 100644
index 0d7a9fd7d..000000000
--- a/toolsrc/src/vcpkg/input.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/packagespec.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg
-{
- PackageSpec Input::check_and_get_package_spec(std::string&& spec_string,
- Triplet default_triplet,
- CStringView example_text)
- {
- const std::string as_lowercase = Strings::ascii_to_lowercase(std::move(spec_string));
- auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet);
- if (const auto spec = expected_spec.get())
- {
- return PackageSpec{spec->package_spec};
- }
-
- // Intentionally show the lowercased string
- System::print2(System::Color::error, expected_spec.error());
- System::print2(example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- void Input::check_triplet(Triplet t, const VcpkgPaths& paths)
- {
- if (!paths.is_valid_triplet(t))
- {
- System::print2(System::Color::error, "Error: invalid triplet: ", t, '\n');
- Metrics::g_metrics.lock()->track_property("error", "invalid triplet: " + t.to_string());
- Help::help_topic_valid_triplet(paths);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- FullPackageSpec Input::check_and_get_full_package_spec(std::string&& full_package_spec_as_string,
- Triplet default_triplet,
- CStringView example_text)
- {
- const std::string as_lowercase = Strings::ascii_to_lowercase(std::move(full_package_spec_as_string));
- auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet);
- if (const auto spec = expected_spec.get())
- {
- return *spec;
- }
-
- // Intentionally show the lowercased string
- System::print2(System::Color::error, expected_spec.error());
- System::print2(example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-}
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
deleted file mode 100644
index 59212d651..000000000
--- a/toolsrc/src/vcpkg/install.cpp
+++ /dev/null
@@ -1,1105 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binarycaching.h>
-#include <vcpkg/build.h>
-#include <vcpkg/cmakevars.h>
-#include <vcpkg/commands.setinstalled.h>
-#include <vcpkg/configuration.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/install.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/remove.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg::Install
-{
- using namespace vcpkg;
- using namespace Dependencies;
-
- using file_pack = std::pair<std::string, std::string>;
-
- InstallDir InstallDir::from_destination_root(const fs::path& destination_root,
- const std::string& destination_subdirectory,
- const fs::path& listfile)
- {
- InstallDir dirs;
- dirs.m_destination = destination_root / destination_subdirectory;
- dirs.m_destination_subdirectory = destination_subdirectory;
- dirs.m_listfile = listfile;
- return dirs;
- }
-
- const fs::path& InstallDir::destination() const { return this->m_destination; }
-
- const std::string& InstallDir::destination_subdirectory() const { return this->m_destination_subdirectory; }
-
- const fs::path& InstallDir::listfile() const { return this->m_listfile; }
-
- void install_package_and_write_listfile(const VcpkgPaths& paths,
- const PackageSpec& spec,
- const InstallDir& destination_dir)
- {
- auto& fs = paths.get_filesystem();
- auto source_dir = paths.package_dir(spec);
- Checks::check_exit(VCPKG_LINE_INFO,
- fs.exists(source_dir),
- Strings::concat("Source directory ", fs::u8string(source_dir), "does not exist"));
- auto files = fs.get_files_recursive(source_dir);
- install_files_and_write_listfile(fs, source_dir, files, destination_dir);
- }
- void install_files_and_write_listfile(Files::Filesystem& fs,
- const fs::path& source_dir,
- const std::vector<fs::path>& files,
- const InstallDir& destination_dir)
- {
- std::vector<std::string> output;
- std::error_code ec;
-
- const size_t prefix_length = fs::generic_u8string(source_dir).size();
- const fs::path& destination = destination_dir.destination();
- const std::string& destination_subdirectory = destination_dir.destination_subdirectory();
- const fs::path& listfile = destination_dir.listfile();
-
- fs.create_directories(destination, ec);
- Checks::check_exit(
- VCPKG_LINE_INFO, !ec, "Could not create destination directory %s", fs::u8string(destination));
- const fs::path listfile_parent = listfile.parent_path();
- fs.create_directories(listfile_parent, ec);
- Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directory for listfile %s", fs::u8string(listfile));
-
- output.push_back(Strings::format(R"(%s/)", destination_subdirectory));
- for (auto&& file : files)
- {
- const auto status = fs.symlink_status(file, ec);
- if (ec)
- {
- System::print2(System::Color::error, "failed: ", fs::u8string(file), ": ", ec.message(), "\n");
- continue;
- }
-
- const std::string filename = fs::generic_u8string(file.filename());
- if (fs::is_regular_file(status) && (Strings::case_insensitive_ascii_equals(filename, "CONTROL") ||
- Strings::case_insensitive_ascii_equals(filename, "vcpkg.json") ||
- Strings::case_insensitive_ascii_equals(filename, "BUILD_INFO")))
- {
- // Do not copy the control file or manifest file
- continue;
- }
-
- const std::string suffix = fs::generic_u8string(file).substr(prefix_length + 1);
- const fs::path target = destination / suffix;
-
- switch (status.type())
- {
- case fs::file_type::directory:
- {
- fs.create_directory(target, ec);
- if (ec)
- {
- System::printf(System::Color::error, "failed: %s: %s\n", fs::u8string(target), ec.message());
- }
-
- // Trailing backslash for directories
- output.push_back(Strings::format(R"(%s/%s/)", destination_subdirectory, suffix));
- break;
- }
- case fs::file_type::regular:
- {
- if (fs.exists(target))
- {
- System::print2(System::Color::warning,
- "File ",
- fs::u8string(target),
- " was already present and will be overwritten\n");
- }
- fs.copy_file(file, target, fs::copy_options::overwrite_existing, ec);
- if (ec)
- {
- System::printf(System::Color::error, "failed: %s: %s\n", fs::u8string(target), ec.message());
- }
- output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix));
- break;
- }
- case fs::file_type::symlink:
- {
- if (fs.exists(target))
- {
- System::print2(System::Color::warning,
- "File ",
- fs::u8string(target),
- " was already present and will be overwritten\n");
- }
- fs.copy_symlink(file, target, ec);
- if (ec)
- {
- System::printf(System::Color::error, "failed: %s: %s\n", fs::u8string(target), ec.message());
- }
- output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix));
- break;
- }
- default:
- System::printf(System::Color::error, "failed: %s: cannot handle file type\n", fs::u8string(file));
- break;
- }
- }
-
- std::sort(output.begin(), output.end());
-
- fs.write_lines(listfile, output, VCPKG_LINE_INFO);
- }
-
- static std::vector<file_pack> extract_files_in_triplet(
- const std::vector<StatusParagraphAndAssociatedFiles>& pgh_and_files,
- Triplet triplet,
- const size_t remove_chars = 0)
- {
- std::vector<file_pack> output;
- for (const StatusParagraphAndAssociatedFiles& t : pgh_and_files)
- {
- if (t.pgh.package.spec.triplet() != triplet)
- {
- continue;
- }
-
- const std::string name = t.pgh.package.displayname();
-
- for (const std::string& file : t.files)
- {
- output.emplace_back(file_pack{std::string(file, remove_chars), name});
- }
- }
-
- std::sort(output.begin(), output.end(), [](const file_pack& lhs, const file_pack& rhs) {
- return lhs.first < rhs.first;
- });
- return output;
- }
-
- static SortedVector<std::string> build_list_of_package_files(const Files::Filesystem& fs,
- const fs::path& package_dir)
- {
- const std::vector<fs::path> package_file_paths = fs.get_files_recursive(package_dir);
- const size_t package_remove_char_count = package_dir.generic_string().size() + 1; // +1 for the slash
- auto package_files = Util::fmap(package_file_paths, [package_remove_char_count](const fs::path& path) {
- return std::string(path.generic_string(), package_remove_char_count);
- });
-
- return SortedVector<std::string>(std::move(package_files));
- }
-
- static SortedVector<file_pack> build_list_of_installed_files(
- const std::vector<StatusParagraphAndAssociatedFiles>& pgh_and_files, Triplet triplet)
- {
- const size_t installed_remove_char_count = triplet.canonical_name().size() + 1; // +1 for the slash
- std::vector<file_pack> installed_files =
- extract_files_in_triplet(pgh_and_files, triplet, installed_remove_char_count);
-
- return SortedVector<file_pack>(std::move(installed_files));
- }
-
- InstallResult install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db)
- {
- const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec);
- Triplet triplet = bcf.core_paragraph.spec.triplet();
- const std::vector<StatusParagraphAndAssociatedFiles> pgh_and_files = get_installed_files(paths, *status_db);
-
- const SortedVector<std::string> package_files =
- build_list_of_package_files(paths.get_filesystem(), package_dir);
- const SortedVector<file_pack> installed_files = build_list_of_installed_files(pgh_and_files, triplet);
-
- struct intersection_compare
- {
- // The VS2015 standard library requires comparison operators of T and U
- // to also support comparison of T and T, and of U and U, due to debug checks.
-#if _MSC_VER <= 1910
- bool operator()(const std::string& lhs, const std::string& rhs) { return lhs < rhs; }
- bool operator()(const file_pack& lhs, const file_pack& rhs) { return lhs.first < rhs.first; }
-#endif
- bool operator()(const std::string& lhs, const file_pack& rhs) { return lhs < rhs.first; }
- bool operator()(const file_pack& lhs, const std::string& rhs) { return lhs.first < rhs; }
- };
-
- std::vector<file_pack> intersection;
-
- std::set_intersection(installed_files.begin(),
- installed_files.end(),
- package_files.begin(),
- package_files.end(),
- std::back_inserter(intersection),
- intersection_compare());
-
- std::sort(intersection.begin(), intersection.end(), [](const file_pack& lhs, const file_pack& rhs) {
- return lhs.second < rhs.second;
- });
-
- if (!intersection.empty())
- {
- const fs::path triplet_install_path = paths.installed / triplet.canonical_name();
- System::printf(System::Color::error,
- "The following files are already installed in %s and are in conflict with %s\n\n",
- triplet_install_path.generic_string(),
- bcf.core_paragraph.spec);
-
- auto i = intersection.begin();
- while (i != intersection.end())
- {
- System::print2("Installed by ", i->second, "\n ");
- auto next =
- std::find_if(i, intersection.end(), [i](const auto& val) { return i->second != val.second; });
-
- System::print2(Strings::join("\n ", i, next, [](const file_pack& file) { return file.first; }));
- System::print2("\n\n");
-
- i = next;
- }
-
- return InstallResult::FILE_CONFLICTS;
- }
-
- StatusParagraph source_paragraph;
- source_paragraph.package = bcf.core_paragraph;
- source_paragraph.want = Want::INSTALL;
- source_paragraph.state = InstallState::HALF_INSTALLED;
-
- write_update(paths, source_paragraph);
- status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
-
- std::vector<StatusParagraph> features_spghs;
- for (auto&& feature : bcf.features)
- {
- features_spghs.emplace_back();
-
- StatusParagraph& feature_paragraph = features_spghs.back();
- feature_paragraph.package = feature;
- feature_paragraph.want = Want::INSTALL;
- feature_paragraph.state = InstallState::HALF_INSTALLED;
-
- write_update(paths, feature_paragraph);
- status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
- }
-
- const InstallDir install_dir = InstallDir::from_destination_root(
- paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph));
-
- install_package_and_write_listfile(paths, bcf.core_paragraph.spec, install_dir);
-
- source_paragraph.state = InstallState::INSTALLED;
- write_update(paths, source_paragraph);
- status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
-
- for (auto&& feature_paragraph : features_spghs)
- {
- feature_paragraph.state = InstallState::INSTALLED;
- write_update(paths, feature_paragraph);
- status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
- }
-
- return InstallResult::SUCCESS;
- }
-
- using Build::BuildResult;
- using Build::ExtendedBuildResult;
-
- static ExtendedBuildResult perform_install_plan_action(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- InstallPlanAction& action,
- StatusParagraphs& status_db,
- IBinaryProvider& binaries_provider,
- const Build::IBuildLogsRecorder& build_logs_recorder)
- {
- const InstallPlanType& plan_type = action.plan_type;
- const std::string display_name = action.spec.to_string();
- const std::string display_name_with_features = action.displayname();
-
- const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED;
- const bool use_head_version = Util::Enum::to_bool(action.build_options.use_head_version);
-
- if (plan_type == InstallPlanType::ALREADY_INSTALLED)
- {
- if (use_head_version && is_user_requested)
- System::printf(System::Color::warning,
- "Package %s is already installed -- not building from HEAD\n",
- display_name);
- else
- System::printf(System::Color::success, "Package %s is already installed\n", display_name);
- return BuildResult::SUCCEEDED;
- }
-
- if (plan_type == InstallPlanType::BUILD_AND_INSTALL)
- {
- if (use_head_version)
- System::printf("Building package %s from HEAD...\n", display_name_with_features);
- else
- System::printf("Building package %s...\n", display_name_with_features);
-
- auto result = Build::build_package(args, paths, action, binaries_provider, build_logs_recorder, status_db);
-
- if (BuildResult::DOWNLOADED == result.code)
- {
- System::print2(
- System::Color::success, "Downloaded sources for package ", display_name_with_features, "\n");
- return result;
- }
-
- if (result.code != Build::BuildResult::SUCCEEDED)
- {
- System::print2(System::Color::error, Build::create_error_message(result.code, action.spec), "\n");
- return result;
- }
-
- System::printf("Building package %s... done\n", display_name_with_features);
-
- auto bcf = std::make_unique<BinaryControlFile>(
- Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO));
- System::printf("Installing package %s...\n", display_name_with_features);
- const auto install_result = install_package(paths, *bcf, &status_db);
- BuildResult code;
- switch (install_result)
- {
- case InstallResult::SUCCESS:
- System::printf(
- System::Color::success, "Installing package %s... done\n", display_name_with_features);
- code = BuildResult::SUCCEEDED;
- break;
- case InstallResult::FILE_CONFLICTS: code = BuildResult::FILE_CONFLICTS; break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- if (action.build_options.clean_packages == Build::CleanPackages::YES)
- {
- auto& fs = paths.get_filesystem();
- const fs::path package_dir = paths.package_dir(action.spec);
- fs.remove_all(package_dir, VCPKG_LINE_INFO);
- }
-
- if (action.build_options.clean_downloads == Build::CleanDownloads::YES)
- {
- auto& fs = paths.get_filesystem();
- const fs::path download_dir = paths.downloads;
- std::error_code ec;
- for (auto& p : fs.get_files_non_recursive(download_dir))
- {
- if (!fs.is_directory(p))
- {
- fs.remove(p, VCPKG_LINE_INFO);
- }
- }
- }
-
- return {code, std::move(bcf)};
- }
-
- if (plan_type == InstallPlanType::EXCLUDED)
- {
- System::printf(System::Color::warning, "Package %s is excluded\n", display_name);
- return BuildResult::EXCLUDED;
- }
-
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- void InstallSummary::print() const
- {
- System::print2("RESULTS\n");
-
- for (const SpecSummary& result : this->results)
- {
- System::printf(" %s: %s: %s\n", result.spec, Build::to_string(result.build_result.code), result.timing);
- }
-
- std::map<BuildResult, int> summary;
- for (const BuildResult& v : Build::BUILD_RESULT_VALUES)
- {
- summary[v] = 0;
- }
-
- for (const SpecSummary& r : this->results)
- {
- summary[r.build_result.code]++;
- }
-
- System::print2("\nSUMMARY\n");
- for (const std::pair<const BuildResult, int>& entry : summary)
- {
- System::printf(" %s: %d\n", Build::to_string(entry.first), entry.second);
- }
- }
-
- struct TrackedPackageInstallGuard
- {
- SpecSummary* current_summary = nullptr;
- Chrono::ElapsedTimer build_timer = Chrono::ElapsedTimer::create_started();
-
- TrackedPackageInstallGuard(const size_t action_index,
- const size_t action_count,
- std::vector<SpecSummary>& results,
- const PackageSpec& spec)
- {
- results.emplace_back(spec, nullptr);
- current_summary = &results.back();
- System::printf("Starting package %zd/%zd: %s\n", action_index, action_count, spec.to_string());
- }
-
- ~TrackedPackageInstallGuard()
- {
- current_summary->timing = build_timer.elapsed();
- System::printf(
- "Elapsed time for package %s: %s\n", current_summary->spec.to_string(), current_summary->timing);
- }
-
- TrackedPackageInstallGuard(const TrackedPackageInstallGuard&) = delete;
- TrackedPackageInstallGuard& operator=(const TrackedPackageInstallGuard&) = delete;
- };
-
- InstallSummary perform(const VcpkgCmdArguments& args,
- ActionPlan& action_plan,
- const KeepGoing keep_going,
- const VcpkgPaths& paths,
- StatusParagraphs& status_db,
- IBinaryProvider& binaryprovider,
- const Build::IBuildLogsRecorder& build_logs_recorder,
- const CMakeVars::CMakeVarProvider& var_provider)
- {
- std::vector<SpecSummary> results;
- const size_t action_count = action_plan.remove_actions.size() + action_plan.install_actions.size();
- size_t action_index = 1;
-
- const auto timer = Chrono::ElapsedTimer::create_started();
- for (auto&& action : action_plan.remove_actions)
- {
- TrackedPackageInstallGuard this_install(action_index++, action_count, results, action.spec);
- Remove::perform_remove_plan_action(paths, action, Remove::Purge::YES, &status_db);
- }
-
- for (auto&& action : action_plan.already_installed)
- {
- results.emplace_back(action.spec, &action);
- results.back().build_result =
- perform_install_plan_action(args, paths, action, status_db, binaryprovider, build_logs_recorder);
- }
-
- Build::compute_all_abis(paths, action_plan, var_provider, status_db);
-
- auto to_prefetch = Util::fmap(action_plan.install_actions, [](const auto& x) { return &x; });
- binaryprovider.prefetch(paths, to_prefetch);
-
- for (auto&& action : action_plan.install_actions)
- {
- TrackedPackageInstallGuard this_install(action_index++, action_count, results, action.spec);
- auto result =
- perform_install_plan_action(args, paths, action, status_db, binaryprovider, build_logs_recorder);
- if (result.code != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO)
- {
- System::print2(Build::create_user_troubleshooting_message(action.spec), '\n');
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- this_install.current_summary->action = &action;
- this_install.current_summary->build_result = std::move(result);
- }
-
- return InstallSummary{std::move(results), timer.to_string()};
- }
-
- static constexpr StringLiteral OPTION_DRY_RUN = "dry-run";
- static constexpr StringLiteral OPTION_USE_HEAD_VERSION = "head";
- static constexpr StringLiteral OPTION_NO_DOWNLOADS = "no-downloads";
- static constexpr StringLiteral OPTION_ONLY_BINARYCACHING = "only-binarycaching";
- static constexpr StringLiteral OPTION_ONLY_DOWNLOADS = "only-downloads";
- static constexpr StringLiteral OPTION_RECURSE = "recurse";
- static constexpr StringLiteral OPTION_KEEP_GOING = "keep-going";
- static constexpr StringLiteral OPTION_EDITABLE = "editable";
- static constexpr StringLiteral OPTION_XUNIT = "x-xunit";
- static constexpr StringLiteral OPTION_USE_ARIA2 = "x-use-aria2";
- static constexpr StringLiteral OPTION_CLEAN_AFTER_BUILD = "clean-after-build";
- static constexpr StringLiteral OPTION_WRITE_PACKAGES_CONFIG = "x-write-nuget-packages-config";
- static constexpr StringLiteral OPTION_MANIFEST_NO_DEFAULT_FEATURES = "x-no-default-features";
- static constexpr StringLiteral OPTION_MANIFEST_FEATURE = "x-feature";
- static constexpr StringLiteral OPTION_PROHIBIT_BACKCOMPAT_FEATURES = "x-prohibit-backcompat-features";
-
- static constexpr std::array<CommandSwitch, 11> INSTALL_SWITCHES = {{
- {OPTION_DRY_RUN, "Do not actually build or install"},
- {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"},
- {OPTION_NO_DOWNLOADS, "Do not download new sources"},
- {OPTION_ONLY_DOWNLOADS, "Download sources but don't build packages"},
- {OPTION_ONLY_BINARYCACHING, "Fail if cached binaries are not available"},
- {OPTION_RECURSE, "Allow removal of packages as part of installation"},
- {OPTION_KEEP_GOING, "Continue installing packages on failure"},
- {OPTION_EDITABLE, "Disable source re-extraction and binary caching for libraries on the command line"},
-
- {OPTION_USE_ARIA2, "Use aria2 to perform download tasks"},
- {OPTION_CLEAN_AFTER_BUILD, "Clean buildtrees, packages and downloads after building each package"},
- {OPTION_PROHIBIT_BACKCOMPAT_FEATURES,
- "(experimental) Fail install if a package attempts to use a deprecated feature"},
- }};
- static constexpr std::array<CommandSwitch, 11> MANIFEST_INSTALL_SWITCHES = {{
- {OPTION_DRY_RUN, "Do not actually build or install"},
- {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"},
- {OPTION_NO_DOWNLOADS, "Do not download new sources"},
- {OPTION_ONLY_DOWNLOADS, "Download sources but don't build packages"},
- {OPTION_ONLY_BINARYCACHING, "Fail if cached binaries are not available"},
- {OPTION_RECURSE, "Allow removal of packages as part of installation"},
- {OPTION_KEEP_GOING, "Continue installing packages on failure"},
- {OPTION_EDITABLE, "Disable source re-extraction and binary caching for libraries on the command line"},
- {OPTION_USE_ARIA2, "Use aria2 to perform download tasks"},
- {OPTION_CLEAN_AFTER_BUILD, "Clean buildtrees, packages and downloads after building each package"},
- {OPTION_MANIFEST_NO_DEFAULT_FEATURES, "Don't install the default features from the manifest."},
- }};
-
- static constexpr std::array<CommandSetting, 2> INSTALL_SETTINGS = {{
- {OPTION_XUNIT, "File to output results in XUnit format (Internal use)"},
- {OPTION_WRITE_PACKAGES_CONFIG,
- "Writes out a NuGet packages.config-formatted file for use with external binary caching.\nSee `vcpkg help "
- "binarycaching` for more information."},
- }};
-
- static constexpr std::array<CommandMultiSetting, 1> MANIFEST_INSTALL_MULTISETTINGS = {{
- {OPTION_MANIFEST_FEATURE, "A feature from the manifest to install."},
- }};
-
- std::vector<std::string> get_all_port_names(const VcpkgPaths& paths)
- {
- auto sources_and_errors = Paragraphs::try_load_all_registry_ports(paths);
-
- return Util::fmap(sources_and_errors.paragraphs, Paragraphs::get_name_of_control_file);
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("install zlib zlib:x64-windows curl boost"),
- 1,
- SIZE_MAX,
- {INSTALL_SWITCHES, INSTALL_SETTINGS},
- &get_all_port_names,
- };
-
- const CommandStructure MANIFEST_COMMAND_STRUCTURE = {
- create_example_string("install --triplet x64-windows"),
- 0,
- 0,
- {MANIFEST_INSTALL_SWITCHES, INSTALL_SETTINGS, MANIFEST_INSTALL_MULTISETTINGS},
- nullptr,
- };
-
- static void print_cmake_information(const BinaryParagraph& bpgh, const VcpkgPaths& paths)
- {
- auto usage = get_cmake_usage(bpgh, paths);
-
- if (!usage.message.empty())
- {
- System::print2(usage.message);
- }
- }
-
- CMakeUsageInfo get_cmake_usage(const BinaryParagraph& bpgh, const VcpkgPaths& paths)
- {
- static const std::regex cmake_library_regex(R"(\badd_library\(([^\$\s\)]+)\s)",
- std::regex_constants::ECMAScript);
-
- CMakeUsageInfo ret;
-
- auto& fs = paths.get_filesystem();
-
- auto usage_file = paths.installed / bpgh.spec.triplet().canonical_name() / "share" / bpgh.spec.name() / "usage";
- if (fs.exists(usage_file))
- {
- ret.usage_file = true;
- auto maybe_contents = fs.read_contents(usage_file);
- if (auto p_contents = maybe_contents.get())
- {
- ret.message = std::move(*p_contents);
- ret.message.push_back('\n');
- }
- return ret;
- }
-
- auto files = fs.read_lines(paths.listfile_path(bpgh));
- if (auto p_lines = files.get())
- {
- std::map<std::string, std::string> config_files;
- std::map<std::string, std::vector<std::string>> library_targets;
- bool is_header_only = true;
- std::string header_path;
-
- for (auto&& suffix : *p_lines)
- {
- if (Strings::case_insensitive_ascii_contains(suffix, "/share/") && Strings::ends_with(suffix, ".cmake"))
- {
- // CMake file is inside the share folder
- auto path = paths.installed / suffix;
- auto maybe_contents = fs.read_contents(path);
- auto find_package_name = fs::u8string(path.parent_path().filename());
- if (auto p_contents = maybe_contents.get())
- {
- std::sregex_iterator next(p_contents->begin(), p_contents->end(), cmake_library_regex);
- std::sregex_iterator last;
-
- while (next != last)
- {
- auto match = *next;
- auto& targets = library_targets[find_package_name];
- if (std::find(targets.cbegin(), targets.cend(), match[1]) == targets.cend())
- targets.push_back(match[1]);
- ++next;
- }
- }
-
- auto filename = fs::u8string(fs::u8path(suffix).filename());
-
- if (Strings::ends_with(filename, "Config.cmake"))
- {
- auto root = filename.substr(0, filename.size() - 12);
- if (Strings::case_insensitive_ascii_equals(root, find_package_name))
- config_files[find_package_name] = root;
- }
- else if (Strings::ends_with(filename, "-config.cmake"))
- {
- auto root = filename.substr(0, filename.size() - 13);
- if (Strings::case_insensitive_ascii_equals(root, find_package_name))
- config_files[find_package_name] = root;
- }
- }
- if (Strings::case_insensitive_ascii_contains(suffix, "/lib/") ||
- Strings::case_insensitive_ascii_contains(suffix, "/bin/"))
- {
- if (!Strings::ends_with(suffix, ".pc") && !Strings::ends_with(suffix, "/")) is_header_only = false;
- }
-
- if (is_header_only && header_path.empty())
- {
- auto it = suffix.find("/include/");
- if (it != std::string::npos && !Strings::ends_with(suffix, "/"))
- {
- header_path = suffix.substr(it + 9);
- }
- }
- }
-
- ret.header_only = is_header_only;
-
- if (library_targets.empty())
- {
- if (is_header_only && !header_path.empty())
- {
- static auto cmakeify = [](std::string name) {
- auto n = Strings::ascii_to_uppercase(Strings::replace_all(std::move(name), "-", "_"));
- if (n.empty() || Parse::ParserBase::is_ascii_digit(n[0]))
- {
- n.insert(n.begin(), '_');
- }
- return n;
- };
-
- const auto name = cmakeify(bpgh.spec.name());
- auto msg = Strings::concat(
- "The package ", bpgh.spec, " is header only and can be used from CMake via:\n\n");
- Strings::append(msg, " find_path(", name, "_INCLUDE_DIRS \"", header_path, "\")\n");
- Strings::append(msg, " target_include_directories(main PRIVATE ${", name, "_INCLUDE_DIRS})\n\n");
-
- ret.message = std::move(msg);
- }
- }
- else
- {
- auto msg = Strings::concat("The package ", bpgh.spec, " provides CMake targets:\n\n");
-
- for (auto&& library_target_pair : library_targets)
- {
- auto config_it = config_files.find(library_target_pair.first);
- if (config_it != config_files.end())
- Strings::append(msg, " find_package(", config_it->second, " CONFIG REQUIRED)\n");
- else
- Strings::append(msg, " find_package(", library_target_pair.first, " CONFIG REQUIRED)\n");
-
- std::sort(library_target_pair.second.begin(),
- library_target_pair.second.end(),
- [](const std::string& l, const std::string& r) {
- if (l.size() < r.size()) return true;
- if (l.size() > r.size()) return false;
- return l < r;
- });
-
- if (library_target_pair.second.size() <= 4)
- {
- Strings::append(msg,
- " target_link_libraries(main PRIVATE ",
- Strings::join(" ", library_target_pair.second),
- ")\n\n");
- }
- else
- {
- auto omitted = library_target_pair.second.size() - 4;
- library_target_pair.second.erase(library_target_pair.second.begin() + 4,
- library_target_pair.second.end());
- msg += Strings::format(" # Note: %zd target(s) were omitted.\n"
- " target_link_libraries(main PRIVATE %s)\n\n",
- omitted,
- Strings::join(" ", library_target_pair.second));
- }
- }
- ret.message = std::move(msg);
- }
- ret.cmake_targets_map = std::move(library_targets);
- }
- return ret;
- }
-
- ///
- /// <summary>
- /// Run "install" command.
- /// </summary>
- ///
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
- {
- // input sanitization
- const ParsedArguments options =
- args.parse_arguments(paths.manifest_mode_enabled() ? MANIFEST_COMMAND_STRUCTURE : COMMAND_STRUCTURE);
-
- auto binaryprovider = create_binary_provider_from_configs(args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
-
- const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
- const bool use_head_version = Util::Sets::contains(options.switches, (OPTION_USE_HEAD_VERSION));
- const bool no_downloads = Util::Sets::contains(options.switches, (OPTION_NO_DOWNLOADS));
- const bool only_downloads = Util::Sets::contains(options.switches, (OPTION_ONLY_DOWNLOADS));
- const bool no_build_missing = Util::Sets::contains(options.switches, OPTION_ONLY_BINARYCACHING);
- const bool is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE));
- const bool is_editable = Util::Sets::contains(options.switches, (OPTION_EDITABLE)) || !args.cmake_args.empty();
- const bool use_aria2 = Util::Sets::contains(options.switches, (OPTION_USE_ARIA2));
- const bool clean_after_build = Util::Sets::contains(options.switches, (OPTION_CLEAN_AFTER_BUILD));
- const KeepGoing keep_going =
- to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING) || only_downloads);
- const bool prohibit_backcompat_features =
- Util::Sets::contains(options.switches, (OPTION_PROHIBIT_BACKCOMPAT_FEATURES));
-
- auto& fs = paths.get_filesystem();
-
- Build::DownloadTool download_tool = Build::DownloadTool::BUILT_IN;
- if (use_aria2) download_tool = Build::DownloadTool::ARIA2;
-
- const Build::BuildPackageOptions install_plan_options = {
- Util::Enum::to_enum<Build::BuildMissing>(!no_build_missing),
- Util::Enum::to_enum<Build::UseHeadVersion>(use_head_version),
- Util::Enum::to_enum<Build::AllowDownloads>(!no_downloads),
- Util::Enum::to_enum<Build::OnlyDownloads>(only_downloads),
- Util::Enum::to_enum<Build::CleanBuildtrees>(clean_after_build),
- Util::Enum::to_enum<Build::CleanPackages>(clean_after_build),
- Util::Enum::to_enum<Build::CleanDownloads>(clean_after_build),
- download_tool,
- Build::PurgeDecompressFailure::NO,
- Util::Enum::to_enum<Build::Editable>(is_editable),
- prohibit_backcompat_features ? Build::BackcompatFeatures::PROHIBIT : Build::BackcompatFeatures::ALLOW,
- };
-
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
- auto var_provider_storage = CMakeVars::make_triplet_cmake_var_provider(paths);
- auto& var_provider = *var_provider_storage;
-
- if (auto manifest = paths.get_manifest().get())
- {
- Optional<fs::path> pkgsconfig;
- auto it_pkgsconfig = options.settings.find(OPTION_WRITE_PACKAGES_CONFIG);
- if (it_pkgsconfig != options.settings.end())
- {
- Metrics::g_metrics.lock()->track_property("x-write-nuget-packages-config", "defined");
- pkgsconfig = fs::u8path(it_pkgsconfig->second);
- }
- const auto& manifest_path = paths.get_manifest_path().value_or_exit(VCPKG_LINE_INFO);
- auto maybe_manifest_scf = SourceControlFile::parse_manifest_file(manifest_path, *manifest);
- if (!maybe_manifest_scf)
- {
- print_error_message(maybe_manifest_scf.error());
- System::print2("See https://github.com/Microsoft/vcpkg/tree/master/docs/users/manifests.md for "
- "more information.\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- auto& manifest_scf = *maybe_manifest_scf.value_or_exit(VCPKG_LINE_INFO);
-
- if (auto maybe_error = manifest_scf.check_against_feature_flags(manifest_path, paths.get_feature_flags()))
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, maybe_error.value_or_exit(VCPKG_LINE_INFO));
- }
-
- std::vector<std::string> features;
- auto manifest_feature_it = options.multisettings.find(OPTION_MANIFEST_FEATURE);
- if (manifest_feature_it != options.multisettings.end())
- {
- features.insert(features.end(), manifest_feature_it->second.begin(), manifest_feature_it->second.end());
- }
- auto core_it = Util::find(features, "core");
- if (core_it == features.end())
- {
- if (!Util::Sets::contains(options.switches, OPTION_MANIFEST_NO_DEFAULT_FEATURES))
- features.push_back("default");
- }
- else
- {
- // remove "core" because resolve_deps_as_top_level uses default-inversion
- features.erase(core_it);
- }
-
- if (!manifest_scf.core_paragraph->overrides.empty())
- {
- Metrics::g_metrics.lock()->track_property("manifest_overrides", "defined");
- }
- if (auto p_baseline = manifest_scf.core_paragraph->builtin_baseline.get())
- {
- Metrics::g_metrics.lock()->track_property("manifest_baseline", "defined");
- if (p_baseline->size() != 40 || !std::all_of(p_baseline->begin(), p_baseline->end(), [](char ch) {
- return (ch >= 'a' || ch <= 'f') || Parse::ParserBase::is_ascii_digit(ch);
- }))
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Error: the top-level builtin-baseline (%s) was not a valid commit sha: "
- "expected 40 lowercase hexadecimal characters.\n%s\n",
- *p_baseline,
- paths.get_current_git_sha_message());
- }
-
- paths.get_configuration().registry_set.experimental_set_builtin_registry_baseline(*p_baseline);
- }
- auto verprovider = PortFileProvider::make_versioned_portfile_provider(paths);
- auto baseprovider = PortFileProvider::make_baseline_provider(paths);
- auto oprovider = PortFileProvider::make_overlay_provider(paths, args.overlay_ports);
-
- auto install_plan =
- Dependencies::create_versioned_install_plan(*verprovider,
- *baseprovider,
- *oprovider,
- var_provider,
- manifest_scf.core_paragraph->dependencies,
- manifest_scf.core_paragraph->overrides,
- {manifest_scf.core_paragraph->name, default_triplet})
- .value_or_exit(VCPKG_LINE_INFO);
-
- for (InstallPlanAction& action : install_plan.install_actions)
- {
- action.build_options = install_plan_options;
- action.build_options.use_head_version = Build::UseHeadVersion::NO;
- action.build_options.editable = Build::Editable::NO;
- }
-
- Commands::SetInstalled::perform_and_exit_ex(args,
- paths,
- provider,
- *binaryprovider,
- var_provider,
- std::move(install_plan),
- dry_run ? Commands::DryRun::Yes : Commands::DryRun::No,
- pkgsconfig);
- }
-
- const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_full_package_spec(
- std::string(arg), default_triplet, COMMAND_STRUCTURE.example_text);
- });
-
- for (auto&& spec : specs)
- {
- Input::check_triplet(spec.package_spec.triplet(), paths);
- }
-
- // create the plan
- System::print2("Computing installation plan...\n");
- StatusParagraphs status_db = database_load_check(paths);
-
- // Note: action_plan will hold raw pointers to SourceControlFileLocations from this map
- auto action_plan = Dependencies::create_feature_install_plan(provider, var_provider, specs, status_db);
-
- for (auto&& action : action_plan.install_actions)
- {
- action.build_options = install_plan_options;
- if (action.request_type != RequestType::USER_REQUESTED)
- {
- action.build_options.use_head_version = Build::UseHeadVersion::NO;
- action.build_options.editable = Build::Editable::NO;
- }
- }
-
- var_provider.load_tag_vars(action_plan, provider);
-
- // install plan will be empty if it is already installed - need to change this at status paragraph part
- Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty");
-
- // log the plan
- std::string specs_string;
- for (auto&& remove_action : action_plan.remove_actions)
- {
- if (!specs_string.empty()) specs_string.push_back(',');
- specs_string += "R$" + Hash::get_string_hash(remove_action.spec.to_string(), Hash::Algorithm::Sha256);
- }
-
- for (auto&& install_action : action_plan.install_actions)
- {
- if (!specs_string.empty()) specs_string.push_back(',');
- specs_string += Hash::get_string_hash(install_action.spec.to_string(), Hash::Algorithm::Sha256);
- }
-
-#if defined(_WIN32)
- const auto maybe_common_triplet = common_projection(
- action_plan.install_actions, [](const InstallPlanAction& to_install) { return to_install.spec.triplet(); });
- if (maybe_common_triplet)
- {
- const auto& common_triplet = maybe_common_triplet.value_or_exit(VCPKG_LINE_INFO);
- const auto maybe_common_arch = common_triplet.guess_architecture();
- if (maybe_common_arch)
- {
- const auto maybe_vs_prompt = System::guess_visual_studio_prompt_target_architecture();
- if (maybe_vs_prompt)
- {
- const auto common_arch = maybe_common_arch.value_or_exit(VCPKG_LINE_INFO);
- const auto vs_prompt = maybe_vs_prompt.value_or_exit(VCPKG_LINE_INFO);
- if (common_arch != vs_prompt)
- {
- const auto vs_prompt_view = to_zstring_view(vs_prompt);
- System::print2(vcpkg::System::Color::warning,
- "warning: vcpkg appears to be in a Visual Studio prompt targeting ",
- vs_prompt_view,
- " but is installing packages for ",
- common_triplet.to_string(),
- ". Consider using --triplet ",
- vs_prompt_view,
- "-windows or --triplet ",
- vs_prompt_view,
- "-uwp.\n");
- }
- }
- }
- }
-#endif // defined(_WIN32)
-
- Metrics::g_metrics.lock()->track_property("installplan_1", specs_string);
-
- Dependencies::print_plan(action_plan, is_recursive, paths.builtin_ports_directory());
-
- auto it_pkgsconfig = options.settings.find(OPTION_WRITE_PACKAGES_CONFIG);
- if (it_pkgsconfig != options.settings.end())
- {
- Metrics::g_metrics.lock()->track_property("x-write-nuget-packages-config", "defined");
- Build::compute_all_abis(paths, action_plan, var_provider, status_db);
-
- auto pkgsconfig_path = Files::combine(paths.original_cwd, fs::u8path(it_pkgsconfig->second));
- auto pkgsconfig_contents = generate_nuget_packages_config(action_plan);
- fs.write_contents(pkgsconfig_path, pkgsconfig_contents, VCPKG_LINE_INFO);
- System::print2("Wrote NuGet packages config information to ", fs::u8string(pkgsconfig_path), "\n");
- }
-
- if (dry_run)
- {
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- const InstallSummary summary =
- perform(args,
- action_plan,
- keep_going,
- paths,
- status_db,
- args.binary_caching_enabled() && !only_downloads ? *binaryprovider : null_binary_provider(),
- Build::null_build_logs_recorder(),
- var_provider);
-
- System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
-
- if (keep_going == KeepGoing::YES)
- {
- summary.print();
- }
-
- auto it_xunit = options.settings.find(OPTION_XUNIT);
- if (it_xunit != options.settings.end())
- {
- std::string xunit_doc = "<assemblies><assembly><collection>\n";
-
- xunit_doc += summary.xunit_results();
-
- xunit_doc += "</collection></assembly></assemblies>\n";
- fs.write_contents(fs::u8path(it_xunit->second), xunit_doc, VCPKG_LINE_INFO);
- }
-
- for (auto&& result : summary.results)
- {
- if (!result.action) continue;
- if (result.action->request_type != RequestType::USER_REQUESTED) continue;
- auto bpgh = result.get_binary_paragraph();
- if (!bpgh) continue;
- print_cmake_information(*bpgh, paths);
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void InstallCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- Install::perform_and_exit(args, paths, default_triplet);
- }
-
- SpecSummary::SpecSummary(const PackageSpec& spec, const Dependencies::InstallPlanAction* action)
- : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, action(action)
- {
- }
-
- const BinaryParagraph* SpecSummary::get_binary_paragraph() const
- {
- if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph;
- if (action)
- if (auto p_status = action->installed_package.get())
- {
- return &p_status->core->package;
- }
- return nullptr;
- }
-
- static std::string xunit_result(const PackageSpec& spec, Chrono::ElapsedTime time, BuildResult code)
- {
- std::string message_block;
- const char* result_string = "";
- switch (code)
- {
- case BuildResult::POST_BUILD_CHECKS_FAILED:
- case BuildResult::FILE_CONFLICTS:
- case BuildResult::BUILD_FAILED:
- case BuildResult::CACHE_MISSING:
- result_string = "Fail";
- message_block =
- Strings::format("<failure><message><![CDATA[%s]]></message></failure>", to_string(code));
- break;
- case BuildResult::EXCLUDED:
- case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES:
- result_string = "Skip";
- message_block = Strings::format("<reason><![CDATA[%s]]></reason>", to_string(code));
- break;
- case BuildResult::SUCCEEDED: result_string = "Pass"; break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- return Strings::format(R"(<test name="%s" method="%s" time="%lld" result="%s">%s</test>)"
- "\n",
- spec,
- spec,
- time.as<std::chrono::seconds>().count(),
- result_string,
- message_block);
- }
-
- std::string InstallSummary::xunit_results() const
- {
- std::string xunit_doc;
- for (auto&& result : results)
- {
- xunit_doc += xunit_result(result.spec, result.timing, result.build_result.code);
- }
- return xunit_doc;
- }
-}
diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp
deleted file mode 100644
index e0a4e5017..000000000
--- a/toolsrc/src/vcpkg/metrics.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-#include <vcpkg/base/chrono.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.process.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/commands.version.h>
-#include <vcpkg/metrics.h>
-
-#if defined(_WIN32)
-#pragma comment(lib, "version")
-#pragma comment(lib, "winhttp")
-#endif
-
-namespace vcpkg::Metrics
-{
- Util::LockGuarded<Metrics> g_metrics;
-
- static std::string get_current_date_time()
- {
- auto maybe_time = Chrono::CTime::get_current_date_time();
- if (auto ptime = maybe_time.get())
- {
- return ptime->to_string();
- }
-
- return "";
- }
-
- struct append_hexits
- {
- constexpr static char hex[17] = "0123456789abcdef";
- void operator()(std::string& res, std::uint8_t bits) const
- {
- res.push_back(hex[(bits >> 4) & 0x0F]);
- res.push_back(hex[(bits >> 0) & 0x0F]);
- }
- };
- constexpr char append_hexits::hex[17];
-
- // note: this ignores the bits of these numbers that would be where format and variant go
- static std::string uuid_of_integers(uint64_t top, uint64_t bottom)
- {
- // uuid_field_size in bytes, not hex characters
- constexpr size_t uuid_top_field_size[] = {4, 2, 2};
- constexpr size_t uuid_bottom_field_size[] = {2, 6};
-
- // uuid_field_size in hex characters, not bytes
- constexpr size_t uuid_size = 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12;
-
- constexpr static append_hexits write_byte;
-
- // set the version bits to 4
- top &= 0xFFFF'FFFF'FFFF'0FFFULL;
- top |= 0x0000'0000'0000'4000ULL;
-
- // set the variant bits to 2 (variant one)
- bottom &= 0x3FFF'FFFF'FFFF'FFFFULL;
- bottom |= 0x8000'0000'0000'0000ULL;
-
- std::string res;
- res.reserve(uuid_size);
-
- bool first = true;
- size_t start_byte = 0;
- for (auto field_size : uuid_top_field_size)
- {
- if (!first)
- {
- res.push_back('-');
- }
- first = false;
- for (size_t i = start_byte; i < start_byte + field_size; ++i)
- {
- auto shift = 64 - (i + 1) * 8;
- write_byte(res, (top >> shift) & 0xFF);
- }
- start_byte += field_size;
- }
-
- start_byte = 0;
- for (auto field_size : uuid_bottom_field_size)
- {
- res.push_back('-');
- for (size_t i = start_byte; i < start_byte + field_size; ++i)
- {
- auto shift = 64 - (i + 1) * 8;
- write_byte(res, (bottom >> shift) & 0xFF);
- }
- start_byte += field_size;
- }
-
- return res;
- }
-
- // UUID format version 4, variant 1
- // http://en.wikipedia.org/wiki/Universally_unique_identifier
- // [0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}
- static std::string generate_random_UUID()
- {
- std::random_device rnd{};
- std::uniform_int_distribution<std::uint64_t> uid{};
- return uuid_of_integers(uid(rnd), uid(rnd));
- }
-
- static const std::string& get_session_id()
- {
- static const std::string ID = generate_random_UUID();
- return ID;
- }
-
- static std::string get_os_version_string()
- {
-#if defined(_WIN32)
- std::wstring path;
- path.resize(MAX_PATH);
- const auto n = GetSystemDirectoryW(&path[0], static_cast<UINT>(path.size()));
- path.resize(n);
- path += L"\\kernel32.dll";
-
- const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr);
- if (versz == 0) return "";
-
- std::vector<char> verbuf;
- verbuf.resize(versz);
-
- if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return "";
-
- void* rootblock;
- UINT rootblocksize;
- if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return "";
-
- auto rootblock_ffi = static_cast<VS_FIXEDFILEINFO*>(rootblock);
-
- return Strings::format("%d.%d.%d",
- static_cast<int>(HIWORD(rootblock_ffi->dwProductVersionMS)),
- static_cast<int>(LOWORD(rootblock_ffi->dwProductVersionMS)),
- static_cast<int>(HIWORD(rootblock_ffi->dwProductVersionLS)));
-#else
- return "unknown";
-#endif
- }
-
- struct MetricMessage
- {
- std::string user_id = generate_random_UUID();
- std::string user_timestamp;
- std::string timestamp = get_current_date_time();
-
- Json::Object properties;
- Json::Object measurements;
-
- Json::Array buildtime_names;
- Json::Array buildtime_times;
-
- void track_property(const std::string& name, const std::string& value)
- {
- properties.insert_or_replace(name, Json::Value::string(value));
- }
-
- void track_metric(const std::string& name, double value)
- {
- measurements.insert_or_replace(name, Json::Value::number(value));
- }
-
- void track_buildtime(const std::string& name, double value)
- {
- buildtime_names.push_back(Json::Value::string(name));
- buildtime_times.push_back(Json::Value::number(value));
- }
- void track_feature(const std::string& name, bool value)
- {
- properties.insert("feature-flag-" + name, Json::Value::boolean(value));
- }
-
- std::string format_event_data_template() const
- {
- auto props_plus_buildtimes = properties;
- if (buildtime_names.size() > 0)
- {
- props_plus_buildtimes.insert("buildnames_1", buildtime_names);
- props_plus_buildtimes.insert("buildtimes", buildtime_times);
- }
-
- Json::Array arr = Json::Array();
- Json::Object& obj = arr.push_back(Json::Object());
-
- obj.insert("ver", Json::Value::integer(1));
- obj.insert("name", Json::Value::string("Microsoft.ApplicationInsights.Event"));
- obj.insert("time", Json::Value::string(timestamp));
- obj.insert("sampleRate", Json::Value::number(100.0));
- obj.insert("seq", Json::Value::string("0:0"));
- obj.insert("iKey", Json::Value::string("b4e88960-4393-4dd9-ab8e-97e8fe6d7603"));
- obj.insert("flags", Json::Value::integer(0));
-
- {
- Json::Object& tags = obj.insert("tags", Json::Object());
-
- tags.insert("ai.device.os", Json::Value::string("Other"));
-
- const char* os_name =
-#if defined(_WIN32)
- "Windows";
-#elif defined(__APPLE__)
- "OSX";
-#elif defined(__linux__)
- "Linux";
-#elif defined(__FreeBSD__)
- "FreeBSD";
-#elif defined(__unix__)
- "Unix";
-#else
- "Other";
-#endif
-
- tags.insert("ai.device.osVersion",
- Json::Value::string(Strings::format("%s-%s", os_name, get_os_version_string())));
- tags.insert("ai.session.id", Json::Value::string(get_session_id()));
- tags.insert("ai.user.id", Json::Value::string(user_id));
- tags.insert("ai.user.accountAcquisitionDate", Json::Value::string(user_timestamp));
- }
-
- {
- Json::Object& data = obj.insert("data", Json::Object());
-
- data.insert("baseType", Json::Value::string("EventData"));
- Json::Object& base_data = data.insert("baseData", Json::Object());
-
- base_data.insert("ver", Json::Value::integer(2));
- base_data.insert("name", Json::Value::string("commandline_test7"));
- base_data.insert("properties", std::move(props_plus_buildtimes));
- base_data.insert("measurements", measurements);
- }
-
- return Json::stringify(arr, vcpkg::Json::JsonStyle());
- }
- };
-
- static MetricMessage g_metricmessage;
- static bool g_should_send_metrics =
-#if defined(NDEBUG)
- true
-#else
- false
-#endif
- ;
- static bool g_should_print_metrics = false;
- static bool g_metrics_disabled = false;
-
- std::string get_MAC_user()
- {
-#if defined(_WIN32)
- if (!g_metrics.lock()->metrics_enabled())
- {
- return "{}";
- }
-
- auto getmac = System::cmd_execute_and_capture_output(System::Command("getmac"));
-
- if (getmac.exit_code != 0) return "0";
-
- std::regex mac_regex("([a-fA-F0-9]{2}(-[a-fA-F0-9]{2}){5})");
- std::sregex_iterator next(getmac.output.begin(), getmac.output.end(), mac_regex);
- std::sregex_iterator last;
-
- while (next != last)
- {
- const auto match = *next;
- if (match[0] != "00-00-00-00-00-00")
- {
- return vcpkg::Hash::get_string_hash(match[0].str(), Hash::Algorithm::Sha256);
- }
- ++next;
- }
-
- return "0";
-#else
- return "{}";
-#endif
- }
-
- void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time)
- {
- g_metricmessage.user_id = user_id;
- g_metricmessage.user_timestamp = first_use_time;
- }
-
- void Metrics::init_user_information(std::string& user_id, std::string& first_use_time)
- {
- user_id = generate_random_UUID();
- first_use_time = get_current_date_time();
- }
-
- void Metrics::set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; }
-
- void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; }
-
- void Metrics::set_disabled(bool disabled) { g_metrics_disabled = disabled; }
-
- bool Metrics::metrics_enabled() { return !g_metrics_disabled; }
-
- void Metrics::track_metric(const std::string& name, double value)
- {
- if (!metrics_enabled())
- {
- return;
- }
- g_metricmessage.track_metric(name, value);
- }
-
- void Metrics::track_buildtime(const std::string& name, double value)
- {
- if (!metrics_enabled())
- {
- return;
- }
- g_metricmessage.track_buildtime(name, value);
- }
-
- void Metrics::track_property(const std::string& name, const std::string& value)
- {
- if (!metrics_enabled())
- {
- return;
- }
- g_metricmessage.track_property(name, value);
- }
-
- void Metrics::track_feature(const std::string& name, bool value)
- {
- if (!metrics_enabled())
- {
- return;
- }
- g_metricmessage.track_feature(name, value);
- }
-
- void Metrics::upload(const std::string& payload)
- {
- if (!metrics_enabled())
- {
- return;
- }
-
-#if defined(_WIN32)
- HINTERNET connect = nullptr, request = nullptr;
- BOOL results = FALSE;
-
- const HINTERNET session = WinHttpOpen(
- L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
-
- unsigned long secure_protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
- if (session && WinHttpSetOption(session, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(DWORD)))
- {
- connect = WinHttpConnect(session, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
- }
-
- if (connect)
- {
- request = WinHttpOpenRequest(connect,
- L"POST",
- L"/v2/track",
- nullptr,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- WINHTTP_FLAG_SECURE);
- }
-
- if (request)
- {
- if (MAXDWORD <= payload.size()) abort();
- std::wstring hdrs = L"Content-Type: application/json\r\n";
- std::string& p = const_cast<std::string&>(payload);
- results = WinHttpSendRequest(request,
- hdrs.c_str(),
- static_cast<DWORD>(hdrs.size()),
- static_cast<void*>(&p[0]),
- static_cast<DWORD>(payload.size()),
- static_cast<DWORD>(payload.size()),
- 0);
- }
-
- if (results)
- {
- results = WinHttpReceiveResponse(request, nullptr);
- }
-
- DWORD http_code = 0, junk = sizeof(DWORD);
-
- if (results)
- {
- results = WinHttpQueryHeaders(request,
- WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
- nullptr,
- &http_code,
- &junk,
- WINHTTP_NO_HEADER_INDEX);
- }
-
- std::vector<char> response_buffer;
- if (results)
- {
- DWORD available_data = 0, read_data = 0, total_data = 0;
- while ((results = WinHttpQueryDataAvailable(request, &available_data)) == TRUE && available_data > 0)
- {
- response_buffer.resize(response_buffer.size() + available_data);
-
- results = WinHttpReadData(request, &response_buffer.data()[total_data], available_data, &read_data);
-
- if (!results)
- {
- break;
- }
-
- total_data += read_data;
-
- response_buffer.resize(total_data);
- }
- }
-
- if (!results)
- {
-#ifndef NDEBUG
- __debugbreak();
- auto err = GetLastError();
- std::cerr << "[DEBUG] failed to connect to server: " << err << "\n";
-#endif // NDEBUG
- }
-
- if (request) WinHttpCloseHandle(request);
- if (connect) WinHttpCloseHandle(connect);
- if (session) WinHttpCloseHandle(session);
-#else // ^^^ _WIN32 // !_WIN32 vvv
- (void)payload;
-#endif // ^^^ !_WIN32
- }
-
- void Metrics::flush(Files::Filesystem& fs)
- {
- if (!metrics_enabled())
- {
- return;
- }
-
- const std::string payload = g_metricmessage.format_event_data_template();
- if (g_should_print_metrics) std::cerr << payload << "\n";
- if (!g_should_send_metrics) return;
-
-#if defined(_WIN32)
- wchar_t temp_folder[MAX_PATH];
- GetTempPathW(MAX_PATH, temp_folder);
-
- const fs::path temp_folder_path = fs::path(temp_folder) / "vcpkg";
- const fs::path temp_folder_path_exe =
- temp_folder_path / Strings::format("vcpkg-%s.exe", Commands::Version::base_version());
-#endif
-
- std::error_code ec;
-#if defined(_WIN32)
- fs.create_directories(temp_folder_path, ec);
- if (ec) return;
- fs.copy_file(
- System::get_exe_path_of_current_process(), temp_folder_path_exe, fs::copy_options::skip_existing, ec);
- if (ec) return;
-#else
- if (!fs.exists("/tmp")) return;
- const fs::path temp_folder_path = "/tmp/vcpkg";
- fs.create_directory(temp_folder_path, ignore_errors);
-#endif
- const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt");
- fs.write_contents(vcpkg_metrics_txt_path, payload, ec);
- if (ec) return;
-
-#if defined(_WIN32)
- System::Command builder;
- builder.path_arg(temp_folder_path_exe);
- builder.string_arg("x-upload-metrics");
- builder.path_arg(vcpkg_metrics_txt_path);
- System::cmd_execute_background(builder);
-#else
- // TODO: convert to cmd_execute_background or something.
- auto curl = System::Command("curl")
- .string_arg("https://dc.services.visualstudio.com/v2/track")
- .string_arg("-H")
- .string_arg("Content-Type: application/json")
- .string_arg("-X")
- .string_arg("POST")
- .string_arg("--tlsv1.2")
- .string_arg("--data")
- .string_arg(Strings::concat("@", fs::u8string(vcpkg_metrics_txt_path)))
- .raw_arg(">/dev/null")
- .raw_arg("2>&1");
- auto remove = System::Command("rm").path_arg(vcpkg_metrics_txt_path);
- System::Command cmd_line;
- cmd_line.raw_arg("(").raw_arg(curl.command_line()).raw_arg(";").raw_arg(remove.command_line()).raw_arg(") &");
- System::cmd_execute_clean(cmd_line);
-#endif
- }
-}
diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp
deleted file mode 100644
index 3f35e118e..000000000
--- a/toolsrc/src/vcpkg/packagespec.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/parse.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/packagespec.h>
-#include <vcpkg/paragraphparser.h>
-
-namespace vcpkg
-{
- std::string FeatureSpec::to_string() const
- {
- std::string ret;
- this->to_string(ret);
- return ret;
- }
- void FeatureSpec::to_string(std::string& out) const
- {
- if (feature().empty()) return spec().to_string(out);
- Strings::append(out, name(), '[', feature(), "]:", triplet());
- }
-
- std::vector<FeatureSpec> FullPackageSpec::to_feature_specs(const std::vector<std::string>& default_features,
- const std::vector<std::string>& all_features) const
- {
- std::vector<FeatureSpec> feature_specs;
-
- if (Util::find(features, "*") != features.end())
- {
- feature_specs.emplace_back(package_spec, "core");
- for (const std::string& feature : all_features)
- {
- feature_specs.emplace_back(package_spec, feature);
- }
- }
- else
- {
- bool core = false;
- for (const std::string& feature : features)
- {
- feature_specs.emplace_back(package_spec, feature);
-
- if (!core)
- {
- core = feature == "core";
- }
- }
-
- if (!core)
- {
- feature_specs.emplace_back(package_spec, "core");
-
- for (const std::string& def : default_features)
- {
- feature_specs.emplace_back(package_spec, def);
- }
- }
- }
-
- return feature_specs;
- }
-
- ExpectedS<FullPackageSpec> FullPackageSpec::from_string(const std::string& spec_as_string, Triplet default_triplet)
- {
- return parse_qualified_specifier(spec_as_string)
- .then([&](ParsedQualifiedSpecifier&& p) -> ExpectedS<FullPackageSpec> {
- if (p.platform)
- return "Error: platform specifier not allowed in this context: " + spec_as_string + "\n";
- auto triplet = p.triplet ? Triplet::from_canonical_name(std::move(*p.triplet.get())) : default_triplet;
- return FullPackageSpec({p.name, triplet}, p.features.value_or({}));
- });
- }
-
- std::vector<PackageSpec> PackageSpec::to_package_specs(const std::vector<std::string>& ports, Triplet triplet)
- {
- return Util::fmap(ports, [&](const std::string& spec_as_string) -> PackageSpec {
- return {spec_as_string, triplet};
- });
- }
-
- const std::string& PackageSpec::name() const { return this->m_name; }
-
- Triplet PackageSpec::triplet() const { return this->m_triplet; }
-
- std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); }
-
- std::string PackageSpec::to_string() const { return Strings::format("%s:%s", this->name(), this->triplet()); }
- void PackageSpec::to_string(std::string& s) const { Strings::append(s, this->name(), ':', this->triplet()); }
-
- bool operator==(const PackageSpec& left, const PackageSpec& right)
- {
- return left.name() == right.name() && left.triplet() == right.triplet();
- }
-
- ExpectedS<Features> Features::from_string(const std::string& name)
- {
- return parse_qualified_specifier(name).then([&](ParsedQualifiedSpecifier&& pqs) -> ExpectedS<Features> {
- if (pqs.triplet) return "Error: triplet not allowed in this context: " + name + "\n";
- if (pqs.platform) return "Error: platform specifier not allowed in this context: " + name + "\n";
- return Features{pqs.name, pqs.features.value_or({})};
- });
- }
-
- static bool is_package_name_char(char32_t ch)
- {
- return Parse::ParserBase::is_lower_alpha(ch) || Parse::ParserBase::is_ascii_digit(ch) || ch == '-';
- }
-
- static bool is_feature_name_char(char32_t ch)
- {
- // TODO: we do not intend underscores to be valid, however there is currently a feature using them
- // (libwebp[vwebp_sdl]).
- // TODO: we need to rename this feature, then remove underscores from this list.
- return is_package_name_char(ch) || ch == '_';
- }
-
- ExpectedS<ParsedQualifiedSpecifier> parse_qualified_specifier(StringView input)
- {
- auto parser = Parse::ParserBase(input, "<unknown>");
- auto maybe_pqs = parse_qualified_specifier(parser);
- if (!parser.at_eof()) parser.add_error("expected eof");
- if (auto e = parser.get_error()) return e->format();
- return std::move(maybe_pqs).value_or_exit(VCPKG_LINE_INFO);
- }
-
- Optional<std::string> parse_feature_name(Parse::ParserBase& parser)
- {
- using Parse::ParserBase;
- auto ret = parser.match_zero_or_more(is_feature_name_char).to_string();
- auto ch = parser.cur();
-
- // ignores the feature name vwebp_sdl as a back-compat thing
- const bool has_underscore = std::find(ret.begin(), ret.end(), '_') != ret.end() && ret != "vwebp_sdl";
- if (has_underscore || ParserBase::is_upper_alpha(ch))
- {
- parser.add_error("invalid character in feature name (must be lowercase, digits, '-')");
- return nullopt;
- }
-
- if (ret.empty())
- {
- parser.add_error("expected feature name (must be lowercase, digits, '-')");
- return nullopt;
- }
- return ret;
- }
- Optional<std::string> parse_package_name(Parse::ParserBase& parser)
- {
- using Parse::ParserBase;
- auto ret = parser.match_zero_or_more(is_package_name_char).to_string();
- auto ch = parser.cur();
- if (ParserBase::is_upper_alpha(ch) || ch == '_')
- {
- parser.add_error("invalid character in package name (must be lowercase, digits, '-')");
- return nullopt;
- }
- if (ret.empty())
- {
- parser.add_error("expected package name (must be lowercase, digits, '-')");
- return nullopt;
- }
- return ret;
- }
-
- Optional<ParsedQualifiedSpecifier> parse_qualified_specifier(Parse::ParserBase& parser)
- {
- using Parse::ParserBase;
- ParsedQualifiedSpecifier ret;
- auto name = parse_package_name(parser);
- if (auto n = name.get())
- ret.name = std::move(*n);
- else
- return nullopt;
- auto ch = parser.cur();
- if (ch == '[')
- {
- std::vector<std::string> features;
- do
- {
- parser.next();
- parser.skip_tabs_spaces();
- if (parser.cur() == '*')
- {
- features.push_back("*");
- parser.next();
- }
- else
- {
- auto feature = parse_feature_name(parser);
- if (auto f = feature.get())
- features.push_back(std::move(*f));
- else
- return nullopt;
- }
- auto skipped_space = parser.skip_tabs_spaces();
- ch = parser.cur();
- if (ch == ']')
- {
- ch = parser.next();
- break;
- }
- else if (ch == ',')
- {
- continue;
- }
- else
- {
- if (skipped_space.size() > 0 || Parse::ParserBase::is_lineend(parser.cur()))
- parser.add_error("expected ',' or ']' in feature list");
- else
- parser.add_error("invalid character in feature name (must be lowercase, digits, '-', or '*')");
- return nullopt;
- }
- } while (true);
- ret.features = std::move(features);
- }
- if (ch == ':')
- {
- parser.next();
- ret.triplet = parser.match_zero_or_more(is_package_name_char).to_string();
- if (ret.triplet.get()->empty())
- {
- parser.add_error("expected triplet name (must be lowercase, digits, '-')");
- return nullopt;
- }
- }
- parser.skip_tabs_spaces();
- ch = parser.cur();
- if (ch == '(')
- {
- auto loc = parser.cur_loc();
- std::string platform_string;
- int depth = 1;
- while (depth > 0 && (ch = parser.next()) != 0)
- {
- if (ch == '(') ++depth;
- if (ch == ')') --depth;
- }
- if (depth > 0)
- {
- parser.add_error("unmatched open braces in platform specifier", loc);
- return nullopt;
- }
- platform_string.append((++loc.it).pointer_to_current(), parser.it().pointer_to_current());
- auto platform_opt = PlatformExpression::parse_platform_expression(
- platform_string, PlatformExpression::MultipleBinaryOperators::Allow);
- if (auto platform = platform_opt.get())
- {
- ret.platform = std::move(*platform);
- }
- else
- {
- parser.add_error(platform_opt.error(), loc);
- }
- parser.next();
- }
- // This makes the behavior of the parser more consistent -- otherwise, it will skip tabs and spaces only if
- // there isn't a qualifier.
- parser.skip_tabs_spaces();
- return ret;
- }
-
- bool operator==(const DependencyConstraint& lhs, const DependencyConstraint& rhs)
- {
- if (lhs.type != rhs.type) return false;
- if (lhs.value != rhs.value) return false;
- return lhs.port_version == rhs.port_version;
- }
- bool operator!=(const DependencyConstraint& lhs, const DependencyConstraint& rhs);
-
- bool operator==(const Dependency& lhs, const Dependency& rhs)
- {
- if (lhs.name != rhs.name) return false;
- if (lhs.features != rhs.features) return false;
- if (!structurally_equal(lhs.platform, rhs.platform)) return false;
- if (lhs.extra_info != rhs.extra_info) return false;
- if (lhs.constraint != rhs.constraint) return false;
-
- return true;
- }
- bool operator!=(const Dependency& lhs, const Dependency& rhs);
-
- bool operator==(const DependencyOverride& lhs, const DependencyOverride& rhs)
- {
- if (lhs.version_scheme != rhs.version_scheme) return false;
- if (lhs.port_version != rhs.port_version) return false;
- if (lhs.name != rhs.name) return false;
- if (lhs.version != rhs.version) return false;
- return lhs.extra_info == rhs.extra_info;
- }
- bool operator!=(const DependencyOverride& lhs, const DependencyOverride& rhs);
-}
diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp
deleted file mode 100644
index 4b4621968..000000000
--- a/toolsrc/src/vcpkg/paragraphs.cpp
+++ /dev/null
@@ -1,531 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/parse.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binaryparagraph.h>
-#include <vcpkg/configuration.h>
-#include <vcpkg/paragraphparser.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/registries.h>
-#include <vcpkg/vcpkgpaths.h>
-
-using namespace vcpkg::Parse;
-using namespace vcpkg;
-
-namespace vcpkg::Parse
-{
- static Optional<std::pair<std::string, TextRowCol>> remove_field(Paragraph* fields, const std::string& fieldname)
- {
- auto it = fields->find(fieldname);
- if (it == fields->end())
- {
- return nullopt;
- }
-
- auto value = std::move(it->second);
- fields->erase(it);
- return value;
- }
-
- void ParagraphParser::required_field(const std::string& fieldname, std::pair<std::string&, TextRowCol&> out)
- {
- auto maybe_field = remove_field(&fields, fieldname);
- if (const auto field = maybe_field.get())
- out = std::move(*field);
- else
- missing_fields.push_back(fieldname);
- }
- void ParagraphParser::optional_field(const std::string& fieldname, std::pair<std::string&, TextRowCol&> out)
- {
- auto maybe_field = remove_field(&fields, fieldname);
- if (auto field = maybe_field.get()) out = std::move(*field);
- }
- void ParagraphParser::required_field(const std::string& fieldname, std::string& out)
- {
- TextRowCol ignore;
- required_field(fieldname, {out, ignore});
- }
- std::string ParagraphParser::optional_field(const std::string& fieldname)
- {
- std::string out;
- TextRowCol ignore;
- optional_field(fieldname, {out, ignore});
- return out;
- }
- std::string ParagraphParser::required_field(const std::string& fieldname)
- {
- std::string out;
- TextRowCol ignore;
- required_field(fieldname, {out, ignore});
- return out;
- }
-
- std::unique_ptr<ParseControlErrorInfo> ParagraphParser::error_info(const std::string& name) const
- {
- if (!fields.empty() || !missing_fields.empty())
- {
- auto err = std::make_unique<ParseControlErrorInfo>();
- err->name = name;
- err->extra_fields["CONTROL"] = Util::extract_keys(fields);
- err->missing_fields["CONTROL"] = std::move(missing_fields);
- err->expected_types = std::move(expected_types);
- return err;
- }
- return nullptr;
- }
-
- template<class T, class F>
- static Optional<std::vector<T>> parse_list_until_eof(StringLiteral plural_item_name, Parse::ParserBase& parser, F f)
- {
- std::vector<T> ret;
- parser.skip_whitespace();
- if (parser.at_eof()) return std::vector<T>{};
- do
- {
- auto item = f(parser);
- if (!item) return nullopt;
- ret.push_back(std::move(item).value_or_exit(VCPKG_LINE_INFO));
- parser.skip_whitespace();
- if (parser.at_eof()) return {std::move(ret)};
- if (parser.cur() != ',')
- {
- parser.add_error(Strings::concat("expected ',' or end of text in ", plural_item_name, " list"));
- return nullopt;
- }
- parser.next();
- parser.skip_whitespace();
- } while (true);
- }
-
- ExpectedS<std::vector<std::string>> parse_default_features_list(const std::string& str,
- StringView origin,
- TextRowCol textrowcol)
- {
- auto parser = Parse::ParserBase(str, origin, textrowcol);
- auto opt = parse_list_until_eof<std::string>("default features", parser, &parse_feature_name);
- if (!opt) return {parser.get_error()->format(), expected_right_tag};
- return {std::move(opt).value_or_exit(VCPKG_LINE_INFO), expected_left_tag};
- }
- ExpectedS<std::vector<ParsedQualifiedSpecifier>> parse_qualified_specifier_list(const std::string& str,
- StringView origin,
- TextRowCol textrowcol)
- {
- auto parser = Parse::ParserBase(str, origin, textrowcol);
- auto opt = parse_list_until_eof<ParsedQualifiedSpecifier>(
- "dependencies", parser, [](ParserBase& parser) { return parse_qualified_specifier(parser); });
- if (!opt) return {parser.get_error()->format(), expected_right_tag};
-
- return {std::move(opt).value_or_exit(VCPKG_LINE_INFO), expected_left_tag};
- }
- ExpectedS<std::vector<Dependency>> parse_dependencies_list(const std::string& str,
- StringView origin,
- TextRowCol textrowcol)
- {
- auto parser = Parse::ParserBase(str, origin, textrowcol);
- auto opt = parse_list_until_eof<Dependency>("dependencies", parser, [](ParserBase& parser) {
- auto loc = parser.cur_loc();
- return parse_qualified_specifier(parser).then([&](ParsedQualifiedSpecifier&& pqs) -> Optional<Dependency> {
- if (pqs.triplet)
- {
- parser.add_error("triplet specifier not allowed in this context", loc);
- return nullopt;
- }
- return Dependency{pqs.name, pqs.features.value_or({}), pqs.platform.value_or({})};
- });
- });
- if (!opt) return {parser.get_error()->format(), expected_right_tag};
-
- return {std::move(opt).value_or_exit(VCPKG_LINE_INFO), expected_left_tag};
- }
-}
-
-namespace vcpkg::Paragraphs
-{
- struct PghParser : private Parse::ParserBase
- {
- private:
- void get_fieldvalue(std::string& fieldvalue)
- {
- fieldvalue.clear();
-
- do
- {
- // scan to end of current line (it is part of the field value)
- Strings::append(fieldvalue, match_until(is_lineend));
- skip_newline();
-
- if (cur() != ' ') return;
- auto spacing = skip_tabs_spaces();
- if (is_lineend(cur())) return add_error("unexpected end of line, to span a blank line use \" .\"");
- Strings::append(fieldvalue, "\n", spacing);
- } while (true);
- }
-
- void get_fieldname(std::string& fieldname)
- {
- fieldname = match_zero_or_more(is_alphanumdash).to_string();
- if (fieldname.empty()) return add_error("expected fieldname");
- }
-
- void get_paragraph(Paragraph& fields)
- {
- fields.clear();
- std::string fieldname;
- std::string fieldvalue;
- do
- {
- if (cur() == '#')
- {
- skip_line();
- continue;
- }
-
- auto loc = cur_loc();
- get_fieldname(fieldname);
- if (cur() != ':') return add_error("expected ':' after field name");
- if (Util::Sets::contains(fields, fieldname)) return add_error("duplicate field", loc);
- next();
- skip_tabs_spaces();
- auto rowcol = cur_rowcol();
- get_fieldvalue(fieldvalue);
-
- fields.emplace(fieldname, std::make_pair(fieldvalue, rowcol));
- } while (!is_lineend(cur()));
- }
-
- public:
- PghParser(StringView text, StringView origin) : Parse::ParserBase(text, origin) { }
-
- ExpectedS<std::vector<Paragraph>> get_paragraphs()
- {
- std::vector<Paragraph> paragraphs;
-
- skip_whitespace();
- while (!at_eof())
- {
- paragraphs.emplace_back();
- get_paragraph(paragraphs.back());
- match_zero_or_more(is_lineend);
- }
- if (get_error()) return get_error()->format();
-
- return paragraphs;
- }
- };
-
- ExpectedS<Paragraph> parse_single_paragraph(const std::string& str, const std::string& origin)
- {
- auto pghs = PghParser(str, origin).get_paragraphs();
-
- if (auto p = pghs.get())
- {
- if (p->size() != 1) return {"There should be exactly one paragraph", expected_right_tag};
- return std::move(p->front());
- }
- else
- {
- return pghs.error();
- }
- }
-
- ExpectedS<Paragraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path)
- {
- const Expected<std::string> contents = fs.read_contents(control_path);
- if (auto spgh = contents.get())
- {
- return parse_single_paragraph(*spgh, fs::u8string(control_path));
- }
-
- return contents.error().message();
- }
-
- ExpectedS<std::vector<Paragraph>> get_paragraphs_text(const std::string& text, const std::string& origin)
- {
- return parse_paragraphs(text, origin);
- }
-
- ExpectedS<std::vector<Paragraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path)
- {
- const Expected<std::string> contents = fs.read_contents(control_path);
- if (auto spgh = contents.get())
- {
- return parse_paragraphs(*spgh, fs::u8string(control_path));
- }
-
- return contents.error().message();
- }
-
- ExpectedS<std::vector<Paragraph>> parse_paragraphs(const std::string& str, const std::string& origin)
- {
- return PghParser(str, origin).get_paragraphs();
- }
-
- bool is_port_directory(const Files::Filesystem& fs, const fs::path& path)
- {
- return fs.exists(path / fs::u8path("CONTROL")) || fs.exists(path / fs::u8path("vcpkg.json"));
- }
-
- static ParseExpected<SourceControlFile> try_load_manifest_object(
- const std::string& origin,
- const ExpectedT<std::pair<vcpkg::Json::Value, vcpkg::Json::JsonStyle>, std::unique_ptr<Parse::IParseError>>&
- res)
- {
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- if (auto val = res.get())
- {
- if (val->first.is_object())
- {
- return SourceControlFile::parse_manifest_object(origin, val->first.object());
- }
- else
- {
- error_info->name = origin;
- error_info->error = "Manifest files must have a top-level object";
- return error_info;
- }
- }
- else
- {
- error_info->name = origin;
- error_info->error = res.error()->format();
- return error_info;
- }
- }
-
- static ParseExpected<SourceControlFile> try_load_manifest_text(const std::string& text, const std::string& origin)
- {
- auto res = Json::parse(text);
- return try_load_manifest_object(origin, res);
- }
-
- static ParseExpected<SourceControlFile> try_load_manifest(const Files::Filesystem& fs,
- const std::string& port_name,
- const fs::path& path_to_manifest,
- std::error_code& ec)
- {
- (void)port_name;
-
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- auto res = Json::parse_file(fs, path_to_manifest, ec);
- if (ec) return error_info;
-
- return try_load_manifest_object(fs::u8string(path_to_manifest), res);
- }
-
- ParseExpected<SourceControlFile> try_load_port_text(const std::string& text,
- const std::string& origin,
- bool is_manifest)
- {
- if (is_manifest)
- {
- return try_load_manifest_text(text, origin);
- }
-
- ExpectedS<std::vector<Paragraph>> pghs = get_paragraphs_text(text, origin);
- if (auto vector_pghs = pghs.get())
- {
- return SourceControlFile::parse_control_file(origin, std::move(*vector_pghs));
- }
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = fs::u8string(origin);
- error_info->error = pghs.error();
- return error_info;
- }
-
- ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& path)
- {
- const auto path_to_manifest = path / fs::u8path("vcpkg.json");
- const auto path_to_control = path / fs::u8path("CONTROL");
- if (fs.exists(path_to_manifest))
- {
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO,
- !fs.exists(path_to_control),
- "Found both manifest and CONTROL file in port %s; please rename one or the other",
- fs::u8string(path));
-
- std::error_code ec;
- auto res = try_load_manifest(fs, fs::u8string(path.filename()), path_to_manifest, ec);
- if (ec)
- {
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = fs::u8string(path.filename());
- error_info->error = Strings::format(
- "Failed to load manifest file for port: %s\n", fs::u8string(path_to_manifest), ec.message());
- return error_info;
- }
-
- return res;
- }
-
- if (fs.exists(path_to_control))
- {
- ExpectedS<std::vector<Paragraph>> pghs = get_paragraphs(fs, path_to_control);
- if (auto vector_pghs = pghs.get())
- {
- return SourceControlFile::parse_control_file(fs::u8string(path_to_control), std::move(*vector_pghs));
- }
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = fs::u8string(path.filename());
- error_info->error = pghs.error();
- return error_info;
- }
-
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = fs::u8string(path.filename());
- if (fs.exists(path))
- {
- error_info->error = "Failed to find either a CONTROL file or vcpkg.json file.";
- }
- else
- {
- error_info->error = "The port directory (" + fs::u8string(path) + ") does not exist";
- }
- return error_info;
- }
-
- ExpectedS<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec)
- {
- ExpectedS<std::vector<Paragraph>> pghs =
- get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL");
-
- if (auto p = pghs.get())
- {
- BinaryControlFile bcf;
- bcf.core_paragraph = BinaryParagraph(p->front());
- p->erase(p->begin());
-
- bcf.features =
- Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); });
-
- if (bcf.core_paragraph.spec != spec)
- {
- return Strings::concat("Mismatched spec in package at ",
- fs::u8string(paths.package_dir(spec)),
- ": expected ",
- spec,
- ", actual ",
- bcf.core_paragraph.spec);
- }
-
- return bcf;
- }
-
- return pghs.error();
- }
-
- LoadResults try_load_all_registry_ports(const VcpkgPaths& paths)
- {
- LoadResults ret;
- const auto& fs = paths.get_filesystem();
-
- std::vector<std::string> ports;
-
- const auto& registries = paths.get_configuration().registry_set;
-
- for (const auto& registry : registries.registries())
- {
- registry.implementation().get_all_port_names(ports, paths);
- }
- if (auto registry = registries.default_registry())
- {
- registry->get_all_port_names(ports, paths);
- }
-
- Util::sort_unique_erase(ports);
-
- for (const auto& port_name : ports)
- {
- auto impl = registries.registry_for_port(port_name);
- if (!impl)
- {
- // this is a port for which no registry is set
- // this can happen when there's no default registry,
- // and a registry has a port definition which it doesn't own the name of.
- continue;
- }
-
- auto port_entry = impl->get_port_entry(paths, port_name);
- auto baseline_version = impl->get_baseline_version(paths, port_name);
- if (port_entry && baseline_version)
- {
- auto port_path =
- port_entry->get_path_to_version(paths, *baseline_version.get()).value_or_exit(VCPKG_LINE_INFO);
- auto maybe_spgh = try_load_port(fs, port_path);
- if (const auto spgh = maybe_spgh.get())
- {
- ret.paragraphs.emplace_back(std::move(*spgh), std::move(port_path));
- }
- else
- {
- ret.errors.emplace_back(std::move(maybe_spgh).error());
- }
- }
- else
- {
- // the registry that owns the name of this port does not actually contain the port
- // this can happen if R1 contains the port definition for <abc>, but doesn't
- // declare it owns <abc>.
- continue;
- }
- }
-
- return ret;
- }
-
- static void load_results_print_error(const LoadResults& results)
- {
- if (!results.errors.empty())
- {
- if (Debug::g_debugging)
- {
- print_error_message(results.errors);
- }
- else
- {
- for (auto&& error : results.errors)
- {
- System::print2(
- System::Color::warning, "Warning: an error occurred while parsing '", error->name, "'\n");
- }
- System::print2(System::Color::warning,
- "Use '--debug' to get more information about the parse failures.\n\n");
- }
- }
- }
-
- std::vector<SourceControlFileLocation> load_all_registry_ports(const VcpkgPaths& paths)
- {
- auto results = try_load_all_registry_ports(paths);
- load_results_print_error(results);
- return std::move(results.paragraphs);
- }
-
- std::vector<SourceControlFileLocation> load_overlay_ports(const Files::Filesystem& fs, const fs::path& directory)
- {
- LoadResults ret;
-
- auto port_dirs = fs.get_files_non_recursive(directory);
- Util::sort(port_dirs);
-
- Util::erase_remove_if(port_dirs,
- [&](auto&& port_dir_entry) { return port_dir_entry.filename() == ".DS_Store"; });
-
- for (auto&& path : port_dirs)
- {
- auto maybe_spgh = try_load_port(fs, path);
- if (const auto spgh = maybe_spgh.get())
- {
- ret.paragraphs.emplace_back(std::move(*spgh), std::move(path));
- }
- else
- {
- ret.errors.emplace_back(std::move(maybe_spgh).error());
- }
- }
-
- load_results_print_error(ret);
- return std::move(ret.paragraphs);
- }
-}
diff --git a/toolsrc/src/vcpkg/platform-expression.cpp b/toolsrc/src/vcpkg/platform-expression.cpp
deleted file mode 100644
index a6177c85f..000000000
--- a/toolsrc/src/vcpkg/platform-expression.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
-#include <vcpkg/base/parse.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/platform-expression.h>
-
-#include <numeric>
-#include <string>
-#include <vector>
-
-namespace vcpkg::PlatformExpression
-{
- using vcpkg::Parse::ParseError;
-
- enum class Identifier
- {
- invalid = -1, // not a recognized identifier
- x86,
- x64,
- arm,
- arm64,
- wasm32,
-
- windows,
- mingw,
- linux,
- osx,
- uwp,
- android,
- emscripten,
- ios,
-
- static_link,
- static_crt,
- };
-
- static Identifier string2identifier(StringView name)
- {
- static const std::map<StringView, Identifier> id_map = {
- {"x86", Identifier::x86},
- {"x64", Identifier::x64},
- {"arm", Identifier::arm},
- {"arm64", Identifier::arm64},
- {"wasm32", Identifier::wasm32},
- {"windows", Identifier::windows},
- {"mingw", Identifier::mingw},
- {"linux", Identifier::linux},
- {"osx", Identifier::osx},
- {"uwp", Identifier::uwp},
- {"android", Identifier::android},
- {"emscripten", Identifier::emscripten},
- {"ios", Identifier::ios},
- {"static", Identifier::static_link},
- {"staticcrt", Identifier::static_link},
- };
-
- auto id_pair = id_map.find(name);
-
- if (id_pair == id_map.end())
- {
- return Identifier::invalid;
- }
-
- return id_pair->second;
- }
-
- namespace detail
- {
- enum class ExprKind
- {
- identifier,
- op_not,
- op_and,
- op_or
- };
-
- struct ExprImpl
- {
- ExprImpl(ExprKind k, std::string i, std::vector<std::unique_ptr<ExprImpl>> es)
- : kind(k), identifier(std::move(i)), exprs(std::move(es))
- {
- }
-
- ExprImpl(ExprKind k, std::string i) : kind(k), identifier(std::move(i)) { }
- ExprImpl(ExprKind k, std::unique_ptr<ExprImpl> a) : kind(k) { exprs.push_back(std::move(a)); }
- ExprImpl(ExprKind k, std::vector<std::unique_ptr<ExprImpl>> es) : kind(k), exprs(std::move(es)) { }
-
- ExprKind kind;
- std::string identifier;
- std::vector<std::unique_ptr<ExprImpl>> exprs;
-
- std::unique_ptr<ExprImpl> clone() const
- {
- return std::make_unique<ExprImpl>(
- ExprImpl{kind, identifier, Util::fmap(exprs, [](auto&& p) { return p->clone(); })});
- }
- };
-
- class ExpressionParser : public Parse::ParserBase
- {
- public:
- ExpressionParser(StringView str, MultipleBinaryOperators multiple_binary_operators)
- : Parse::ParserBase(str, "CONTROL"), multiple_binary_operators(multiple_binary_operators)
- {
- }
-
- MultipleBinaryOperators multiple_binary_operators;
-
- bool allow_multiple_binary_operators() const
- {
- return multiple_binary_operators == MultipleBinaryOperators::Allow;
- }
-
- // top-level-platform-expression = optional-whitespace, platform-expression
- PlatformExpression::Expr parse()
- {
- skip_whitespace();
- auto res = expr();
-
- if (!at_eof())
- {
- add_error("invalid logic expression, unexpected character");
- }
-
- return Expr(std::move(res));
- }
-
- private:
- // identifier-character =
- // | lowercase-alpha
- // | digit ;
- static bool is_identifier_char(char32_t ch) { return is_lower_alpha(ch) || is_ascii_digit(ch); }
-
- // platform-expression =
- // | platform-expression-not
- // | platform-expression-and
- // | platform-expression-or ;
- std::unique_ptr<ExprImpl> expr()
- {
- // this is the common prefix of all the variants
- // platform-expression-not,
- auto result = expr_not();
-
- switch (cur())
- {
- case '|':
- {
- // { "|", optional-whitespace, platform-expression-not }
- return expr_binary<'|', '&'>(std::make_unique<ExprImpl>(ExprKind::op_or, std::move(result)));
- }
- case '&':
- {
- // { "&", optional-whitespace, platform-expression-not }
- return expr_binary<'&', '|'>(std::make_unique<ExprImpl>(ExprKind::op_and, std::move(result)));
- }
- default: return result;
- }
- }
-
- // platform-expression-simple =
- // | platform-expression-identifier
- // | "(", optional-whitespace, platform-expression, ")", optional-whitespace ;
- std::unique_ptr<ExprImpl> expr_simple()
- {
- if (cur() == '(')
- {
- // "(",
- next();
- // optional-whitespace,
- skip_whitespace();
- // platform-expression,
- auto result = expr();
- if (cur() != ')')
- {
- add_error("missing closing )");
- return result;
- }
- // ")",
- next();
- // optional-whitespace
- skip_whitespace();
- return result;
- }
-
- // platform-expression-identifier
- return expr_identifier();
- }
-
- // platform-expression-identifier =
- // | identifier-character, { identifier-character }, optional-whitespace ;
- std::unique_ptr<ExprImpl> expr_identifier()
- {
- // identifier-character, { identifier-character },
- std::string name = match_zero_or_more(is_identifier_char).to_string();
-
- if (name.empty())
- {
- add_error("unexpected character in logic expression");
- }
-
- // optional-whitespace
- skip_whitespace();
-
- return std::make_unique<ExprImpl>(ExprKind::identifier, std::move(name));
- }
-
- // platform-expression-not =
- // | platform-expression-simple
- // | "!", optional-whitespace, platform-expression-simple ;
- std::unique_ptr<ExprImpl> expr_not()
- {
- if (cur() == '!')
- {
- // "!",
- next();
- // optional-whitespace,
- skip_whitespace();
- // platform-expression-simple
- return std::make_unique<ExprImpl>(ExprKind::op_not, expr_simple());
- }
-
- // platform-expression-simple
- return expr_simple();
- }
-
- // platform-expression-and =
- // | platform-expression-not, { "&", optional-whitespace, platform-expression-not } ;
- //
- // platform-expression-or =
- // | platform-expression-not, { "|", optional-whitespace, platform-expression-not } ;
- //
- // already taken care of by the caller: platform-expression-not
- // so we start at either "&" or "|"
- template<char oper, char other>
- std::unique_ptr<ExprImpl> expr_binary(std::unique_ptr<ExprImpl>&& seed)
- {
- do
- {
- // Support chains of the operator to avoid breaking backwards compatibility
- do
- {
- // "&" or "|",
- next();
- } while (allow_multiple_binary_operators() && cur() == oper);
-
- // optional-whitespace,
- skip_whitespace();
- // platform-expression-not, (go back to start of repetition)
- seed->exprs.push_back(expr_not());
- } while (cur() == oper);
-
- if (cur() == other)
- {
- add_error("mixing & and | is not allowed; use () to specify order of operations");
- }
-
- return std::move(seed);
- }
- };
- }
-
- using namespace detail;
-
- Expr::Expr() = default;
- Expr::Expr(Expr&& other) = default;
- Expr& Expr::operator=(Expr&& other) = default;
-
- Expr::Expr(const Expr& other)
- {
- if (other.underlying_)
- {
- this->underlying_ = other.underlying_->clone();
- }
- }
- Expr& Expr::operator=(const Expr& other)
- {
- if (other.underlying_)
- {
- this->underlying_ = other.underlying_->clone();
- }
- else
- {
- this->underlying_.reset();
- }
-
- return *this;
- }
-
- Expr::Expr(std::unique_ptr<ExprImpl>&& e) : underlying_(std::move(e)) { }
- Expr::~Expr() = default;
-
- Expr Expr::Identifier(StringView id)
- {
- return Expr(std::make_unique<ExprImpl>(ExprKind::identifier, id.to_string()));
- }
- Expr Expr::Not(Expr&& e) { return Expr(std::make_unique<ExprImpl>(ExprKind::op_not, std::move(e.underlying_))); }
- Expr Expr::And(std::vector<Expr>&& exprs)
- {
- return Expr(std::make_unique<ExprImpl>(
- ExprKind::op_and, Util::fmap(exprs, [](Expr& expr) { return std::move(expr.underlying_); })));
- }
- Expr Expr::Or(std::vector<Expr>&& exprs)
- {
- return Expr(std::make_unique<ExprImpl>(
- ExprKind::op_or, Util::fmap(exprs, [](Expr& expr) { return std::move(expr.underlying_); })));
- }
-
- bool Expr::evaluate(const Context& context) const
- {
- if (!this->underlying_)
- {
- return true; // empty expression is always true
- }
-
- std::map<std::string, bool> override_ctxt;
- {
- auto override_vars = context.find("VCPKG_DEP_INFO_OVERRIDE_VARS");
- if (override_vars != context.end())
- {
- auto cmake_list = Strings::split(override_vars->second, ';');
- for (auto& override_id : cmake_list)
- {
- if (!override_id.empty())
- {
- if (override_id[0] == '!')
- {
- override_ctxt.insert({override_id.substr(1), false});
- }
- else
- {
- override_ctxt.insert({override_id, true});
- }
- }
- }
- }
- }
-
- struct Visitor
- {
- const Context& context;
- const std::map<std::string, bool>& override_ctxt;
-
- bool true_if_exists_and_equal(const std::string& variable_name, const std::string& value) const
- {
- auto iter = context.find(variable_name);
- if (iter == context.end())
- {
- return false;
- }
- return iter->second == value;
- }
-
- bool visit(const ExprImpl& expr) const
- {
- if (expr.kind == ExprKind::identifier)
- {
- if (!override_ctxt.empty())
- {
- auto override_id = override_ctxt.find(expr.identifier);
- if (override_id != override_ctxt.end())
- {
- return override_id->second;
- }
- // Fall through to use the cmake logic if the id does not have an override
- }
-
- auto id = string2identifier(expr.identifier);
- switch (id)
- {
- case Identifier::invalid:
- // Point out in the diagnostic that they should add to the override list because that is
- // what most users should do, however it is also valid to update the built in identifiers to
- // recognize the name.
- System::printf(
- System::Color::error,
- "Error: Unrecognized identifer name %s. Add to override list in triplet file.\n",
- expr.identifier);
- return false;
- case Identifier::x64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x64");
- case Identifier::x86: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x86");
- case Identifier::arm:
- // For backwards compatability arm is also true for arm64.
- // This is because it previously was only checking for a substring.
- return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm") ||
- true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm64");
- case Identifier::arm64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm64");
- case Identifier::windows:
- return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "") ||
- true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore");
- case Identifier::mingw: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "MinGW");
- case Identifier::linux: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Linux");
- case Identifier::osx: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Darwin");
- case Identifier::uwp:
- return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore");
- case Identifier::android: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Android");
- case Identifier::emscripten:
- return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Emscripten");
- case Identifier::ios: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "iOS");
- case Identifier::wasm32: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "wasm32");
- case Identifier::static_link:
- return true_if_exists_and_equal("VCPKG_LIBRARY_LINKAGE", "static");
- case Identifier::static_crt: return true_if_exists_and_equal("VCPKG_CRT_LINKAGE", "static");
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- else if (expr.kind == ExprKind::op_not)
- {
- return !visit(*expr.exprs.at(0));
- }
- else if (expr.kind == ExprKind::op_and)
- {
- bool valid = true;
-
- // we want to print errors in all expressions, so we check all of the expressions all the time
- for (const auto& e : expr.exprs)
- {
- valid &= visit(*e);
- }
-
- return valid;
- }
- else if (expr.kind == ExprKind::op_or)
- {
- bool valid = false;
-
- // we want to print errors in all expressions, so we check all of the expressions all the time
- for (const auto& e : expr.exprs)
- {
- valid |= visit(*e);
- }
-
- return valid;
- }
- else
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- };
-
- return Visitor{context, override_ctxt}.visit(*this->underlying_);
- }
-
- int Expr::complexity() const
- {
- if (is_empty()) return 0;
-
- struct Impl
- {
- int operator()(const std::unique_ptr<detail::ExprImpl>& expr) const { return (*this)(*expr); }
- int operator()(const detail::ExprImpl& expr) const
- {
- if (expr.kind == ExprKind::identifier) return 1;
-
- if (expr.kind == ExprKind::op_not) return 1 + (*this)(expr.exprs.at(0));
-
- return 1 + std::accumulate(expr.exprs.begin(), expr.exprs.end(), 0, [](int acc, const auto& el) {
- return acc + Impl{}(el);
- });
- }
- };
-
- return Impl{}(underlying_);
- }
-
- ExpectedS<Expr> parse_platform_expression(StringView expression, MultipleBinaryOperators multiple_binary_operators)
- {
- ExpressionParser parser(expression, multiple_binary_operators);
- auto res = parser.parse();
-
- if (auto p = parser.extract_error())
- {
- return p->format();
- }
- else
- {
- return res;
- }
- }
-
- bool structurally_equal(const Expr& lhs, const Expr& rhs)
- {
- struct Impl
- {
- bool operator()(const std::unique_ptr<detail::ExprImpl>& lhs,
- const std::unique_ptr<detail::ExprImpl>& rhs) const
- {
- return (*this)(*lhs, *rhs);
- }
- bool operator()(const detail::ExprImpl& lhs, const detail::ExprImpl& rhs) const
- {
- if (lhs.kind != rhs.kind) return false;
-
- if (lhs.kind == ExprKind::identifier)
- {
- return lhs.identifier == rhs.identifier;
- }
- else
- {
- const auto& exprs_l = lhs.exprs;
- const auto& exprs_r = rhs.exprs;
- return std::equal(exprs_l.begin(), exprs_l.end(), exprs_r.begin(), exprs_r.end(), *this);
- }
- }
- };
-
- if (lhs.is_empty())
- {
- return rhs.is_empty();
- }
- if (rhs.is_empty())
- {
- return false;
- }
- return Impl{}(lhs.underlying_, rhs.underlying_);
- }
-
- int compare(const Expr& lhs, const Expr& rhs)
- {
- auto lhs_platform_complexity = lhs.complexity();
- auto rhs_platform_complexity = lhs.complexity();
-
- if (lhs_platform_complexity < rhs_platform_complexity) return -1;
- if (rhs_platform_complexity < lhs_platform_complexity) return 1;
-
- auto lhs_platform = to_string(lhs);
- auto rhs_platform = to_string(rhs);
-
- if (lhs_platform.size() < rhs_platform.size()) return -1;
- if (rhs_platform.size() < lhs_platform.size()) return 1;
-
- auto platform_cmp = lhs_platform.compare(rhs_platform);
- if (platform_cmp < 0) return -1;
- if (platform_cmp > 0) return 1;
-
- return 0;
- }
-
- std::string to_string(const Expr& expr)
- {
- struct Impl
- {
- std::string operator()(const std::unique_ptr<detail::ExprImpl>& expr) const
- {
- return (*this)(*expr, false);
- }
- std::string operator()(const detail::ExprImpl& expr, bool outer) const
- {
- const char* join = nullptr;
- switch (expr.kind)
- {
- case ExprKind::identifier: return expr.identifier;
- case ExprKind::op_and: join = " & "; break;
- case ExprKind::op_or: join = " | "; break;
- case ExprKind::op_not: return Strings::format("!%s", (*this)(expr.exprs.at(0)));
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- if (outer)
- {
- return Strings::join(join, expr.exprs, *this);
- }
- else
- {
- return Strings::format("(%s)", Strings::join(join, expr.exprs, *this));
- }
- }
- };
-
- if (expr.is_empty())
- {
- return std::string{};
- }
- return Impl{}(*expr.underlying_, true);
- }
-}
diff --git a/toolsrc/src/vcpkg/portfileprovider.cpp b/toolsrc/src/vcpkg/portfileprovider.cpp
deleted file mode 100644
index 47aa2976c..000000000
--- a/toolsrc/src/vcpkg/portfileprovider.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/system.debug.h>
-
-#include <vcpkg/configuration.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/registries.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/versiondeserializers.h>
-
-#include <regex>
-
-using namespace vcpkg;
-using namespace Versions;
-
-namespace
-{
- using namespace vcpkg;
-
- struct OverlayRegistryEntry final : RegistryEntry
- {
- OverlayRegistryEntry(fs::path&& p, VersionT&& v) : path(p), version(v) { }
-
- View<VersionT> get_port_versions() const override { return {&version, 1}; }
- ExpectedS<fs::path> get_path_to_version(const VcpkgPaths&, const VersionT& v) const override
- {
- if (v == version)
- {
- return path;
- }
- return Strings::format("Version %s not found; only %s is available.", v.to_string(), version.to_string());
- }
-
- fs::path path;
- VersionT version;
- };
-}
-
-namespace vcpkg::PortFileProvider
-{
- MapPortFileProvider::MapPortFileProvider(const std::unordered_map<std::string, SourceControlFileLocation>& map)
- : ports(map)
- {
- }
-
- ExpectedS<const SourceControlFileLocation&> MapPortFileProvider::get_control_file(const std::string& spec) const
- {
- auto scf = ports.find(spec);
- if (scf == ports.end()) return std::string("does not exist in map");
- return scf->second;
- }
-
- std::vector<const SourceControlFileLocation*> MapPortFileProvider::load_all_control_files() const
- {
- return Util::fmap(ports, [](auto&& kvpair) -> const SourceControlFileLocation* { return &kvpair.second; });
- }
-
- PathsPortFileProvider::PathsPortFileProvider(const VcpkgPaths& paths, const std::vector<std::string>& overlay_ports)
- : m_baseline(make_baseline_provider(paths))
- , m_versioned(make_versioned_portfile_provider(paths))
- , m_overlay(make_overlay_provider(paths, overlay_ports))
- {
- }
-
- ExpectedS<const SourceControlFileLocation&> PathsPortFileProvider::get_control_file(const std::string& spec) const
- {
- auto maybe_scfl = m_overlay->get_control_file(spec);
- if (auto scfl = maybe_scfl.get())
- {
- return *scfl;
- }
- auto maybe_baseline = m_baseline->get_baseline_version(spec);
- if (auto baseline = maybe_baseline.get())
- {
- return m_versioned->get_control_file({spec, *baseline});
- }
- else
- {
- return Strings::concat("Error: unable to get baseline for port ", spec);
- }
- }
-
- std::vector<const SourceControlFileLocation*> PathsPortFileProvider::load_all_control_files() const
- {
- std::map<std::string, const SourceControlFileLocation*> m;
- m_overlay->load_all_control_files(m);
- m_versioned->load_all_control_files(m);
- return Util::fmap(m, [](const auto& p) { return p.second; });
- }
-
- namespace
- {
- struct BaselineProviderImpl : IBaselineProvider, Util::ResourceBase
- {
- BaselineProviderImpl(const VcpkgPaths& paths_) : paths(paths_) { }
-
- virtual Optional<VersionT> get_baseline_version(StringView port_name) const override
- {
- auto it = m_baseline_cache.find(port_name);
- if (it != m_baseline_cache.end())
- {
- return it->second;
- }
- else
- {
- auto version = paths.get_configuration().registry_set.baseline_for_port(paths, port_name);
- m_baseline_cache.emplace(port_name.to_string(), version);
- return version;
- }
- }
-
- private:
- const VcpkgPaths& paths; // TODO: remove this data member
- mutable std::map<std::string, Optional<VersionT>, std::less<>> m_baseline_cache;
- };
-
- struct VersionedPortfileProviderImpl : IVersionedPortfileProvider, Util::ResourceBase
- {
- VersionedPortfileProviderImpl(const VcpkgPaths& paths_) : paths(paths_) { }
-
- const ExpectedS<std::unique_ptr<RegistryEntry>>& entry(StringView name) const
- {
- auto entry_it = m_entry_cache.find(name);
- if (entry_it == m_entry_cache.end())
- {
- if (auto reg = paths.get_configuration().registry_set.registry_for_port(name))
- {
- if (auto entry = reg->get_port_entry(paths, name))
- {
- entry_it = m_entry_cache.emplace(name.to_string(), std::move(entry)).first;
- }
- else
- {
- entry_it =
- m_entry_cache
- .emplace(name.to_string(),
- Strings::concat("Error: Could not find a definition for port ", name))
- .first;
- }
- }
- else
- {
- entry_it = m_entry_cache
- .emplace(name.to_string(),
- Strings::concat("Error: no registry configured for port ", name))
- .first;
- }
- }
- return entry_it->second;
- }
-
- virtual View<VersionT> get_port_versions(StringView port_name) const override
- {
- return entry(port_name).value_or_exit(VCPKG_LINE_INFO)->get_port_versions();
- }
-
- ExpectedS<std::unique_ptr<SourceControlFileLocation>> load_control_file(
- const VersionSpec& version_spec) const
- {
- const auto& maybe_ent = entry(version_spec.port_name);
- if (auto ent = maybe_ent.get())
- {
- auto maybe_path = ent->get()->get_path_to_version(paths, version_spec.version);
- if (auto path = maybe_path.get())
- {
- auto maybe_control_file = Paragraphs::try_load_port(paths.get_filesystem(), *path);
- if (auto scf = maybe_control_file.get())
- {
- if (scf->get()->core_paragraph->name == version_spec.port_name)
- {
- return std::make_unique<SourceControlFileLocation>(std::move(*scf), std::move(*path));
- }
- else
- {
- return Strings::format("Error: Failed to load port from %s: names did "
- "not match: '%s' != '%s'",
- fs::u8string(*path),
- version_spec.port_name,
- scf->get()->core_paragraph->name);
- }
- }
- else
- {
- // This should change to a soft error when ParseExpected is eliminated.
- print_error_message(maybe_control_file.error());
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Error: Failed to load port %s from %s",
- version_spec.port_name,
- fs::u8string(*path));
- }
- }
- else
- {
- return maybe_path.error();
- }
- }
- return maybe_ent.error();
- }
-
- virtual ExpectedS<const SourceControlFileLocation&> get_control_file(
- const VersionSpec& version_spec) const override
- {
- auto it = m_control_cache.find(version_spec);
- if (it == m_control_cache.end())
- {
- it = m_control_cache.emplace(version_spec, load_control_file(version_spec)).first;
- }
- return it->second.map([](const auto& x) -> const SourceControlFileLocation& { return *x.get(); });
- }
-
- virtual void load_all_control_files(
- std::map<std::string, const SourceControlFileLocation*>& out) const override
- {
- auto all_ports = Paragraphs::load_all_registry_ports(paths);
- for (auto&& scfl : all_ports)
- {
- auto port_name = scfl.source_control_file->core_paragraph->name;
- auto version = scfl.source_control_file->core_paragraph->to_versiont();
- auto it = m_control_cache
- .emplace(VersionSpec{std::move(port_name), std::move(version)},
- std::make_unique<SourceControlFileLocation>(std::move(scfl)))
- .first;
- Checks::check_exit(VCPKG_LINE_INFO, it->second.has_value());
- out.emplace(it->first.port_name, it->second.get()->get());
- }
- }
-
- private:
- const VcpkgPaths& paths; // TODO: remove this data member
- mutable std::
- unordered_map<VersionSpec, ExpectedS<std::unique_ptr<SourceControlFileLocation>>, VersionSpecHasher>
- m_control_cache;
- mutable std::map<std::string, ExpectedS<std::unique_ptr<RegistryEntry>>, std::less<>> m_entry_cache;
- };
-
- struct OverlayProviderImpl : IOverlayProvider, Util::ResourceBase
- {
- OverlayProviderImpl(const VcpkgPaths& paths, View<std::string> overlay_ports)
- : m_fs(paths.get_filesystem())
- , m_overlay_ports(Util::fmap(overlay_ports, [&paths](const std::string& s) -> fs::path {
- return Files::combine(paths.original_cwd, fs::u8path(s));
- }))
- {
- for (auto&& overlay : m_overlay_ports)
- {
- auto s_overlay = fs::u8string(overlay);
- Debug::print("Using overlay: ", s_overlay, "\n");
-
- Checks::check_exit(VCPKG_LINE_INFO,
- fs::is_directory(m_fs.status(VCPKG_LINE_INFO, overlay)),
- "Error: Overlay path \"%s\" must exist and must be a directory",
- s_overlay);
- }
- }
-
- Optional<SourceControlFileLocation> load_port(StringView port_name) const
- {
- auto s_port_name = port_name.to_string();
-
- for (auto&& ports_dir : m_overlay_ports)
- {
- // Try loading individual port
- if (Paragraphs::is_port_directory(m_fs, ports_dir))
- {
- auto maybe_scf = Paragraphs::try_load_port(m_fs, ports_dir);
- if (auto scfp = maybe_scf.get())
- {
- auto& scf = *scfp;
- if (scf->core_paragraph->name == port_name)
- {
- return SourceControlFileLocation{std::move(scf), fs::path(ports_dir)};
- }
- }
- else
- {
- print_error_message(maybe_scf.error());
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Error: Failed to load port %s from %s",
- port_name,
- fs::u8string(ports_dir));
- }
-
- continue;
- }
-
- auto ports_spec = ports_dir / fs::u8path(port_name);
- if (Paragraphs::is_port_directory(m_fs, ports_spec))
- {
- auto found_scf = Paragraphs::try_load_port(m_fs, ports_spec);
- if (auto scfp = found_scf.get())
- {
- auto& scf = *scfp;
- if (scf->core_paragraph->name == port_name)
- {
- return SourceControlFileLocation{std::move(scf), std::move(ports_spec)};
- }
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- "Error: Failed to load port from %s: names did not match: '%s' != '%s'",
- fs::u8string(ports_spec),
- port_name,
- scf->core_paragraph->name);
- }
- else
- {
- print_error_message(found_scf.error());
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Error: Failed to load port %s from %s",
- port_name,
- fs::u8string(ports_dir));
- }
- }
- }
- return nullopt;
- }
-
- virtual Optional<const SourceControlFileLocation&> get_control_file(StringView port_name) const override
- {
- auto it = m_overlay_cache.find(port_name);
- if (it == m_overlay_cache.end())
- {
- it = m_overlay_cache.emplace(port_name.to_string(), load_port(port_name)).first;
- }
- return it->second;
- }
-
- virtual void load_all_control_files(
- std::map<std::string, const SourceControlFileLocation*>& out) const override
- {
- for (auto&& ports_dir : m_overlay_ports)
- {
- // Try loading individual port
- if (Paragraphs::is_port_directory(m_fs, ports_dir))
- {
- auto maybe_scf = Paragraphs::try_load_port(m_fs, ports_dir);
- if (auto scfp = maybe_scf.get())
- {
- SourceControlFileLocation scfl{std::move(*scfp), fs::path(ports_dir)};
- auto name = scfl.source_control_file->core_paragraph->name;
- auto it = m_overlay_cache.emplace(std::move(name), std::move(scfl)).first;
- Checks::check_exit(VCPKG_LINE_INFO, it->second.get());
- out.emplace(it->first, it->second.get());
- }
- else
- {
- print_error_message(maybe_scf.error());
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO, "Error: Failed to load port from %s", fs::u8string(ports_dir));
- }
-
- continue;
- }
-
- // Try loading all ports inside ports_dir
- auto found_scfls = Paragraphs::load_overlay_ports(m_fs, ports_dir);
- for (auto&& scfl : found_scfls)
- {
- auto name = scfl.source_control_file->core_paragraph->name;
- auto it = m_overlay_cache.emplace(std::move(name), std::move(scfl)).first;
- Checks::check_exit(VCPKG_LINE_INFO, it->second.get());
- out.emplace(it->first, it->second.get());
- }
- }
- }
-
- private:
- const Files::Filesystem& m_fs;
- const std::vector<fs::path> m_overlay_ports;
- mutable std::map<std::string, Optional<SourceControlFileLocation>, std::less<>> m_overlay_cache;
- };
- }
-
- std::unique_ptr<IBaselineProvider> make_baseline_provider(const vcpkg::VcpkgPaths& paths)
- {
- return std::make_unique<BaselineProviderImpl>(paths);
- }
-
- std::unique_ptr<IVersionedPortfileProvider> make_versioned_portfile_provider(const vcpkg::VcpkgPaths& paths)
- {
- return std::make_unique<VersionedPortfileProviderImpl>(paths);
- }
-
- std::unique_ptr<IOverlayProvider> make_overlay_provider(const vcpkg::VcpkgPaths& paths,
- View<std::string> overlay_ports)
- {
- return std::make_unique<OverlayProviderImpl>(paths, std::move(overlay_ports));
- }
-}
diff --git a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp
deleted file mode 100644
index 182625b78..000000000
--- a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <vcpkg/base/checks.h>
-
-#include <vcpkg/postbuildlint.buildtype.h>
-
-using vcpkg::Build::ConfigurationType;
-
-namespace vcpkg::PostBuildLint
-{
- BuildType BuildType::value_of(const ConfigurationType& config, const Build::LinkageType& linkage)
- {
- if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::STATIC)
- {
- return BuildTypeC::DEBUG_STATIC;
- }
-
- if (config == ConfigurationType::DEBUG && linkage == Build::LinkageType::DYNAMIC)
- {
- return BuildTypeC::DEBUG_DYNAMIC;
- }
-
- if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::STATIC)
- {
- return BuildTypeC::RELEASE_STATIC;
- }
-
- if (config == ConfigurationType::RELEASE && linkage == Build::LinkageType::DYNAMIC)
- {
- return BuildTypeC::RELEASE_DYNAMIC;
- }
-
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- const ConfigurationType& BuildType::config() const { return this->m_config; }
-
- const Build::LinkageType& BuildType::linkage() const { return this->m_linkage; }
-
- const std::regex& BuildType::crt_regex() const
- {
- static const std::regex REGEX_DEBUG_STATIC(R"(/DEFAULTLIB:LIBCMTD)", std::regex_constants::icase);
- static const std::regex REGEX_DEBUG_DYNAMIC(R"(/DEFAULTLIB:MSVCRTD)", std::regex_constants::icase);
- static const std::regex REGEX_RELEASE_STATIC(R"(/DEFAULTLIB:LIBCMT[^D])", std::regex_constants::icase);
- static const std::regex REGEX_RELEASE_DYNAMIC(R"(/DEFAULTLIB:MSVCRT[^D])", std::regex_constants::icase);
-
- switch (backing_enum)
- {
- case BuildTypeC::DEBUG_STATIC: return REGEX_DEBUG_STATIC;
- case BuildTypeC::DEBUG_DYNAMIC: return REGEX_DEBUG_DYNAMIC;
- case BuildTypeC::RELEASE_STATIC: return REGEX_RELEASE_STATIC;
- case BuildTypeC::RELEASE_DYNAMIC: return REGEX_RELEASE_DYNAMIC;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- const std::string& BuildType::to_string() const
- {
- static const std::string NAME_DEBUG_STATIC("Debug,Static");
- static const std::string NAME_DEBUG_DYNAMIC("Debug,Dynamic");
- static const std::string NAME_RELEASE_STATIC("Release,Static");
- static const std::string NAME_RELEASE_DYNAMIC("Release,Dynamic");
-
- switch (backing_enum)
- {
- case BuildTypeC::DEBUG_STATIC: return NAME_DEBUG_STATIC;
- case BuildTypeC::DEBUG_DYNAMIC: return NAME_DEBUG_DYNAMIC;
- case BuildTypeC::RELEASE_STATIC: return NAME_RELEASE_STATIC;
- case BuildTypeC::RELEASE_DYNAMIC: return NAME_RELEASE_DYNAMIC;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp
deleted file mode 100644
index 29f6a9b32..000000000
--- a/toolsrc/src/vcpkg/postbuildlint.cpp
+++ /dev/null
@@ -1,981 +0,0 @@
-#include <vcpkg/base/cofffilereader.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/build.h>
-#include <vcpkg/packagespec.h>
-#include <vcpkg/postbuildlint.buildtype.h>
-#include <vcpkg/postbuildlint.h>
-#include <vcpkg/vcpkgpaths.h>
-
-using vcpkg::Build::BuildInfo;
-using vcpkg::Build::BuildPolicy;
-using vcpkg::Build::PreBuildInfo;
-
-namespace vcpkg::PostBuildLint
-{
- static auto not_extension_pred(const Files::Filesystem& fs, const std::string& ext)
- {
- return [&fs, ext](const fs::path& path) { return fs.is_directory(path) || path.extension() != ext; };
- }
-
- enum class LintStatus
- {
- SUCCESS = 0,
- ERROR_DETECTED = 1
- };
-
- struct OutdatedDynamicCrt
- {
- std::string name;
- std::regex regex;
-
- OutdatedDynamicCrt(const std::string& name, const std::string& regex_as_string)
- : name(name), regex(std::regex(regex_as_string, std::regex_constants::icase))
- {
- }
- };
-
- static Span<const OutdatedDynamicCrt> get_outdated_dynamic_crts(const Optional<std::string>& toolset_version)
- {
- static const std::vector<OutdatedDynamicCrt> V_NO_120 = {
- {"msvcp100.dll", R"(msvcp100\.dll)"},
- {"msvcp100d.dll", R"(msvcp100d\.dll)"},
- {"msvcp110.dll", R"(msvcp110\.dll)"},
- {"msvcp110_win.dll", R"(msvcp110_win\.dll)"},
- {"msvcp60.dll", R"(msvcp60\.dll)"},
- {"msvcp60.dll", R"(msvcp60\.dll)"},
-
- {"msvcrt.dll", R"(msvcrt\.dll)"},
- {"msvcr100.dll", R"(msvcr100\.dll)"},
- {"msvcr100d.dll", R"(msvcr100d\.dll)"},
- {"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"},
- {"msvcr110.dll", R"(msvcr110\.dll)"},
- {"msvcrt20.dll", R"(msvcrt20\.dll)"},
- {"msvcrt40.dll", R"(msvcrt40\.dll)"},
- };
-
- static const std::vector<OutdatedDynamicCrt> V_NO_MSVCRT = [&]() {
- auto ret = V_NO_120;
- ret.push_back({"msvcp120.dll", R"(msvcp120\.dll)"});
- ret.push_back({"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"});
- ret.push_back({"msvcr120.dll", R"(msvcr120\.dll)"});
- ret.push_back({"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"});
- return ret;
- }();
-
- const auto tsv = toolset_version.get();
- if (tsv && (*tsv) == "v120")
- {
- return V_NO_120;
- }
-
- // Default case for all version >= VS 2015.
- return V_NO_MSVCRT;
- }
-
- static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs,
- const Build::BuildPolicies& policies,
- const fs::path& package_dir)
- {
- if (policies.is_enabled(BuildPolicy::EMPTY_INCLUDE_FOLDER))
- {
- return LintStatus::SUCCESS;
- }
-
- const fs::path include_dir = package_dir / "include";
- if (!fs.exists(include_dir) || fs.is_empty(include_dir))
- {
- System::print2(System::Color::warning,
- "The folder /include is empty or not present. This indicates the library was not correctly "
- "installed.\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_for_restricted_include_files(const Files::Filesystem& fs,
- const Build::BuildPolicies& policies,
- const fs::path& package_dir)
- {
- if (policies.is_enabled(BuildPolicy::ALLOW_RESTRICTED_HEADERS))
- {
- return LintStatus::SUCCESS;
- }
-
- // These files are taken from the libc6-dev package on Ubuntu inside /usr/include/x86_64-linux-gnu/sys/
- static constexpr StringLiteral restricted_sys_filenames[] = {
- "acct.h", "auxv.h", "bitypes.h", "cdefs.h", "debugreg.h", "dir.h", "elf.h",
- "epoll.h", "errno.h", "eventfd.h", "fanotify.h", "fcntl.h", "file.h", "fsuid.h",
- "gmon.h", "gmon_out.h", "inotify.h", "io.h", "ioctl.h", "ipc.h", "kd.h",
- "klog.h", "mman.h", "mount.h", "msg.h", "mtio.h", "param.h", "pci.h",
- "perm.h", "personality.h", "poll.h", "prctl.h", "procfs.h", "profil.h", "ptrace.h",
- "queue.h", "quota.h", "random.h", "raw.h", "reboot.h", "reg.h", "resource.h",
- "select.h", "sem.h", "sendfile.h", "shm.h", "signal.h", "signalfd.h", "socket.h",
- "socketvar.h", "soundcard.h", "stat.h", "statfs.h", "statvfs.h", "stropts.h", "swap.h",
- "syscall.h", "sysctl.h", "sysinfo.h", "syslog.h", "sysmacros.h", "termios.h", "time.h",
- "timeb.h", "timerfd.h", "times.h", "timex.h", "ttychars.h", "ttydefaults.h", "types.h",
- "ucontext.h", "uio.h", "un.h", "unistd.h", "user.h", "ustat.h", "utsname.h",
- "vfs.h", "vlimit.h", "vm86.h", "vt.h", "vtimes.h", "wait.h", "xattr.h",
- };
- // These files are taken from the libc6-dev package on Ubuntu inside the /usr/include/ folder
- static constexpr StringLiteral restricted_crt_filenames[] = {
- "_G_config.h", "aio.h", "aliases.h", "alloca.h", "ar.h", "argp.h",
- "argz.h", "assert.h", "byteswap.h", "complex.h", "cpio.h", "crypt.h",
- "ctype.h", "dirent.h", "dlfcn.h", "elf.h", "endian.h", "envz.h",
- "err.h", "errno.h", "error.h", "execinfo.h", "fcntl.h", "features.h",
- "fenv.h", "fmtmsg.h", "fnmatch.h", "fstab.h", "fts.h", "ftw.h",
- "gconv.h", "getopt.h", "glob.h", "gnu-versions.h", "grp.h", "gshadow.h",
- "iconv.h", "ifaddrs.h", "inttypes.h", "langinfo.h", "lastlog.h", "libgen.h",
- "libintl.h", "libio.h", "limits.h", "link.h", "locale.h", "malloc.h",
- "math.h", "mcheck.h", "memory.h", "mntent.h", "monetary.h", "mqueue.h",
- "netash", "netdb.h", "nl_types.h", "nss.h", "obstack.h", "paths.h",
- "poll.h", "printf.h", "proc_service.h", "pthread.h", "pty.h", "pwd.h",
- "re_comp.h", "regex.h", "regexp.h", "resolv.h", "sched.h", "search.h",
- "semaphore.h", "setjmp.h", "sgtty.h", "shadow.h", "signal.h", "spawn.h",
- "stab.h", "stdc-predef.h", "stdint.h", "stdio.h", "stdio_ext.h", "stdlib.h",
- "string.h", "strings.h", "stropts.h", "syscall.h", "sysexits.h", "syslog.h",
- "tar.h", "termio.h", "termios.h", "tgmath.h", "thread_db.h", "time.h",
- "ttyent.h", "uchar.h", "ucontext.h", "ulimit.h", "unistd.h", "ustat.h",
- "utime.h", "utmp.h", "utmpx.h", "values.h", "wait.h", "wchar.h",
- "wctype.h", "wordexp.h",
- };
- // These files are general names that have shown to be problematic in the past
- static constexpr StringLiteral restricted_general_filenames[] = {
- "json.h",
- "parser.h",
- "lexer.h",
- "config.h",
- "local.h",
- "slice.h",
- "platform.h",
- };
- static constexpr Span<const StringLiteral> restricted_lists[] = {
- restricted_sys_filenames, restricted_crt_filenames, restricted_general_filenames};
- const fs::path include_dir = package_dir / "include";
- auto files = fs.get_files_non_recursive(include_dir);
- auto filenames_v = Util::fmap(files, [](const auto& file) { return fs::u8string(file.filename()); });
- std::set<std::string> filenames_s(filenames_v.begin(), filenames_v.end());
-
- std::vector<fs::path> violations;
- for (auto&& flist : restricted_lists)
- for (auto&& f : flist)
- {
- if (Util::Sets::contains(filenames_s, f))
- {
- violations.push_back(fs::u8path("include") / fs::u8path(f.c_str()));
- }
- }
-
- if (!violations.empty())
- {
- System::print2(System::Color::warning,
- "Restricted headers paths are present. These files can prevent the core C++ runtime and "
- "other packages from compiling correctly:\n");
- Files::print_paths(violations);
- System::print2("In exceptional circumstances, this policy can be disabled via ",
- Build::to_cmake_variable(BuildPolicy::ALLOW_RESTRICTED_HEADERS),
- "\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_for_files_in_debug_include_directory(const Files::Filesystem& fs,
- const fs::path& package_dir)
- {
- const fs::path debug_include_dir = package_dir / "debug" / "include";
-
- std::vector<fs::path> files_found = fs.get_files_recursive(debug_include_dir);
-
- Util::erase_remove_if(
- files_found, [&fs](const fs::path& path) { return fs.is_directory(path) || path.extension() == ".ifc"; });
-
- if (!files_found.empty())
- {
- System::print2(System::Color::warning,
- "Include files should not be duplicated into the /debug/include directory. If this cannot "
- "be disabled in the project cmake, use\n"
- " file(REMOVE_RECURSE \"${CURRENT_PACKAGES_DIR}/debug/include\")\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_for_files_in_debug_share_directory(const Files::Filesystem& fs, const fs::path& package_dir)
- {
- const fs::path debug_share = package_dir / "debug" / "share";
-
- if (fs.exists(debug_share))
- {
- System::print2(System::Color::warning,
- "/debug/share should not exist. Please reorganize any important files, then use\n"
- " file(REMOVE_RECURSE \"${CURRENT_PACKAGES_DIR}/debug/share\")\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_folder_lib_cmake(const Files::Filesystem& fs,
- const fs::path& package_dir,
- const PackageSpec& spec)
- {
- const fs::path lib_cmake = package_dir / "lib" / "cmake";
- if (fs.exists(lib_cmake))
- {
- System::printf(System::Color::warning,
- "The /lib/cmake folder should be merged with /debug/lib/cmake and moved to "
- "/share/%s/cmake.\nPlease use the helper function `vcpkg_fixup_cmake_targets()`\n",
- spec.name());
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_for_misplaced_cmake_files(const Files::Filesystem& fs,
- const fs::path& package_dir,
- const PackageSpec& spec)
- {
- std::vector<fs::path> dirs = {
- package_dir / "cmake",
- package_dir / "debug" / "cmake",
- package_dir / "lib" / "cmake",
- package_dir / "debug" / "lib" / "cmake",
- };
-
- std::vector<fs::path> misplaced_cmake_files;
- for (auto&& dir : dirs)
- {
- auto files = fs.get_files_recursive(dir);
- for (auto&& file : files)
- {
- if (!fs.is_directory(file) && file.extension() == ".cmake")
- misplaced_cmake_files.push_back(std::move(file));
- }
- }
-
- if (!misplaced_cmake_files.empty())
- {
- System::printf(
- System::Color::warning,
- "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.\n",
- spec.name(),
- spec.name());
- Files::print_paths(misplaced_cmake_files);
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_folder_debug_lib_cmake(const Files::Filesystem& fs,
- const fs::path& package_dir,
- const PackageSpec& spec)
- {
- const fs::path lib_cmake_debug = package_dir / "debug" / "lib" / "cmake";
- if (fs.exists(lib_cmake_debug))
- {
- System::printf(System::Color::warning,
- "The /debug/lib/cmake folder should be merged with /lib/cmake into /share/%s\n",
- spec.name());
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_for_dlls_in_lib_dir(const Files::Filesystem& fs, const fs::path& package_dir)
- {
- std::vector<fs::path> dlls = fs.get_files_recursive(package_dir / "lib");
- Util::erase_remove_if(dlls, not_extension_pred(fs, ".dll"));
-
- if (!dlls.empty())
- {
- System::print2(System::Color::warning,
- "\nThe following dlls were found in /lib or /debug/lib. Please move them to /bin or "
- "/debug/bin, respectively.\n");
- Files::print_paths(dlls);
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_for_copyright_file(const Files::Filesystem& fs,
- const PackageSpec& spec,
- const VcpkgPaths& paths)
- {
- const fs::path packages_dir = paths.packages / spec.dir();
- const fs::path copyright_file = packages_dir / "share" / spec.name() / "copyright";
- if (fs.exists(copyright_file))
- {
- return LintStatus::SUCCESS;
- }
- const fs::path current_buildtrees_dir = paths.build_dir(spec);
- const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src";
-
- std::vector<fs::path> potential_copyright_files;
- // We only search in the root of each unpacked source archive to reduce false positives
- auto src_dirs = fs.get_files_non_recursive(current_buildtrees_dir_src);
- for (auto&& src_dir : src_dirs)
- {
- if (!fs.is_directory(src_dir)) continue;
-
- for (auto&& src_file : fs.get_files_non_recursive(src_dir))
- {
- const std::string filename = src_file.filename().string();
-
- if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING")
- {
- potential_copyright_files.push_back(src_file);
- }
- }
- }
-
- System::printf(System::Color::warning,
- "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright\n",
- spec.name());
- if (potential_copyright_files.size() == 1)
- {
- // if there is only one candidate, provide the cmake lines needed to place it in the proper location
- const fs::path found_file = potential_copyright_files[0];
- auto found_relative_native = found_file.native();
- found_relative_native.erase(current_buildtrees_dir.native().size() +
- 1); // The +1 is needed to remove the "/"
- const fs::path relative_path = found_relative_native;
- System::printf("\n configure_file(\"${CURRENT_BUILDTREES_DIR}/%s/%s\" "
- "\"${CURRENT_PACKAGES_DIR}/share/%s/copyright\" COPYONLY)\n",
- relative_path.generic_string(),
- found_file.filename().generic_string(),
- spec.name());
- }
- else if (potential_copyright_files.size() > 1)
- {
- System::print2(System::Color::warning, "The following files are potential copyright files:\n");
- Files::print_paths(potential_copyright_files);
- }
- return LintStatus::ERROR_DETECTED;
- }
-
- static LintStatus check_for_exes(const Files::Filesystem& fs, const fs::path& package_dir)
- {
- std::vector<fs::path> exes = fs.get_files_recursive(package_dir / "bin");
- Util::erase_remove_if(exes, not_extension_pred(fs, ".exe"));
-
- if (!exes.empty())
- {
- System::print2(
- System::Color::warning,
- "The following EXEs were found in /bin or /debug/bin. EXEs are not valid distribution targets.\n");
- Files::print_paths(exes);
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_exports_of_dlls(const Build::BuildPolicies& policies,
- const std::vector<fs::path>& dlls,
- const fs::path& dumpbin_exe)
- {
- if (policies.is_enabled(BuildPolicy::DLLS_WITHOUT_EXPORTS)) return LintStatus::SUCCESS;
-
- std::vector<fs::path> dlls_with_no_exports;
- for (const fs::path& dll : dlls)
- {
- auto cmd_line = System::Command(dumpbin_exe).string_arg("/exports").path_arg(dll);
- System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(
- VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line.command_line());
-
- if (ec_data.output.find("ordinal hint RVA name") == std::string::npos)
- {
- dlls_with_no_exports.push_back(dll);
- }
- }
-
- if (!dlls_with_no_exports.empty())
- {
- System::print2(System::Color::warning, "The following DLLs have no exports:\n");
- Files::print_paths(dlls_with_no_exports);
- System::print2(System::Color::warning, "DLLs without any exports are likely a bug in the build script.\n");
- System::printf(System::Color::warning,
- "If this is intended, add the following line in the portfile:\n"
- " SET(%s enabled)\n",
- to_cmake_variable(BuildPolicy::DLLS_WITHOUT_EXPORTS));
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_uwp_bit_of_dlls(const std::string& expected_system_name,
- const std::vector<fs::path>& dlls,
- const fs::path dumpbin_exe)
- {
- if (expected_system_name != "WindowsStore")
- {
- return LintStatus::SUCCESS;
- }
-
- std::vector<fs::path> dlls_with_improper_uwp_bit;
- for (const fs::path& dll : dlls)
- {
- auto cmd_line = System::Command(dumpbin_exe).string_arg("/headers").path_arg(dll);
- System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(
- VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line.command_line());
-
- if (ec_data.output.find("App Container") == std::string::npos)
- {
- dlls_with_improper_uwp_bit.push_back(dll);
- }
- }
-
- if (!dlls_with_improper_uwp_bit.empty())
- {
- System::print2(System::Color::warning, "The following DLLs do not have the App Container bit set:\n");
- Files::print_paths(dlls_with_improper_uwp_bit);
- System::print2(System::Color::warning, "This bit is required for Windows Store apps.\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- struct FileAndArch
- {
- fs::path file;
- std::string actual_arch;
- };
-
-#if defined(_WIN32)
- static std::string get_actual_architecture(const MachineType& machine_type)
- {
- switch (machine_type)
- {
- case MachineType::AMD64:
- case MachineType::IA64: return "x64";
- case MachineType::I386: return "x86";
- case MachineType::ARM:
- case MachineType::ARMNT: return "arm";
- case MachineType::ARM64: return "arm64";
- default: return "Machine Type Code = " + std::to_string(static_cast<uint16_t>(machine_type));
- }
- }
-#endif
-
-#if defined(_WIN32)
- static void print_invalid_architecture_files(const std::string& expected_architecture,
- std::vector<FileAndArch> binaries_with_invalid_architecture)
- {
- System::print2(System::Color::warning, "The following files were built for an incorrect architecture:\n\n");
- for (const FileAndArch& b : binaries_with_invalid_architecture)
- {
- System::print2(" ",
- fs::u8string(b.file),
- "\n"
- "Expected ",
- expected_architecture,
- ", but was: ",
- b.actual_arch,
- "\n\n");
- }
- }
-
- static LintStatus check_dll_architecture(const std::string& expected_architecture,
- const std::vector<fs::path>& files)
- {
- std::vector<FileAndArch> binaries_with_invalid_architecture;
-
- for (const fs::path& file : files)
- {
- Checks::check_exit(VCPKG_LINE_INFO,
- file.extension() == ".dll",
- "The file extension was not .dll: %s",
- file.generic_string());
- const CoffFileReader::DllInfo info = CoffFileReader::read_dll(file);
- const std::string actual_architecture = get_actual_architecture(info.machine_type);
-
- if (expected_architecture != actual_architecture)
- {
- binaries_with_invalid_architecture.push_back({file, actual_architecture});
- }
- }
-
- if (!binaries_with_invalid_architecture.empty())
- {
- print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture);
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-#endif
-
- static LintStatus check_lib_architecture(const std::string& expected_architecture,
- const std::vector<fs::path>& files)
- {
-#if defined(_WIN32)
- std::vector<FileAndArch> binaries_with_invalid_architecture;
-
- for (const fs::path& file : files)
- {
- Checks::check_exit(VCPKG_LINE_INFO,
- file.extension() == ".lib",
- "The file extension was not .lib: %s",
- file.generic_string());
- CoffFileReader::LibInfo info = CoffFileReader::read_lib(file);
-
- // This is zero for folly's debug library
- // TODO: Why?
- if (info.machine_types.size() == 0) return LintStatus::SUCCESS;
-
- Checks::check_exit(VCPKG_LINE_INFO,
- info.machine_types.size() == 1,
- "Found more than 1 architecture in file %s",
- file.generic_string());
-
- const std::string actual_architecture = get_actual_architecture(info.machine_types.at(0));
- if (expected_architecture != actual_architecture)
- {
- binaries_with_invalid_architecture.push_back({file, actual_architecture});
- }
- }
-
- if (!binaries_with_invalid_architecture.empty())
- {
- print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture);
- return LintStatus::ERROR_DETECTED;
- }
-#endif
- (void)expected_architecture;
- (void)files;
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_no_dlls_present(const Build::BuildPolicies& policies, const std::vector<fs::path>& dlls)
- {
- if (dlls.empty() || policies.is_enabled(BuildPolicy::DLLS_IN_STATIC_LIBRARY))
- {
- return LintStatus::SUCCESS;
- }
-
- System::print2(System::Color::warning,
- "DLLs should not be present in a static build, but the following DLLs were found:\n");
- Files::print_paths(dlls);
- return LintStatus::ERROR_DETECTED;
- }
-
- static LintStatus check_matching_debug_and_release_binaries(const std::vector<fs::path>& debug_binaries,
- const std::vector<fs::path>& release_binaries)
- {
- const size_t debug_count = debug_binaries.size();
- const size_t release_count = release_binaries.size();
- if (debug_count == release_count)
- {
- return LintStatus::SUCCESS;
- }
-
- System::printf(System::Color::warning,
- "Mismatching number of debug and release binaries. Found %zd for debug but %zd for release.\n",
- debug_count,
- release_count);
- System::print2("Debug binaries\n");
- Files::print_paths(debug_binaries);
-
- System::print2("Release binaries\n");
- Files::print_paths(release_binaries);
-
- if (debug_count == 0)
- {
- System::print2(System::Color::warning, "Debug binaries were not found\n");
- }
- if (release_count == 0)
- {
- System::print2(System::Color::warning, "Release binaries were not found\n");
- }
-
- System::print2("\n");
-
- return LintStatus::ERROR_DETECTED;
- }
-
- static LintStatus check_lib_files_are_available_if_dlls_are_available(const Build::BuildPolicies& policies,
- const size_t lib_count,
- const size_t dll_count,
- const fs::path& lib_dir)
- {
- if (policies.is_enabled(BuildPolicy::DLLS_WITHOUT_LIBS)) return LintStatus::SUCCESS;
-
- if (lib_count == 0 && dll_count != 0)
- {
- System::print2(System::Color::warning, "Import libs were not present in ", fs::u8string(lib_dir), "\n");
- System::printf(System::Color::warning,
- "If this is intended, add the following line in the portfile:\n"
- " SET(%s enabled)\n",
- to_cmake_variable(BuildPolicy::DLLS_WITHOUT_LIBS));
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_bin_folders_are_not_present_in_static_build(const Build::BuildPolicies& policies,
- const Files::Filesystem& fs,
- const fs::path& package_dir)
- {
- if (policies.is_enabled(BuildPolicy::DLLS_IN_STATIC_LIBRARY)) return LintStatus::SUCCESS;
-
- const fs::path bin = package_dir / "bin";
- const fs::path debug_bin = package_dir / "debug" / "bin";
-
- if (!fs.exists(bin) && !fs.exists(debug_bin))
- {
- return LintStatus::SUCCESS;
- }
-
- if (fs.exists(bin))
- {
- System::printf(System::Color::warning,
- R"(There should be no bin\ directory in a static build, but %s is present.)"
- "\n",
- fs::u8string(bin));
- }
-
- if (fs.exists(debug_bin))
- {
- System::printf(System::Color::warning,
- R"(There should be no debug\bin\ directory in a static build, but %s is present.)"
- "\n",
- fs::u8string(debug_bin));
- }
-
- System::print2(
- System::Color::warning,
- R"(If the creation of bin\ and/or debug\bin\ cannot be disabled, use this in the portfile to remove them)"
- "\n"
- "\n"
- R"###( if(VCPKG_LIBRARY_LINKAGE STREQUAL "static"))###"
- "\n"
- R"###( file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/bin" "${CURRENT_PACKAGES_DIR}/debug/bin"))###"
- "\n"
- R"###( endif())###"
- "\n\n");
-
- return LintStatus::ERROR_DETECTED;
- }
-
- static LintStatus check_no_empty_folders(const Files::Filesystem& fs, const fs::path& dir)
- {
- std::vector<fs::path> empty_directories = fs.get_files_recursive(dir);
-
- Util::erase_remove_if(empty_directories, [&fs](const fs::path& current) {
- return !fs.is_directory(current) || !fs.is_empty(current);
- });
-
- if (!empty_directories.empty())
- {
- System::print2(System::Color::warning, "There should be no empty directories in ", fs::u8string(dir), "\n");
- System::print2("The following empty directories were found:\n");
- Files::print_paths(empty_directories);
- System::print2(
- System::Color::warning,
- "If a directory should be populated but is not, this might indicate an error in the portfile.\n"
- "If the directories are not needed and their creation cannot be disabled, use something like this in "
- "the portfile to remove them:\n"
- "\n"
- R"###( file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/a/dir" "${CURRENT_PACKAGES_DIR}/some/other/dir"))###"
- "\n"
- "\n"
- "\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- struct BuildTypeAndFile
- {
- fs::path file;
- BuildType build_type;
- };
-
- static LintStatus check_crt_linkage_of_libs(const BuildType& expected_build_type,
- const std::vector<fs::path>& libs,
- const fs::path dumpbin_exe)
- {
- std::vector<BuildType> bad_build_types(BuildTypeC::VALUES.cbegin(), BuildTypeC::VALUES.cend());
- bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type),
- bad_build_types.end());
-
- std::vector<BuildTypeAndFile> libs_with_invalid_crt;
-
- for (const fs::path& lib : libs)
- {
- auto cmd_line = System::Command(dumpbin_exe).string_arg("/directives").path_arg(lib);
- System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(VCPKG_LINE_INFO,
- ec_data.exit_code == 0,
- "Running command:\n %s\n failed with message:\n%s",
- cmd_line.command_line(),
- ec_data.output);
-
- for (const BuildType& bad_build_type : bad_build_types)
- {
- if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), bad_build_type.crt_regex()))
- {
- libs_with_invalid_crt.push_back({lib, bad_build_type});
- break;
- }
- }
- }
-
- if (!libs_with_invalid_crt.empty())
- {
- System::printf(System::Color::warning,
- "Expected %s crt linkage, but the following libs had invalid crt linkage:\n\n",
- expected_build_type.to_string());
- for (const BuildTypeAndFile& btf : libs_with_invalid_crt)
- {
- System::printf(" %s: %s\n", btf.file.generic_string(), btf.build_type.to_string());
- }
- System::print2("\n");
-
- System::print2(System::Color::warning,
- "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- struct OutdatedDynamicCrtAndFile
- {
- fs::path file;
- OutdatedDynamicCrt outdated_crt;
- };
-
- static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls,
- const fs::path dumpbin_exe,
- const BuildInfo& build_info,
- const PreBuildInfo& pre_build_info)
- {
- if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS;
-
- std::vector<OutdatedDynamicCrtAndFile> dlls_with_outdated_crt;
-
- for (const fs::path& dll : dlls)
- {
- auto cmd_line = System::Command(dumpbin_exe).string_arg("/dependents").path_arg(dll);
- System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(
- VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line.command_line());
-
- for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts(pre_build_info.platform_toolset))
- {
- if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex))
- {
- dlls_with_outdated_crt.push_back({dll, outdated_crt});
- break;
- }
- }
- }
-
- if (!dlls_with_outdated_crt.empty())
- {
- System::print2(System::Color::warning, "Detected outdated dynamic CRT in the following files:\n\n");
- for (const OutdatedDynamicCrtAndFile& btf : dlls_with_outdated_crt)
- {
- System::print2(" ", fs::u8string(btf.file), ": ", btf.outdated_crt.name, "\n");
- }
- System::print2("\n");
-
- System::print2(System::Color::warning,
- "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static LintStatus check_no_files_in_dir(const Files::Filesystem& fs, const fs::path& dir)
- {
- std::vector<fs::path> misplaced_files = fs.get_files_non_recursive(dir);
- Util::erase_remove_if(misplaced_files, [&fs](const fs::path& path) {
- const std::string filename = path.filename().generic_string();
- if (Strings::case_insensitive_ascii_equals(filename, "CONTROL") ||
- Strings::case_insensitive_ascii_equals(filename, "BUILD_INFO"))
- {
- return true;
- }
-
- return fs.is_directory(path);
- });
-
- if (!misplaced_files.empty())
- {
- System::print2(System::Color::warning, "The following files are placed in\n", fs::u8string(dir), ":\n");
- Files::print_paths(misplaced_files);
- System::print2(System::Color::warning, "Files cannot be present in those directories.\n\n");
- return LintStatus::ERROR_DETECTED;
- }
-
- return LintStatus::SUCCESS;
- }
-
- static void operator+=(size_t& left, const LintStatus& right) { left += static_cast<size_t>(right); }
-
- static size_t perform_all_checks_and_return_error_count(const PackageSpec& spec,
- const VcpkgPaths& paths,
- const PreBuildInfo& pre_build_info,
- const BuildInfo& build_info)
- {
- const auto& fs = paths.get_filesystem();
-
- // for dumpbin
- const Toolset& toolset = paths.get_toolset(pre_build_info);
- const fs::path package_dir = paths.package_dir(spec);
-
- size_t error_count = 0;
-
- if (build_info.policies.is_enabled(BuildPolicy::EMPTY_PACKAGE))
- {
- return error_count;
- }
-
- error_count += check_for_files_in_include_directory(fs, build_info.policies, package_dir);
- error_count += check_for_restricted_include_files(fs, build_info.policies, package_dir);
- error_count += check_for_files_in_debug_include_directory(fs, package_dir);
- error_count += check_for_files_in_debug_share_directory(fs, package_dir);
- error_count += check_folder_lib_cmake(fs, package_dir, spec);
- error_count += check_for_misplaced_cmake_files(fs, package_dir, spec);
- error_count += check_folder_debug_lib_cmake(fs, package_dir, spec);
- error_count += check_for_dlls_in_lib_dir(fs, package_dir);
- error_count += check_for_dlls_in_lib_dir(fs, package_dir / "debug");
- error_count += check_for_copyright_file(fs, spec, paths);
- error_count += check_for_exes(fs, package_dir);
- error_count += check_for_exes(fs, package_dir / "debug");
-
- const fs::path debug_lib_dir = package_dir / "debug" / "lib";
- const fs::path release_lib_dir = package_dir / "lib";
- const fs::path debug_bin_dir = package_dir / "debug" / "bin";
- const fs::path release_bin_dir = package_dir / "bin";
-
- std::vector<fs::path> debug_libs = fs.get_files_recursive(debug_lib_dir);
- Util::erase_remove_if(debug_libs, not_extension_pred(fs, ".lib"));
- std::vector<fs::path> release_libs = fs.get_files_recursive(release_lib_dir);
- Util::erase_remove_if(release_libs, not_extension_pred(fs, ".lib"));
-
- if (!pre_build_info.build_type && !build_info.policies.is_enabled(BuildPolicy::MISMATCHED_NUMBER_OF_BINARIES))
- error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs);
-
- if (!build_info.policies.is_enabled(BuildPolicy::SKIP_ARCHITECTURE_CHECK))
- {
- std::vector<fs::path> libs;
- libs.insert(libs.cend(), debug_libs.cbegin(), debug_libs.cend());
- libs.insert(libs.cend(), release_libs.cbegin(), release_libs.cend());
- error_count += check_lib_architecture(pre_build_info.target_architecture, libs);
- }
-
- std::vector<fs::path> debug_dlls = fs.get_files_recursive(debug_bin_dir);
- Util::erase_remove_if(debug_dlls, not_extension_pred(fs, ".dll"));
- std::vector<fs::path> release_dlls = fs.get_files_recursive(release_bin_dir);
- Util::erase_remove_if(release_dlls, not_extension_pred(fs, ".dll"));
-
- switch (build_info.library_linkage)
- {
- case Build::LinkageType::DYNAMIC:
- {
- if (!pre_build_info.build_type &&
- !build_info.policies.is_enabled(BuildPolicy::MISMATCHED_NUMBER_OF_BINARIES))
- error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls);
-
- error_count += check_lib_files_are_available_if_dlls_are_available(
- build_info.policies, debug_libs.size(), debug_dlls.size(), debug_lib_dir);
- error_count += check_lib_files_are_available_if_dlls_are_available(
- build_info.policies, release_libs.size(), release_dlls.size(), release_lib_dir);
-
- std::vector<fs::path> dlls;
- dlls.insert(dlls.cend(), debug_dlls.cbegin(), debug_dlls.cend());
- dlls.insert(dlls.cend(), release_dlls.cbegin(), release_dlls.cend());
-
- if (!toolset.dumpbin.empty() && !build_info.policies.is_enabled(BuildPolicy::SKIP_DUMPBIN_CHECKS))
- {
- error_count += check_exports_of_dlls(build_info.policies, dlls, toolset.dumpbin);
- error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin);
- error_count +=
- check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info, pre_build_info);
- }
-
-#if defined(_WIN32)
- error_count += check_dll_architecture(pre_build_info.target_architecture, dlls);
-#endif
- break;
- }
- case Build::LinkageType::STATIC:
- {
- auto dlls = release_dlls;
- dlls.insert(dlls.end(), debug_dlls.begin(), debug_dlls.end());
- error_count += check_no_dlls_present(build_info.policies, dlls);
-
- error_count += check_bin_folders_are_not_present_in_static_build(build_info.policies, fs, package_dir);
-
- if (!toolset.dumpbin.empty() && !build_info.policies.is_enabled(BuildPolicy::SKIP_DUMPBIN_CHECKS))
- {
- if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT))
- {
- error_count += check_crt_linkage_of_libs(
- BuildType::value_of(Build::ConfigurationType::DEBUG, build_info.crt_linkage),
- debug_libs,
- toolset.dumpbin);
- }
- error_count += check_crt_linkage_of_libs(
- BuildType::value_of(Build::ConfigurationType::RELEASE, build_info.crt_linkage),
- release_libs,
- toolset.dumpbin);
- }
- break;
- }
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- error_count += check_no_empty_folders(fs, package_dir);
- error_count += check_no_files_in_dir(fs, package_dir);
- error_count += check_no_files_in_dir(fs, package_dir / "debug");
-
- return error_count;
- }
-
- size_t perform_all_checks(const PackageSpec& spec,
- const VcpkgPaths& paths,
- const PreBuildInfo& pre_build_info,
- const BuildInfo& build_info,
- const fs::path& port_dir)
- {
- System::print2("-- Performing post-build validation\n");
- const size_t error_count = perform_all_checks_and_return_error_count(spec, paths, pre_build_info, build_info);
-
- if (error_count != 0)
- {
- const fs::path portfile = port_dir / "portfile.cmake";
- System::print2(System::Color::error,
- "Found ",
- error_count,
- " error(s). Please correct the portfile:\n ",
- fs::u8string(portfile),
- "\n");
- }
-
- System::print2("-- Performing post-build validation done\n");
-
- return error_count;
- }
-}
diff --git a/toolsrc/src/vcpkg/registries.cpp b/toolsrc/src/vcpkg/registries.cpp
deleted file mode 100644
index 971e8d0c2..000000000
--- a/toolsrc/src/vcpkg/registries.cpp
+++ /dev/null
@@ -1,1204 +0,0 @@
-#include <vcpkg/base/delayed_init.h>
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/jsonreader.h>
-#include <vcpkg/base/system.debug.h>
-
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/registries.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/versiondeserializers.h>
-#include <vcpkg/versiont.h>
-
-#include <map>
-
-namespace
-{
- using namespace vcpkg;
-
- using Baseline = std::map<std::string, VersionT, std::less<>>;
-
- static const fs::path registry_versions_dir_name = fs::u8path("versions");
-
- // this class is an implementation detail of `BuiltinRegistryEntry`;
- // when `BuiltinRegistryEntry` is using a port versions file for a port,
- // it uses this as it's underlying type;
- // when `BuiltinRegistryEntry` is using a port tree, it uses the scfl
- struct GitRegistryEntry final : RegistryEntry
- {
- View<VersionT> get_port_versions() const override { return port_versions; }
- ExpectedS<fs::path> get_path_to_version(const VcpkgPaths&, const VersionT& version) const override;
-
- std::string port_name;
-
- // these two map port versions to git trees
- // these shall have the same size, and git_trees[i] shall be the git tree for port_versions[i]
- std::vector<VersionT> port_versions;
- std::vector<std::string> git_trees;
- };
-
- struct GitRegistry final : RegistryImplementation
- {
- GitRegistry(std::string&& repo, std::string&& baseline)
- : m_repo(std::move(repo)), m_baseline_identifier(std::move(baseline))
- {
- }
-
- std::unique_ptr<RegistryEntry> get_port_entry(const VcpkgPaths&, StringView) const override;
-
- void get_all_port_names(std::vector<std::string>&, const VcpkgPaths&) const override;
-
- Optional<VersionT> get_baseline_version(const VcpkgPaths&, StringView) const override;
-
- StringView get_commit_of_repo(const VcpkgPaths& paths) const
- {
- return m_commit.get([this, &paths]() -> std::string {
- auto maybe_hash = paths.git_fetch_from_remote_registry(m_repo);
- if (!maybe_hash.has_value())
- {
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: Failed to fetch from remote registry `%s`: %s",
- m_repo,
- maybe_hash.error());
- }
- return std::move(*maybe_hash.get());
- });
- }
-
- fs::path get_versions_tree_path(const VcpkgPaths& paths) const
- {
- return m_versions_tree.get([this, &paths]() -> fs::path {
- auto maybe_tree = paths.git_find_object_id_for_remote_registry_path(get_commit_of_repo(paths),
- registry_versions_dir_name);
- if (!maybe_tree)
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "Error: could not find the git tree for `versions` in repo `%s` at commit `%s`: %s",
- m_repo,
- get_commit_of_repo(paths),
- maybe_tree.error());
- }
- auto maybe_path = paths.git_checkout_object_from_remote_registry(*maybe_tree.get());
- if (!maybe_path)
- {
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: failed to check out `port_versions` from repo %s: %s",
- m_repo,
- maybe_path.error());
- }
- return std::move(*maybe_path.get());
- });
- }
-
- std::string m_repo;
- DelayedInit<std::string> m_commit; // TODO: eventually this should end up in the vcpkg-lock.json file
- DelayedInit<fs::path> m_versions_tree;
- std::string m_baseline_identifier;
- DelayedInit<Baseline> m_baseline;
- };
-
- struct BuiltinPortTreeRegistryEntry final : RegistryEntry
- {
- View<VersionT> get_port_versions() const override { return {&version, 1}; }
- ExpectedS<fs::path> get_path_to_version(const VcpkgPaths&, const VersionT& v) const override
- {
- if (v == version)
- {
- return path;
- }
-
- return {Strings::format("Error: no version entry for %s at version %s.\n"
- "We are currently using the version in the ports tree (%s).",
- name,
- v.to_string(),
- version.to_string()),
- expected_right_tag};
- }
-
- std::string name;
- fs::path path;
- VersionT version;
- };
-
- struct BuiltinGitRegistryEntry final : RegistryEntry
- {
- View<VersionT> get_port_versions() const override { return port_versions; }
- ExpectedS<fs::path> get_path_to_version(const VcpkgPaths&, const VersionT& version) const override;
-
- std::string port_name;
-
- // these two map port versions to git trees
- // these shall have the same size, and git_trees[i] shall be the git tree for port_versions[i]
- std::vector<VersionT> port_versions;
- std::vector<std::string> git_trees;
- };
-
- struct FilesystemRegistryEntry final : RegistryEntry
- {
- explicit FilesystemRegistryEntry(std::string&& port_name) : port_name(port_name) { }
-
- View<VersionT> get_port_versions() const override { return port_versions; }
-
- ExpectedS<fs::path> get_path_to_version(const VcpkgPaths& paths, const VersionT& version) const override;
-
- std::string port_name;
-
- // these two map port versions to paths
- // these shall have the same size, and paths[i] shall be the path for port_versions[i]
- std::vector<VersionT> port_versions;
- std::vector<fs::path> version_paths;
- };
-
- struct BuiltinRegistry final : RegistryImplementation
- {
- BuiltinRegistry(std::string&& baseline) : m_baseline_identifier(std::move(baseline))
- {
- Debug::print("BuiltinRegistry initialized with: \"", m_baseline_identifier, "\"\n");
- }
-
- std::unique_ptr<RegistryEntry> get_port_entry(const VcpkgPaths& paths, StringView port_name) const override;
-
- void get_all_port_names(std::vector<std::string>&, const VcpkgPaths&) const override;
-
- Optional<VersionT> get_baseline_version(const VcpkgPaths& paths, StringView port_name) const override;
-
- ~BuiltinRegistry() = default;
-
- std::string m_baseline_identifier;
- DelayedInit<Baseline> m_baseline;
- };
-
- struct FilesystemRegistry final : RegistryImplementation
- {
- FilesystemRegistry(fs::path&& path, std::string&& baseline)
- : m_path(std::move(path)), m_baseline_identifier(baseline)
- {
- }
-
- std::unique_ptr<RegistryEntry> get_port_entry(const VcpkgPaths&, StringView) const override;
-
- void get_all_port_names(std::vector<std::string>&, const VcpkgPaths&) const override;
-
- Optional<VersionT> get_baseline_version(const VcpkgPaths&, StringView) const override;
-
- private:
- fs::path m_path;
- std::string m_baseline_identifier;
- DelayedInit<Baseline> m_baseline;
- };
-
- struct VersionDbEntry
- {
- VersionT version;
- Versions::Scheme scheme = Versions::Scheme::String;
-
- // only one of these may be non-empty
- std::string git_tree;
- fs::path path;
- };
-
- // VersionDbType::Git => VersionDbEntry.git_tree is filled
- // VersionDbType::Filesystem => VersionDbEntry.path is filled
- enum class VersionDbType
- {
- Git,
- Filesystem,
- };
-
- fs::path relative_path_to_versions(StringView port_name);
- ExpectedS<std::vector<VersionDbEntry>> load_versions_file(const Files::Filesystem& fs,
- VersionDbType vdb,
- const fs::path& port_versions,
- StringView port_name,
- const fs::path& registry_root = {});
-
- // returns nullopt if the baseline is valid, but doesn't contain the specified baseline,
- // or (equivalently) if the baseline does not exist.
- ExpectedS<Optional<Baseline>> parse_baseline_versions(StringView contents, StringView baseline, StringView origin);
- ExpectedS<Optional<Baseline>> load_baseline_versions(const VcpkgPaths& paths,
- const fs::path& path_to_baseline,
- StringView identifier = {});
-
- void load_all_port_names_from_registry_versions(std::vector<std::string>& out,
- const VcpkgPaths& paths,
- const fs::path& port_versions_path)
- {
- for (auto super_directory : fs::directory_iterator(port_versions_path))
- {
- if (!fs::is_directory(paths.get_filesystem().status(VCPKG_LINE_INFO, super_directory))) continue;
-
- for (auto file : fs::directory_iterator(super_directory))
- {
- auto filename = fs::u8string(file.path().filename());
- if (!Strings::ends_with(filename, ".json")) continue;
-
- auto port_name = filename.substr(0, filename.size() - 5);
- if (!Json::PackageNameDeserializer::is_package_name(port_name))
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO, "Error: found invalid port version file name: `%s`.", fs::u8string(file));
- }
- out.push_back(std::move(port_name));
- }
- }
- }
-
- // { RegistryImplementation
-
- // { BuiltinRegistry::RegistryImplementation
- std::unique_ptr<RegistryEntry> BuiltinRegistry::get_port_entry(const VcpkgPaths& paths, StringView port_name) const
- {
- const auto& fs = paths.get_filesystem();
- if (!m_baseline_identifier.empty())
- {
- auto versions_path = paths.builtin_registry_versions / relative_path_to_versions(port_name);
- if (fs.exists(versions_path))
- {
- auto maybe_version_entries =
- load_versions_file(fs, VersionDbType::Git, paths.builtin_registry_versions, port_name);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, maybe_version_entries.has_value(), "Error: " + maybe_version_entries.error());
- auto version_entries = std::move(maybe_version_entries).value_or_exit(VCPKG_LINE_INFO);
-
- auto res = std::make_unique<BuiltinGitRegistryEntry>();
- res->port_name = port_name.to_string();
- for (auto&& version_entry : version_entries)
- {
- res->port_versions.push_back(version_entry.version);
- res->git_trees.push_back(version_entry.git_tree);
- }
- return res;
- }
- }
-
- // Fall back to current available version
- auto port_directory = paths.builtin_ports_directory() / fs::u8path(port_name);
- if (fs.exists(port_directory))
- {
- auto found_scf = Paragraphs::try_load_port(fs, port_directory);
- if (auto scfp = found_scf.get())
- {
- auto& scf = *scfp;
- auto maybe_error = scf->check_against_feature_flags(port_directory, paths.get_feature_flags());
- if (maybe_error)
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Parsing manifest failed: %s", *maybe_error.get());
- }
-
- if (scf->core_paragraph->name == port_name)
- {
- auto res = std::make_unique<BuiltinPortTreeRegistryEntry>();
- res->name = std::move(scf->core_paragraph->name);
- res->path = std::move(port_directory);
- res->version = scf->to_versiont();
- return res;
- }
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Error: Failed to load port from %s: names did not match: '%s' != '%s'",
- fs::u8string(port_directory),
- port_name,
- scf->core_paragraph->name);
- }
- }
-
- return nullptr;
- }
-
- ExpectedS<Baseline> try_parse_builtin_baseline(const VcpkgPaths& paths, StringView baseline_identifier)
- {
- if (baseline_identifier.size() == 0) return Baseline{};
- auto path_to_baseline = paths.builtin_registry_versions / fs::u8path("baseline.json");
- auto res_baseline = load_baseline_versions(paths, path_to_baseline, baseline_identifier);
-
- if (!res_baseline.has_value())
- {
- return res_baseline.error();
- }
-
- auto opt_baseline = res_baseline.get();
- if (auto p = opt_baseline->get())
- {
- return std::move(*p);
- }
-
- if (baseline_identifier == "default")
- {
- return Strings::format(
- "Error: Couldn't find explicitly specified baseline `\"default\"` in baseline file: %s",
- fs::u8string(path_to_baseline));
- }
-
- // attempt to check out the baseline:
- auto maybe_path = paths.git_checkout_baseline(baseline_identifier);
- if (!maybe_path.has_value())
- {
- return Strings::format("Error: Couldn't find explicitly specified baseline `\"%s\"` in the baseline file, "
- "and there was no baseline at that commit or the commit didn't exist.\n%s\n%s",
- baseline_identifier,
- maybe_path.error(),
- paths.get_current_git_sha_message());
- }
-
- res_baseline = load_baseline_versions(paths, *maybe_path.get());
- if (!res_baseline.has_value())
- {
- return res_baseline.error();
- }
- opt_baseline = res_baseline.get();
- if (auto p = opt_baseline->get())
- {
- return std::move(*p);
- }
-
- return Strings::format("Error: Couldn't find explicitly specified baseline `\"%s\"` in the baseline "
- "file, and the `\"default\"` baseline does not exist at that commit.",
- baseline_identifier);
- }
-
- Baseline parse_builtin_baseline(const VcpkgPaths& paths, StringView baseline_identifier)
- {
- auto maybe_baseline = try_parse_builtin_baseline(paths, baseline_identifier);
- return maybe_baseline.value_or_exit(VCPKG_LINE_INFO);
- }
- Optional<VersionT> BuiltinRegistry::get_baseline_version(const VcpkgPaths& paths, StringView port_name) const
- {
- if (!m_baseline_identifier.empty())
- {
- const auto& baseline = m_baseline.get(
- [this, &paths]() -> Baseline { return parse_builtin_baseline(paths, m_baseline_identifier); });
-
- auto it = baseline.find(port_name);
- if (it != baseline.end())
- {
- return it->second;
- }
- return nullopt;
- }
-
- // if a baseline is not specified, use the ports directory version
- auto port_path = paths.builtin_ports_directory() / fs::u8path(port_name);
- auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), port_path);
- if (auto pscf = maybe_scf.get())
- {
- auto& scf = *pscf;
- return scf->to_versiont();
- }
- print_error_message(maybe_scf.error());
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Error: failed to load port from %s", fs::u8string(port_path));
- }
-
- void BuiltinRegistry::get_all_port_names(std::vector<std::string>& out, const VcpkgPaths& paths) const
- {
- const auto& fs = paths.get_filesystem();
-
- if (!m_baseline_identifier.empty() && fs.exists(paths.builtin_registry_versions))
- {
- load_all_port_names_from_registry_versions(out, paths, paths.builtin_registry_versions);
- }
- std::error_code ec;
- fs::directory_iterator dir_it(paths.builtin_ports_directory(), ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Error: failed while enumerating the builtin ports directory %s: %s",
- fs::u8string(paths.builtin_ports_directory()),
- ec.message());
- for (auto port_directory : dir_it)
- {
- if (!fs::is_directory(fs.status(VCPKG_LINE_INFO, port_directory))) continue;
- auto filename = fs::u8string(port_directory.path().filename());
- if (filename == ".DS_Store") continue;
- out.push_back(filename);
- }
- }
- // } BuiltinRegistry::RegistryImplementation
-
- // { FilesystemRegistry::RegistryImplementation
- Baseline parse_filesystem_baseline(const VcpkgPaths& paths, const fs::path& root, StringView baseline_identifier)
- {
- auto path_to_baseline = root / registry_versions_dir_name / fs::u8path("baseline.json");
- auto res_baseline = load_baseline_versions(paths, path_to_baseline, baseline_identifier);
- if (auto opt_baseline = res_baseline.get())
- {
- if (auto p = opt_baseline->get())
- {
- return std::move(*p);
- }
-
- if (baseline_identifier.size() == 0)
- {
- return {};
- }
-
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- "Error: could not find explicitly specified baseline `\"%s\"` in baseline file `%s`.",
- baseline_identifier,
- fs::u8string(path_to_baseline));
- }
-
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, res_baseline.error());
- }
- Optional<VersionT> FilesystemRegistry::get_baseline_version(const VcpkgPaths& paths, StringView port_name) const
- {
- const auto& baseline = m_baseline.get(
- [this, &paths]() -> Baseline { return parse_filesystem_baseline(paths, m_path, m_baseline_identifier); });
-
- auto it = baseline.find(port_name);
- if (it != baseline.end())
- {
- return it->second;
- }
- else
- {
- return nullopt;
- }
- }
-
- std::unique_ptr<RegistryEntry> FilesystemRegistry::get_port_entry(const VcpkgPaths& paths,
- StringView port_name) const
- {
- auto maybe_version_entries = load_versions_file(
- paths.get_filesystem(), VersionDbType::Filesystem, m_path / registry_versions_dir_name, port_name, m_path);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, maybe_version_entries.has_value(), "Error: %s", maybe_version_entries.error());
- auto version_entries = std::move(maybe_version_entries).value_or_exit(VCPKG_LINE_INFO);
-
- auto res = std::make_unique<FilesystemRegistryEntry>(port_name.to_string());
- for (auto&& version_entry : version_entries)
- {
- res->port_versions.push_back(std::move(version_entry.version));
- res->version_paths.push_back(std::move(version_entry.path));
- }
- return res;
- }
-
- void FilesystemRegistry::get_all_port_names(std::vector<std::string>& out, const VcpkgPaths& paths) const
- {
- load_all_port_names_from_registry_versions(out, paths, m_path / registry_versions_dir_name);
- }
- // } FilesystemRegistry::RegistryImplementation
-
- // { GitRegistry::RegistryImplementation
- std::unique_ptr<RegistryEntry> GitRegistry::get_port_entry(const VcpkgPaths& paths, StringView port_name) const
- {
- auto port_versions = get_versions_tree_path(paths);
- auto maybe_version_entries =
- load_versions_file(paths.get_filesystem(), VersionDbType::Git, port_versions, port_name);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, maybe_version_entries.has_value(), "Error: " + maybe_version_entries.error());
- auto version_entries = std::move(maybe_version_entries).value_or_exit(VCPKG_LINE_INFO);
-
- auto res = std::make_unique<GitRegistryEntry>();
- res->port_name = port_name.to_string();
- for (auto&& version_entry : version_entries)
- {
- res->port_versions.push_back(version_entry.version);
- res->git_trees.push_back(version_entry.git_tree);
- }
- return res;
- }
-
- Optional<VersionT> GitRegistry::get_baseline_version(const VcpkgPaths& paths, StringView port_name) const
- {
- const auto& baseline = m_baseline.get([this, &paths]() -> Baseline {
- auto baseline_file = get_versions_tree_path(paths) / fs::u8path("baseline.json");
-
- auto res_baseline = load_baseline_versions(paths, baseline_file, m_baseline_identifier);
-
- if (!res_baseline.has_value())
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, res_baseline.error());
- }
- auto opt_baseline = res_baseline.get();
- if (auto p = opt_baseline->get())
- {
- return std::move(*p);
- }
-
- if (m_baseline_identifier.empty())
- {
- return {};
- }
-
- if (m_baseline_identifier == "default")
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "Couldn't find explicitly specified baseline `\"default\"` in the baseline file.",
- m_baseline_identifier);
- }
-
- // attempt to check out the baseline:
- auto explicit_hash = paths.git_fetch_from_remote_registry(m_repo, m_baseline_identifier);
- if (!explicit_hash.has_value())
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "Error: Couldn't find explicitly specified baseline `\"%s\"` in the baseline file for repo %s, "
- "and that commit doesn't exist.\n%s",
- m_baseline_identifier,
- m_repo,
- explicit_hash.error());
- }
- auto path_to_baseline = registry_versions_dir_name / fs::u8path("baseline.json");
- auto maybe_contents = paths.git_show_from_remote_registry(*explicit_hash.get(), path_to_baseline);
- if (!maybe_contents.has_value())
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO,
- "Error: Couldn't find explicitly specified baseline `\"%s\"` in the baseline file for repo %s, "
- "and the baseline file doesn't exist at that commit.\n%s\n",
- m_baseline_identifier,
- m_repo,
- maybe_contents.error());
- }
-
- auto contents = maybe_contents.get();
- res_baseline = parse_baseline_versions(*contents, "default", fs::u8string(path_to_baseline));
- if (!res_baseline.has_value())
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, res_baseline.error());
- }
- opt_baseline = res_baseline.get();
- if (auto p = opt_baseline->get())
- {
- return std::move(*p);
- }
- else
- {
- Checks::exit_maybe_upgrade(
- VCPKG_LINE_INFO,
- "Couldn't find explicitly specified baseline `\"%s\"` in the baseline file for repo %s, "
- "and the `\"default\"` baseline does not exist at that commit.",
- m_baseline_identifier,
- m_repo);
- }
- });
-
- auto it = baseline.find(port_name);
- if (it != baseline.end())
- {
- return it->second;
- }
-
- return nullopt;
- }
-
- void GitRegistry::get_all_port_names(std::vector<std::string>& out, const VcpkgPaths& paths) const
- {
- auto versions_path = get_versions_tree_path(paths);
- load_all_port_names_from_registry_versions(out, paths, versions_path);
- }
- // } GitRegistry::RegistryImplementation
-
- // } RegistryImplementation
-
- // { RegistryEntry
-
- // { BuiltinRegistryEntry::RegistryEntry
- ExpectedS<fs::path> BuiltinGitRegistryEntry::get_path_to_version(const VcpkgPaths& paths,
- const VersionT& version) const
- {
- auto it = std::find(port_versions.begin(), port_versions.end(), version);
- if (it == port_versions.end())
- {
- return {Strings::concat("Error: No version entry for ",
- port_name,
- " at version ",
- version,
- ". This may be fixed by updating vcpkg to the latest master via `git "
- "pull`.\nAvailable versions:\n",
- Strings::join("",
- port_versions,
- [](const VersionT& v) { return Strings::concat(" ", v, "\n"); }),
- "\nSee `vcpkg help versioning` for more information."),
- expected_right_tag};
- }
-
- const auto& git_tree = git_trees[it - port_versions.begin()];
- return paths.git_checkout_port(port_name, git_tree, paths.root / fs::u8path(".git"));
- }
- // } BuiltinRegistryEntry::RegistryEntry
-
- // { FilesystemRegistryEntry::RegistryEntry
- ExpectedS<fs::path> FilesystemRegistryEntry::get_path_to_version(const VcpkgPaths&, const VersionT& version) const
- {
- auto it = std::find(port_versions.begin(), port_versions.end(), version);
- if (it == port_versions.end())
- {
- return Strings::concat("Error: No version entry for ", port_name, " at version ", version, ".");
- }
- return version_paths[it - port_versions.begin()];
- }
- // } FilesystemRegistryEntry::RegistryEntry
-
- // { GitRegistryEntry::RegistryEntry
- ExpectedS<fs::path> GitRegistryEntry::get_path_to_version(const VcpkgPaths& paths, const VersionT& version) const
- {
- auto it = std::find(port_versions.begin(), port_versions.end(), version);
- if (it == port_versions.end())
- {
- // This message suggests that the user updates vcpkg -- this is appropriate for the builtin registry for now
- // but needs tweaking for external git registries
- return {Strings::concat("Error: No version entry for ",
- port_name,
- " at version ",
- version,
- ". This may be fixed by updating vcpkg to the latest master via `git "
- "pull`.\nAvailable versions:\n",
- Strings::join("",
- port_versions,
- [](const VersionT& v) { return Strings::concat(" ", v, "\n"); }),
- "\nSee `vcpkg help versioning` for more information."),
- expected_right_tag};
- }
-
- const auto& git_tree = git_trees[it - port_versions.begin()];
- return paths.git_checkout_object_from_remote_registry(git_tree);
- }
- // } GitRegistryEntry::RegistryEntry
-
- // } RegistryEntry
-}
-
-// deserializers
-namespace
-{
- using namespace vcpkg;
-
- struct BaselineDeserializer final : Json::IDeserializer<std::map<std::string, VersionT, std::less<>>>
- {
- StringView type_name() const override { return "a baseline object"; }
-
- Optional<type> visit_object(Json::Reader& r, const Json::Object& obj) override
- {
- std::map<std::string, VersionT, std::less<>> result;
-
- for (auto pr : obj)
- {
- const auto& version_value = pr.second;
- VersionT version;
- r.visit_in_key(version_value, pr.first, version, get_versiontag_deserializer_instance());
-
- result.emplace(pr.first.to_string(), std::move(version));
- }
-
- return std::move(result);
- }
-
- static BaselineDeserializer instance;
- };
- BaselineDeserializer BaselineDeserializer::instance;
-
- struct VersionDbEntryDeserializer final : Json::IDeserializer<VersionDbEntry>
- {
- static constexpr StringLiteral GIT_TREE = "git-tree";
- static constexpr StringLiteral PATH = "path";
-
- StringView type_name() const override { return "a version database entry"; }
- View<StringView> valid_fields() const override
- {
- static const StringView u_git[] = {GIT_TREE};
- static const StringView u_path[] = {PATH};
- static const auto t_git = vcpkg::Util::Vectors::concat<StringView>(schemed_deserializer_fields(), u_git);
- static const auto t_path = vcpkg::Util::Vectors::concat<StringView>(schemed_deserializer_fields(), u_path);
-
- return type == VersionDbType::Git ? t_git : t_path;
- }
-
- Optional<VersionDbEntry> visit_object(Json::Reader& r, const Json::Object& obj) override
- {
- VersionDbEntry ret;
-
- auto schemed_version = visit_required_schemed_deserializer(type_name(), r, obj);
- ret.scheme = schemed_version.scheme;
- ret.version = std::move(schemed_version.versiont);
-
- static Json::StringDeserializer git_tree_deserializer("a git object SHA");
- static Json::StringDeserializer path_deserializer("a registry path");
-
- switch (type)
- {
- case VersionDbType::Git:
- {
- r.required_object_field(type_name(), obj, GIT_TREE, ret.git_tree, git_tree_deserializer);
- break;
- }
- case VersionDbType::Filesystem:
- {
- std::string path_res;
- r.required_object_field(type_name(), obj, PATH, path_res, path_deserializer);
- fs::path p = fs::u8path(path_res);
- if (p.is_absolute())
- {
- r.add_generic_error("a registry path",
- "A registry path may not be absolute, and must start with a `$` to mean "
- "the registry root; e.g., `$/foo/bar`.");
- return ret;
- }
- else if (p.empty())
- {
- r.add_generic_error("a registry path", "A registry path must not be empty.");
- return ret;
- }
-
- auto it = p.begin();
- if (*it != "$")
- {
- r.add_generic_error(
- "a registry path",
- "A registry path must start with `$` to mean the registry root; e.g., `$/foo/bar`");
- }
-
- ret.path = registry_root;
- ++it;
- std::for_each(it, p.end(), [&r, &ret](const fs::path& p) {
- if (p == "..")
- {
- r.add_generic_error("a registry path", "A registry path must not contain `..`.");
- }
- else
- {
- ret.path /= p;
- }
- });
-
- break;
- }
- }
-
- return ret;
- }
-
- VersionDbEntryDeserializer(VersionDbType type, const fs::path& root) : type(type), registry_root(root) { }
-
- VersionDbType type;
- fs::path registry_root;
- };
-
- struct VersionDbEntryArrayDeserializer final : Json::IDeserializer<std::vector<VersionDbEntry>>
- {
- virtual StringView type_name() const override { return "an array of versions"; }
-
- virtual Optional<std::vector<VersionDbEntry>> visit_array(Json::Reader& r, const Json::Array& arr) override
- {
- return r.array_elements(arr, underlying);
- }
-
- VersionDbEntryArrayDeserializer(VersionDbType type, const fs::path& root) : underlying{type, root} { }
-
- VersionDbEntryDeserializer underlying;
- };
-
- struct RegistryImplDeserializer : Json::IDeserializer<std::unique_ptr<RegistryImplementation>>
- {
- constexpr static StringLiteral KIND = "kind";
- constexpr static StringLiteral BASELINE = "baseline";
- constexpr static StringLiteral PATH = "path";
- constexpr static StringLiteral REPO = "repository";
-
- constexpr static StringLiteral KIND_BUILTIN = "builtin";
- constexpr static StringLiteral KIND_FILESYSTEM = "filesystem";
- constexpr static StringLiteral KIND_GIT = "git";
-
- virtual StringView type_name() const override { return "a registry"; }
- virtual View<StringView> valid_fields() const override;
-
- virtual Optional<std::unique_ptr<RegistryImplementation>> visit_null(Json::Reader&) override;
- virtual Optional<std::unique_ptr<RegistryImplementation>> visit_object(Json::Reader&,
- const Json::Object&) override;
-
- RegistryImplDeserializer(const fs::path& configuration_directory)
- : config_directory(configuration_directory) { }
-
- fs::path config_directory;
- };
- constexpr StringLiteral RegistryImplDeserializer::KIND;
- constexpr StringLiteral RegistryImplDeserializer::BASELINE;
- constexpr StringLiteral RegistryImplDeserializer::PATH;
- constexpr StringLiteral RegistryImplDeserializer::REPO;
- constexpr StringLiteral RegistryImplDeserializer::KIND_BUILTIN;
- constexpr StringLiteral RegistryImplDeserializer::KIND_FILESYSTEM;
- constexpr StringLiteral RegistryImplDeserializer::KIND_GIT;
-
- struct RegistryDeserializer final : Json::IDeserializer<Registry>
- {
- constexpr static StringLiteral PACKAGES = "packages";
-
- virtual StringView type_name() const override { return "a registry"; }
- virtual View<StringView> valid_fields() const override;
-
- virtual Optional<Registry> visit_object(Json::Reader&, const Json::Object&) override;
-
- explicit RegistryDeserializer(const fs::path& configuration_directory) : impl_des(configuration_directory) { }
-
- RegistryImplDeserializer impl_des;
- };
- constexpr StringLiteral RegistryDeserializer::PACKAGES;
-
- View<StringView> RegistryImplDeserializer::valid_fields() const
- {
- static const StringView t[] = {KIND, BASELINE, PATH, REPO};
- return t;
- }
- View<StringView> valid_builtin_fields()
- {
- static const StringView t[] = {
- RegistryImplDeserializer::KIND,
- RegistryImplDeserializer::BASELINE,
- RegistryDeserializer::PACKAGES,
- };
- return t;
- }
- View<StringView> valid_filesystem_fields()
- {
- static const StringView t[] = {
- RegistryImplDeserializer::KIND,
- RegistryImplDeserializer::BASELINE,
- RegistryImplDeserializer::PATH,
- RegistryDeserializer::PACKAGES,
- };
- return t;
- }
- View<StringView> valid_git_fields()
- {
- static const StringView t[] = {
- RegistryImplDeserializer::KIND,
- RegistryImplDeserializer::BASELINE,
- RegistryImplDeserializer::REPO,
- RegistryDeserializer::PACKAGES,
- };
- return t;
- }
-
- Optional<std::unique_ptr<RegistryImplementation>> RegistryImplDeserializer::visit_null(Json::Reader&)
- {
- return nullptr;
- }
-
- Optional<std::unique_ptr<RegistryImplementation>> RegistryImplDeserializer::visit_object(Json::Reader& r,
- const Json::Object& obj)
- {
- static Json::StringDeserializer kind_deserializer{"a registry implementation kind"};
- static Json::StringDeserializer baseline_deserializer{"a baseline"};
- std::string kind;
- std::string baseline;
-
- r.required_object_field(type_name(), obj, KIND, kind, kind_deserializer);
- r.optional_object_field(obj, BASELINE, baseline, baseline_deserializer);
-
- std::unique_ptr<RegistryImplementation> res;
-
- if (kind == KIND_BUILTIN)
- {
- r.check_for_unexpected_fields(obj, valid_builtin_fields(), "a builtin registry");
- res = std::make_unique<BuiltinRegistry>(std::move(baseline));
- }
- else if (kind == KIND_FILESYSTEM)
- {
- r.check_for_unexpected_fields(obj, valid_filesystem_fields(), "a filesystem registry");
-
- fs::path path;
- r.required_object_field("a filesystem registry", obj, PATH, path, Json::PathDeserializer::instance);
-
- res = std::make_unique<FilesystemRegistry>(Files::combine(config_directory, path), std::move(baseline));
- }
- else if (kind == KIND_GIT)
- {
- r.check_for_unexpected_fields(obj, valid_git_fields(), "a git registry");
-
- std::string repo;
- Json::StringDeserializer repo_des{"a git repository URL"};
- r.required_object_field("a git registry", obj, REPO, repo, repo_des);
-
- res = std::make_unique<GitRegistry>(std::move(repo), std::move(baseline));
- }
- else
- {
- StringLiteral valid_kinds[] = {KIND_BUILTIN, KIND_FILESYSTEM, KIND_GIT};
- r.add_generic_error(type_name(),
- "Field \"kind\" did not have an expected value (expected one of: \"",
- Strings::join("\", \"", valid_kinds),
- "\", found \"",
- kind,
- "\").");
- return nullopt;
- }
-
- return std::move(res);
- }
-
- View<StringView> RegistryDeserializer::valid_fields() const
- {
- static const StringView t[] = {
- RegistryImplDeserializer::KIND,
- RegistryImplDeserializer::BASELINE,
- RegistryImplDeserializer::PATH,
- RegistryImplDeserializer::REPO,
- PACKAGES,
- };
- return t;
- }
-
- Optional<Registry> RegistryDeserializer::visit_object(Json::Reader& r, const Json::Object& obj)
- {
- auto impl = impl_des.visit_object(r, obj);
-
- if (!impl.has_value())
- {
- return nullopt;
- }
-
- static Json::ArrayDeserializer<Json::PackageNameDeserializer> package_names_deserializer{
- "an array of package names"};
-
- std::vector<std::string> packages;
- r.required_object_field(type_name(), obj, PACKAGES, packages, package_names_deserializer);
-
- return Registry{std::move(packages), std::move(impl).value_or_exit(VCPKG_LINE_INFO)};
- }
-
- fs::path relative_path_to_versions(StringView port_name)
- {
- auto port_filename = fs::u8path(port_name.to_string() + ".json");
- return fs::u8path({port_name.byte_at_index(0), '-'}) / port_filename;
- }
-
- ExpectedS<std::vector<VersionDbEntry>> load_versions_file(const Files::Filesystem& fs,
- VersionDbType type,
- const fs::path& registry_versions,
- StringView port_name,
- const fs::path& registry_root)
- {
- Checks::check_exit(VCPKG_LINE_INFO,
- !(type == VersionDbType::Filesystem && registry_root.empty()),
- "Bug in vcpkg; type should never = Filesystem when registry_root is empty.");
-
- auto versions_file_path = registry_versions / relative_path_to_versions(port_name);
-
- if (!fs.exists(versions_file_path))
- {
- return Strings::format("Couldn't find the versions database file: %s", fs::u8string(versions_file_path));
- }
-
- auto maybe_contents = fs.read_contents(versions_file_path);
- if (!maybe_contents.has_value())
- {
- return Strings::format("Failed to load the versions database file %s: %s",
- fs::u8string(versions_file_path),
- maybe_contents.error().message());
- }
-
- auto maybe_versions_json = Json::parse(*maybe_contents.get());
- if (!maybe_versions_json.has_value())
- {
- return Strings::format(
- "Error: failed to parse versions file for `%s`: %s", port_name, maybe_versions_json.error()->format());
- }
- if (!maybe_versions_json.get()->first.is_object())
- {
- return Strings::format("Error: versions file for `%s` does not have a top level object.", port_name);
- }
-
- const auto& versions_object = maybe_versions_json.get()->first.object();
- auto maybe_versions_array = versions_object.get("versions");
- if (!maybe_versions_array || !maybe_versions_array->is_array())
- {
- return Strings::format("Error: versions file for `%s` does not contain a versions array.", port_name);
- }
-
- std::vector<VersionDbEntry> db_entries;
- VersionDbEntryArrayDeserializer deserializer{type, registry_root};
- // Avoid warning treated as error.
- if (maybe_versions_array != nullptr)
- {
- Json::Reader r;
- r.visit_in_key(*maybe_versions_array, "versions", db_entries, deserializer);
- if (!r.errors().empty())
- {
- return Strings::format(
- "Error: failed to parse versions file for `%s`:\n%s", port_name, Strings::join("\n", r.errors()));
- }
- }
- return db_entries;
- }
-
- ExpectedS<Optional<Baseline>> parse_baseline_versions(StringView contents, StringView baseline, StringView origin)
- {
- auto maybe_value = Json::parse(contents, origin);
- if (!maybe_value.has_value())
- {
- return Strings::format(
- "Error: failed to parse baseline file: %s\n%s", origin, maybe_value.error()->format());
- }
-
- auto& value = *maybe_value.get();
-
- if (!value.first.is_object())
- {
- return Strings::concat("Error: baseline does not have a top-level object: ", origin);
- }
-
- auto real_baseline = baseline.size() == 0 ? "default" : baseline;
-
- const auto& obj = value.first.object();
- auto baseline_value = obj.get(real_baseline);
- if (!baseline_value)
- {
- return {nullopt, expected_left_tag};
- }
-
- Json::Reader r;
- std::map<std::string, VersionT, std::less<>> result;
- r.visit_in_key(*baseline_value, real_baseline, result, BaselineDeserializer::instance);
- if (r.errors().empty())
- {
- return {std::move(result), expected_left_tag};
- }
- else
- {
- return Strings::format("Error: failed to parse baseline: %s\n%s", origin, Strings::join("\n", r.errors()));
- }
- }
-
- ExpectedS<Optional<Baseline>> load_baseline_versions(const VcpkgPaths& paths,
- const fs::path& path_to_baseline,
- StringView baseline)
- {
- auto maybe_contents = paths.get_filesystem().read_contents(path_to_baseline);
- if (auto contents = maybe_contents.get())
- {
- return parse_baseline_versions(*contents, baseline, fs::u8string(path_to_baseline));
- }
- else if (maybe_contents.error() == std::errc::no_such_file_or_directory)
- {
- Debug::print("Failed to find baseline.json\n");
- return {nullopt, expected_left_tag};
- }
- else
- {
- return Strings::format("Error: failed to read file `%s`: %s",
- fs::u8string(path_to_baseline),
- maybe_contents.error().message());
- }
- }
-}
-
-namespace vcpkg
-{
- std::unique_ptr<Json::IDeserializer<std::unique_ptr<RegistryImplementation>>>
- get_registry_implementation_deserializer(const fs::path& configuration_directory)
- {
- return std::make_unique<RegistryImplDeserializer>(configuration_directory);
- }
- std::unique_ptr<Json::IDeserializer<std::vector<Registry>>> get_registry_array_deserializer(
- const fs::path& configuration_directory)
- {
- return std::make_unique<Json::ArrayDeserializer<RegistryDeserializer>>(
- "an array of registries", RegistryDeserializer(configuration_directory));
- }
-
- Registry::Registry(std::vector<std::string>&& packages, std::unique_ptr<RegistryImplementation>&& impl)
- : packages_(std::move(packages)), implementation_(std::move(impl))
- {
- Checks::check_exit(VCPKG_LINE_INFO, implementation_ != nullptr);
- }
-
- RegistrySet::RegistrySet() : default_registry_(std::make_unique<BuiltinRegistry>("")) { }
-
- const RegistryImplementation* RegistrySet::registry_for_port(StringView name) const
- {
- for (const auto& registry : registries())
- {
- const auto& packages = registry.packages();
- if (std::find(packages.begin(), packages.end(), name) != packages.end())
- {
- return &registry.implementation();
- }
- }
- return default_registry();
- }
-
- Optional<VersionT> RegistrySet::baseline_for_port(const VcpkgPaths& paths, StringView port_name) const
- {
- auto impl = registry_for_port(port_name);
- if (!impl) return nullopt;
- return impl->get_baseline_version(paths, port_name);
- }
-
- void RegistrySet::add_registry(Registry&& r) { registries_.push_back(std::move(r)); }
-
- void RegistrySet::set_default_registry(std::unique_ptr<RegistryImplementation>&& r)
- {
- default_registry_ = std::move(r);
- }
- void RegistrySet::set_default_registry(std::nullptr_t) { default_registry_.reset(); }
-
- void RegistrySet::experimental_set_builtin_registry_baseline(StringView baseline) const
- {
- // to check if we should warn
- bool default_registry_is_builtin = false;
- if (auto builtin_registry = dynamic_cast<BuiltinRegistry*>(default_registry_.get()))
- {
- default_registry_is_builtin = true;
- builtin_registry->m_baseline_identifier.assign(baseline.begin(), baseline.end());
- }
-
- if (!default_registry_is_builtin || registries_.size() != 0)
- {
- System::print2(System::Color::warning,
- "Warning: when using the registries feature, one should not use `\"builtin-baseline\"` "
- "to set the baseline.\n",
- " Instead, use the \"baseline\" field of the registry.\n");
- }
-
- for (auto& reg : registries_)
- {
- if (auto builtin_registry = dynamic_cast<BuiltinRegistry*>(reg.implementation_.get()))
- {
- builtin_registry->m_baseline_identifier.assign(baseline.begin(), baseline.end());
- }
- }
- }
-
- bool RegistrySet::has_modifications() const
- {
- if (!registries_.empty())
- {
- return true;
- }
- if (auto builtin_reg = dynamic_cast<const BuiltinRegistry*>(default_registry_.get()))
- {
- if (builtin_reg->m_baseline_identifier.empty())
- {
- return false;
- }
- return true;
- }
- // default_registry_ is not a BuiltinRegistry
- return true;
- }
-
- ExpectedS<std::vector<std::pair<SchemedVersion, std::string>>> get_builtin_versions(const VcpkgPaths& paths,
- StringView port_name)
- {
- auto maybe_versions =
- load_versions_file(paths.get_filesystem(), VersionDbType::Git, paths.builtin_registry_versions, port_name);
- if (auto pversions = maybe_versions.get())
- {
- return Util::fmap(
- *pversions, [](auto&& entry) -> auto {
- return std::make_pair(SchemedVersion{entry.scheme, entry.version}, entry.git_tree);
- });
- }
-
- return maybe_versions.error();
- }
-
- ExpectedS<std::map<std::string, VersionT, std::less<>>> get_builtin_baseline(const VcpkgPaths& paths)
- {
- return try_parse_builtin_baseline(paths, "default");
- }
-}
diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp
deleted file mode 100644
index e29ae16c8..000000000
--- a/toolsrc/src/vcpkg/remove.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/dependencies.h>
-#include <vcpkg/help.h>
-#include <vcpkg/input.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/remove.h>
-#include <vcpkg/update.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Remove
-{
- using Dependencies::RemovePlanAction;
- using Dependencies::RemovePlanType;
- using Dependencies::RequestType;
- using Update::OutdatedPackage;
-
- void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db)
- {
- auto& fs = paths.get_filesystem();
- auto maybe_ipv = status_db->get_installed_package_view(spec);
-
- Checks::check_exit(
- VCPKG_LINE_INFO, maybe_ipv.has_value(), "unable to remove package %s: already removed", spec);
-
- auto&& ipv = maybe_ipv.value_or_exit(VCPKG_LINE_INFO);
-
- std::vector<StatusParagraph> spghs;
- spghs.emplace_back(*ipv.core);
- for (auto&& feature : ipv.features)
- {
- spghs.emplace_back(*feature);
- }
-
- for (auto&& spgh : spghs)
- {
- spgh.want = Want::PURGE;
- spgh.state = InstallState::HALF_INSTALLED;
- write_update(paths, spgh);
- }
-
- auto maybe_lines = fs.read_lines(paths.listfile_path(ipv.core->package));
-
- if (const auto lines = maybe_lines.get())
- {
- std::vector<fs::path> dirs_touched;
- for (auto&& suffix : *lines)
- {
- if (!suffix.empty() && suffix.back() == '\r') suffix.pop_back();
-
- std::error_code ec;
-
- auto target = paths.installed / suffix;
-
- const auto status = fs.symlink_status(target, ec);
- if (ec)
- {
- System::print2(
- System::Color::error, "failed: status(", fs::u8string(target), "): ", ec.message(), "\n");
- continue;
- }
-
- if (fs::is_directory(status))
- {
- dirs_touched.push_back(target);
- }
- else if (fs::is_regular_file(status) || fs::is_symlink(status))
- {
- fs.remove(target, ec);
- if (ec)
- {
- // TODO: this is racy; should we ignore this error?
-#if defined(_WIN32)
- fs::stdfs::permissions(target, fs::perms::owner_all | fs::perms::group_all, ec);
- fs.remove(target, ec);
- if (ec)
- {
- System::printf(
- System::Color::error, "failed: remove(%s): %s\n", fs::u8string(target), ec.message());
- }
-#else
- System::printf(
- System::Color::error, "failed: remove(%s): %s\n", fs::u8string(target), ec.message());
-#endif
- }
- }
- else if (!fs::exists(status))
- {
- System::printf(System::Color::warning, "Warning: %s: file not found\n", fs::u8string(target));
- }
- else
- {
- System::printf(
- System::Color::warning, "Warning: %s: cannot handle file type\n", fs::u8string(target));
- }
- }
-
- auto b = dirs_touched.rbegin();
- const auto e = dirs_touched.rend();
- for (; b != e; ++b)
- {
- if (fs.is_empty(*b))
- {
- std::error_code ec;
- fs.remove(*b, ec);
- if (ec)
- {
- System::print2(System::Color::error, "failed: ", ec.message(), "\n");
- }
- }
- }
-
- fs.remove(paths.listfile_path(ipv.core->package), VCPKG_LINE_INFO);
- }
-
- for (auto&& spgh : spghs)
- {
- spgh.state = InstallState::NOT_INSTALLED;
- write_update(paths, spgh);
-
- status_db->insert(std::make_unique<StatusParagraph>(std::move(spgh)));
- }
- }
-
- static void print_plan(const std::map<RemovePlanType, std::vector<const RemovePlanAction*>>& group_by_plan_type)
- {
- static constexpr std::array<RemovePlanType, 2> ORDER = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE};
-
- for (const RemovePlanType plan_type : ORDER)
- {
- const auto it = group_by_plan_type.find(plan_type);
- if (it == group_by_plan_type.cend())
- {
- continue;
- }
-
- std::vector<const RemovePlanAction*> cont = it->second;
- std::sort(cont.begin(), cont.end(), &RemovePlanAction::compare_by_name);
- const std::string as_string = Strings::join("\n", cont, [](const RemovePlanAction* p) {
- return Dependencies::to_output_string(p->request_type, p->spec.to_string());
- });
-
- switch (plan_type)
- {
- case RemovePlanType::NOT_INSTALLED:
- System::print2("The following packages are not installed, so not removed:\n", as_string, "\n");
- continue;
- case RemovePlanType::REMOVE:
- System::print2("The following packages will be removed:\n", as_string, "\n");
- continue;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- }
-
- void perform_remove_plan_action(const VcpkgPaths& paths,
- const RemovePlanAction& action,
- const Purge purge,
- StatusParagraphs* status_db)
- {
- const std::string display_name = action.spec.to_string();
-
- switch (action.plan_type)
- {
- case RemovePlanType::NOT_INSTALLED:
- System::printf(System::Color::success, "Package %s is not installed\n", display_name);
- break;
- case RemovePlanType::REMOVE:
- System::printf("Removing package %s...\n", display_name);
- remove_package(paths, action.spec, status_db);
- System::printf(System::Color::success, "Removing package %s... done\n", display_name);
- break;
- case RemovePlanType::UNKNOWN:
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- if (purge == Purge::YES)
- {
- Files::Filesystem& fs = paths.get_filesystem();
- fs.remove_all(paths.packages / action.spec.dir(), VCPKG_LINE_INFO);
- }
- }
-
- static constexpr StringLiteral OPTION_PURGE = "purge";
- static constexpr StringLiteral OPTION_NO_PURGE = "no-purge";
- static constexpr StringLiteral OPTION_RECURSE = "recurse";
- static constexpr StringLiteral OPTION_DRY_RUN = "dry-run";
- static constexpr StringLiteral OPTION_OUTDATED = "outdated";
-
- static constexpr std::array<CommandSwitch, 5> SWITCHES = {{
- {OPTION_PURGE, "Remove the cached copy of the package (default)"},
- {OPTION_NO_PURGE, "Do not remove the cached copy of the package (deprecated)"},
- {OPTION_RECURSE, "Allow removal of packages not explicitly specified on the command line"},
- {OPTION_DRY_RUN, "Print the packages to be removed, but do not remove them"},
- {OPTION_OUTDATED, "Select all packages with versions that do not match the portfiles"},
- }};
-
- static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
- {
- const StatusParagraphs status_db = database_load_check(paths);
- auto installed_packages = get_installed_ports(status_db);
-
- return Util::fmap(installed_packages, [](auto&& pgh) -> std::string { return pgh.spec().to_string(); });
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("remove zlib zlib:x64-windows curl boost"),
- 0,
- SIZE_MAX,
- {SWITCHES, {}},
- &valid_arguments,
- };
-
- void RemoveCommand::perform_and_exit(const VcpkgCmdArguments& args,
- const VcpkgPaths& paths,
- Triplet default_triplet) const
- {
- if (paths.manifest_mode_enabled())
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "vcpkg remove does not support manifest mode. In order to remove dependencies, "
- "you will need to edit your manifest (vcpkg.json).");
- }
- const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
-
- StatusParagraphs status_db = database_load_check(paths);
- std::vector<PackageSpec> specs;
- if (Util::Sets::contains(options.switches, OPTION_OUTDATED))
- {
- if (args.command_arguments.size() != 0)
- {
- System::print2(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- // Load ports from ports dirs
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
-
- specs = Util::fmap(Update::find_outdated_packages(provider, status_db),
- [](auto&& outdated) { return outdated.spec; });
-
- if (specs.empty())
- {
- System::print2(System::Color::success, "There are no outdated packages.\n");
- Checks::exit_success(VCPKG_LINE_INFO);
- }
- }
- else
- {
- if (args.command_arguments.size() < 1)
- {
- System::print2(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(
- std::string(arg), default_triplet, COMMAND_STRUCTURE.example_text);
- });
-
- for (auto&& spec : specs)
- Input::check_triplet(spec.triplet(), paths);
- }
-
- const bool no_purge_was_passed = Util::Sets::contains(options.switches, OPTION_NO_PURGE);
- const bool purge_was_passed = Util::Sets::contains(options.switches, OPTION_PURGE);
- if (purge_was_passed && no_purge_was_passed)
- {
- System::print2(System::Color::error, "Error: cannot specify both --no-purge and --purge.\n");
- System::print2(COMMAND_STRUCTURE.example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed);
- const bool is_recursive = Util::Sets::contains(options.switches, OPTION_RECURSE);
- const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
-
- const std::vector<RemovePlanAction> remove_plan = Dependencies::create_remove_plan(specs, status_db);
- Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty");
-
- std::map<RemovePlanType, std::vector<const RemovePlanAction*>> group_by_plan_type;
- Util::group_by(remove_plan, &group_by_plan_type, [](const RemovePlanAction& p) { return p.plan_type; });
- print_plan(group_by_plan_type);
-
- const bool has_non_user_requested_packages =
- Util::find_if(remove_plan, [](const RemovePlanAction& package) -> bool {
- return package.request_type != RequestType::USER_REQUESTED;
- }) != remove_plan.cend();
-
- if (has_non_user_requested_packages)
- {
- System::print2(System::Color::warning,
- "Additional packages (*) need to be removed to complete this operation.\n");
-
- if (!is_recursive)
- {
- System::print2(System::Color::warning,
- "If you are sure you want to remove them, run the command with the --recurse option\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- for (const auto& action : remove_plan)
- {
- if (action.plan_type == RemovePlanType::NOT_INSTALLED && action.request_type == RequestType::USER_REQUESTED)
- {
- // The user requested removing a package that was not installed. If the port is installed for another
- // triplet, warn the user that they may have meant that other package.
- for (const auto& package : status_db)
- {
- if (package->is_installed() && !package->package.is_feature() &&
- package->package.spec.name() == action.spec.name())
- {
- System::print2(
- System::Color::warning,
- "Another installed package matches the name of an unmatched request. Did you mean ",
- package->package.spec,
- "?\n");
- }
- }
- }
- }
-
- if (dry_run)
- {
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- for (const RemovePlanAction& action : remove_plan)
- {
- perform_remove_plan_action(paths, action, purge, &status_db);
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-}
diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp
deleted file mode 100644
index 52f72da94..000000000
--- a/toolsrc/src/vcpkg/sourceparagraph.cpp
+++ /dev/null
@@ -1,1389 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/expected.h>
-#include <vcpkg/base/jsonreader.h>
-#include <vcpkg/base/span.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/packagespec.h>
-#include <vcpkg/platform-expression.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/triplet.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/versiondeserializers.h>
-
-namespace vcpkg
-{
- using namespace vcpkg::Parse;
-
- template<class Lhs, class Rhs>
- static bool paragraph_equal(const Lhs& lhs, const Rhs& rhs)
- {
- return std::equal(
- lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](const std::string& lhs, const std::string& rhs) {
- return Strings::trim(StringView(lhs)) == Strings::trim(StringView(rhs));
- });
- }
-
- bool operator==(const SourceParagraph& lhs, const SourceParagraph& rhs)
- {
- if (lhs.name != rhs.name) return false;
- if (lhs.version != rhs.version) return false;
- if (lhs.version_scheme != rhs.version_scheme) return false;
- if (lhs.port_version != rhs.port_version) return false;
- if (!paragraph_equal(lhs.description, rhs.description)) return false;
- if (!paragraph_equal(lhs.maintainers, rhs.maintainers)) return false;
- if (lhs.homepage != rhs.homepage) return false;
- if (lhs.documentation != rhs.documentation) return false;
- if (lhs.dependencies != rhs.dependencies) return false;
- if (lhs.default_features != rhs.default_features) return false;
- if (lhs.license != rhs.license) return false;
-
- if (lhs.type != rhs.type) return false;
- if (!structurally_equal(lhs.supports_expression, rhs.supports_expression)) return false;
-
- if (lhs.extra_info != rhs.extra_info) return false;
-
- return true;
- }
-
- bool operator==(const FeatureParagraph& lhs, const FeatureParagraph& rhs)
- {
- if (lhs.name != rhs.name) return false;
- if (lhs.dependencies != rhs.dependencies) return false;
- if (!paragraph_equal(lhs.description, rhs.description)) return false;
- if (lhs.extra_info != rhs.extra_info) return false;
-
- return true;
- }
-
- bool operator==(const SourceControlFile& lhs, const SourceControlFile& rhs)
- {
- if (*lhs.core_paragraph != *rhs.core_paragraph) return false;
- return std::equal(lhs.feature_paragraphs.begin(),
- lhs.feature_paragraphs.end(),
- rhs.feature_paragraphs.begin(),
- rhs.feature_paragraphs.end(),
- [](const std::unique_ptr<FeatureParagraph>& lhs,
- const std::unique_ptr<FeatureParagraph>& rhs) { return *lhs == *rhs; });
- }
-
- namespace SourceParagraphFields
- {
- static const std::string BUILD_DEPENDS = "Build-Depends";
- static const std::string DEFAULT_FEATURES = "Default-Features";
- static const std::string DESCRIPTION = "Description";
- static const std::string FEATURE = "Feature";
- static const std::string MAINTAINERS = "Maintainer";
- static const std::string NAME = "Source";
- static const std::string VERSION = "Version";
- static const std::string PORT_VERSION = "Port-Version";
- static const std::string HOMEPAGE = "Homepage";
- static const std::string TYPE = "Type";
- static const std::string SUPPORTS = "Supports";
- }
-
- static Span<const StringView> get_list_of_valid_fields()
- {
- static const StringView valid_fields[] = {
- SourceParagraphFields::NAME,
- SourceParagraphFields::VERSION,
- SourceParagraphFields::PORT_VERSION,
- SourceParagraphFields::DESCRIPTION,
- SourceParagraphFields::MAINTAINERS,
- SourceParagraphFields::BUILD_DEPENDS,
- SourceParagraphFields::HOMEPAGE,
- SourceParagraphFields::TYPE,
- SourceParagraphFields::SUPPORTS,
- SourceParagraphFields::DEFAULT_FEATURES,
- };
-
- return valid_fields;
- }
-
- void print_error_message(Span<const std::unique_ptr<Parse::ParseControlErrorInfo>> error_info_list);
-
- std::string Type::to_string(const Type& t)
- {
- switch (t.type)
- {
- case Type::ALIAS: return "Alias";
- case Type::PORT: return "Port";
- default: return "Unknown";
- }
- }
-
- Type Type::from_string(const std::string& t)
- {
- if (t == "Alias") return Type{Type::ALIAS};
- if (t == "Port" || t.empty()) return Type{Type::PORT};
- return Type{Type::UNKNOWN};
- }
-
- bool operator==(const Type& lhs, const Type& rhs) { return lhs.type == rhs.type; }
- bool operator!=(const Type& lhs, const Type& rhs) { return !(lhs == rhs); }
-
- static void trim_all(std::vector<std::string>& arr)
- {
- for (auto& el : arr)
- {
- el = Strings::trim(std::move(el));
- }
- }
-
- namespace
- {
- constexpr static struct Canonicalize
- {
- struct FeatureLess
- {
- bool operator()(const std::unique_ptr<FeatureParagraph>& lhs,
- const std::unique_ptr<FeatureParagraph>& rhs) const
- {
- return (*this)(*lhs, *rhs);
- }
- bool operator()(const FeatureParagraph& lhs, const FeatureParagraph& rhs) const
- {
- return lhs.name < rhs.name;
- }
- };
- struct FeatureEqual
- {
- bool operator()(const std::unique_ptr<FeatureParagraph>& lhs,
- const std::unique_ptr<FeatureParagraph>& rhs) const
- {
- return (*this)(*lhs, *rhs);
- }
- bool operator()(const FeatureParagraph& lhs, const FeatureParagraph& rhs) const
- {
- return lhs.name == rhs.name;
- }
- };
-
- // assume canonicalized feature list
- struct DependencyLess
- {
- bool operator()(const std::unique_ptr<Dependency>& lhs, const std::unique_ptr<Dependency>& rhs) const
- {
- return (*this)(*lhs, *rhs);
- }
- bool operator()(const Dependency& lhs, const Dependency& rhs) const
- {
- auto cmp = lhs.name.compare(rhs.name);
- if (cmp < 0) return true;
- if (cmp > 0) return false;
-
- // same dependency name
-
- // order by platform string:
- auto platform_cmp = compare(lhs.platform, rhs.platform);
- if (platform_cmp < 0) return true;
- if (platform_cmp > 0) return false;
-
- // then order by features
- // smaller list first, then lexicographical
- if (lhs.features.size() < rhs.features.size()) return true;
- if (rhs.features.size() < lhs.features.size()) return false;
-
- // then finally order by feature list
- if (std::lexicographical_compare(
- lhs.features.begin(), lhs.features.end(), rhs.features.begin(), rhs.features.end()))
- {
- return true;
- }
- return false;
- }
- };
-
- template<class T>
- void operator()(std::unique_ptr<T>& ptr) const
- {
- (*this)(*ptr);
- }
-
- void operator()(Dependency& dep) const
- {
- std::sort(dep.features.begin(), dep.features.end());
- dep.extra_info.sort_keys();
- }
- void operator()(SourceParagraph& spgh) const
- {
- std::for_each(spgh.dependencies.begin(), spgh.dependencies.end(), *this);
- std::sort(spgh.dependencies.begin(), spgh.dependencies.end(), DependencyLess{});
-
- std::sort(spgh.default_features.begin(), spgh.default_features.end());
-
- spgh.extra_info.sort_keys();
- }
- void operator()(FeatureParagraph& fpgh) const
- {
- std::for_each(fpgh.dependencies.begin(), fpgh.dependencies.end(), *this);
- std::sort(fpgh.dependencies.begin(), fpgh.dependencies.end(), DependencyLess{});
-
- fpgh.extra_info.sort_keys();
- }
- [[nodiscard]] std::unique_ptr<ParseControlErrorInfo> operator()(SourceControlFile& scf) const
- {
- (*this)(*scf.core_paragraph);
- std::for_each(scf.feature_paragraphs.begin(), scf.feature_paragraphs.end(), *this);
- std::sort(scf.feature_paragraphs.begin(), scf.feature_paragraphs.end(), FeatureLess{});
-
- auto adjacent_equal =
- std::adjacent_find(scf.feature_paragraphs.begin(), scf.feature_paragraphs.end(), FeatureEqual{});
- if (adjacent_equal != scf.feature_paragraphs.end())
- {
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = scf.core_paragraph->name;
- error_info->error = Strings::format(R"(Multiple features with the same name for port %s: %s
- This is invalid; please make certain that features have distinct names.)",
- scf.core_paragraph->name,
- (*adjacent_equal)->name);
- return error_info;
- }
- return nullptr;
- }
- } canonicalize{};
- }
-
- static ParseExpected<SourceParagraph> parse_source_paragraph(const std::string& origin, Paragraph&& fields)
- {
- ParagraphParser parser(std::move(fields));
-
- auto spgh = std::make_unique<SourceParagraph>();
-
- parser.required_field(SourceParagraphFields::NAME, spgh->name);
- parser.required_field(SourceParagraphFields::VERSION, spgh->version);
-
- auto pv_str = parser.optional_field(SourceParagraphFields::PORT_VERSION);
- if (!pv_str.empty())
- {
- auto pv_opt = Strings::strto<int>(pv_str);
- if (auto pv = pv_opt.get())
- {
- spgh->port_version = *pv;
- }
- else
- {
- parser.add_type_error(SourceParagraphFields::PORT_VERSION, "a non-negative integer");
- }
- }
-
- spgh->description = Strings::split(parser.optional_field(SourceParagraphFields::DESCRIPTION), '\n');
- trim_all(spgh->description);
-
- spgh->maintainers = Strings::split(parser.optional_field(SourceParagraphFields::MAINTAINERS), '\n');
- trim_all(spgh->maintainers);
-
- spgh->homepage = parser.optional_field(SourceParagraphFields::HOMEPAGE);
- TextRowCol textrowcol;
- std::string buf;
- parser.optional_field(SourceParagraphFields::BUILD_DEPENDS, {buf, textrowcol});
-
- auto maybe_dependencies = parse_dependencies_list(buf, origin, textrowcol);
- if (maybe_dependencies.has_value())
- {
- spgh->dependencies = maybe_dependencies.value_or_exit(VCPKG_LINE_INFO);
- }
- else
- {
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = origin;
- error_info->error = maybe_dependencies.error();
- return error_info;
- }
-
- buf.clear();
- parser.optional_field(SourceParagraphFields::DEFAULT_FEATURES, {buf, textrowcol});
-
- auto maybe_default_features = parse_default_features_list(buf, origin, textrowcol);
- if (maybe_default_features.has_value())
- {
- spgh->default_features = maybe_default_features.value_or_exit(VCPKG_LINE_INFO);
- }
- else
- {
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = origin;
- error_info->error = maybe_default_features.error();
- return error_info;
- }
-
- auto supports_expr = parser.optional_field(SourceParagraphFields::SUPPORTS);
- if (!supports_expr.empty())
- {
- auto maybe_expr = PlatformExpression::parse_platform_expression(
- supports_expr, PlatformExpression::MultipleBinaryOperators::Allow);
- if (auto expr = maybe_expr.get())
- {
- spgh->supports_expression = std::move(*expr);
- }
- else
- {
- parser.add_type_error(SourceParagraphFields::SUPPORTS, "a platform expression");
- }
- }
-
- spgh->type = Type::from_string(parser.optional_field(SourceParagraphFields::TYPE));
- auto err = parser.error_info(spgh->name.empty() ? origin : spgh->name);
- if (err)
- return err;
- else
- return spgh;
- }
-
- static ParseExpected<FeatureParagraph> parse_feature_paragraph(const std::string& origin, Paragraph&& fields)
- {
- ParagraphParser parser(std::move(fields));
-
- auto fpgh = std::make_unique<FeatureParagraph>();
-
- parser.required_field(SourceParagraphFields::FEATURE, fpgh->name);
- fpgh->description = Strings::split(parser.required_field(SourceParagraphFields::DESCRIPTION), '\n');
- trim_all(fpgh->description);
-
- auto maybe_dependencies =
- parse_dependencies_list(parser.optional_field(SourceParagraphFields::BUILD_DEPENDS), origin);
- if (maybe_dependencies.has_value())
- {
- fpgh->dependencies = maybe_dependencies.value_or_exit(VCPKG_LINE_INFO);
- }
- else
- {
- auto error_info = std::make_unique<ParseControlErrorInfo>();
- error_info->name = origin;
- error_info->error = maybe_dependencies.error();
- return error_info;
- }
-
- auto err = parser.error_info(fpgh->name.empty() ? origin : fpgh->name);
- if (err)
- return err;
- else
- return fpgh;
- }
-
- ParseExpected<SourceControlFile> SourceControlFile::parse_control_file(
- const std::string& origin, std::vector<Parse::Paragraph>&& control_paragraphs)
- {
- if (control_paragraphs.size() == 0)
- {
- auto ret = std::make_unique<Parse::ParseControlErrorInfo>();
- ret->name = origin;
- return ret;
- }
-
- auto control_file = std::make_unique<SourceControlFile>();
-
- auto maybe_source = parse_source_paragraph(origin, std::move(control_paragraphs.front()));
- if (const auto source = maybe_source.get())
- control_file->core_paragraph = std::move(*source);
- else
- return std::move(maybe_source).error();
-
- control_paragraphs.erase(control_paragraphs.begin());
-
- for (auto&& feature_pgh : control_paragraphs)
- {
- auto maybe_feature = parse_feature_paragraph(origin, std::move(feature_pgh));
- if (const auto feature = maybe_feature.get())
- control_file->feature_paragraphs.emplace_back(std::move(*feature));
- else
- return std::move(maybe_feature).error();
- }
-
- if (auto maybe_error = canonicalize(*control_file))
- {
- return std::move(maybe_error);
- }
- return control_file;
- }
-
- struct PlatformExprDeserializer : Json::IDeserializer<PlatformExpression::Expr>
- {
- virtual StringView type_name() const override { return "a platform expression"; }
-
- virtual Optional<PlatformExpression::Expr> visit_string(Json::Reader& r, StringView sv) override
- {
- auto opt =
- PlatformExpression::parse_platform_expression(sv, PlatformExpression::MultipleBinaryOperators::Deny);
- if (auto res = opt.get())
- {
- return std::move(*res);
- }
- else
- {
- r.add_generic_error(type_name(), opt.error());
- return PlatformExpression::Expr::Empty();
- }
- }
-
- static PlatformExprDeserializer instance;
- };
- PlatformExprDeserializer PlatformExprDeserializer::instance;
-
- struct DependencyDeserializer : Json::IDeserializer<Dependency>
- {
- virtual StringView type_name() const override { return "a dependency"; }
-
- constexpr static StringLiteral NAME = "name";
- constexpr static StringLiteral FEATURES = "features";
- constexpr static StringLiteral DEFAULT_FEATURES = "default-features";
- constexpr static StringLiteral PLATFORM = "platform";
- constexpr static StringLiteral VERSION_GE = "version>=";
-
- virtual Span<const StringView> valid_fields() const override
- {
- static const StringView t[] = {
- NAME,
- FEATURES,
- DEFAULT_FEATURES,
- PLATFORM,
- VERSION_GE,
- };
-
- return t;
- }
-
- virtual Optional<Dependency> visit_string(Json::Reader& r, StringView sv) override
- {
- if (!Json::PackageNameDeserializer::is_package_name(sv))
- {
- r.add_generic_error(type_name(),
- "must be lowercase alphanumeric+hyphens, split with periods, and not reserved");
- }
-
- Dependency dep;
- dep.name = sv.to_string();
- return dep;
- }
-
- virtual Optional<Dependency> visit_object(Json::Reader& r, const Json::Object& obj) override
- {
- Dependency dep;
-
- for (const auto& el : obj)
- {
- if (Strings::starts_with(el.first, "$"))
- {
- dep.extra_info.insert_or_replace(el.first.to_string(), el.second);
- }
- }
-
- static Json::ArrayDeserializer<Json::IdentifierDeserializer> arr_id_d{"an array of identifiers"};
-
- r.required_object_field(type_name(), obj, NAME, dep.name, Json::PackageNameDeserializer::instance);
- r.optional_object_field(obj, FEATURES, dep.features, arr_id_d);
-
- bool default_features = true;
- r.optional_object_field(obj, DEFAULT_FEATURES, default_features, Json::BooleanDeserializer::instance);
- if (!default_features)
- {
- dep.features.push_back("core");
- }
-
- r.optional_object_field(obj, PLATFORM, dep.platform, PlatformExprDeserializer::instance);
-
- static Json::StringDeserializer version_deserializer("a version");
-
- auto has_ge_constraint =
- r.optional_object_field(obj, VERSION_GE, dep.constraint.value, version_deserializer);
-
- if (has_ge_constraint)
- {
- dep.constraint.type = Versions::Constraint::Type::Minimum;
- auto h = dep.constraint.value.find('#');
- if (h != std::string::npos)
- {
- auto opt = Strings::strto<int>(dep.constraint.value.c_str() + h + 1);
- auto v = opt.get();
- if (v && *v > 0)
- {
- dep.constraint.port_version = *v;
- }
- else
- {
- r.add_generic_error(type_name(),
- "embedded port-version ('#') in the primary "
- "constraint (\"",
- VERSION_GE,
- "\") must be a positive integer");
- }
- dep.constraint.value.erase(h);
- }
- }
-
- return dep;
- }
-
- static DependencyDeserializer instance;
- };
- DependencyDeserializer DependencyDeserializer::instance;
-
- struct DependencyArrayDeserializer final : Json::IDeserializer<std::vector<Dependency>>
- {
- virtual StringView type_name() const override { return "an array of dependencies"; }
-
- virtual Optional<std::vector<Dependency>> visit_array(Json::Reader& r, const Json::Array& arr) override
- {
- return r.array_elements(arr, DependencyDeserializer::instance);
- }
-
- static DependencyArrayDeserializer instance;
- };
- DependencyArrayDeserializer DependencyArrayDeserializer::instance;
-
- constexpr StringLiteral DependencyDeserializer::NAME;
- constexpr StringLiteral DependencyDeserializer::FEATURES;
- constexpr StringLiteral DependencyDeserializer::DEFAULT_FEATURES;
- constexpr StringLiteral DependencyDeserializer::PLATFORM;
- constexpr StringLiteral DependencyDeserializer::VERSION_GE;
-
- struct DependencyOverrideDeserializer : Json::IDeserializer<DependencyOverride>
- {
- virtual StringView type_name() const override { return "an override"; }
-
- constexpr static StringLiteral NAME = "name";
-
- virtual Span<const StringView> valid_fields() const override
- {
- static const StringView u[] = {NAME};
- static const auto t = Util::Vectors::concat<StringView>(schemed_deserializer_fields(), u);
- return t;
- }
-
- static void visit_impl(StringView type_name,
- Json::Reader& r,
- const Json::Object& obj,
- std::string& name,
- std::string& version,
- Versions::Scheme& version_scheme,
- int& port_version)
- {
- r.required_object_field(type_name, obj, NAME, name, Json::IdentifierDeserializer::instance);
-
- auto schemed_version = visit_required_schemed_deserializer(type_name, r, obj);
- version = schemed_version.versiont.text();
- version_scheme = schemed_version.scheme;
- port_version = schemed_version.versiont.port_version();
- }
-
- virtual Optional<DependencyOverride> visit_object(Json::Reader& r, const Json::Object& obj) override
- {
- DependencyOverride dep;
-
- for (const auto& el : obj)
- {
- if (Strings::starts_with(el.first, "$"))
- {
- dep.extra_info.insert_or_replace(el.first.to_string(), el.second);
- }
- }
-
- visit_impl(type_name(), r, obj, dep.name, dep.version, dep.version_scheme, dep.port_version);
-
- return dep;
- }
-
- static DependencyOverrideDeserializer instance;
- };
- DependencyOverrideDeserializer DependencyOverrideDeserializer::instance;
-
- constexpr StringLiteral DependencyOverrideDeserializer::NAME;
-
- // reasoning for these two distinct types -- FeatureDeserializer and ArrayFeatureDeserializer:
- // `"features"` may be defined in one of two ways:
- // - An array of feature objects, which contains the `"name"` field
- // - An object mapping feature names to feature objects, which do not contain the `"name"` field
- // `ArrayFeatureDeserializer` is used for the former, `FeatureDeserializer` is used for the latter.
- struct FeatureDeserializer : Json::IDeserializer<std::unique_ptr<FeatureParagraph>>
- {
- virtual StringView type_name() const override { return "a feature"; }
-
- constexpr static StringLiteral NAME = "name";
- constexpr static StringLiteral DESCRIPTION = "description";
- constexpr static StringLiteral DEPENDENCIES = "dependencies";
-
- virtual Span<const StringView> valid_fields() const override
- {
- static const StringView t[] = {DESCRIPTION, DEPENDENCIES};
- return t;
- }
-
- virtual Optional<std::unique_ptr<FeatureParagraph>> visit_object(Json::Reader& r,
- const Json::Object& obj) override
- {
- auto feature = std::make_unique<FeatureParagraph>();
- for (const auto& el : obj)
- {
- if (Strings::starts_with(el.first, "$"))
- {
- feature->extra_info.insert_or_replace(el.first.to_string(), el.second);
- }
- }
-
- r.required_object_field(
- type_name(), obj, DESCRIPTION, feature->description, Json::ParagraphDeserializer::instance);
- r.optional_object_field(obj, DEPENDENCIES, feature->dependencies, DependencyArrayDeserializer::instance);
-
- return std::move(feature);
- }
- static FeatureDeserializer instance;
- };
- FeatureDeserializer FeatureDeserializer::instance;
- constexpr StringLiteral FeatureDeserializer::NAME;
- constexpr StringLiteral FeatureDeserializer::DESCRIPTION;
- constexpr StringLiteral FeatureDeserializer::DEPENDENCIES;
-
- struct ArrayFeatureDeserializer : Json::IDeserializer<std::unique_ptr<FeatureParagraph>>
- {
- virtual StringView type_name() const override { return "a feature"; }
-
- virtual Span<const StringView> valid_fields() const override
- {
- static const StringView t[] = {
- FeatureDeserializer::NAME,
- FeatureDeserializer::DESCRIPTION,
- FeatureDeserializer::DEPENDENCIES,
- };
- return t;
- }
-
- virtual Optional<std::unique_ptr<FeatureParagraph>> visit_object(Json::Reader& r,
- const Json::Object& obj) override
- {
- std::string name;
- r.required_object_field(
- type_name(), obj, FeatureDeserializer::NAME, name, Json::IdentifierDeserializer::instance);
- auto opt = FeatureDeserializer::instance.visit_object(r, obj);
- if (auto p = opt.get())
- {
- p->get()->name = std::move(name);
- }
- return opt;
- }
-
- static Json::ArrayDeserializer<ArrayFeatureDeserializer> array_instance;
- };
- Json::ArrayDeserializer<ArrayFeatureDeserializer> ArrayFeatureDeserializer::array_instance{
- "an array of feature objects"};
-
- struct FeaturesFieldDeserializer : Json::IDeserializer<std::vector<std::unique_ptr<FeatureParagraph>>>
- {
- virtual StringView type_name() const override { return "a set of features"; }
-
- virtual Span<const StringView> valid_fields() const override { return {}; }
-
- virtual Optional<std::vector<std::unique_ptr<FeatureParagraph>>> visit_array(Json::Reader& r,
- const Json::Array& arr) override
- {
- return ArrayFeatureDeserializer::array_instance.visit_array(r, arr);
- }
-
- virtual Optional<std::vector<std::unique_ptr<FeatureParagraph>>> visit_object(Json::Reader& r,
- const Json::Object& obj) override
- {
- std::vector<std::unique_ptr<FeatureParagraph>> res;
- std::vector<std::string> extra_fields;
-
- for (const auto& pr : obj)
- {
- if (!Json::IdentifierDeserializer::is_ident(pr.first))
- {
- r.add_generic_error(type_name(),
- "unexpected field '",
- pr.first,
- "': must be lowercase alphanumeric+hyphens and not reserved");
- continue;
- }
- std::unique_ptr<FeatureParagraph> v;
- r.visit_in_key(pr.second, pr.first, v, FeatureDeserializer::instance);
- if (v)
- {
- v->name = pr.first.to_string();
- res.push_back(std::move(v));
- }
- }
-
- return std::move(res);
- }
-
- static FeaturesFieldDeserializer instance;
- };
- FeaturesFieldDeserializer FeaturesFieldDeserializer::instance;
-
- static constexpr StringView EXPRESSION_WORDS[] = {
- "WITH",
- "AND",
- "OR",
- };
- static constexpr StringView VALID_LICENSES[] =
-#include "spdx-licenses.inc"
- ;
- static constexpr StringView VALID_EXCEPTIONS[] =
-#include "spdx-licenses.inc"
- ;
-
- // We "parse" this so that we can add actual license parsing at some point in the future
- // without breaking anyone
- struct LicenseExpressionDeserializer : Json::IDeserializer<std::string>
- {
- virtual StringView type_name() const override { return "an SPDX license expression"; }
-
- enum class Mode
- {
- ExpectExpression,
- ExpectContinue,
- ExpectException,
- };
-
- virtual Optional<std::string> visit_string(Json::Reader&, StringView sv) override
- {
- Mode mode = Mode::ExpectExpression;
- size_t open_parens = 0;
- std::string current_word;
-
- const auto check_current_word = [&current_word, &mode] {
- if (current_word.empty())
- {
- return true;
- }
-
- Span<const StringView> valid_ids;
- bool case_sensitive = false;
- switch (mode)
- {
- case Mode::ExpectExpression:
- valid_ids = VALID_LICENSES;
- mode = Mode::ExpectContinue;
- // a single + is allowed on the end of licenses
- if (current_word.back() == '+')
- {
- current_word.pop_back();
- }
- break;
- case Mode::ExpectContinue:
- valid_ids = EXPRESSION_WORDS;
- mode = Mode::ExpectExpression;
- case_sensitive = true;
- break;
- case Mode::ExpectException:
- valid_ids = VALID_EXCEPTIONS;
- mode = Mode::ExpectContinue;
- break;
- }
-
- const auto equal = [&](StringView sv) {
- if (case_sensitive)
- {
- return sv == current_word;
- }
- else
- {
- return Strings::case_insensitive_ascii_equals(sv, current_word);
- }
- };
-
- if (std::find_if(valid_ids.begin(), valid_ids.end(), equal) == valid_ids.end())
- {
- return false;
- }
-
- if (current_word == "WITH")
- {
- mode = Mode::ExpectException;
- }
-
- current_word.clear();
- return true;
- };
-
- for (const auto& ch : sv)
- {
- if (ch == ' ' || ch == '\t')
- {
- if (!check_current_word())
- {
- return nullopt;
- }
- }
- else if (ch == '(')
- {
- if (!check_current_word())
- {
- return nullopt;
- }
- if (mode != Mode::ExpectExpression)
- {
- return nullopt;
- }
- ++open_parens;
- }
- else if (ch == ')')
- {
- if (!check_current_word())
- {
- return nullopt;
- }
- if (mode != Mode::ExpectContinue)
- {
- return nullopt;
- }
- if (open_parens == 0)
- {
- return nullopt;
- }
- --open_parens;
- }
- else
- {
- current_word.push_back(ch);
- }
- }
-
- if (!check_current_word())
- {
- return nullopt;
- }
- else
- {
- return sv.to_string();
- }
- }
-
- static LicenseExpressionDeserializer instance;
- };
- LicenseExpressionDeserializer LicenseExpressionDeserializer::instance;
-
- struct BaselineCommitDeserializer final : Json::IDeserializer<std::string>
- {
- virtual StringView type_name() const override { return "a vcpkg repository commit"; }
-
- virtual Optional<std::string> visit_string(Json::Reader&, StringView s) override
- {
- // We allow non-sha strings here to allow the core vcpkg code to provide better error
- // messages including the current git commit
- return s.to_string();
- }
-
- static BaselineCommitDeserializer instance;
- };
- BaselineCommitDeserializer BaselineCommitDeserializer::instance;
-
- struct ManifestDeserializer : Json::IDeserializer<std::unique_ptr<SourceControlFile>>
- {
- virtual StringView type_name() const override { return "a manifest"; }
-
- constexpr static StringLiteral NAME = "name";
- constexpr static StringLiteral MAINTAINERS = "maintainers";
- constexpr static StringLiteral DESCRIPTION = "description";
- constexpr static StringLiteral HOMEPAGE = "homepage";
- constexpr static StringLiteral DOCUMENTATION = "documentation";
- constexpr static StringLiteral LICENSE = "license";
- constexpr static StringLiteral DEPENDENCIES = "dependencies";
- constexpr static StringLiteral DEV_DEPENDENCIES = "dev-dependencies";
- constexpr static StringLiteral FEATURES = "features";
- constexpr static StringLiteral DEFAULT_FEATURES = "default-features";
- constexpr static StringLiteral SUPPORTS = "supports";
- constexpr static StringLiteral OVERRIDES = "overrides";
- constexpr static StringLiteral BUILTIN_BASELINE = "builtin-baseline";
-
- virtual Span<const StringView> valid_fields() const override
- {
- static const StringView u[] = {
- NAME,
- MAINTAINERS,
- DESCRIPTION,
- HOMEPAGE,
- DOCUMENTATION,
- LICENSE,
- DEPENDENCIES,
- DEV_DEPENDENCIES,
- FEATURES,
- DEFAULT_FEATURES,
- SUPPORTS,
- OVERRIDES,
- BUILTIN_BASELINE,
- };
- static const auto t = Util::Vectors::concat<StringView>(schemed_deserializer_fields(), u);
-
- return t;
- }
-
- virtual Optional<std::unique_ptr<SourceControlFile>> visit_object(Json::Reader& r,
- const Json::Object& obj) override
- {
- auto control_file = std::make_unique<SourceControlFile>();
- control_file->core_paragraph = std::make_unique<SourceParagraph>();
-
- auto& spgh = control_file->core_paragraph;
- spgh->type = Type{Type::PORT};
-
- for (const auto& el : obj)
- {
- if (Strings::starts_with(el.first, "$"))
- {
- spgh->extra_info.insert_or_replace(el.first.to_string(), el.second);
- }
- }
-
- static Json::StringDeserializer url_deserializer{"a url"};
-
- constexpr static StringView inner_type_name = "vcpkg.json";
- DependencyOverrideDeserializer::visit_impl(
- inner_type_name, r, obj, spgh->name, spgh->version, spgh->version_scheme, spgh->port_version);
-
- r.optional_object_field(obj, MAINTAINERS, spgh->maintainers, Json::ParagraphDeserializer::instance);
- r.optional_object_field(obj, DESCRIPTION, spgh->description, Json::ParagraphDeserializer::instance);
- r.optional_object_field(obj, HOMEPAGE, spgh->homepage, url_deserializer);
- r.optional_object_field(obj, DOCUMENTATION, spgh->documentation, url_deserializer);
- r.optional_object_field(obj, LICENSE, spgh->license, LicenseExpressionDeserializer::instance);
- r.optional_object_field(obj, DEPENDENCIES, spgh->dependencies, DependencyArrayDeserializer::instance);
- static Json::ArrayDeserializer<DependencyOverrideDeserializer> overrides_deserializer{
- "an array of overrides"};
- r.optional_object_field(obj, OVERRIDES, spgh->overrides, overrides_deserializer);
-
- if (obj.contains(DEV_DEPENDENCIES))
- {
- r.add_generic_error(type_name(), DEV_DEPENDENCIES, " are not yet supported");
- }
- std::string baseline;
- if (r.optional_object_field(obj, BUILTIN_BASELINE, baseline, BaselineCommitDeserializer::instance))
- {
- spgh->builtin_baseline = std::move(baseline);
- }
-
- r.optional_object_field(obj, SUPPORTS, spgh->supports_expression, PlatformExprDeserializer::instance);
-
- r.optional_object_field(
- obj, DEFAULT_FEATURES, spgh->default_features, Json::IdentifierArrayDeserializer::instance);
-
- r.optional_object_field(
- obj, FEATURES, control_file->feature_paragraphs, FeaturesFieldDeserializer::instance);
-
- if (auto maybe_error = canonicalize(*control_file))
- {
- Checks::exit_with_message(VCPKG_LINE_INFO, maybe_error->error);
- }
- return std::move(control_file);
- }
-
- static ManifestDeserializer instance;
- };
- ManifestDeserializer ManifestDeserializer::instance;
-
- constexpr StringLiteral ManifestDeserializer::NAME;
- constexpr StringLiteral ManifestDeserializer::MAINTAINERS;
- constexpr StringLiteral ManifestDeserializer::DESCRIPTION;
- constexpr StringLiteral ManifestDeserializer::HOMEPAGE;
- constexpr StringLiteral ManifestDeserializer::DOCUMENTATION;
- constexpr StringLiteral ManifestDeserializer::LICENSE;
- constexpr StringLiteral ManifestDeserializer::DEPENDENCIES;
- constexpr StringLiteral ManifestDeserializer::DEV_DEPENDENCIES;
- constexpr StringLiteral ManifestDeserializer::FEATURES;
- constexpr StringLiteral ManifestDeserializer::DEFAULT_FEATURES;
- constexpr StringLiteral ManifestDeserializer::SUPPORTS;
- constexpr StringLiteral ManifestDeserializer::OVERRIDES;
-
- SourceControlFile SourceControlFile::clone() const
- {
- SourceControlFile ret;
- ret.core_paragraph = std::make_unique<SourceParagraph>(*core_paragraph);
- for (const auto& feat_ptr : feature_paragraphs)
- {
- ret.feature_paragraphs.push_back(std::make_unique<FeatureParagraph>(*feat_ptr));
- }
- return ret;
- }
-
- Parse::ParseExpected<SourceControlFile> SourceControlFile::parse_manifest_object(const std::string& origin,
- const Json::Object& manifest)
- {
- Json::Reader reader;
-
- auto res = reader.visit(manifest, ManifestDeserializer::instance);
-
- if (!reader.errors().empty())
- {
- auto err = std::make_unique<ParseControlErrorInfo>();
- err->name = origin;
- err->other_errors = std::move(reader.errors());
- return std::move(err);
- }
- else if (auto p = res.get())
- {
- return std::move(*p);
- }
- else
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- Optional<std::string> SourceControlFile::check_against_feature_flags(const fs::path& origin,
- const FeatureFlagSettings& flags) const
- {
- static constexpr StringLiteral s_extended_help = "See `vcpkg help versioning` for more information.";
- if (!flags.versions)
- {
- auto check_deps = [&](View<Dependency> deps) -> Optional<std::string> {
- for (auto&& dep : deps)
- {
- if (dep.constraint.type != Versions::Constraint::Type::None)
- {
- return Strings::concat(
- fs::u8string(origin),
- " was rejected because it uses constraints and the `",
- VcpkgCmdArguments::VERSIONS_FEATURE,
- "` feature flag is disabled.\nThis can be fixed by removing uses of \"version>=\".\n",
- s_extended_help);
- }
- }
- return nullopt;
- };
-
- if (auto r = check_deps(core_paragraph->dependencies)) return r;
-
- for (auto&& fpgh : feature_paragraphs)
- {
- if (auto r = check_deps(fpgh->dependencies)) return r;
- }
-
- if (core_paragraph->overrides.size() != 0)
- {
- return Strings::concat(fs::u8string(origin),
- " was rejected because it uses overrides and the `",
- VcpkgCmdArguments::VERSIONS_FEATURE,
- "` feature flag is disabled.\nThis can be fixed by removing \"overrides\".\n",
- s_extended_help);
- }
-
- if (core_paragraph->builtin_baseline.has_value())
- {
- return Strings::concat(
- fs::u8string(origin),
- " was rejected because it uses builtin-baseline and the `",
- VcpkgCmdArguments::VERSIONS_FEATURE,
- "` feature flag is disabled.\nThis can be fixed by removing \"builtin-baseline\".\n",
- s_extended_help);
- }
- }
- return nullopt;
- }
-
- Parse::ParseExpected<SourceControlFile> SourceControlFile::parse_manifest_file(const fs::path& path_to_manifest,
- const Json::Object& manifest)
- {
- return parse_manifest_object(fs::u8string(path_to_manifest), manifest);
- }
-
- void print_error_message(Span<const std::unique_ptr<Parse::ParseControlErrorInfo>> error_info_list)
- {
- Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0);
-
- for (auto&& error_info : error_info_list)
- {
- Checks::check_exit(VCPKG_LINE_INFO, error_info != nullptr);
- if (!error_info->error.empty())
- {
- System::print2(
- System::Color::error, "Error: while loading ", error_info->name, ":\n", error_info->error, '\n');
- }
-
- if (!error_info->other_errors.empty())
- {
- System::print2(System::Color::error, "Errors occurred while parsing ", error_info->name, "\n");
- for (auto&& msg : error_info->other_errors)
- System::print2(" ", msg, '\n');
- }
- }
-
- bool have_remaining_fields = false;
- for (auto&& error_info : error_info_list)
- {
- if (!error_info->extra_fields.empty())
- {
- System::print2(System::Color::error,
- "Error: There are invalid fields in the control or manifest file of ",
- error_info->name,
- '\n');
- System::print2("The following fields were not expected:\n");
-
- for (const auto& pr : error_info->extra_fields)
- {
- System::print2(" In ", pr.first, ": ", Strings::join(", ", pr.second), "\n");
- }
- have_remaining_fields = true;
- }
- }
-
- if (have_remaining_fields)
- {
- System::print2("This is the list of valid fields for CONTROL files (case-sensitive): \n\n ",
- Strings::join("\n ", get_list_of_valid_fields()),
- "\n\n");
-#if defined(_WIN32)
- auto bootstrap = ".\\bootstrap-vcpkg.bat";
-#else
- auto bootstrap = "./bootstrap-vcpkg.sh";
-#endif
- System::printf("You may need to update the vcpkg binary; try running %s to update.\n\n", bootstrap);
- }
-
- for (auto&& error_info : error_info_list)
- {
- if (!error_info->missing_fields.empty())
- {
- System::print2(System::Color::error,
- "Error: There are missing fields in the control file of ",
- error_info->name,
- '\n');
- System::print2("The following fields were missing:\n");
- for (const auto& pr : error_info->missing_fields)
- {
- System::print2(" In ", pr.first, ": ", Strings::join(", ", pr.second), "\n");
- }
- }
- }
-
- for (auto&& error_info : error_info_list)
- {
- if (!error_info->expected_types.empty())
- {
- System::print2(System::Color::error,
- "Error: There are invalid field types in the CONTROL or manifest file of ",
- error_info->name,
- '\n');
- System::print2("The following fields had the wrong types:\n\n");
-
- for (const auto& pr : error_info->expected_types)
- {
- System::printf(" %s was expected to be %s\n", pr.first, pr.second);
- }
- System::print2("\n");
- }
- }
- }
-
- Optional<const FeatureParagraph&> SourceControlFile::find_feature(const std::string& featurename) const
- {
- auto it = Util::find_if(feature_paragraphs,
- [&](const std::unique_ptr<FeatureParagraph>& p) { return p->name == featurename; });
- if (it != feature_paragraphs.end())
- return **it;
- else
- return nullopt;
- }
- Optional<const std::vector<Dependency>&> SourceControlFile::find_dependencies_for_feature(
- const std::string& featurename) const
- {
- if (featurename == "core")
- {
- return core_paragraph->dependencies;
- }
- else if (auto p_feature = find_feature(featurename).get())
- return p_feature->dependencies;
- else
- return nullopt;
- }
-
- std::vector<FullPackageSpec> filter_dependencies(const std::vector<vcpkg::Dependency>& deps,
- Triplet t,
- const std::unordered_map<std::string, std::string>& cmake_vars)
- {
- std::vector<FullPackageSpec> ret;
- for (auto&& dep : deps)
- {
- if (dep.platform.evaluate(cmake_vars))
- {
- ret.emplace_back(FullPackageSpec({dep.name, t}, dep.features));
- }
- }
- return ret;
- }
-
- static bool is_dependency_trivial(const Dependency& dep)
- {
- return dep.features.empty() && dep.platform.is_empty() && dep.extra_info.is_empty() &&
- dep.constraint.type == Versions::Constraint::Type::None;
- }
-
- static Json::Object serialize_manifest_impl(const SourceControlFile& scf, bool debug)
- {
- auto serialize_paragraph =
- [&](Json::Object& obj, StringLiteral name, const std::vector<std::string>& pgh, bool always = false) {
- if (!debug)
- {
- if (pgh.empty())
- {
- if (always)
- {
- obj.insert(name, Json::Array());
- }
- return;
- }
- if (pgh.size() == 1)
- {
- obj.insert(name, Json::Value::string(pgh.front()));
- return;
- }
- }
-
- auto& arr = obj.insert(name, Json::Array());
- for (const auto& s : pgh)
- {
- arr.push_back(Json::Value::string(s));
- }
- };
- auto serialize_optional_array =
- [&](Json::Object& obj, StringLiteral name, const std::vector<std::string>& pgh) {
- if (pgh.empty() && !debug) return;
-
- auto& arr = obj.insert(name, Json::Array());
- for (const auto& s : pgh)
- {
- arr.push_back(Json::Value::string(s));
- }
- };
- auto serialize_optional_string = [&](Json::Object& obj, StringLiteral name, const std::string& s) {
- if (!s.empty() || debug)
- {
- obj.insert(name, Json::Value::string(s));
- }
- };
- auto serialize_dependency = [&](Json::Array& arr, const Dependency& dep) {
- if (is_dependency_trivial(dep))
- {
- arr.push_back(Json::Value::string(dep.name));
- }
- else
- {
- auto& dep_obj = arr.push_back(Json::Object());
- for (const auto& el : dep.extra_info)
- {
- dep_obj.insert(el.first.to_string(), el.second);
- }
-
- dep_obj.insert(DependencyDeserializer::NAME, Json::Value::string(dep.name));
-
- auto features_copy = dep.features;
- auto core_it = std::find(features_copy.begin(), features_copy.end(), "core");
- if (core_it != features_copy.end())
- {
- dep_obj.insert(DependencyDeserializer::DEFAULT_FEATURES, Json::Value::boolean(false));
- features_copy.erase(core_it);
- }
-
- serialize_optional_array(dep_obj, DependencyDeserializer::FEATURES, features_copy);
- serialize_optional_string(dep_obj, DependencyDeserializer::PLATFORM, to_string(dep.platform));
- if (dep.constraint.type == Versions::Constraint::Type::Minimum)
- {
- auto s = dep.constraint.value;
- if (dep.constraint.port_version != 0)
- {
- Strings::append(s, '#', dep.constraint.port_version);
- }
- dep_obj.insert(DependencyDeserializer::VERSION_GE, Json::Value::string(std::move(s)));
- }
- }
- };
-
- auto serialize_override = [&](Json::Array& arr, const DependencyOverride& dep) {
- auto& dep_obj = arr.push_back(Json::Object());
- for (const auto& el : dep.extra_info)
- {
- dep_obj.insert(el.first.to_string(), el.second);
- }
-
- dep_obj.insert(DependencyOverrideDeserializer::NAME, Json::Value::string(dep.name));
-
- serialize_schemed_version(dep_obj, dep.version_scheme, dep.version, dep.port_version);
- };
-
- Json::Object obj;
-
- for (const auto& el : scf.core_paragraph->extra_info)
- {
- obj.insert(el.first.to_string(), el.second);
- }
-
- obj.insert(ManifestDeserializer::NAME, Json::Value::string(scf.core_paragraph->name));
-
- serialize_schemed_version(obj,
- scf.core_paragraph->version_scheme,
- scf.core_paragraph->version,
- scf.core_paragraph->port_version,
- debug);
-
- serialize_paragraph(obj, ManifestDeserializer::MAINTAINERS, scf.core_paragraph->maintainers);
- serialize_paragraph(obj, ManifestDeserializer::DESCRIPTION, scf.core_paragraph->description);
-
- serialize_optional_string(obj, ManifestDeserializer::HOMEPAGE, scf.core_paragraph->homepage);
- serialize_optional_string(obj, ManifestDeserializer::DOCUMENTATION, scf.core_paragraph->documentation);
- serialize_optional_string(obj, ManifestDeserializer::LICENSE, scf.core_paragraph->license);
- serialize_optional_string(
- obj, ManifestDeserializer::SUPPORTS, to_string(scf.core_paragraph->supports_expression));
- if (scf.core_paragraph->builtin_baseline.has_value())
- {
- obj.insert(ManifestDeserializer::BUILTIN_BASELINE,
- Json::Value::string(scf.core_paragraph->builtin_baseline.value_or_exit(VCPKG_LINE_INFO)));
- }
-
- if (!scf.core_paragraph->dependencies.empty() || debug)
- {
- auto& deps = obj.insert(ManifestDeserializer::DEPENDENCIES, Json::Array());
-
- for (const auto& dep : scf.core_paragraph->dependencies)
- {
- serialize_dependency(deps, dep);
- }
- }
-
- serialize_optional_array(obj, ManifestDeserializer::DEFAULT_FEATURES, scf.core_paragraph->default_features);
-
- if (!scf.feature_paragraphs.empty() || debug)
- {
- auto& map = obj.insert(ManifestDeserializer::FEATURES, Json::Object());
- for (const auto& feature : scf.feature_paragraphs)
- {
- auto& feature_obj = map.insert(feature->name, Json::Object());
- for (const auto& el : feature->extra_info)
- {
- feature_obj.insert(el.first.to_string(), el.second);
- }
-
- serialize_paragraph(feature_obj, FeatureDeserializer::DESCRIPTION, feature->description, true);
-
- if (!feature->dependencies.empty() || debug)
- {
- auto& deps = feature_obj.insert(FeatureDeserializer::DEPENDENCIES, Json::Array());
- for (const auto& dep : feature->dependencies)
- {
- serialize_dependency(deps, dep);
- }
- }
- }
- }
-
- if (!scf.core_paragraph->overrides.empty() || debug)
- {
- auto& overrides = obj.insert(ManifestDeserializer::OVERRIDES, Json::Array());
-
- for (const auto& over : scf.core_paragraph->overrides)
- {
- serialize_override(overrides, over);
- }
- }
-
- if (debug)
- {
- obj.insert("TYPE", Json::Value::string(Type::to_string(scf.core_paragraph->type)));
- }
-
- return obj;
- }
-
- Json::Object serialize_debug_manifest(const SourceControlFile& scf) { return serialize_manifest_impl(scf, true); }
-
- Json::Object serialize_manifest(const SourceControlFile& scf) { return serialize_manifest_impl(scf, false); }
-}
diff --git a/toolsrc/src/vcpkg/spdx-exceptions.inc b/toolsrc/src/vcpkg/spdx-exceptions.inc
deleted file mode 100644
index c6ef04b70..000000000
--- a/toolsrc/src/vcpkg/spdx-exceptions.inc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Data downloaded from https://raw.githubusercontent.com/spdx/license-list-data/a3cab5c04eaf399ea8ee07ac69c749a9ad6a3f17/json/exceptions.json
-// Generated by scripts/Generate-SpdxLicenseList.ps1
-{
- "GCC-exception-2.0",
- "openvpn-openssl-exception",
- "Nokia-Qt-exception-1.1",
- "GPL-3.0-linking-exception",
- "Fawkes-Runtime-exception",
- "u-boot-exception-2.0",
- "PS-or-PDF-font-exception-20170817",
- "gnu-javamail-exception",
- "LGPL-3.0-linking-exception",
- "DigiRule-FOSS-exception",
- "LLVM-exception",
- "Linux-syscall-note",
- "GPL-3.0-linking-source-exception",
- "Qwt-exception-1.0",
- "389-exception",
- "mif-exception",
- "eCos-exception-2.0",
- "CLISP-exception-2.0",
- "Bison-exception-2.2",
- "Libtool-exception",
- "LZMA-exception",
- "OpenJDK-assembly-exception-1.0",
- "Font-exception-2.0",
- "OCaml-LGPL-linking-exception",
- "GCC-exception-3.1",
- "Bootloader-exception",
- "SHL-2.0",
- "Classpath-exception-2.0",
- "Swift-exception",
- "Autoconf-exception-2.0",
- "FLTK-exception",
- "freertos-exception-2.0",
- "Universal-FOSS-exception-1.0",
- "WxWindows-exception-3.1",
- "OCCT-exception-1.0",
- "Autoconf-exception-3.0",
- "i2p-gpl-java-exception",
- "GPL-CC-1.0",
- "Qt-LGPL-exception-1.1",
- "SHL-2.1",
- "Qt-GPL-exception-1.0",
-}
diff --git a/toolsrc/src/vcpkg/spdx-licenses.inc b/toolsrc/src/vcpkg/spdx-licenses.inc
deleted file mode 100644
index ad3523934..000000000
--- a/toolsrc/src/vcpkg/spdx-licenses.inc
+++ /dev/null
@@ -1,426 +0,0 @@
-// Data downloaded from https://raw.githubusercontent.com/spdx/license-list-data/a3cab5c04eaf399ea8ee07ac69c749a9ad6a3f17/json/licenses.json
-// Generated by scripts/Generate-SpdxLicenseList.ps1
-{
- "0BSD",
- "AAL",
- "ADSL",
- "AFL-1.1",
- "AFL-1.2",
- "AFL-2.0",
- "AFL-2.1",
- "AFL-3.0",
- "AGPL-1.0",
- "AGPL-1.0-only",
- "AGPL-1.0-or-later",
- "AGPL-3.0",
- "AGPL-3.0-only",
- "AGPL-3.0-or-later",
- "AMDPLPA",
- "AML",
- "AMPAS",
- "ANTLR-PD",
- "APAFML",
- "APL-1.0",
- "APSL-1.0",
- "APSL-1.1",
- "APSL-1.2",
- "APSL-2.0",
- "Abstyles",
- "Adobe-2006",
- "Adobe-Glyph",
- "Afmparse",
- "Aladdin",
- "Apache-1.0",
- "Apache-1.1",
- "Apache-2.0",
- "Artistic-1.0",
- "Artistic-1.0-Perl",
- "Artistic-1.0-cl8",
- "Artistic-2.0",
- "BSD-1-Clause",
- "BSD-2-Clause",
- "BSD-2-Clause-FreeBSD",
- "BSD-2-Clause-NetBSD",
- "BSD-2-Clause-Patent",
- "BSD-3-Clause",
- "BSD-3-Clause-Attribution",
- "BSD-3-Clause-Clear",
- "BSD-3-Clause-LBNL",
- "BSD-3-Clause-No-Nuclear-License",
- "BSD-3-Clause-No-Nuclear-License-2014",
- "BSD-3-Clause-No-Nuclear-Warranty",
- "BSD-3-Clause-Open-MPI",
- "BSD-4-Clause",
- "BSD-4-Clause-UC",
- "BSD-Protection",
- "BSD-Source-Code",
- "BSL-1.0",
- "Bahyph",
- "Barr",
- "Beerware",
- "BitTorrent-1.0",
- "BitTorrent-1.1",
- "BlueOak-1.0.0",
- "Borceux",
- "CAL-1.0",
- "CAL-1.0-Combined-Work-Exception",
- "CATOSL-1.1",
- "CC-BY-1.0",
- "CC-BY-2.0",
- "CC-BY-2.5",
- "CC-BY-3.0",
- "CC-BY-4.0",
- "CC-BY-NC-1.0",
- "CC-BY-NC-2.0",
- "CC-BY-NC-2.5",
- "CC-BY-NC-3.0",
- "CC-BY-NC-4.0",
- "CC-BY-NC-ND-1.0",
- "CC-BY-NC-ND-2.0",
- "CC-BY-NC-ND-2.5",
- "CC-BY-NC-ND-3.0",
- "CC-BY-NC-ND-4.0",
- "CC-BY-NC-SA-1.0",
- "CC-BY-NC-SA-2.0",
- "CC-BY-NC-SA-2.5",
- "CC-BY-NC-SA-3.0",
- "CC-BY-NC-SA-4.0",
- "CC-BY-ND-1.0",
- "CC-BY-ND-2.0",
- "CC-BY-ND-2.5",
- "CC-BY-ND-3.0",
- "CC-BY-ND-4.0",
- "CC-BY-SA-1.0",
- "CC-BY-SA-2.0",
- "CC-BY-SA-2.5",
- "CC-BY-SA-3.0",
- "CC-BY-SA-4.0",
- "CC-PDDC",
- "CC0-1.0",
- "CDDL-1.0",
- "CDDL-1.1",
- "CDLA-Permissive-1.0",
- "CDLA-Sharing-1.0",
- "CECILL-1.0",
- "CECILL-1.1",
- "CECILL-2.0",
- "CECILL-2.1",
- "CECILL-B",
- "CECILL-C",
- "CERN-OHL-1.1",
- "CERN-OHL-1.2",
- "CERN-OHL-P-2.0",
- "CERN-OHL-S-2.0",
- "CERN-OHL-W-2.0",
- "CNRI-Jython",
- "CNRI-Python",
- "CNRI-Python-GPL-Compatible",
- "CPAL-1.0",
- "CPL-1.0",
- "CPOL-1.02",
- "CUA-OPL-1.0",
- "Caldera",
- "ClArtistic",
- "Condor-1.1",
- "Crossword",
- "CrystalStacker",
- "Cube",
- "D-FSL-1.0",
- "DOC",
- "DSDP",
- "Dotseqn",
- "ECL-1.0",
- "ECL-2.0",
- "EFL-1.0",
- "EFL-2.0",
- "EPL-1.0",
- "EPL-2.0",
- "EUDatagrid",
- "EUPL-1.0",
- "EUPL-1.1",
- "EUPL-1.2",
- "Entessa",
- "ErlPL-1.1",
- "Eurosym",
- "FSFAP",
- "FSFUL",
- "FSFULLR",
- "FTL",
- "Fair",
- "Frameworx-1.0",
- "FreeImage",
- "GFDL-1.1",
- "GFDL-1.1-only",
- "GFDL-1.1-or-later",
- "GFDL-1.2",
- "GFDL-1.2-only",
- "GFDL-1.2-or-later",
- "GFDL-1.3",
- "GFDL-1.3-only",
- "GFDL-1.3-or-later",
- "GL2PS",
- "GPL-1.0",
- "GPL-1.0+",
- "GPL-1.0-only",
- "GPL-1.0-or-later",
- "GPL-2.0",
- "GPL-2.0+",
- "GPL-2.0-only",
- "GPL-2.0-or-later",
- "GPL-2.0-with-GCC-exception",
- "GPL-2.0-with-autoconf-exception",
- "GPL-2.0-with-bison-exception",
- "GPL-2.0-with-classpath-exception",
- "GPL-2.0-with-font-exception",
- "GPL-3.0",
- "GPL-3.0+",
- "GPL-3.0-only",
- "GPL-3.0-or-later",
- "GPL-3.0-with-GCC-exception",
- "GPL-3.0-with-autoconf-exception",
- "Giftware",
- "Glide",
- "Glulxe",
- "HPND",
- "HPND-sell-variant",
- "HaskellReport",
- "Hippocratic-2.1",
- "IBM-pibs",
- "ICU",
- "IJG",
- "IPA",
- "IPL-1.0",
- "ISC",
- "ImageMagick",
- "Imlib2",
- "Info-ZIP",
- "Intel",
- "Intel-ACPI",
- "Interbase-1.0",
- "JPNIC",
- "JSON",
- "JasPer-2.0",
- "LAL-1.2",
- "LAL-1.3",
- "LGPL-2.0",
- "LGPL-2.0+",
- "LGPL-2.0-only",
- "LGPL-2.0-or-later",
- "LGPL-2.1",
- "LGPL-2.1+",
- "LGPL-2.1-only",
- "LGPL-2.1-or-later",
- "LGPL-3.0",
- "LGPL-3.0+",
- "LGPL-3.0-only",
- "LGPL-3.0-or-later",
- "LGPLLR",
- "LPL-1.0",
- "LPL-1.02",
- "LPPL-1.0",
- "LPPL-1.1",
- "LPPL-1.2",
- "LPPL-1.3a",
- "LPPL-1.3c",
- "Latex2e",
- "Leptonica",
- "LiLiQ-P-1.1",
- "LiLiQ-R-1.1",
- "LiLiQ-Rplus-1.1",
- "Libpng",
- "Linux-OpenIB",
- "MIT",
- "MIT-0",
- "MIT-CMU",
- "MIT-advertising",
- "MIT-enna",
- "MIT-feh",
- "MITNFA",
- "MPL-1.0",
- "MPL-1.1",
- "MPL-2.0",
- "MPL-2.0-no-copyleft-exception",
- "MS-PL",
- "MS-RL",
- "MTLL",
- "MakeIndex",
- "MirOS",
- "Motosoto",
- "MulanPSL-1.0",
- "MulanPSL-2.0",
- "Multics",
- "Mup",
- "NASA-1.3",
- "NBPL-1.0",
- "NCGL-UK-2.0",
- "NCSA",
- "NGPL",
- "NLOD-1.0",
- "NLPL",
- "NOSL",
- "NPL-1.0",
- "NPL-1.1",
- "NPOSL-3.0",
- "NRL",
- "NTP",
- "NTP-0",
- "Naumen",
- "Net-SNMP",
- "NetCDF",
- "Newsletr",
- "Nokia",
- "Noweb",
- "Nunit",
- "O-UDA-1.0",
- "OCCT-PL",
- "OCLC-2.0",
- "ODC-By-1.0",
- "ODbL-1.0",
- "OFL-1.0",
- "OFL-1.0-RFN",
- "OFL-1.0-no-RFN",
- "OFL-1.1",
- "OFL-1.1-RFN",
- "OFL-1.1-no-RFN",
- "OGC-1.0",
- "OGL-Canada-2.0",
- "OGL-UK-1.0",
- "OGL-UK-2.0",
- "OGL-UK-3.0",
- "OGTSL",
- "OLDAP-1.1",
- "OLDAP-1.2",
- "OLDAP-1.3",
- "OLDAP-1.4",
- "OLDAP-2.0",
- "OLDAP-2.0.1",
- "OLDAP-2.1",
- "OLDAP-2.2",
- "OLDAP-2.2.1",
- "OLDAP-2.2.2",
- "OLDAP-2.3",
- "OLDAP-2.4",
- "OLDAP-2.5",
- "OLDAP-2.6",
- "OLDAP-2.7",
- "OLDAP-2.8",
- "OML",
- "OPL-1.0",
- "OSET-PL-2.1",
- "OSL-1.0",
- "OSL-1.1",
- "OSL-2.0",
- "OSL-2.1",
- "OSL-3.0",
- "OpenSSL",
- "PDDL-1.0",
- "PHP-3.0",
- "PHP-3.01",
- "PSF-2.0",
- "Parity-6.0.0",
- "Parity-7.0.0",
- "Plexus",
- "PolyForm-Noncommercial-1.0.0",
- "PolyForm-Small-Business-1.0.0",
- "PostgreSQL",
- "Python-2.0",
- "QPL-1.0",
- "Qhull",
- "RHeCos-1.1",
- "RPL-1.1",
- "RPL-1.5",
- "RPSL-1.0",
- "RSA-MD",
- "RSCPL",
- "Rdisc",
- "Ruby",
- "SAX-PD",
- "SCEA",
- "SGI-B-1.0",
- "SGI-B-1.1",
- "SGI-B-2.0",
- "SHL-0.5",
- "SHL-0.51",
- "SISSL",
- "SISSL-1.2",
- "SMLNJ",
- "SMPPL",
- "SNIA",
- "SPL-1.0",
- "SSH-OpenSSH",
- "SSH-short",
- "SSPL-1.0",
- "SWL",
- "Saxpath",
- "Sendmail",
- "Sendmail-8.23",
- "SimPL-2.0",
- "Sleepycat",
- "Spencer-86",
- "Spencer-94",
- "Spencer-99",
- "StandardML-NJ",
- "SugarCRM-1.1.3",
- "TAPR-OHL-1.0",
- "TCL",
- "TCP-wrappers",
- "TMate",
- "TORQUE-1.1",
- "TOSL",
- "TU-Berlin-1.0",
- "TU-Berlin-2.0",
- "UCL-1.0",
- "UPL-1.0",
- "Unicode-DFS-2015",
- "Unicode-DFS-2016",
- "Unicode-TOU",
- "Unlicense",
- "VOSTROM",
- "VSL-1.0",
- "Vim",
- "W3C",
- "W3C-19980720",
- "W3C-20150513",
- "WTFPL",
- "Watcom-1.0",
- "Wsuipa",
- "X11",
- "XFree86-1.1",
- "XSkat",
- "Xerox",
- "Xnet",
- "YPL-1.0",
- "YPL-1.1",
- "ZPL-1.1",
- "ZPL-2.0",
- "ZPL-2.1",
- "Zed",
- "Zend-2.0",
- "Zimbra-1.3",
- "Zimbra-1.4",
- "Zlib",
- "blessing",
- "bzip2-1.0.5",
- "bzip2-1.0.6",
- "copyleft-next-0.3.0",
- "copyleft-next-0.3.1",
- "curl",
- "diffmark",
- "dvipdfm",
- "eCos-2.0",
- "eGenix",
- "etalab-2.0",
- "gSOAP-1.3b",
- "gnuplot",
- "iMatix",
- "libpng-2.0",
- "libselinux-1.0",
- "libtiff",
- "mpich2",
- "psfrag",
- "psutils",
- "wxWindows",
- "xinetd",
- "xpp",
- "zlib-acknowledgement",
-}
diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp
deleted file mode 100644
index ff3700d4b..000000000
--- a/toolsrc/src/vcpkg/statusparagraph.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/statusparagraph.h>
-
-using namespace vcpkg::Parse;
-
-namespace vcpkg
-{
- namespace BinaryParagraphRequiredField
- {
- static const std::string STATUS = "Status";
- }
-
- StatusParagraph::StatusParagraph() noexcept : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) { }
-
- void serialize(const StatusParagraph& pgh, std::string& out_str)
- {
- serialize(pgh.package, out_str);
- out_str.append("Status: ")
- .append(to_string(pgh.want))
- .append(" ok ")
- .append(to_string(pgh.state))
- .push_back('\n');
- }
-
- StatusParagraph::StatusParagraph(Parse::Paragraph&& fields)
- : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE)
- {
- auto status_it = fields.find(BinaryParagraphRequiredField::STATUS);
- Checks::check_maybe_upgrade(
- VCPKG_LINE_INFO, status_it != fields.end(), "Expected 'Status' field in status paragraph");
- std::string status_field = std::move(status_it->second.first);
- fields.erase(status_it);
-
- this->package = BinaryParagraph(std::move(fields));
-
- auto b = status_field.begin();
- const auto mark = b;
- const auto e = status_field.end();
-
- // Todo: improve error handling
- while (b != e && *b != ' ')
- ++b;
-
- want = [](const std::string& text) {
- if (text == "unknown") return Want::UNKNOWN;
- if (text == "install") return Want::INSTALL;
- if (text == "hold") return Want::HOLD;
- if (text == "deinstall") return Want::DEINSTALL;
- if (text == "purge") return Want::PURGE;
- return Want::ERROR_STATE;
- }(std::string(mark, b));
-
- if (std::distance(b, e) < 4) return;
- b += 4;
-
- state = [](const std::string& text) {
- if (text == "not-installed") return InstallState::NOT_INSTALLED;
- if (text == "installed") return InstallState::INSTALLED;
- if (text == "half-installed") return InstallState::HALF_INSTALLED;
- return InstallState::ERROR_STATE;
- }(std::string(b, e));
- }
-
- std::string to_string(InstallState f)
- {
- switch (f)
- {
- case InstallState::HALF_INSTALLED: return "half-installed";
- case InstallState::INSTALLED: return "installed";
- case InstallState::NOT_INSTALLED: return "not-installed";
- default: return "error";
- }
- }
-
- std::string to_string(Want f)
- {
- switch (f)
- {
- case Want::DEINSTALL: return "deinstall";
- case Want::HOLD: return "hold";
- case Want::INSTALL: return "install";
- case Want::PURGE: return "purge";
- case Want::UNKNOWN: return "unknown";
- default: return "error";
- }
- }
-
- std::map<std::string, std::vector<FeatureSpec>> InstalledPackageView::feature_dependencies() const
- {
- auto extract_deps = [&](const std::string& name) { return FeatureSpec{{name, spec().triplet()}, "core"}; };
-
- std::map<std::string, std::vector<FeatureSpec>> deps;
-
- deps.emplace("core", Util::fmap(core->package.dependencies, extract_deps));
-
- for (const StatusParagraph* const& feature : features)
- deps.emplace(feature->package.feature, Util::fmap(feature->package.dependencies, extract_deps));
-
- return deps;
- }
-
- std::vector<PackageSpec> InstalledPackageView::dependencies() const
- {
- // accumulate all features in installed dependencies
- // Todo: make this unneeded by collapsing all package dependencies into the core package
- std::vector<std::string> deps;
- for (auto&& feature : features)
- for (auto&& dep : feature->package.dependencies)
- deps.push_back(dep);
-
- // Add the core paragraph dependencies to the list
- for (auto&& dep : core->package.dependencies)
- deps.push_back(dep);
-
- Util::erase_remove_if(deps, [&](const std::string& pspec) { return pspec == spec().name(); });
- Util::sort_unique_erase(deps);
-
- return PackageSpec::to_package_specs(deps, spec().triplet());
- }
-}
diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp
deleted file mode 100644
index ba1815224..000000000
--- a/toolsrc/src/vcpkg/statusparagraphs.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <vcpkg/base/checks.h>
-
-#include <vcpkg/install.h>
-#include <vcpkg/statusparagraphs.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg
-{
- StatusParagraphs::StatusParagraphs() = default;
-
- StatusParagraphs::StatusParagraphs(std::vector<std::unique_ptr<StatusParagraph>>&& ps) : paragraphs(std::move(ps))
- {
- }
-
- std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name, Triplet triplet)
- {
- std::vector<std::unique_ptr<StatusParagraph>*> spghs;
- for (auto&& p : *this)
- {
- if (p->package.spec.name() == name && p->package.spec.triplet() == triplet)
- {
- if (p->package.is_feature())
- spghs.emplace_back(&p);
- else
- spghs.emplace(spghs.begin(), &p);
- }
- }
- return spghs;
- }
-
- Optional<InstalledPackageView> StatusParagraphs::get_installed_package_view(const PackageSpec& spec) const
- {
- InstalledPackageView ipv;
- for (auto&& p : *this)
- {
- if (p->package.spec.name() == spec.name() && p->package.spec.triplet() == spec.triplet() &&
- p->is_installed())
- {
- if (p->package.is_feature())
- {
- ipv.features.emplace_back(p.get());
- }
- else
- {
- Checks::check_exit(VCPKG_LINE_INFO, ipv.core == nullptr);
- ipv.core = p.get();
- }
- }
- }
- if (ipv.core != nullptr)
- return ipv;
- else
- return nullopt;
- }
-
- StatusParagraphs::iterator StatusParagraphs::find(const std::string& name,
- Triplet triplet,
- const std::string& feature)
- {
- if (feature == "core")
- {
- // The core feature maps to .feature is empty
- return find(name, triplet, {});
- }
- return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
- const PackageSpec& spec = pgh->package.spec;
- return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature;
- });
- }
-
- StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name,
- Triplet triplet,
- const std::string& feature) const
- {
- if (feature == "core")
- {
- // The core feature maps to .feature == ""
- return find(name, triplet, "");
- }
- return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
- const PackageSpec& spec = pgh->package.spec;
- return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature;
- });
- }
-
- StatusParagraphs::const_iterator StatusParagraphs::find_installed(const PackageSpec& spec) const
- {
- auto it = find(spec);
- if (it != end() && (*it)->is_installed())
- {
- return it;
- }
- else
- {
- return end();
- }
- }
-
- StatusParagraphs::const_iterator StatusParagraphs::find_installed(const FeatureSpec& spec) const
- {
- auto it = find(spec);
- if (it != end() && (*it)->is_installed())
- {
- return it;
- }
- else
- {
- return end();
- }
- }
-
- bool vcpkg::StatusParagraphs::is_installed(const PackageSpec& spec) const
- {
- auto it = find(spec);
- return it != end() && (*it)->is_installed();
- }
-
- bool vcpkg::StatusParagraphs::is_installed(const FeatureSpec& spec) const
- {
- auto it = find(spec);
- return it != end() && (*it)->is_installed();
- }
-
- StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr<StatusParagraph> pgh)
- {
- Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph");
- const PackageSpec& spec = pgh->package.spec;
- const auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature);
- if (ptr == end())
- {
- paragraphs.push_back(std::move(pgh));
- return paragraphs.rbegin();
- }
-
- // consume data from provided pgh.
- **ptr = std::move(*pgh);
- return ptr;
- }
-
- void serialize(const StatusParagraphs& pghs, std::string& out_str)
- {
- for (auto& pgh : pghs.paragraphs)
- {
- serialize(*pgh, out_str);
- out_str.push_back('\n');
- }
- }
-
- Json::Value serialize_ipv(const InstalledPackageView& ipv, const VcpkgPaths& paths)
- {
- const auto& fs = paths.get_filesystem();
- Json::Object iobj;
- iobj.insert("version-string", Json::Value::string(ipv.core->package.version));
- iobj.insert("port-version", Json::Value::integer(ipv.core->package.port_version));
- iobj.insert("triplet", Json::Value::string(ipv.spec().triplet().to_string()));
- iobj.insert("abi", Json::Value::string(ipv.core->package.abi));
- Json::Array deps;
- for (auto&& dep : ipv.dependencies())
- deps.push_back(Json::Value::string(dep.to_string()));
- if (deps.size() != 0)
- {
- iobj.insert("dependencies", std::move(deps));
- }
- Json::Array features;
- for (auto&& feature : ipv.features)
- {
- features.push_back(Json::Value::string(feature->package.feature));
- }
- if (features.size() != 0)
- {
- iobj.insert("features", std::move(features));
- }
- auto usage = Install::get_cmake_usage(ipv.core->package, paths);
- if (!usage.message.empty())
- {
- iobj.insert("usage", Json::Value::string(std::move(usage.message)));
- }
- auto owns_files = fs.read_lines(paths.listfile_path(ipv.core->package)).value_or_exit(VCPKG_LINE_INFO);
- Json::Array owns;
- for (auto&& owns_file : owns_files)
- owns.push_back(Json::Value::string(std::move(owns_file)));
-
- iobj.insert("owns", std::move(owns));
- return Json::Value::object(std::move(iobj));
- }
-}
diff --git a/toolsrc/src/vcpkg/tools.cpp b/toolsrc/src/vcpkg/tools.cpp
deleted file mode 100644
index eaef5a6b9..000000000
--- a/toolsrc/src/vcpkg/tools.cpp
+++ /dev/null
@@ -1,615 +0,0 @@
-#include <vcpkg/base/checks.h>
-#include <vcpkg/base/downloads.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/optional.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/stringview.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/archives.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg
-{
- struct ToolData
- {
- std::array<int, 3> version;
- fs::path exe_path;
- std::string url;
- fs::path download_path;
- bool is_archive;
- fs::path tool_dir_path;
- std::string sha512;
- };
-
- static Optional<std::array<int, 3>> parse_version_string(const std::string& version_as_string)
- {
- static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###");
-
- std::match_results<std::string::const_iterator> match;
- const auto found = std::regex_search(version_as_string, match, RE);
- if (!found)
- {
- return {};
- }
-
- const int d1 = atoi(match[1].str().c_str());
- const int d2 = atoi(match[2].str().c_str());
- const int d3 = atoi(match[3].str().c_str());
- const std::array<int, 3> result = {d1, d2, d3};
- return result;
- }
-
- static ExpectedT<ToolData, std::string> parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool)
- {
-#if defined(_WIN32)
- static constexpr StringLiteral OS_STRING = "windows";
-#elif defined(__APPLE__)
- static constexpr StringLiteral OS_STRING = "osx";
-#elif defined(__linux__)
- static constexpr StringLiteral OS_STRING = "linux";
-#elif defined(__FreeBSD__)
- static constexpr StringLiteral OS_STRING = "freebsd";
-#elif defined(__OpenBSD__)
- static constexpr StringLiteral OS_STRING = "openbsd";
-#else
- return std::string("operating system is unknown");
-#endif
-
-#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
- static const std::string XML_VERSION = "2";
- static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml";
- static const std::regex XML_VERSION_REGEX{R"###(<tools[\s]+version="([^"]+)">)###"};
- static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO);
- std::smatch match_xml_version;
- const bool has_xml_version = std::regex_search(XML.cbegin(), XML.cend(), match_xml_version, XML_VERSION_REGEX);
- Checks::check_exit(VCPKG_LINE_INFO,
- has_xml_version,
- R"(Could not find <tools version="%s"> in %s)",
- XML_VERSION,
- fs::u8string(XML_PATH));
- Checks::check_exit(VCPKG_LINE_INFO,
- XML_VERSION == match_xml_version[1],
- "Expected %s version: [%s], but was [%s]. Please re-run bootstrap-vcpkg.",
- fs::u8string(XML_PATH),
- XML_VERSION,
- match_xml_version[1]);
-
- const std::regex tool_regex{Strings::format(R"###(<tool[\s]+name="%s"[\s]+os="%s">)###", tool, OS_STRING)};
- std::smatch match_tool_entry;
- const bool has_tool_entry = std::regex_search(XML.cbegin(), XML.cend(), match_tool_entry, tool_regex);
- if (!has_tool_entry)
- {
- StringLiteral add_info = "";
- if (tool == "mono")
- {
-#if defined(__APPLE__)
- add_info = " (brew install mono)";
-#else
- add_info = " (e.g. sudo apt install mono-complete). Ubuntu 18.04 users may "
- "need a newer version of mono, available at https://www.mono-project.com/download/stable/";
-#endif
- }
- return Strings::format("Could not automatically acquire %s because there is no entry in %s for os=%s. You "
- "may be able to install %s via your system package manager%s.",
- tool,
- fs::u8string(XML_PATH),
- OS_STRING,
- tool,
- add_info);
- }
-
- const std::string tool_data =
- Strings::find_exactly_one_enclosed(XML, match_tool_entry[0].str(), "</tool>").to_string();
- const std::string version_as_string =
- Strings::find_exactly_one_enclosed(tool_data, "<version>", "</version>").to_string();
- const std::string exe_relative_path =
- Strings::find_exactly_one_enclosed(tool_data, "<exeRelativePath>", "</exeRelativePath>").to_string();
- const std::string url = Strings::find_exactly_one_enclosed(tool_data, "<url>", "</url>").to_string();
- const std::string sha512 = Strings::find_exactly_one_enclosed(tool_data, "<sha512>", "</sha512>").to_string();
- auto archive_name = Strings::find_at_most_one_enclosed(tool_data, "<archiveName>", "</archiveName>");
-
- const Optional<std::array<int, 3>> version = parse_version_string(version_as_string);
- Checks::check_exit(VCPKG_LINE_INFO,
- version.has_value(),
- "Could not parse version for tool %s. Version string was: %s",
- tool,
- version_as_string);
-
- const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING);
- const fs::path tool_dir_path = paths.tools / tool_dir_name;
- const fs::path exe_path = tool_dir_path / exe_relative_path;
- fs::path download_path;
- if (auto a = archive_name.get())
- {
- download_path = paths.downloads / fs::u8path(a->to_string());
- }
- else
- {
- download_path = paths.downloads / fs::u8path(Strings::concat(sha512.substr(0, 8), '-', exe_relative_path));
- }
-
- return ToolData{*version.get(), exe_path, url, download_path, archive_name.has_value(), tool_dir_path, sha512};
-#endif
- }
-
- struct PathAndVersion
- {
- fs::path path;
- std::string version;
- };
-
- struct ToolProvider
- {
- virtual const std::string& tool_data_name() const = 0;
- virtual const std::string& exe_stem() const = 0;
- virtual std::array<int, 3> default_min_version() const = 0;
-
- virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const { (void)out_candidate_paths; }
- virtual ExpectedS<std::string> get_version(const VcpkgPaths& paths, const fs::path& path_to_exe) const = 0;
- };
-
- static Optional<PathAndVersion> find_first_with_sufficient_version(const VcpkgPaths& paths,
- const ToolProvider& tool_provider,
- const std::vector<fs::path>& candidates,
- const std::array<int, 3>& expected_version)
- {
- const auto& fs = paths.get_filesystem();
- for (auto&& candidate : candidates)
- {
- if (!fs.exists(candidate)) continue;
- auto maybe_version = tool_provider.get_version(paths, candidate);
- const auto version = maybe_version.get();
- if (!version) continue;
- const auto parsed_version = parse_version_string(*version);
- if (!parsed_version) continue;
- auto& actual_version = *parsed_version.get();
- const auto version_acceptable =
- actual_version[0] > expected_version[0] ||
- (actual_version[0] == expected_version[0] && actual_version[1] > expected_version[1]) ||
- (actual_version[0] == expected_version[0] && actual_version[1] == expected_version[1] &&
- actual_version[2] >= expected_version[2]);
- if (!version_acceptable) continue;
-
- return PathAndVersion{candidate, *version};
- }
-
- return nullopt;
- }
-
- static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
- {
- const std::array<int, 3>& version = tool_data.version;
- const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]);
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- !tool_data.url.empty(),
- "A suitable version of %s was not found (required v%s) and unable to automatically "
- "download a portable one. Please install a newer version of %s.",
- tool_name,
- version_as_string,
- tool_name);
- System::printf("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...\n",
- tool_name,
- version_as_string,
- tool_name,
- version_as_string);
- auto& fs = paths.get_filesystem();
- if (!fs.exists(tool_data.download_path))
- {
- System::print2("Downloading ", tool_name, "...\n");
- System::print2(" ", tool_data.url, " -> ", fs::u8string(tool_data.download_path), "\n");
- Downloads::download_file(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
- }
- else
- {
- Downloads::verify_downloaded_file_hash(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
- }
-
- if (tool_data.is_archive)
- {
- System::print2("Extracting ", tool_name, "...\n");
- Archives::extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
- }
- else
- {
- std::error_code ec;
- fs.create_directories(tool_data.exe_path.parent_path(), ec);
- fs.rename(tool_data.download_path, tool_data.exe_path, ec);
- }
-
- Checks::check_exit(VCPKG_LINE_INFO,
- fs.exists(tool_data.exe_path),
- "Expected %s to exist after fetching",
- fs::u8string(tool_data.exe_path));
-
- return tool_data.exe_path;
- }
-
- static PathAndVersion fetch_tool(const VcpkgPaths& paths,
- const ToolProvider& tool_provider,
- const ToolData& tool_data)
- {
- auto downloaded_path = fetch_tool(paths, tool_provider.tool_data_name(), tool_data);
- auto downloaded_version = tool_provider.get_version(paths, downloaded_path).value_or_exit(VCPKG_LINE_INFO);
- return {std::move(downloaded_path), std::move(downloaded_version)};
- }
-
- static PathAndVersion get_path(const VcpkgPaths& paths, const ToolProvider& tool)
- {
- auto& fs = paths.get_filesystem();
-
- std::array<int, 3> min_version = tool.default_min_version();
-
- std::vector<fs::path> candidate_paths;
- auto maybe_tool_data = parse_tool_data_from_xml(paths, tool.tool_data_name());
- if (auto tool_data = maybe_tool_data.get())
- {
- candidate_paths.push_back(tool_data->exe_path);
- min_version = tool_data->version;
- }
-
- auto& exe_stem = tool.exe_stem();
- if (!exe_stem.empty())
- {
- auto paths_from_path = fs.find_from_PATH(exe_stem);
- candidate_paths.insert(candidate_paths.end(), paths_from_path.cbegin(), paths_from_path.cend());
- }
-
- tool.add_special_paths(candidate_paths);
-
- const auto maybe_path = find_first_with_sufficient_version(paths, tool, candidate_paths, min_version);
- if (const auto p = maybe_path.get())
- {
- return *p;
- }
- if (auto tool_data = maybe_tool_data.get())
- {
- return fetch_tool(paths, tool, *tool_data);
- }
-
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, maybe_tool_data.error());
- }
-
- struct CMakeProvider : ToolProvider
- {
- std::string m_exe = "cmake";
-
- virtual const std::string& tool_data_name() const override { return m_exe; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {3, 17, 1}; }
-
- virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const override
- {
-#if defined(_WIN32)
- const auto& program_files = System::get_program_files_platform_bitness();
- if (const auto pf = program_files.get()) out_candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
- const auto& program_files_32_bit = System::get_program_files_32_bit();
- if (const auto pf = program_files_32_bit.get())
- out_candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
-#else
- // TODO: figure out if this should do anything on non-Windows
- (void)out_candidate_paths;
-#endif
- }
- virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
- {
- auto cmd = System::Command(path_to_exe).string_arg("--version");
- auto rc = System::cmd_execute_and_capture_output(cmd);
- if (rc.exit_code != 0)
- {
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
- }
-
- /* Sample output:
-cmake version 3.10.2
-
-CMake suite maintained and supported by Kitware (kitware.com/cmake).
- */
- return {Strings::find_exactly_one_enclosed(rc.output, "cmake version ", "\n").to_string(),
- expected_left_tag};
- }
- };
-
- struct NinjaProvider : ToolProvider
- {
- std::string m_exe = "ninja";
-
- virtual const std::string& tool_data_name() const override { return m_exe; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {3, 5, 1}; }
-
- virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
- {
- auto cmd = System::Command(path_to_exe).string_arg("--version");
- auto rc = System::cmd_execute_and_capture_output(cmd);
- if (rc.exit_code != 0)
- {
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
- }
-
- /* Sample output:
-1.8.2
- */
- return {std::move(rc.output), expected_left_tag};
- }
- };
-
- struct NuGetProvider : ToolProvider
- {
- std::string m_exe = "nuget";
-
- virtual const std::string& tool_data_name() const override { return m_exe; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {4, 6, 2}; }
-
- virtual ExpectedS<std::string> get_version(const VcpkgPaths& paths, const fs::path& path_to_exe) const override
- {
- System::Command cmd;
-#ifndef _WIN32
- cmd.path_arg(paths.get_tool_exe(Tools::MONO));
-#else
- (void)paths;
-#endif
- cmd.path_arg(path_to_exe);
- auto rc = System::cmd_execute_and_capture_output(cmd);
- if (rc.exit_code != 0)
- {
-#ifndef _WIN32
- return {Strings::concat(
- std::move(rc.output),
- "\n\nFailed to get version of ",
- fs::u8string(path_to_exe),
- "\nThis may be caused by an incomplete mono installation. Full mono is "
- "available on some systems via `sudo apt install mono-complete`. Ubuntu 18.04 users may "
- "need a newer version of mono, available at https://www.mono-project.com/download/stable/"),
- expected_right_tag};
-#else
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
-#endif
- }
-
- /* Sample output:
-NuGet Version: 4.6.2.5055
-usage: NuGet <command> [args] [options]
-Type 'NuGet help <command>' for help on a specific command.
-
-[[[List of available commands follows]]]
- */
- return {Strings::find_exactly_one_enclosed(rc.output, "NuGet Version: ", "\n").to_string(),
- expected_left_tag};
- }
- };
-
- struct GitProvider : ToolProvider
- {
- std::string m_exe = "git";
-
- virtual const std::string& tool_data_name() const override { return m_exe; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {2, 7, 4}; }
-
- virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const override
- {
-#if defined(_WIN32)
- const auto& program_files = System::get_program_files_platform_bitness();
- if (const auto pf = program_files.get()) out_candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
- const auto& program_files_32_bit = System::get_program_files_32_bit();
- if (const auto pf = program_files_32_bit.get())
- out_candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
-#else
- // TODO: figure out if this should do anything on non-windows
- (void)out_candidate_paths;
-#endif
- }
-
- virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
- {
- auto cmd = System::Command(path_to_exe).string_arg("--version");
- auto rc = System::cmd_execute_and_capture_output(cmd);
- if (rc.exit_code != 0)
- {
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
- }
-
- /* Sample output:
-git version 2.17.1.windows.2
- */
- const auto idx = rc.output.find("git version ");
- Checks::check_exit(
- VCPKG_LINE_INFO, idx != std::string::npos, "Unexpected format of git version string: %s", rc.output);
- return {rc.output.substr(idx), expected_left_tag};
- }
- };
-
- struct MonoProvider : ToolProvider
- {
- std::string m_exe = "mono";
-
- virtual const std::string& tool_data_name() const override { return m_exe; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {0, 0, 0}; }
-
- virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
- {
- auto rc = System::cmd_execute_and_capture_output(System::Command(path_to_exe).string_arg("--version"));
- if (rc.exit_code != 0)
- {
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
- }
-
- /* Sample output:
-Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50 UTC 2020)
- */
- const auto idx = rc.output.find("Mono JIT compiler version ");
- Checks::check_exit(
- VCPKG_LINE_INFO, idx != std::string::npos, "Unexpected format of mono version string: %s", rc.output);
- return {rc.output.substr(idx), expected_left_tag};
- }
- };
-
- struct IfwInstallerBaseProvider : ToolProvider
- {
- std::string m_exe;
- std::string m_toolname = "installerbase";
-
- virtual const std::string& tool_data_name() const override { return m_toolname; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {0, 0, 0}; }
-
- virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const override
- {
- (void)out_candidate_paths;
- // TODO: Uncomment later
- // const std::vector<fs::path> from_path = Files::find_from_PATH("installerbase");
- // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
- // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) /
- // "Qt" / "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe");
- // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) /
- // "Qt" / "QtIFW-3.1.0" / "bin" / "installerbase.exe");
- }
-
- virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
- {
- auto cmd = System::Command(path_to_exe).string_arg("--framework-version");
- auto rc = System::cmd_execute_and_capture_output(cmd);
- if (rc.exit_code != 0)
- {
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
- }
-
- /* Sample output:
-3.1.81
- */
- return {std::move(rc.output), expected_left_tag};
- }
- };
-
- struct PowerShellCoreProvider : ToolProvider
- {
- std::string m_exe = "pwsh";
- std::string m_name = "powershell-core";
-
- virtual const std::string& tool_data_name() const override { return m_name; }
- virtual const std::string& exe_stem() const override { return m_exe; }
- virtual std::array<int, 3> default_min_version() const override { return {7, 0, 3}; }
-
- virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
- {
- auto rc = System::cmd_execute_and_capture_output(System::Command(path_to_exe).string_arg("--version"));
- if (rc.exit_code != 0)
- {
- return {Strings::concat(
- std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
- expected_right_tag};
- }
-
- // Sample output: PowerShell 7.0.3\r\n
- auto output = std::move(rc.output);
- if (!Strings::starts_with(output, "PowerShell "))
- {
- return {Strings::concat("Unexpected format of powershell-core version string: ", output),
- expected_right_tag};
- }
-
- output.erase(0, 11);
- return {Strings::trim(std::move(output)), expected_left_tag};
- }
- };
-
- struct ToolCacheImpl final : ToolCache
- {
- vcpkg::Cache<std::string, fs::path> path_only_cache;
- vcpkg::Cache<std::string, PathAndVersion> path_version_cache;
-
- virtual const fs::path& get_tool_path(const VcpkgPaths& paths, const std::string& tool) const override
- {
- return path_only_cache.get_lazy(tool, [&]() {
- if (tool == Tools::IFW_BINARYCREATOR)
- return get_tool_path(paths, Tools::IFW_INSTALLER_BASE).parent_path() / "binarycreator.exe";
- if (tool == Tools::IFW_REPOGEN)
- return get_tool_path(paths, Tools::IFW_INSTALLER_BASE).parent_path() / "repogen.exe";
-
- return get_tool_pathversion(paths, tool).path;
- });
- }
-
- const PathAndVersion& get_tool_pathversion(const VcpkgPaths& paths, const std::string& tool) const
- {
- return path_version_cache.get_lazy(tool, [&]() -> PathAndVersion {
- // First deal with specially handled tools.
- // For these we may look in locations like Program Files, the PATH etc as well as the auto-downloaded
- // location.
- if (tool == Tools::CMAKE)
- {
- if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
- {
- return {"cmake", "0"};
- }
- return get_path(paths, CMakeProvider());
- }
- if (tool == Tools::GIT)
- {
- if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
- {
- return {"git", "0"};
- }
- return get_path(paths, GitProvider());
- }
- if (tool == Tools::NINJA)
- {
- if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
- {
- return {"ninja", "0"};
- }
- return get_path(paths, NinjaProvider());
- }
- if (tool == Tools::POWERSHELL_CORE)
- {
- if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value())
- {
- return {"pwsh", "0"};
- }
- return get_path(paths, PowerShellCoreProvider());
- }
- if (tool == Tools::NUGET) return get_path(paths, NuGetProvider());
- if (tool == Tools::IFW_INSTALLER_BASE) return get_path(paths, IfwInstallerBaseProvider());
- if (tool == Tools::MONO) return get_path(paths, MonoProvider());
-
- // For other tools, we simply always auto-download them.
- auto maybe_tool_data = parse_tool_data_from_xml(paths, tool);
- if (auto p_tool_data = maybe_tool_data.get())
- {
- if (paths.get_filesystem().exists(p_tool_data->exe_path))
- {
- return {p_tool_data->exe_path, p_tool_data->sha512};
- }
- return {fetch_tool(paths, tool, *p_tool_data), p_tool_data->sha512};
- }
-
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Unknown or unavailable tool: %s", tool);
- });
- }
-
- virtual const std::string& get_tool_version(const VcpkgPaths& paths, const std::string& tool) const override
- {
- return get_tool_pathversion(paths, tool).version;
- }
- };
-
- std::unique_ptr<ToolCache> get_tool_cache() { return std::make_unique<ToolCacheImpl>(); }
-}
diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp
deleted file mode 100644
index 9943ec9a8..000000000
--- a/toolsrc/src/vcpkg/triplet.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <vcpkg/base/strings.h>
-
-#include <vcpkg/triplet.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-namespace vcpkg
-{
- struct TripletInstance
- {
- TripletInstance(std::string&& s) : value(std::move(s)), hash(std::hash<std::string>()(value)) { }
-
- const std::string value;
- const size_t hash = 0;
-
- bool operator==(const TripletInstance& o) const { return o.value == value; }
- };
- const TripletInstance Triplet::DEFAULT_INSTANCE({});
-}
-
-namespace std
-{
- template<>
- struct hash<vcpkg::TripletInstance>
- {
- size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; }
- };
-}
-
-namespace vcpkg
-{
- Triplet Triplet::from_canonical_name(std::string&& triplet_as_string)
- {
- static std::unordered_set<TripletInstance> g_triplet_instances;
- std::string s(Strings::ascii_to_lowercase(std::move(triplet_as_string)));
- const auto p = g_triplet_instances.emplace(std::move(s));
- return &*p.first;
- }
-
- const std::string& Triplet::canonical_name() const { return this->m_instance->value; }
-
- const std::string& Triplet::to_string() const { return this->canonical_name(); }
- void Triplet::to_string(std::string& out) const { out.append(this->canonical_name()); }
- size_t Triplet::hash_code() const { return m_instance->hash; }
-
- Optional<System::CPUArchitecture> Triplet::guess_architecture() const noexcept
- {
- using System::CPUArchitecture;
- if (Strings::starts_with(this->canonical_name(), "x86-"))
- {
- return CPUArchitecture::X86;
- }
- if (Strings::starts_with(this->canonical_name(), "x64-"))
- {
- return CPUArchitecture::X64;
- }
- if (Strings::starts_with(this->canonical_name(), "arm-"))
- {
- return CPUArchitecture::ARM;
- }
- if (Strings::starts_with(this->canonical_name(), "arm64-"))
- {
- return CPUArchitecture::ARM64;
- }
- if (Strings::starts_with(this->canonical_name(), "s390x-"))
- {
- return CPUArchitecture::S390X;
- }
- if (Strings::starts_with(this->canonical_name(), "ppc64le-"))
- {
- return CPUArchitecture::PPC64LE;
- }
-
- return nullopt;
- }
-
- Triplet default_triplet(const VcpkgCmdArguments& args)
- {
- if (args.triplet != nullptr)
- {
- return Triplet::from_canonical_name(std::string(*args.triplet));
- }
- else
- {
-#if defined(_WIN32)
- return Triplet::from_canonical_name("x86-windows");
-#elif defined(__APPLE__)
- return Triplet::from_canonical_name("x64-osx");
-#elif defined(__FreeBSD__)
- return Triplet::from_canonical_name("x64-freebsd");
-#elif defined(__OpenBSD__)
- return Triplet::from_canonical_name("x64-openbsd");
-#elif defined(__GLIBC__)
-#if defined(__aarch64__)
- return Triplet::from_canonical_name("arm64-linux");
-#elif defined(__arm__)
- return Triplet::from_canonical_name("arm-linux");
-#elif defined(__s390x__)
- return Triplet::from_canonical_name("s390x-linux");
-#elif (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) && \
- defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
- return Triplet::from_canonical_name("ppc64le-linux");
-#else
- return Triplet::from_canonical_name("x64-linux");
-#endif
-#else
- return Triplet::from_canonical_name("x64-linux-musl");
-#endif
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp
deleted file mode 100644
index a9ef4a3f7..000000000
--- a/toolsrc/src/vcpkg/update.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/portfileprovider.h>
-#include <vcpkg/update.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkglib.h>
-
-namespace vcpkg::Update
-{
- bool OutdatedPackage::compare_by_name(const OutdatedPackage& left, const OutdatedPackage& right)
- {
- return left.spec.name() < right.spec.name();
- }
-
- std::vector<OutdatedPackage> find_outdated_packages(const PortFileProvider::PortFileProvider& provider,
- const StatusParagraphs& status_db)
- {
- auto installed_packages = get_installed_ports(status_db);
-
- std::vector<OutdatedPackage> output;
- for (auto&& ipv : installed_packages)
- {
- const auto& pgh = ipv.core;
- auto maybe_scfl = provider.get_control_file(pgh->package.spec.name());
- if (auto p_scfl = maybe_scfl.get())
- {
- const auto& latest_pgh = *p_scfl->source_control_file->core_paragraph;
- auto latest_version = VersionT(latest_pgh.version, latest_pgh.port_version);
- auto installed_version = VersionT(pgh->package.version, pgh->package.port_version);
- if (latest_version != installed_version)
- {
- output.push_back(
- {pgh->package.spec, VersionDiff(std::move(installed_version), std::move(latest_version))});
- }
- }
- else
- {
- // No portfile available
- }
- }
-
- return output;
- }
-
- const CommandStructure COMMAND_STRUCTURE = {
- create_example_string("update"),
- 0,
- 0,
- {},
- nullptr,
- };
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
- {
- (void)args.parse_arguments(COMMAND_STRUCTURE);
- System::print2("Using local portfile versions. To update the local portfiles, use `git pull`.\n");
-
- const StatusParagraphs status_db = database_load_check(paths);
-
- PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
-
- const auto outdated_packages = SortedVector<OutdatedPackage>(find_outdated_packages(provider, status_db),
- &OutdatedPackage::compare_by_name);
-
- if (outdated_packages.empty())
- {
- System::print2("No packages need updating.\n");
- }
- else
- {
- System::print2("The following packages differ from their port versions:\n");
- for (auto&& package : outdated_packages)
- {
- System::printf(" %-32s %s\n", package.spec, package.version_diff.to_string());
- }
-
-#if defined(_WIN32)
- auto vcpkg_cmd = ".\\vcpkg";
-#else
- auto vcpkg_cmd = "./vcpkg";
-#endif
- System::printf("\n"
- "To update these packages and all dependencies, run\n"
- " %s upgrade\n"
- "\n"
- "To only remove outdated packages, run\n"
- " %s remove --outdated\n"
- "\n",
- vcpkg_cmd,
- vcpkg_cmd);
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
- }
-
- void UpdateCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
- {
- Update::perform_and_exit(args, paths);
- }
-}
diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp
deleted file mode 100644
index 5236a3c3b..000000000
--- a/toolsrc/src/vcpkg/userconfig.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/lazy.h>
-#include <vcpkg/base/system.h>
-
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/userconfig.h>
-
-namespace vcpkg
-{
- fs::path get_user_dir()
- {
-#if defined(_WIN32)
- return System::get_appdata_local().value_or_exit(VCPKG_LINE_INFO) / "vcpkg";
-#else
- auto maybe_home = System::get_environment_variable("HOME");
- return fs::path(maybe_home.value_or("/var")) / ".vcpkg";
-#endif
- }
-
- static fs::path get_config_path() { return get_user_dir() / "config"; }
-
- UserConfig UserConfig::try_read_data(const Files::Filesystem& fs)
- {
- UserConfig ret;
- try
- {
- auto maybe_pghs = Paragraphs::get_paragraphs(fs, get_config_path());
- if (const auto p_pghs = maybe_pghs.get())
- {
- const auto& pghs = *p_pghs;
-
- Parse::Paragraph keys;
- if (pghs.size() > 0) keys = pghs[0];
-
- for (size_t x = 1; x < pghs.size(); ++x)
- {
- for (auto&& p : pghs[x])
- keys.insert(p);
- }
-
- ret.user_id = keys["User-Id"].first;
- ret.user_time = keys["User-Since"].first;
- ret.user_mac = keys["Mac-Hash"].first;
- ret.last_completed_survey = keys["Survey-Completed"].first;
- }
- }
- catch (...)
- {
- }
-
- return ret;
- }
-
- void UserConfig::try_write_data(Files::Filesystem& fs) const
- {
- try
- {
- auto config_path = get_config_path();
- auto config_dir = config_path.parent_path();
- std::error_code ec;
- fs.create_directory(config_dir, ec);
- fs.write_contents(config_path,
- Strings::format("User-Id: %s\n"
- "User-Since: %s\n"
- "Mac-Hash: %s\n"
- "Survey-Completed: %s\n",
- user_id,
- user_time,
- user_mac,
- last_completed_survey),
- ec);
- }
- catch (...)
- {
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
deleted file mode 100644
index 6ac05e538..000000000
--- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
+++ /dev/null
@@ -1,960 +0,0 @@
-#include <vcpkg/base/json.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.print.h>
-
-#include <vcpkg/commands.h>
-#include <vcpkg/commands.integrate.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-
-namespace vcpkg
-{
- static void set_from_feature_flag(const std::vector<std::string>& flags, StringView flag, Optional<bool>& place)
- {
- if (!place.has_value())
- {
- const auto not_flag = [flag](const std::string& el) {
- return !el.empty() && el[0] == '-' && flag == StringView{el.data() + 1, el.data() + el.size()};
- };
-
- if (std::find(flags.begin(), flags.end(), flag) != flags.end())
- {
- place = true;
- }
- if (std::find_if(flags.begin(), flags.end(), not_flag) != flags.end())
- {
- if (place.has_value())
- {
- System::printf(
- System::Color::error, "Error: both %s and -%s were specified as feature flags\n", flag, flag);
- Metrics::g_metrics.lock()->track_property("error", "error feature flag +-" + flag.to_string());
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- place = false;
- }
- }
- }
-
- static void parse_feature_flags(const std::vector<std::string>& flags, VcpkgCmdArguments& args)
- {
- // NOTE: when these features become default, switch the value_or(false) to value_or(true)
- struct FeatureFlag
- {
- StringView flag_name;
- Optional<bool>& local_option;
- };
-
- const FeatureFlag flag_descriptions[] = {
- {VcpkgCmdArguments::BINARY_CACHING_FEATURE, args.binary_caching},
- {VcpkgCmdArguments::MANIFEST_MODE_FEATURE, args.manifest_mode},
- {VcpkgCmdArguments::COMPILER_TRACKING_FEATURE, args.compiler_tracking},
- {VcpkgCmdArguments::REGISTRIES_FEATURE, args.registries_feature},
- {VcpkgCmdArguments::VERSIONS_FEATURE, args.versions_feature},
- };
-
- for (const auto& desc : flag_descriptions)
- {
- set_from_feature_flag(flags, desc.flag_name, desc.local_option);
- }
- }
-
- static void parse_cojoined_value(StringView new_value,
- StringView option_name,
- std::unique_ptr<std::string>& option_field)
- {
- if (nullptr != option_field)
- {
- System::printf(System::Color::error, "Error: --%s specified multiple times\n", option_name);
- Metrics::g_metrics.lock()->track_property("error", "error option specified multiple times");
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- option_field = std::make_unique<std::string>(new_value.begin(), new_value.end());
- }
-
- static void parse_switch(bool new_setting, StringView option_name, Optional<bool>& option_field)
- {
- if (option_field && option_field != new_setting)
- {
- System::print2(System::Color::error, "Error: conflicting values specified for --", option_name, '\n');
- Metrics::g_metrics.lock()->track_property("error", "error conflicting switches");
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- option_field = new_setting;
- }
-
- static void parse_cojoined_multivalue(StringView new_value,
- StringView option_name,
- std::vector<std::string>& option_field)
- {
- if (new_value.size() == 0)
- {
- System::print2(System::Color::error, "Error: expected value after ", option_name, '\n');
- Metrics::g_metrics.lock()->track_property("error", "error option name");
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- option_field.emplace_back(new_value.begin(), new_value.end());
- }
-
- static void parse_cojoined_list_multivalue(StringView new_value,
- StringView option_name,
- std::vector<std::string>& option_field)
- {
- if (new_value.size() == 0)
- {
- System::print2(System::Color::error, "Error: expected value after ", option_name, '\n');
- Metrics::g_metrics.lock()->track_property("error", "error option name");
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- for (const auto& v : Strings::split(new_value, ','))
- {
- option_field.emplace_back(v.begin(), v.end());
- }
- }
-
- VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const Files::Filesystem& fs,
- const int argc,
- const CommandLineCharType* const* const argv)
- {
- std::vector<std::string> v;
- for (int i = 1; i < argc; ++i)
- {
- std::string arg;
-#if defined(_WIN32)
- arg = Strings::to_utf8(argv[i]);
-#else
- arg = argv[i];
-#endif
- // Response file?
- if (arg.size() > 0 && arg[0] == '@')
- {
- arg.erase(arg.begin());
- auto lines = fs.read_lines(fs::u8path(arg));
- if (!lines.has_value())
- {
- System::print2(System::Color::error, "Error: Could not open response file ", arg, '\n');
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- std::copy(lines.get()->begin(), lines.get()->end(), std::back_inserter(v));
- }
- else
- {
- v.emplace_back(std::move(arg));
- }
- }
-
- return VcpkgCmdArguments::create_from_arg_sequence(v.data(), v.data() + v.size());
- }
-
- enum class TryParseArgumentResult
- {
- NotFound,
- Found,
- FoundAndConsumedLookahead
- };
-
- template<class T, class F>
- static TryParseArgumentResult try_parse_argument_as_option(
- StringView arg, Optional<StringView> lookahead, StringView option, T& place, F parser)
- {
- if (Strings::starts_with(arg, "x-") && !Strings::starts_with(option, "x-"))
- {
- arg = arg.substr(2);
- }
-
- if (Strings::starts_with(arg, option))
- {
- if (arg.size() == option.size())
- {
- if (auto next = lookahead.get())
- {
- parser(*next, option, place);
- return TryParseArgumentResult::FoundAndConsumedLookahead;
- }
-
- System::print2(System::Color::error, "Error: expected value after ", option, '\n');
- Metrics::g_metrics.lock()->track_property("error", "error option name");
- print_usage();
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- if (arg.byte_at_index(option.size()) == '=')
- {
- parser(arg.substr(option.size() + 1), option, place);
- return TryParseArgumentResult::Found;
- }
- }
-
- return TryParseArgumentResult::NotFound;
- }
-
- static bool equals_modulo_experimental(StringView arg, StringView option)
- {
- if (Strings::starts_with(arg, "x-") && !Strings::starts_with(option, "x-"))
- {
- return arg.substr(2) == option;
- }
- else
- {
- return arg == option;
- }
- }
-
- // returns true if this does parse this argument as this option
- template<class T>
- static bool try_parse_argument_as_switch(StringView option, StringView arg, T& place)
- {
- if (equals_modulo_experimental(arg, option))
- {
- parse_switch(true, option, place);
- return true;
- }
-
- if (Strings::starts_with(arg, "no-") && equals_modulo_experimental(arg.substr(3), option))
- {
- parse_switch(false, option, place);
- return true;
- }
-
- return false;
- }
-
- VcpkgCmdArguments VcpkgCmdArguments::create_from_arg_sequence(const std::string* arg_first,
- const std::string* arg_last)
- {
- VcpkgCmdArguments args;
- std::vector<std::string> feature_flags;
-
- for (auto it = arg_first; it != arg_last; ++it)
- {
- std::string basic_arg = *it;
-
- if (basic_arg.empty())
- {
- continue;
- }
-
- if (basic_arg.size() >= 2 && basic_arg[0] == '-' && basic_arg[1] != '-')
- {
- Metrics::g_metrics.lock()->track_property("error", "error short options are not supported");
- Checks::exit_with_message(VCPKG_LINE_INFO, "Error: short options are not supported: %s", basic_arg);
- }
-
- if (basic_arg.size() < 2 || basic_arg[0] != '-')
- {
- if (args.command.empty())
- {
- args.command = std::move(basic_arg);
- }
- else
- {
- args.command_arguments.push_back(std::move(basic_arg));
- }
- continue;
- }
-
- // make argument case insensitive before the first =
- auto first_eq = std::find(std::begin(basic_arg), std::end(basic_arg), '=');
- Strings::ascii_to_lowercase(std::begin(basic_arg), first_eq);
- // basic_arg[0] == '-' && basic_arg[1] == '-'
- StringView arg = StringView(basic_arg).substr(2);
- constexpr static std::pair<StringView, std::unique_ptr<std::string> VcpkgCmdArguments::*>
- cojoined_values[] = {
- {VCPKG_ROOT_DIR_ARG, &VcpkgCmdArguments::vcpkg_root_dir},
- {TRIPLET_ARG, &VcpkgCmdArguments::triplet},
- {MANIFEST_ROOT_DIR_ARG, &VcpkgCmdArguments::manifest_root_dir},
- {BUILDTREES_ROOT_DIR_ARG, &VcpkgCmdArguments::buildtrees_root_dir},
- {DOWNLOADS_ROOT_DIR_ARG, &VcpkgCmdArguments::downloads_root_dir},
- {INSTALL_ROOT_DIR_ARG, &VcpkgCmdArguments::install_root_dir},
- {PACKAGES_ROOT_DIR_ARG, &VcpkgCmdArguments::packages_root_dir},
- {SCRIPTS_ROOT_DIR_ARG, &VcpkgCmdArguments::scripts_root_dir},
- {BUILTIN_PORTS_ROOT_DIR_ARG, &VcpkgCmdArguments::builtin_ports_root_dir},
- {BUILTIN_REGISTRY_VERSIONS_DIR_ARG, &VcpkgCmdArguments::builtin_registry_versions_dir},
- };
-
- constexpr static std::pair<StringView, std::vector<std::string> VcpkgCmdArguments::*>
- cojoined_multivalues[] = {
- {OVERLAY_PORTS_ARG, &VcpkgCmdArguments::overlay_ports},
- {OVERLAY_TRIPLETS_ARG, &VcpkgCmdArguments::overlay_triplets},
- {BINARY_SOURCES_ARG, &VcpkgCmdArguments::binary_sources},
- {CMAKE_SCRIPT_ARG, &VcpkgCmdArguments::cmake_args},
- };
-
- constexpr static std::pair<StringView, Optional<bool> VcpkgCmdArguments::*> switches[] = {
- {DEBUG_SWITCH, &VcpkgCmdArguments::debug},
- {DISABLE_METRICS_SWITCH, &VcpkgCmdArguments::disable_metrics},
- {SEND_METRICS_SWITCH, &VcpkgCmdArguments::send_metrics},
- {PRINT_METRICS_SWITCH, &VcpkgCmdArguments::print_metrics},
- {FEATURE_PACKAGES_SWITCH, &VcpkgCmdArguments::feature_packages},
- {BINARY_CACHING_SWITCH, &VcpkgCmdArguments::binary_caching},
- {WAIT_FOR_LOCK_SWITCH, &VcpkgCmdArguments::wait_for_lock},
- {IGNORE_LOCK_FAILURES_SWITCH, &VcpkgCmdArguments::ignore_lock_failures},
- {JSON_SWITCH, &VcpkgCmdArguments::json},
- };
-
- Optional<StringView> lookahead;
- if (it + 1 != arg_last)
- {
- lookahead = it[1];
- }
-
- bool found = false;
- for (const auto& pr : cojoined_values)
- {
- switch (try_parse_argument_as_option(arg, lookahead, pr.first, args.*pr.second, parse_cojoined_value))
- {
- case TryParseArgumentResult::FoundAndConsumedLookahead: ++it; [[fallthrough]];
- case TryParseArgumentResult::Found: found = true; break;
- case TryParseArgumentResult::NotFound: break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- if (found) continue;
-
- for (const auto& pr : cojoined_multivalues)
- {
- switch (
- try_parse_argument_as_option(arg, lookahead, pr.first, args.*pr.second, parse_cojoined_multivalue))
- {
- case TryParseArgumentResult::FoundAndConsumedLookahead: ++it; [[fallthrough]];
- case TryParseArgumentResult::Found: found = true; break;
- case TryParseArgumentResult::NotFound: break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- if (found) continue;
-
- switch (try_parse_argument_as_option(
- arg, lookahead, FEATURE_FLAGS_ARG, feature_flags, parse_cojoined_list_multivalue))
- {
- case TryParseArgumentResult::FoundAndConsumedLookahead: ++it; [[fallthrough]];
- case TryParseArgumentResult::Found: found = true; break;
- case TryParseArgumentResult::NotFound: break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- for (const auto& pr : switches)
- {
- if (try_parse_argument_as_switch(pr.first, arg, args.*pr.second))
- {
- found = true;
- break;
- }
- }
- if (found) continue;
-
- const auto eq_pos = std::find(arg.begin(), arg.end(), '=');
- if (eq_pos != arg.end())
- {
- const auto& key = StringView(arg.begin(), eq_pos);
- const auto& value = StringView(eq_pos + 1, arg.end());
-
- args.command_options[key.to_string()].push_back(value.to_string());
- }
- else
- {
- args.command_switches.insert(arg.to_string());
- }
- }
-
- parse_feature_flags(feature_flags, args);
-
- return args;
- }
-
- ParsedArguments VcpkgCmdArguments::parse_arguments(const CommandStructure& command_structure) const
- {
- bool failed = false;
- ParsedArguments output;
-
- const size_t actual_arg_count = command_arguments.size();
-
- if (command_structure.minimum_arity == command_structure.maximum_arity)
- {
- if (actual_arg_count != command_structure.minimum_arity)
- {
- System::printf(System::Color::error,
- "Error: '%s' requires %u arguments, but %u were provided.\n",
- this->command,
- command_structure.minimum_arity,
- actual_arg_count);
- failed = true;
- }
- }
- else
- {
- if (actual_arg_count < command_structure.minimum_arity)
- {
- System::printf(System::Color::error,
- "Error: '%s' requires at least %u arguments, but %u were provided\n",
- this->command,
- command_structure.minimum_arity,
- actual_arg_count);
- failed = true;
- }
- if (actual_arg_count > command_structure.maximum_arity)
- {
- System::printf(System::Color::error,
- "Error: '%s' requires at most %u arguments, but %u were provided\n",
- this->command,
- command_structure.maximum_arity,
- actual_arg_count);
- failed = true;
- }
- }
-
- auto switches_copy = this->command_switches;
- auto options_copy = this->command_options;
-
- const auto find_option = [](const auto& set, StringLiteral name) {
- auto it = set.find(name);
- if (it == set.end() && !Strings::starts_with(name, "x-"))
- {
- it = set.find(Strings::format("x-%s", name));
- }
-
- return it;
- };
-
- for (const auto& switch_ : command_structure.options.switches)
- {
- const auto it = find_option(switches_copy, switch_.name);
- if (it != switches_copy.end())
- {
- output.switches.insert(switch_.name);
- switches_copy.erase(it);
- }
- const auto option_it = find_option(options_copy, switch_.name);
- if (option_it != options_copy.end())
- {
- // This means that the switch was passed like '--a=xyz'
- System::printf(
- System::Color::error, "Error: The option '--%s' does not accept an argument.\n", switch_.name);
- options_copy.erase(option_it);
- failed = true;
- }
- }
-
- for (const auto& option : command_structure.options.settings)
- {
- const auto it = find_option(options_copy, option.name);
- if (it != options_copy.end())
- {
- const auto& value = it->second;
- if (value.empty())
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- if (value.size() > 1)
- {
- System::printf(
- System::Color::error, "Error: The option '%s' can only be passed once.\n", option.name);
- failed = true;
- }
- else if (value.front().empty())
- {
- // Fail when not given a value, e.g.: "vcpkg install sqlite3 --additional-ports="
- System::printf(System::Color::error,
- "Error: The option '--%s' must be passed a non-empty argument.\n",
- option.name);
- failed = true;
- }
- else
- {
- output.settings.emplace(option.name, value.front());
- options_copy.erase(it);
- }
- }
- const auto switch_it = find_option(switches_copy, option.name);
- if (switch_it != switches_copy.end())
- {
- // This means that the option was passed like '--a'
- System::printf(
- System::Color::error, "Error: The option '--%s' must be passed an argument.\n", option.name);
- switches_copy.erase(switch_it);
- failed = true;
- }
- }
-
- for (const auto& option : command_structure.options.multisettings)
- {
- const auto it = find_option(options_copy, option.name);
- if (it != options_copy.end())
- {
- const auto& value = it->second;
- for (const auto& v : value)
- {
- if (v.empty())
- {
- System::printf(System::Color::error,
- "Error: The option '--%s' must be passed non-empty arguments.\n",
- option.name);
- failed = true;
- }
- else
- {
- output.multisettings[option.name].push_back(v);
- }
- }
- options_copy.erase(it);
- }
- const auto switch_it = find_option(switches_copy, option.name);
- if (switch_it != switches_copy.end())
- {
- // This means that the option was passed like '--a'
- System::printf(
- System::Color::error, "Error: The option '--%s' must be passed an argument.\n", option.name);
- switches_copy.erase(switch_it);
- failed = true;
- }
- }
-
- if (!switches_copy.empty() || !options_copy.empty())
- {
- System::printf(System::Color::error, "Unknown option(s) for command '%s':\n", this->command);
- for (auto&& switch_ : switches_copy)
- {
- System::print2(" '--", switch_, "'\n");
- }
- for (auto&& option : options_copy)
- {
- System::print2(" '--", option.first, "'\n");
- }
- System::print2("\n");
- failed = true;
- }
-
- if (failed)
- {
- print_usage(command_structure);
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- return output;
- }
-
- void print_usage()
- {
- HelpTableFormatter table;
- table.header("Commands");
- table.format("vcpkg search [pat]", "Search for packages available to be built");
- table.format("vcpkg install <pkg>...", "Install a package");
- table.format("vcpkg remove <pkg>...", "Uninstall a package");
- table.format("vcpkg remove --outdated", "Uninstall all out-of-date packages");
- table.format("vcpkg list", "List installed packages");
- table.format("vcpkg update", "Display list of packages for updating");
- table.format("vcpkg upgrade", "Rebuild all outdated packages");
- table.format("vcpkg x-history <pkg>", "(Experimental) Shows the history of CONTROL versions of a package");
- table.format("vcpkg hash <file> [alg]", "Hash a file by specific algorithm, default SHA512");
- table.format("vcpkg help topics", "Display the list of help topics");
- table.format("vcpkg help <topic>", "Display help for a specific topic");
- table.blank();
- Commands::Integrate::append_helpstring(table);
- table.blank();
- table.format("vcpkg export <pkg>... [opt]...", "Exports a package");
- table.format("vcpkg edit <pkg>",
- "Open up a port for editing (uses " + format_environment_variable("EDITOR") + ", default 'code')");
- table.format("vcpkg create <pkg> <url> [archivename]", "Create a new package");
- table.format("vcpkg owns <pat>", "Search for files in installed packages");
- table.format("vcpkg depend-info <pkg>...", "Display a list of dependencies for packages");
- table.format("vcpkg env", "Creates a clean shell environment for development or compiling");
- table.format("vcpkg version", "Display version information");
- table.format("vcpkg contact", "Display contact information to send feedback");
- table.blank();
- table.header("Options");
- VcpkgCmdArguments::append_common_options(table);
- table.blank();
- table.format("@response_file", "Specify a response file to provide additional parameters");
- table.blank();
- table.example("For more help (including examples) see the accompanying README.md and docs folder.");
- System::print2(table.m_str);
- }
-
- void print_usage(const CommandStructure& command_structure)
- {
- HelpTableFormatter table;
- if (!command_structure.example_text.empty())
- {
- table.example(command_structure.example_text);
- }
-
- table.header("Options");
- for (auto&& option : command_structure.options.switches)
- {
- table.format(Strings::format("--%s", option.name), option.short_help_text);
- }
- for (auto&& option : command_structure.options.settings)
- {
- table.format(Strings::format("--%s=...", option.name), option.short_help_text);
- }
- for (auto&& option : command_structure.options.multisettings)
- {
- table.format(Strings::format("--%s=...", option.name), option.short_help_text);
- }
-
- VcpkgCmdArguments::append_common_options(table);
- System::print2(table.m_str);
- }
-
- void VcpkgCmdArguments::append_common_options(HelpTableFormatter& table)
- {
- static auto opt = [](StringView arg, StringView joiner, StringView value) {
- return Strings::concat("--", arg, joiner, value);
- };
-
- table.format(opt(TRIPLET_ARG, "=", "<t>"), "Specify the target architecture triplet. See 'vcpkg help triplet'");
- table.format("", "(default: " + format_environment_variable("VCPKG_DEFAULT_TRIPLET") + ')');
- table.format(opt(OVERLAY_PORTS_ARG, "=", "<path>"), "Specify directories to be used when searching for ports");
- table.format("", "(also: " + format_environment_variable("VCPKG_OVERLAY_PORTS") + ')');
- table.format(opt(OVERLAY_TRIPLETS_ARG, "=", "<path>"), "Specify directories containing triplets files");
- table.format("", "(also: " + format_environment_variable("VCPKG_OVERLAY_TRIPLETS") + ')');
- table.format(opt(BINARY_SOURCES_ARG, "=", "<path>"),
- "Add sources for binary caching. See 'vcpkg help binarycaching'");
- table.format(opt(DOWNLOADS_ROOT_DIR_ARG, "=", "<path>"), "Specify the downloads root directory");
- table.format("", "(default: " + format_environment_variable("VCPKG_DOWNLOADS") + ')');
- table.format(opt(VCPKG_ROOT_DIR_ARG, "=", "<path>"), "Specify the vcpkg root directory");
- table.format("", "(default: " + format_environment_variable("VCPKG_ROOT") + ')');
- table.format(opt(BUILDTREES_ROOT_DIR_ARG, "=", "<path>"),
- "(Experimental) Specify the buildtrees root directory");
- table.format(opt(INSTALL_ROOT_DIR_ARG, "=", "<path>"), "(Experimental) Specify the install root directory");
- table.format(opt(PACKAGES_ROOT_DIR_ARG, "=", "<path>"), "(Experimental) Specify the packages root directory");
- table.format(opt(SCRIPTS_ROOT_DIR_ARG, "=", "<path>"), "(Experimental) Specify the scripts root directory");
- table.format(opt(BUILTIN_PORTS_ROOT_DIR_ARG, "=", "<path>"),
- "(Experimental) Specify the packages root directory");
- table.format(opt(BUILTIN_REGISTRY_VERSIONS_DIR_ARG, "=", "<path>"),
- "(Experimental) Specify the versions root directory");
- table.format(opt(JSON_SWITCH, "", ""), "(Experimental) Request JSON output");
- }
-
- static void from_env(ZStringView var, std::unique_ptr<std::string>& dst)
- {
- if (dst) return;
-
- auto maybe_val = System::get_environment_variable(var);
- if (auto val = maybe_val.get())
- {
- dst = std::make_unique<std::string>(std::move(*val));
- }
- }
-
- void VcpkgCmdArguments::imbue_from_environment()
- {
- if (!disable_metrics)
- {
- const auto vcpkg_disable_metrics_env = System::get_environment_variable(DISABLE_METRICS_ENV);
- if (vcpkg_disable_metrics_env.has_value())
- {
- disable_metrics = true;
- }
- }
-
- from_env(TRIPLET_ENV, triplet);
- from_env(VCPKG_ROOT_DIR_ENV, vcpkg_root_dir);
- from_env(DOWNLOADS_ROOT_DIR_ENV, downloads_root_dir);
- from_env(DEFAULT_VISUAL_STUDIO_PATH_ENV, default_visual_studio_path);
-
- {
- const auto vcpkg_disable_lock = System::get_environment_variable(IGNORE_LOCK_FAILURES_ENV);
- if (vcpkg_disable_lock.has_value() && !ignore_lock_failures.has_value())
- {
- ignore_lock_failures = true;
- }
- }
-
- {
- const auto vcpkg_overlay_ports_env = System::get_environment_variable(OVERLAY_PORTS_ENV);
- if (const auto unpacked = vcpkg_overlay_ports_env.get())
- {
- auto overlays = Strings::split_paths(*unpacked);
- overlay_ports.insert(std::end(overlay_ports), std::begin(overlays), std::end(overlays));
- }
- }
- {
- const auto vcpkg_overlay_triplets_env = System::get_environment_variable(OVERLAY_TRIPLETS_ENV);
- if (const auto unpacked = vcpkg_overlay_triplets_env.get())
- {
- auto triplets = Strings::split_paths(*unpacked);
- overlay_triplets.insert(std::end(overlay_triplets), std::begin(triplets), std::end(triplets));
- }
- }
- {
- const auto vcpkg_feature_flags_env = System::get_environment_variable(FEATURE_FLAGS_ENV);
- if (const auto v = vcpkg_feature_flags_env.get())
- {
- auto flags = Strings::split(*v, ',');
- parse_feature_flags(flags, *this);
- }
- }
- }
-
- void VcpkgCmdArguments::imbue_or_apply_process_recursion(VcpkgCmdArguments& args)
- {
- static bool s_reentrancy_guard = false;
- Checks::check_exit(
- VCPKG_LINE_INFO,
- !s_reentrancy_guard,
- "VcpkgCmdArguments::imbue_or_apply_process_recursion() modifies global state and thus may only be "
- "called once per process.");
- s_reentrancy_guard = true;
-
- auto maybe_vcpkg_recursive_data = System::get_environment_variable(RECURSIVE_DATA_ENV);
- if (auto vcpkg_recursive_data = maybe_vcpkg_recursive_data.get())
- {
- auto rec_doc = Json::parse(*vcpkg_recursive_data).value_or_exit(VCPKG_LINE_INFO).first;
- const auto& obj = rec_doc.object();
-
- if (auto entry = obj.get(DOWNLOADS_ROOT_DIR_ENV))
- {
- args.downloads_root_dir = std::make_unique<std::string>(entry->string().to_string());
- }
-
- if (obj.get(DISABLE_METRICS_ENV))
- {
- args.disable_metrics = true;
- }
-
- // Setting the recursive data to 'poison' prevents more than one level of recursion because
- // Json::parse() will fail.
- System::set_environment_variable(RECURSIVE_DATA_ENV, "poison");
- }
- else
- {
- Json::Object obj;
- if (args.downloads_root_dir)
- {
- obj.insert(DOWNLOADS_ROOT_DIR_ENV, Json::Value::string(*args.downloads_root_dir.get()));
- }
-
- if (args.disable_metrics)
- {
- obj.insert(DISABLE_METRICS_ENV, Json::Value::boolean(true));
- }
-
- System::set_environment_variable(RECURSIVE_DATA_ENV, Json::stringify(obj, Json::JsonStyle::with_spaces(0)));
- }
- }
-
- void VcpkgCmdArguments::check_feature_flag_consistency() const
- {
- struct
- {
- StringView flag;
- StringView option;
- bool is_inconsistent;
- } possible_inconsistencies[] = {
- {BINARY_CACHING_FEATURE, BINARY_SOURCES_ARG, !binary_sources.empty() && !binary_caching.value_or(true)},
- {MANIFEST_MODE_FEATURE, MANIFEST_ROOT_DIR_ARG, manifest_root_dir && !manifest_mode.value_or(true)},
- };
- for (const auto& el : possible_inconsistencies)
- {
- if (el.is_inconsistent)
- {
- System::printf(System::Color::warning,
- "Warning: %s feature specifically turned off, but --%s was specified.\n",
- el.flag,
- el.option);
- System::printf(System::Color::warning, "Warning: Defaulting to %s being on.\n", el.flag);
- Metrics::g_metrics.lock()->track_property(
- "warning", Strings::format("warning %s alongside %s", el.flag, el.option));
- }
- }
- }
-
- void VcpkgCmdArguments::debug_print_feature_flags() const
- {
- struct
- {
- StringView name;
- Optional<bool> flag;
- } flags[] = {
- {BINARY_CACHING_FEATURE, binary_caching},
- {MANIFEST_MODE_FEATURE, manifest_mode},
- {COMPILER_TRACKING_FEATURE, compiler_tracking},
- {REGISTRIES_FEATURE, registries_feature},
- {VERSIONS_FEATURE, versions_feature},
- };
-
- for (const auto& flag : flags)
- {
- if (auto r = flag.flag.get())
- {
- Debug::print("Feature flag '", flag.name, "' = ", *r ? "on" : "off", "\n");
- }
- else
- {
- Debug::print("Feature flag '", flag.name, "' unset\n");
- }
- }
- }
-
- void VcpkgCmdArguments::track_feature_flag_metrics() const
- {
- struct
- {
- StringView flag;
- bool enabled;
- } flags[] = {
- {BINARY_CACHING_FEATURE, binary_caching_enabled()},
- {COMPILER_TRACKING_FEATURE, compiler_tracking_enabled()},
- {REGISTRIES_FEATURE, registries_enabled()},
- {VERSIONS_FEATURE, versions_enabled()},
- };
-
- for (const auto& flag : flags)
- {
- Metrics::g_metrics.lock()->track_feature(flag.flag.to_string(), flag.enabled);
- }
- }
-
- std::string format_environment_variable(StringLiteral lit)
- {
- std::string result;
-#if defined(_WIN32)
- result.reserve(lit.size() + 2);
- result.push_back('%');
- result.append(lit.data(), lit.size());
- result.push_back('%');
-#else
- result.reserve(lit.size() + 1);
- result.push_back('$');
- result.append(lit.data(), lit.size());
-#endif
- return result;
- }
-
- std::string create_example_string(const std::string& command_and_arguments)
- {
- std::string cs = Strings::format("Example:\n"
- " vcpkg %s\n",
- command_and_arguments);
- return cs;
- }
-
- static void help_table_newline_indent(std::string& target)
- {
- target.push_back('\n');
- target.append(34, ' ');
- }
-
- static constexpr ptrdiff_t S_MAX_LINE_LENGTH = 100;
-
- void HelpTableFormatter::format(StringView col1, StringView col2)
- {
- // 2 space, 31 col1, 1 space, 65 col2 = 99
- m_str.append(2, ' ');
- Strings::append(m_str, col1);
- if (col1.size() > 31)
- {
- help_table_newline_indent(m_str);
- }
- else
- {
- m_str.append(32 - col1.size(), ' ');
- }
- text(col2, 34);
-
- m_str.push_back('\n');
- }
-
- void HelpTableFormatter::header(StringView name)
- {
- m_str.append(name.data(), name.size());
- m_str.push_back(':');
- m_str.push_back('\n');
- }
-
- void HelpTableFormatter::example(StringView example_text)
- {
- m_str.append(example_text.data(), example_text.size());
- m_str.push_back('\n');
- }
-
- void HelpTableFormatter::blank() { m_str.push_back('\n'); }
-
- // Note: this formatting code does not properly handle unicode, however all of our documentation strings are English
- // ASCII.
- void HelpTableFormatter::text(StringView text, int indent)
- {
- const char* line_start = text.begin();
- const char* const e = text.end();
- const char* best_break = std::find_if(line_start, e, [](char ch) { return ch == ' ' || ch == '\n'; });
-
- while (best_break != e)
- {
- const char* next_break = std::find_if(best_break + 1, e, [](char ch) { return ch == ' ' || ch == '\n'; });
- if (*best_break == '\n' || next_break - line_start + indent > S_MAX_LINE_LENGTH)
- {
- m_str.append(line_start, best_break);
- m_str.push_back('\n');
- line_start = best_break + 1;
- best_break = next_break;
- m_str.append(indent, ' ');
- }
- else
- {
- best_break = next_break;
- }
- }
- m_str.append(line_start, best_break);
- }
-
- // out-of-line definitions since C++14 doesn't allow inline constexpr static variables
- constexpr StringLiteral VcpkgCmdArguments::VCPKG_ROOT_DIR_ENV;
- constexpr StringLiteral VcpkgCmdArguments::VCPKG_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::MANIFEST_ROOT_DIR_ARG;
-
- constexpr StringLiteral VcpkgCmdArguments::BUILDTREES_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::DOWNLOADS_ROOT_DIR_ENV;
- constexpr StringLiteral VcpkgCmdArguments::DOWNLOADS_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::INSTALL_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::PACKAGES_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::SCRIPTS_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::BUILTIN_PORTS_ROOT_DIR_ARG;
- constexpr StringLiteral VcpkgCmdArguments::BUILTIN_REGISTRY_VERSIONS_DIR_ARG;
-
- constexpr StringLiteral VcpkgCmdArguments::DEFAULT_VISUAL_STUDIO_PATH_ENV;
-
- constexpr StringLiteral VcpkgCmdArguments::TRIPLET_ENV;
- constexpr StringLiteral VcpkgCmdArguments::TRIPLET_ARG;
- constexpr StringLiteral VcpkgCmdArguments::OVERLAY_PORTS_ENV;
- constexpr StringLiteral VcpkgCmdArguments::OVERLAY_PORTS_ARG;
- constexpr StringLiteral VcpkgCmdArguments::OVERLAY_TRIPLETS_ENV;
- constexpr StringLiteral VcpkgCmdArguments::OVERLAY_TRIPLETS_ARG;
-
- constexpr StringLiteral VcpkgCmdArguments::BINARY_SOURCES_ARG;
-
- constexpr StringLiteral VcpkgCmdArguments::DEBUG_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::SEND_METRICS_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::DISABLE_METRICS_ENV;
- constexpr StringLiteral VcpkgCmdArguments::DISABLE_METRICS_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::PRINT_METRICS_SWITCH;
-
- constexpr StringLiteral VcpkgCmdArguments::WAIT_FOR_LOCK_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::IGNORE_LOCK_FAILURES_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::IGNORE_LOCK_FAILURES_ENV;
-
- constexpr StringLiteral VcpkgCmdArguments::JSON_SWITCH;
-
- constexpr StringLiteral VcpkgCmdArguments::FEATURE_FLAGS_ENV;
- constexpr StringLiteral VcpkgCmdArguments::FEATURE_FLAGS_ARG;
-
- constexpr StringLiteral VcpkgCmdArguments::FEATURE_PACKAGES_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::BINARY_CACHING_FEATURE;
- constexpr StringLiteral VcpkgCmdArguments::BINARY_CACHING_SWITCH;
- constexpr StringLiteral VcpkgCmdArguments::COMPILER_TRACKING_FEATURE;
- constexpr StringLiteral VcpkgCmdArguments::MANIFEST_MODE_FEATURE;
- constexpr StringLiteral VcpkgCmdArguments::REGISTRIES_FEATURE;
- constexpr StringLiteral VcpkgCmdArguments::RECURSIVE_DATA_ENV;
- constexpr StringLiteral VcpkgCmdArguments::VERSIONS_FEATURE;
-
- constexpr StringLiteral VcpkgCmdArguments::CMAKE_SCRIPT_ARG;
-}
diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp
deleted file mode 100644
index 5b8e4b439..000000000
--- a/toolsrc/src/vcpkg/vcpkglib.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/metrics.h>
-#include <vcpkg/paragraphs.h>
-#include <vcpkg/vcpkglib.h>
-#include <vcpkg/vcpkgpaths.h>
-
-namespace vcpkg
-{
- static StatusParagraphs load_current_database(Files::Filesystem& fs,
- const fs::path& vcpkg_dir_status_file,
- const fs::path& vcpkg_dir_status_file_old)
- {
- if (!fs.exists(vcpkg_dir_status_file))
- {
- if (!fs.exists(vcpkg_dir_status_file_old))
- {
- // no status file, use empty db
- return StatusParagraphs();
- }
-
- fs.rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file, VCPKG_LINE_INFO);
- }
-
- auto pghs = Paragraphs::get_paragraphs(fs, vcpkg_dir_status_file).value_or_exit(VCPKG_LINE_INFO);
-
- std::vector<std::unique_ptr<StatusParagraph>> status_pghs;
- for (auto&& p : pghs)
- {
- status_pghs.push_back(std::make_unique<StatusParagraph>(std::move(p)));
- }
-
- return StatusParagraphs(std::move(status_pghs));
- }
-
- StatusParagraphs database_load_check(const VcpkgPaths& paths)
- {
- auto& fs = paths.get_filesystem();
-
- const auto updates_dir = paths.vcpkg_dir_updates;
-
- std::error_code ec;
- fs.create_directory(paths.installed, ec);
- fs.create_directory(paths.vcpkg_dir, ec);
- fs.create_directory(paths.vcpkg_dir_info, ec);
- fs.create_directory(updates_dir, ec);
-
- const fs::path& status_file = paths.vcpkg_dir_status_file;
- const fs::path status_file_old = status_file.parent_path() / "status-old";
- const fs::path status_file_new = status_file.parent_path() / "status-new";
-
- StatusParagraphs current_status_db = load_current_database(fs, status_file, status_file_old);
-
- auto update_files = fs.get_files_non_recursive(updates_dir);
- Util::sort(update_files);
- if (update_files.empty())
- {
- // updates directory is empty, control file is up-to-date.
- return current_status_db;
- }
- for (auto&& file : update_files)
- {
- if (!fs.is_regular_file(file)) continue;
- if (file.filename() == "incomplete") continue;
-
- auto pghs = Paragraphs::get_paragraphs(fs, file).value_or_exit(VCPKG_LINE_INFO);
- for (auto&& p : pghs)
- {
- current_status_db.insert(std::make_unique<StatusParagraph>(std::move(p)));
- }
- }
-
- fs.write_contents(status_file_new, Strings::serialize(current_status_db), VCPKG_LINE_INFO);
-
- fs.rename(status_file_new, status_file, VCPKG_LINE_INFO);
-
- for (auto&& file : update_files)
- {
- if (!fs.is_regular_file(file)) continue;
-
- fs.remove(file, VCPKG_LINE_INFO);
- }
-
- return current_status_db;
- }
-
- void write_update(const VcpkgPaths& paths, const StatusParagraph& p)
- {
- static int update_id = 0;
- auto& fs = paths.get_filesystem();
-
- const auto my_update_id = update_id++;
- const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete";
- const auto update_filename = paths.vcpkg_dir_updates / Strings::format("%010d", my_update_id);
-
- fs.write_contents(tmp_update_filename, Strings::serialize(p), VCPKG_LINE_INFO);
- fs.rename(tmp_update_filename, update_filename, VCPKG_LINE_INFO);
- }
-
- static void upgrade_to_slash_terminated_sorted_format(Files::Filesystem& fs,
- std::vector<std::string>* lines,
- const fs::path& listfile_path)
- {
- static bool was_tracked = false;
-
- if (lines->empty())
- {
- return;
- }
-
- if (lines->at(0).back() == '/')
- {
- return; // File already in the new format
- }
-
- if (!was_tracked)
- {
- was_tracked = true;
- Metrics::g_metrics.lock()->track_property("listfile", "update to new format");
- }
-
- // The files are sorted such that directories are placed just before the files they contain
- // (They are not necessarily sorted alphabetically, e.g. libflac)
- // Therefore we can detect the entries that represent directories by comparing every element with the next one
- // and checking if the next has a slash immediately after the current one's length
- for (size_t i = 0; i < lines->size() - 1; i++)
- {
- std::string& current_string = lines->at(i);
- const std::string& next_string = lines->at(i + 1);
-
- const size_t potential_slash_char_index = current_string.length();
- // Make sure the index exists first
- if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/')
- {
- current_string += '/'; // Mark as a directory
- }
- }
-
- // After suffixing the directories with a slash, we can now sort.
- // We cannot sort before adding the suffixes because the following (actual example):
- /*
- x86-windows/include/FLAC <<<<<< This would be separated from its group due to sorting
- x86-windows/include/FLAC/all.h
- x86-windows/include/FLAC/assert.h
- x86-windows/include/FLAC/callback.h
- x86-windows/include/FLAC++
- x86-windows/include/FLAC++/all.h
- x86-windows/include/FLAC++/decoder.h
- x86-windows/include/FLAC++/encoder.h
- *
- x86-windows/include/FLAC/ <<<<<< This will now be kept with its group when sorting
- x86-windows/include/FLAC/all.h
- x86-windows/include/FLAC/assert.h
- x86-windows/include/FLAC/callback.h
- x86-windows/include/FLAC++/
- x86-windows/include/FLAC++/all.h
- x86-windows/include/FLAC++/decoder.h
- x86-windows/include/FLAC++/encoder.h
- */
- // Note that after sorting, the FLAC++/ group will be placed before the FLAC/ group
- // The new format is lexicographically sorted
- std::sort(lines->begin(), lines->end());
-
- // Replace the listfile on disk
- const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated";
- fs.write_lines(updated_listfile_path, *lines, VCPKG_LINE_INFO);
- fs.rename(updated_listfile_path, listfile_path, VCPKG_LINE_INFO);
- }
-
- std::vector<InstalledPackageView> get_installed_ports(const StatusParagraphs& status_db)
- {
- std::map<PackageSpec, InstalledPackageView> ipv_map;
-
- for (auto&& pgh : status_db)
- {
- if (!pgh->is_installed()) continue;
- auto& ipv = ipv_map[pgh->package.spec];
- if (!pgh->package.is_feature())
- {
- ipv.core = pgh.get();
- }
- else
- {
- ipv.features.emplace_back(pgh.get());
- }
- }
-
- for (auto&& ipv : ipv_map)
- {
- Checks::check_maybe_upgrade(VCPKG_LINE_INFO,
- ipv.second.core != nullptr,
- "Database is corrupted: package %s has features but no core paragraph.",
- ipv.first);
- }
-
- return Util::fmap(ipv_map, [](auto&& p) -> InstalledPackageView { return std::move(p.second); });
- }
-
- std::vector<StatusParagraphAndAssociatedFiles> get_installed_files(const VcpkgPaths& paths,
- const StatusParagraphs& status_db)
- {
- auto& fs = paths.get_filesystem();
-
- std::vector<StatusParagraphAndAssociatedFiles> installed_files;
-
- for (const std::unique_ptr<StatusParagraph>& pgh : status_db)
- {
- if (!pgh->is_installed() || pgh->package.is_feature())
- {
- continue;
- }
-
- const fs::path listfile_path = paths.listfile_path(pgh->package);
- std::vector<std::string> installed_files_of_current_pgh =
- fs.read_lines(listfile_path).value_or_exit(VCPKG_LINE_INFO);
- Strings::trim_all_and_remove_whitespace_strings(&installed_files_of_current_pgh);
- upgrade_to_slash_terminated_sorted_format(fs, &installed_files_of_current_pgh, listfile_path);
-
- // Remove the directories
- Util::erase_remove_if(installed_files_of_current_pgh,
- [](const std::string& file) { return file.back() == '/'; });
-
- StatusParagraphAndAssociatedFiles pgh_and_files = {
- *pgh, SortedVector<std::string>(std::move(installed_files_of_current_pgh))};
- installed_files.push_back(std::move(pgh_and_files));
- }
-
- return installed_files;
- }
-
- std::string shorten_text(const std::string& desc, const size_t length)
- {
- Checks::check_exit(VCPKG_LINE_INFO, length >= 3);
- auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " ");
- return simple_desc.size() <= length ? simple_desc : simple_desc.substr(0, length - 3) + "...";
- }
-}
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
deleted file mode 100644
index b9f1f3f9c..000000000
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ /dev/null
@@ -1,1086 +0,0 @@
-#include <vcpkg/base/expected.h>
-#include <vcpkg/base/files.h>
-#include <vcpkg/base/hash.h>
-#include <vcpkg/base/jsonreader.h>
-#include <vcpkg/base/system.debug.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/binaryparagraph.h>
-#include <vcpkg/build.h>
-#include <vcpkg/commands.h>
-#include <vcpkg/configuration.h>
-#include <vcpkg/globalstate.h>
-#include <vcpkg/metrics.h>
-#include <vcpkg/packagespec.h>
-#include <vcpkg/registries.h>
-#include <vcpkg/sourceparagraph.h>
-#include <vcpkg/tools.h>
-#include <vcpkg/vcpkgcmdarguments.h>
-#include <vcpkg/vcpkgpaths.h>
-#include <vcpkg/visualstudio.h>
-
-namespace
-{
- using namespace vcpkg;
- fs::path process_input_directory_impl(
- Files::Filesystem& filesystem, const fs::path& root, std::string* option, StringLiteral name, LineInfo li)
- {
- if (option)
- {
- // input directories must exist, so we use canonical
- return filesystem.canonical(li, fs::u8path(*option));
- }
- else
- {
- return root / fs::u8path(name.begin(), name.end());
- }
- }
-
- fs::path process_input_directory(
- Files::Filesystem& filesystem, const fs::path& root, std::string* option, StringLiteral name, LineInfo li)
- {
- auto result = process_input_directory_impl(filesystem, root, option, name, li);
- Debug::print("Using ", name, "-root: ", fs::u8string(result), '\n');
- return result;
- }
-
- fs::path process_output_directory_impl(
- Files::Filesystem& filesystem, const fs::path& root, std::string* option, StringLiteral name, LineInfo li)
- {
- if (option)
- {
- // output directories might not exist, so we use merely absolute
- return filesystem.absolute(li, fs::u8path(*option));
- }
- else
- {
- return root / fs::u8path(name.begin(), name.end());
- }
- }
-
- fs::path process_output_directory(
- Files::Filesystem& filesystem, const fs::path& root, std::string* option, StringLiteral name, LineInfo li)
- {
- auto result = process_output_directory_impl(filesystem, root, option, name, li);
-#if defined(_WIN32)
- result = vcpkg::Files::win32_fix_path_case(result);
-#endif // _WIN32
- Debug::print("Using ", name, "-root: ", fs::u8string(result), '\n');
- return result;
- }
-
- System::Command git_cmd_builder(const VcpkgPaths& paths, const fs::path& dot_git_dir, const fs::path& work_tree)
- {
- return System::Command()
- .path_arg(paths.get_tool_exe(Tools::GIT))
- .string_arg(Strings::concat("--git-dir=", fs::u8string(dot_git_dir)))
- .string_arg(Strings::concat("--work-tree=", fs::u8string(work_tree)));
- }
-} // unnamed namespace
-
-namespace vcpkg
-{
- static Configuration deserialize_configuration(const Json::Object& obj,
- const VcpkgCmdArguments& args,
- const fs::path& filepath)
- {
- Json::Reader reader;
- auto deserializer = make_configuration_deserializer(filepath.parent_path());
-
- auto parsed_config_opt = reader.visit(obj, *deserializer);
- if (!reader.errors().empty())
- {
- System::print2(System::Color::error, "Errors occurred while parsing ", fs::u8string(filepath), "\n");
- for (auto&& msg : reader.errors())
- System::print2(" ", msg, '\n');
-
- System::print2("See https://github.com/Microsoft/vcpkg/tree/master/docs/specifications/registries.md for "
- "more information.\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- parsed_config_opt.get()->validate_feature_flags(args.feature_flag_settings());
-
- return std::move(parsed_config_opt).value_or_exit(VCPKG_LINE_INFO);
- }
-
- struct ManifestAndConfig
- {
- fs::path config_directory;
- Configuration config;
- };
-
- static std::pair<Json::Object, Json::JsonStyle> load_manifest(const Files::Filesystem& fs,
- const fs::path& manifest_dir)
- {
- std::error_code ec;
- auto manifest_path = manifest_dir / fs::u8path("vcpkg.json");
- auto manifest_opt = Json::parse_file(fs, manifest_path, ec);
- if (ec)
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Failed to load manifest from directory %s: %s",
- fs::u8string(manifest_dir),
- ec.message());
- }
-
- if (!manifest_opt.has_value())
- {
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
- "Failed to parse manifest at %s:\n%s",
- fs::u8string(manifest_path),
- manifest_opt.error()->format());
- }
- auto manifest_value = std::move(manifest_opt).value_or_exit(VCPKG_LINE_INFO);
-
- if (!manifest_value.first.is_object())
- {
- System::print2(System::Color::error,
- "Failed to parse manifest at ",
- fs::u8string(manifest_path),
- ": Manifest files must have a top-level object\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- return {std::move(manifest_value.first.object()), std::move(manifest_value.second)};
- }
-
- struct ConfigAndPath
- {
- fs::path config_directory;
- Configuration config;
- };
-
- // doesn't yet implement searching upwards for configurations, nor inheritance of configurations
- static ConfigAndPath load_configuration(const Files::Filesystem& fs,
- const VcpkgCmdArguments& args,
- const fs::path& vcpkg_root,
- const fs::path& manifest_dir)
- {
- fs::path config_dir;
- if (manifest_dir.empty())
- {
- // classic mode
- config_dir = vcpkg_root;
- }
- else
- {
- // manifest mode
- config_dir = manifest_dir;
- }
-
- auto path_to_config = config_dir / fs::u8path("vcpkg-configuration.json");
- if (!fs.exists(path_to_config))
- {
- return {};
- }
-
- auto parsed_config = Json::parse_file(VCPKG_LINE_INFO, fs, path_to_config);
- if (!parsed_config.first.is_object())
- {
- System::print2(System::Color::error,
- "Failed to parse ",
- fs::u8string(path_to_config),
- ": configuration files must have a top-level object\n");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- auto config_obj = std::move(parsed_config.first.object());
-
- return {std::move(config_dir), deserialize_configuration(config_obj, args, path_to_config)};
- }
-
- namespace details
- {
- struct VcpkgPathsImpl
- {
- VcpkgPathsImpl(Files::Filesystem& fs, FeatureFlagSettings ff_settings)
- : fs_ptr(&fs)
- , m_tool_cache(get_tool_cache())
- , m_env_cache(ff_settings.compiler_tracking)
- , m_ff_settings(ff_settings)
- {
- const auto& cache_root =
- System::get_platform_cache_home().value_or_exit(VCPKG_LINE_INFO) / fs::u8path("vcpkg");
- registries_work_tree_dir = cache_root / fs::u8path("registries") / fs::u8path("git");
- registries_dot_git_dir = registries_work_tree_dir / fs::u8path(".git");
- registries_git_trees = cache_root / fs::u8path("registries") / fs::u8path("git-trees");
- }
-
- Lazy<std::vector<VcpkgPaths::TripletFile>> available_triplets;
- Lazy<std::vector<Toolset>> toolsets;
- Lazy<std::map<std::string, std::string>> cmake_script_hashes;
-
- Files::Filesystem* fs_ptr;
-
- fs::path default_vs_path;
- std::vector<fs::path> triplets_dirs;
-
- std::unique_ptr<ToolCache> m_tool_cache;
- Cache<Triplet, fs::path> m_triplets_cache;
- Build::EnvCache m_env_cache;
-
- fs::SystemHandle file_lock_handle;
-
- Optional<std::pair<Json::Object, Json::JsonStyle>> m_manifest_doc;
- fs::path m_manifest_path;
- Configuration m_config;
-
- FeatureFlagSettings m_ff_settings;
-
- fs::path registries_work_tree_dir;
- fs::path registries_dot_git_dir;
- fs::path registries_git_trees;
- };
- }
-
- VcpkgPaths::VcpkgPaths(Files::Filesystem& filesystem, const VcpkgCmdArguments& args)
- : m_pimpl(std::make_unique<details::VcpkgPathsImpl>(filesystem, args.feature_flag_settings()))
- {
- original_cwd = filesystem.current_path(VCPKG_LINE_INFO);
-#if defined(_WIN32)
- original_cwd = vcpkg::Files::win32_fix_path_case(original_cwd);
-#endif // _WIN32
-
- if (args.vcpkg_root_dir)
- {
- root = filesystem.canonical(VCPKG_LINE_INFO, fs::u8path(*args.vcpkg_root_dir));
- }
- else
- {
- root = filesystem.find_file_recursively_up(original_cwd, ".vcpkg-root");
- if (root.empty())
- {
- root = filesystem.find_file_recursively_up(
- filesystem.canonical(VCPKG_LINE_INFO, System::get_exe_path_of_current_process()), ".vcpkg-root");
- }
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, !root.empty(), "Error: Could not detect vcpkg-root.");
- Debug::print("Using vcpkg-root: ", fs::u8string(root), '\n');
-
- std::error_code ec;
- bool manifest_mode_on = args.manifest_mode.value_or(args.manifest_root_dir != nullptr);
- if (args.manifest_root_dir)
- {
- manifest_root_dir = filesystem.canonical(VCPKG_LINE_INFO, fs::u8path(*args.manifest_root_dir));
- }
- else
- {
- manifest_root_dir = filesystem.find_file_recursively_up(original_cwd, fs::u8path("vcpkg.json"));
- }
-
- if (!manifest_root_dir.empty() && manifest_mode_on)
- {
- Debug::print("Using manifest-root: ", fs::u8string(manifest_root_dir), '\n');
-
- installed = process_output_directory(
- filesystem, manifest_root_dir, args.install_root_dir.get(), "vcpkg_installed", VCPKG_LINE_INFO);
-
- const auto vcpkg_lock = root / ".vcpkg-root";
- if (args.wait_for_lock.value_or(false))
- {
- m_pimpl->file_lock_handle = filesystem.take_exclusive_file_lock(vcpkg_lock, ec);
- }
- else
- {
- m_pimpl->file_lock_handle = filesystem.try_take_exclusive_file_lock(vcpkg_lock, ec);
- }
-
- if (ec)
- {
- if (ec == std::errc::device_or_resource_busy || args.ignore_lock_failures.value_or(false))
- {
- System::printf(
- System::Color::error, "Failed to take the filesystem lock on %s:\n", fs::u8string(vcpkg_lock));
- System::printf(System::Color::error, " %s\n", ec.message());
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- m_pimpl->m_manifest_doc = load_manifest(filesystem, manifest_root_dir);
- m_pimpl->m_manifest_path = manifest_root_dir / fs::u8path("vcpkg.json");
- }
- else
- {
- // we ignore the manifest root dir if the user requests -manifest
- if (!manifest_root_dir.empty() && !args.manifest_mode.has_value() && !args.output_json())
- {
- System::print2(System::Color::warning,
- "Warning: manifest-root detected at ",
- fs::generic_u8string(manifest_root_dir),
- ", but manifests are not enabled.\n");
- System::printf(System::Color::warning,
- R"(If you wish to use manifest mode, you may do one of the following:
- * Add the `%s` feature flag to the comma-separated environment
- variable `%s`.
- * Add the `%s` feature flag to the `--%s` option.
- * Pass your manifest directory to the `--%s` option.
-If you wish to silence this error and use classic mode, you can:
- * Add the `-%s` feature flag to `%s`.
- * Add the `-%s` feature flag to `--%s`.
-)",
- VcpkgCmdArguments::MANIFEST_MODE_FEATURE,
- VcpkgCmdArguments::FEATURE_FLAGS_ENV,
- VcpkgCmdArguments::MANIFEST_MODE_FEATURE,
- VcpkgCmdArguments::FEATURE_FLAGS_ARG,
- VcpkgCmdArguments::MANIFEST_ROOT_DIR_ARG,
- VcpkgCmdArguments::MANIFEST_MODE_FEATURE,
- VcpkgCmdArguments::FEATURE_FLAGS_ENV,
- VcpkgCmdArguments::MANIFEST_MODE_FEATURE,
- VcpkgCmdArguments::FEATURE_FLAGS_ARG);
- }
-
- manifest_root_dir.clear();
- installed =
- process_output_directory(filesystem, root, args.install_root_dir.get(), "installed", VCPKG_LINE_INFO);
- }
-
- auto config_file = load_configuration(filesystem, args, root, manifest_root_dir);
-
- config_root_dir = std::move(config_file.config_directory);
- m_pimpl->m_config = std::move(config_file.config);
-
- buildtrees =
- process_output_directory(filesystem, root, args.buildtrees_root_dir.get(), "buildtrees", VCPKG_LINE_INFO);
- downloads =
- process_output_directory(filesystem, root, args.downloads_root_dir.get(), "downloads", VCPKG_LINE_INFO);
- packages =
- process_output_directory(filesystem, root, args.packages_root_dir.get(), "packages", VCPKG_LINE_INFO);
- scripts = process_input_directory(filesystem, root, args.scripts_root_dir.get(), "scripts", VCPKG_LINE_INFO);
- builtin_ports =
- process_output_directory(filesystem, root, args.builtin_ports_root_dir.get(), "ports", VCPKG_LINE_INFO);
- builtin_registry_versions = process_output_directory(
- filesystem, root, args.builtin_registry_versions_dir.get(), "versions", VCPKG_LINE_INFO);
- prefab = root / fs::u8path("prefab");
-
- if (args.default_visual_studio_path)
- {
- m_pimpl->default_vs_path =
- filesystem.canonical(VCPKG_LINE_INFO, fs::u8path(*args.default_visual_studio_path));
- }
-
- triplets = filesystem.canonical(VCPKG_LINE_INFO, root / fs::u8path("triplets"));
- community_triplets = filesystem.canonical(VCPKG_LINE_INFO, triplets / fs::u8path("community"));
-
- tools = downloads / fs::u8path("tools");
- buildsystems = scripts / fs::u8path("buildsystems");
- const auto msbuildDirectory = buildsystems / fs::u8path("msbuild");
- buildsystems_msbuild_targets = msbuildDirectory / fs::u8path("vcpkg.targets");
- buildsystems_msbuild_props = msbuildDirectory / fs::u8path("vcpkg.props");
-
- vcpkg_dir = installed / fs::u8path("vcpkg");
- vcpkg_dir_status_file = vcpkg_dir / fs::u8path("status");
- vcpkg_dir_info = vcpkg_dir / fs::u8path("info");
- vcpkg_dir_updates = vcpkg_dir / fs::u8path("updates");
-
- const auto versioning_tmp = buildtrees / fs::u8path("versioning_tmp");
- const auto versioning_output = buildtrees / fs::u8path("versioning");
-
- baselines_dot_git_dir = versioning_tmp / fs::u8path(".baselines.git");
- baselines_work_tree = versioning_tmp / fs::u8path("baselines-worktree");
- baselines_output = versioning_output / fs::u8path("baselines");
-
- versions_dot_git_dir = versioning_tmp / fs::u8path(".versions.git");
- versions_work_tree = versioning_tmp / fs::u8path("versions-worktree");
- versions_output = versioning_output / fs::u8path("versions");
-
- ports_cmake = filesystem.canonical(VCPKG_LINE_INFO, scripts / fs::u8path("ports.cmake"));
-
- for (auto&& overlay_triplets_dir : args.overlay_triplets)
- {
- m_pimpl->triplets_dirs.emplace_back(
- filesystem.canonical(VCPKG_LINE_INFO, fs::u8path(overlay_triplets_dir)));
- }
- m_pimpl->triplets_dirs.emplace_back(triplets);
- m_pimpl->triplets_dirs.emplace_back(community_triplets);
- }
-
- fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / fs::u8path(spec.dir()); }
- fs::path VcpkgPaths::build_dir(const PackageSpec& spec) const { return this->buildtrees / fs::u8path(spec.name()); }
- fs::path VcpkgPaths::build_dir(const std::string& package_name) const
- {
- return this->buildtrees / fs::u8path(package_name);
- }
-
- fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const
- {
- return this->package_dir(spec) / "BUILD_INFO";
- }
-
- fs::path VcpkgPaths::listfile_path(const BinaryParagraph& pgh) const
- {
- return this->vcpkg_dir_info / (pgh.fullstem() + ".list");
- }
-
- bool VcpkgPaths::is_valid_triplet(Triplet t) const
- {
- const auto it = Util::find_if(this->get_available_triplets(), [&](auto&& available_triplet) {
- return t.canonical_name() == available_triplet.name;
- });
- return it != this->get_available_triplets().cend();
- }
-
- const std::vector<std::string> VcpkgPaths::get_available_triplets_names() const
- {
- return vcpkg::Util::fmap(this->get_available_triplets(),
- [](auto&& triplet_file) -> std::string { return triplet_file.name; });
- }
-
- const std::vector<VcpkgPaths::TripletFile>& VcpkgPaths::get_available_triplets() const
- {
- return m_pimpl->available_triplets.get_lazy([this]() -> std::vector<TripletFile> {
- std::vector<TripletFile> output;
- Files::Filesystem& fs = this->get_filesystem();
- for (auto&& triplets_dir : m_pimpl->triplets_dirs)
- {
- for (auto&& path : fs.get_files_non_recursive(triplets_dir))
- {
- if (fs::is_regular_file(fs.status(VCPKG_LINE_INFO, path)))
- {
- output.emplace_back(TripletFile(fs::u8string(path.stem().filename()), triplets_dir));
- }
- }
- }
- return output;
- });
- }
-
- const std::map<std::string, std::string>& VcpkgPaths::get_cmake_script_hashes() const
- {
- return m_pimpl->cmake_script_hashes.get_lazy([this]() -> std::map<std::string, std::string> {
- auto& fs = this->get_filesystem();
- std::map<std::string, std::string> helpers;
- auto files = fs.get_files_non_recursive(this->scripts / fs::u8path("cmake"));
- for (auto&& file : files)
- {
- helpers.emplace(fs::u8string(file.stem()),
- Hash::get_file_hash(VCPKG_LINE_INFO, fs, file, Hash::Algorithm::Sha1));
- }
- return helpers;
- });
- }
-
- const fs::path VcpkgPaths::get_triplet_file_path(Triplet triplet) const
- {
- return m_pimpl->m_triplets_cache.get_lazy(
- triplet, [&]() -> auto {
- for (const auto& triplet_dir : m_pimpl->triplets_dirs)
- {
- auto path = triplet_dir / (triplet.canonical_name() + ".cmake");
- if (this->get_filesystem().exists(path))
- {
- return path;
- }
- }
-
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Error: Triplet file %s.cmake not found", triplet.canonical_name());
- });
- }
-
- const fs::path& VcpkgPaths::get_tool_exe(const std::string& tool) const
- {
- return m_pimpl->m_tool_cache->get_tool_path(*this, tool);
- }
- const std::string& VcpkgPaths::get_tool_version(const std::string& tool) const
- {
- return m_pimpl->m_tool_cache->get_tool_version(*this, tool);
- }
-
- void VcpkgPaths::git_checkout_subpath(const VcpkgPaths& paths,
- StringView commit_sha,
- const fs::path& subpath,
- const fs::path& local_repo,
- const fs::path& destination,
- const fs::path& dot_git_dir,
- const fs::path& work_tree)
- {
- Files::Filesystem& fs = paths.get_filesystem();
- fs.remove_all(work_tree, VCPKG_LINE_INFO);
- fs.remove_all(destination, VCPKG_LINE_INFO);
- fs.remove_all(dot_git_dir, VCPKG_LINE_INFO);
-
- // All git commands are run with: --git-dir={dot_git_dir} --work-tree={work_tree_temp}
- // git clone --no-checkout --local --no-hardlinks {vcpkg_root} {dot_git_dir}
- // note that `--no-hardlinks` is added because otherwise, git fails to clone in some cases
- System::Command clone_cmd_builder = git_cmd_builder(paths, dot_git_dir, work_tree)
- .string_arg("clone")
- .string_arg("--no-checkout")
- .string_arg("--local")
- .string_arg("--no-hardlinks")
- .path_arg(local_repo)
- .path_arg(dot_git_dir);
- const auto clone_output = System::cmd_execute_and_capture_output(clone_cmd_builder);
- Checks::check_exit(VCPKG_LINE_INFO,
- clone_output.exit_code == 0,
- "Failed to clone temporary vcpkg instance.\n%s\n",
- clone_output.output);
-
- // git checkout {commit-sha} -- {subpath}
- System::Command checkout_cmd_builder = git_cmd_builder(paths, dot_git_dir, work_tree)
- .string_arg("checkout")
- .string_arg(commit_sha)
- .string_arg("--")
- .path_arg(subpath);
- const auto checkout_output = System::cmd_execute_and_capture_output(checkout_cmd_builder);
- Checks::check_exit(VCPKG_LINE_INFO,
- checkout_output.exit_code == 0,
- "Error: Failed to checkout %s:%s\n%s\n",
- commit_sha,
- fs::u8string(subpath),
- checkout_output.output);
-
- const fs::path checked_out_path = work_tree / subpath;
- const auto& containing_folder = destination.parent_path();
- if (!fs.exists(containing_folder))
- {
- fs.create_directories(containing_folder, VCPKG_LINE_INFO);
- }
-
- std::error_code ec;
- fs.rename_or_copy(checked_out_path, destination, ".tmp", ec);
- fs.remove_all(work_tree, VCPKG_LINE_INFO);
- fs.remove_all(dot_git_dir, VCPKG_LINE_INFO);
- if (ec)
- {
- System::printf(System::Color::error,
- "Error: Couldn't move checked out files from %s to destination %s",
- fs::u8string(checked_out_path),
- fs::u8string(destination));
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
- ExpectedS<std::string> VcpkgPaths::get_current_git_sha() const
- {
- auto cmd = git_cmd_builder(*this, this->root / fs::u8path(".git"), this->root);
- cmd.string_arg("rev-parse").string_arg("HEAD");
- auto output = System::cmd_execute_and_capture_output(cmd);
- if (output.exit_code != 0)
- {
- return {std::move(output.output), expected_right_tag};
- }
- else
- {
- return {Strings::trim(std::move(output.output)), expected_left_tag};
- }
- }
- std::string VcpkgPaths::get_current_git_sha_message() const
- {
- auto maybe_cur_sha = get_current_git_sha();
- if (auto p_sha = maybe_cur_sha.get())
- {
- return Strings::concat("The current commit is \"", *p_sha, '"');
- }
- else
- {
- return Strings::concat("Failed to determine the current commit:\n", maybe_cur_sha.error());
- }
- }
-
- ExpectedS<std::string> VcpkgPaths::git_show(const std::string& treeish, const fs::path& dot_git_dir) const
- {
- // All git commands are run with: --git-dir={dot_git_dir} --work-tree={work_tree_temp}
- // git clone --no-checkout --local {vcpkg_root} {dot_git_dir}
- System::Command showcmd =
- git_cmd_builder(*this, dot_git_dir, dot_git_dir).string_arg("show").string_arg(treeish);
-
- auto output = System::cmd_execute_and_capture_output(showcmd);
- if (output.exit_code == 0)
- {
- return {std::move(output.output), expected_left_tag};
- }
- else
- {
- return {std::move(output.output), expected_right_tag};
- }
- }
-
- ExpectedS<std::map<std::string, std::string, std::less<>>> VcpkgPaths::git_get_local_port_treeish_map() const
- {
- const auto local_repo = this->root / fs::u8path(".git");
- const auto path_with_separator =
- Strings::concat(fs::u8string(this->builtin_ports_directory()), Files::preferred_separator);
- const auto git_cmd = git_cmd_builder(*this, local_repo, this->root)
- .string_arg("ls-tree")
- .string_arg("-d")
- .string_arg("HEAD")
- .string_arg("--")
- .path_arg(path_with_separator);
-
- auto output = System::cmd_execute_and_capture_output(git_cmd);
- if (output.exit_code != 0)
- return Strings::format("Error: Couldn't get local treeish objects for ports.\n%s", output.output);
-
- std::map<std::string, std::string, std::less<>> ret;
- auto lines = Strings::split(output.output, '\n');
- // The first line of the output is always the parent directory itself.
- for (auto line : lines)
- {
- // The default output comes in the format:
- // <mode> SP <type> SP <object> TAB <file>
- auto split_line = Strings::split(line, '\t');
- if (split_line.size() != 2)
- return Strings::format("Error: Unexpected output from command `%s`. Couldn't split by `\\t`.\n%s",
- git_cmd.command_line(),
- line);
-
- auto file_info_section = Strings::split(split_line[0], ' ');
- if (file_info_section.size() != 3)
- return Strings::format("Error: Unexepcted output from command `%s`. Couldn't split by ` `.\n%s",
- git_cmd.command_line(),
- line);
-
- const auto index = split_line[1].find_last_of('/');
- if (index == std::string::npos)
- {
- return Strings::format("Error: Unexpected output from command `%s`. Couldn't split by `/`.\n%s",
- git_cmd.command_line(),
- line);
- }
-
- ret.emplace(split_line[1].substr(index + 1), file_info_section.back());
- }
- return ret;
- }
-
- ExpectedS<fs::path> VcpkgPaths::git_checkout_baseline(StringView commit_sha) const
- {
- Files::Filesystem& fs = get_filesystem();
- const fs::path destination_parent = this->baselines_output / fs::u8path(commit_sha);
- fs::path destination = destination_parent / fs::u8path("baseline.json");
-
- if (!fs.exists(destination))
- {
- const fs::path destination_tmp = destination_parent / fs::u8path("baseline.json.tmp");
- auto treeish = Strings::concat(commit_sha, ":versions/baseline.json");
- auto maybe_contents = git_show(treeish, this->root / fs::u8path(".git"));
- if (auto contents = maybe_contents.get())
- {
- std::error_code ec;
- fs.create_directories(destination_parent, ec);
- if (ec)
- {
- return {Strings::format(
- "Error: while checking out baseline %s\nError: while creating directories %s: %s",
- commit_sha,
- fs::u8string(destination_parent),
- ec.message()),
- expected_right_tag};
- }
- fs.write_contents(destination_tmp, *contents, ec);
- if (ec)
- {
- return {Strings::format("Error: while checking out baseline %s\nError: while writing %s: %s",
- commit_sha,
- fs::u8string(destination_tmp),
- ec.message()),
- expected_right_tag};
- }
- fs.rename(destination_tmp, destination, ec);
- if (ec)
- {
- return {Strings::format("Error: while checking out baseline %s\nError: while renaming %s to %s: %s",
- commit_sha,
- fs::u8string(destination_tmp),
- fs::u8string(destination),
- ec.message()),
- expected_right_tag};
- }
- }
- else
- {
- return {Strings::format("Error: while checking out baseline '%s':\n%s\nThis may be fixed by updating "
- "vcpkg to the latest master via `git pull`.",
- treeish,
- maybe_contents.error()),
- expected_right_tag};
- }
- }
- return destination;
- }
-
- ExpectedS<fs::path> VcpkgPaths::git_checkout_port(StringView port_name,
- StringView git_tree,
- const fs::path& dot_git_dir) const
- {
- /* Check out a git tree into the versioned port recipes folder
- *
- * Since we are checking a git tree object, all files will be checked out to the root of `work-tree`.
- * Because of that, it makes sense to use the git hash as the name for the directory.
- */
- Files::Filesystem& fs = get_filesystem();
- fs::path destination = this->versions_output / fs::u8path(port_name) / fs::u8path(git_tree);
- if (fs.exists(destination))
- {
- return destination;
- }
-
- const fs::path destination_tmp =
- this->versions_output / fs::u8path(port_name) / fs::u8path(Strings::concat(git_tree, ".tmp"));
- const fs::path destination_tar =
- this->versions_output / fs::u8path(port_name) / fs::u8path(Strings::concat(git_tree, ".tar"));
-#define PRELUDE "Error: while checking out port ", port_name, " with git tree ", git_tree, "\n"
- std::error_code ec;
- fs::path failure_point;
- fs.remove_all(destination_tmp, ec, failure_point);
- if (ec)
- {
- return {Strings::concat(PRELUDE, "Error: while removing ", fs::u8string(failure_point), ": ", ec.message()),
- expected_right_tag};
- }
- fs.create_directories(destination_tmp, ec);
- if (ec)
- {
- return {
- Strings::concat(
- PRELUDE, "Error: while creating directories ", fs::u8string(destination_tmp), ": ", ec.message()),
- expected_right_tag};
- }
-
- auto tar_cmd_builder = git_cmd_builder(*this, dot_git_dir, dot_git_dir)
- .string_arg("archive")
- .string_arg(git_tree)
- .string_arg("-o")
- .path_arg(destination_tar);
- const auto tar_output = System::cmd_execute_and_capture_output(tar_cmd_builder);
- if (tar_output.exit_code != 0)
- {
- return {Strings::concat(PRELUDE, "Error: Failed to tar port directory\n", tar_output.output),
- expected_right_tag};
- }
-
- auto extract_cmd_builder = System::Command{this->get_tool_exe(Tools::CMAKE)}
- .string_arg("-E")
- .string_arg("tar")
- .string_arg("xf")
- .path_arg(destination_tar);
-
- const auto extract_output =
- System::cmd_execute_and_capture_output(extract_cmd_builder, System::InWorkingDirectory{destination_tmp});
- if (extract_output.exit_code != 0)
- {
- return {Strings::concat(PRELUDE, "Error: Failed to extract port directory\n", extract_output.output),
- expected_right_tag};
- }
- fs.remove(destination_tar, ec);
- if (ec)
- {
- return {
- Strings::concat(PRELUDE, "Error: while removing ", fs::u8string(destination_tar), ": ", ec.message()),
- expected_right_tag};
- }
- fs.rename(destination_tmp, destination, ec);
- if (ec)
- {
- return {Strings::concat(PRELUDE,
- "Error: while renaming ",
- fs::u8string(destination_tmp),
- " to ",
- fs::u8string(destination),
- ": ",
- ec.message()),
- expected_right_tag};
- }
-
- return destination;
-#undef PRELUDE
- }
-
- ExpectedS<std::string> VcpkgPaths::git_fetch_from_remote_registry(StringView repo, StringView treeish) const
- {
- auto& fs = get_filesystem();
-
- auto work_tree = m_pimpl->registries_work_tree_dir;
- fs.create_directories(work_tree, VCPKG_LINE_INFO);
- auto dot_git_dir = m_pimpl->registries_dot_git_dir;
-
- System::Command init_registries_git_dir = git_cmd_builder(*this, dot_git_dir, work_tree).string_arg("init");
- auto init_output = System::cmd_execute_and_capture_output(init_registries_git_dir);
- if (init_output.exit_code != 0)
- {
- return {Strings::format("Error: Failed to initialize local repository %s.\n%s\n",
- fs::u8string(work_tree),
- init_output.output),
- expected_right_tag};
- }
-
- auto lock_file = work_tree / fs::u8path(".vcpkg-lock");
-
- std::error_code ec;
- Files::ExclusiveFileLock guard(Files::ExclusiveFileLock::Wait::Yes, fs, lock_file, ec);
-
- System::Command fetch_git_ref =
- git_cmd_builder(*this, dot_git_dir, work_tree).string_arg("fetch").string_arg("--").string_arg(repo);
- if (treeish.size() != 0)
- {
- fetch_git_ref.string_arg(treeish);
- }
-
- auto fetch_output = System::cmd_execute_and_capture_output(fetch_git_ref);
- if (fetch_output.exit_code != 0)
- {
- return {Strings::format("Error: Failed to fetch %s%s from repository %s.\n%s\n",
- treeish.size() != 0 ? "ref " : "",
- treeish,
- repo,
- fetch_output.output),
- expected_right_tag};
- }
-
- System::Command get_fetch_head =
- git_cmd_builder(*this, dot_git_dir, work_tree).string_arg("rev-parse").string_arg("FETCH_HEAD");
- auto fetch_head_output = System::cmd_execute_and_capture_output(get_fetch_head);
- if (fetch_head_output.exit_code != 0)
- {
- return {Strings::format("Error: Failed to rev-parse FETCH_HEAD.\n%s\n", fetch_head_output.output),
- expected_right_tag};
- }
- return {Strings::trim(fetch_head_output.output).to_string(), expected_left_tag};
- }
- // returns an error if there was an unexpected error; returns nullopt if the file doesn't exist at the specified
- // hash
- ExpectedS<std::string> VcpkgPaths::git_show_from_remote_registry(StringView hash,
- const fs::path& relative_path) const
- {
- auto revision = Strings::format("%s:%s", hash, fs::generic_u8string(relative_path));
- System::Command git_show =
- git_cmd_builder(*this, m_pimpl->registries_dot_git_dir, m_pimpl->registries_work_tree_dir)
- .string_arg("show")
- .string_arg(revision);
-
- auto git_show_output = System::cmd_execute_and_capture_output(git_show);
- if (git_show_output.exit_code != 0)
- {
- return {git_show_output.output, expected_right_tag};
- }
- return {git_show_output.output, expected_left_tag};
- }
- ExpectedS<std::string> VcpkgPaths::git_find_object_id_for_remote_registry_path(StringView hash,
- const fs::path& relative_path) const
- {
- auto revision = Strings::format("%s:%s", hash, fs::generic_u8string(relative_path));
- System::Command git_rev_parse =
- git_cmd_builder(*this, m_pimpl->registries_dot_git_dir, m_pimpl->registries_work_tree_dir)
- .string_arg("rev-parse")
- .string_arg(revision);
-
- auto git_rev_parse_output = System::cmd_execute_and_capture_output(git_rev_parse);
- if (git_rev_parse_output.exit_code != 0)
- {
- return {git_rev_parse_output.output, expected_right_tag};
- }
- return {Strings::trim(git_rev_parse_output.output).to_string(), expected_left_tag};
- }
- ExpectedS<fs::path> VcpkgPaths::git_checkout_object_from_remote_registry(StringView object) const
- {
- auto& fs = get_filesystem();
- fs.create_directories(m_pimpl->registries_git_trees, VCPKG_LINE_INFO);
-
- auto git_tree_final = m_pimpl->registries_git_trees / fs::u8path(object);
- if (fs.exists(git_tree_final))
- {
- return std::move(git_tree_final);
- }
-
- auto pid = System::get_process_id();
-
- fs::path git_tree_temp = fs::u8path(Strings::format("%s.tmp%ld", fs::u8string(git_tree_final), pid));
- fs::path git_tree_temp_tar = fs::u8path(Strings::format("%s.tmp%ld.tar", fs::u8string(git_tree_final), pid));
- fs.remove_all(git_tree_temp, VCPKG_LINE_INFO);
- fs.create_directory(git_tree_temp, VCPKG_LINE_INFO);
-
- auto dot_git_dir = m_pimpl->registries_dot_git_dir;
- System::Command git_archive = git_cmd_builder(*this, dot_git_dir, m_pimpl->registries_work_tree_dir)
- .string_arg("archive")
- .string_arg("--format")
- .string_arg("tar")
- .string_arg(object)
- .string_arg("--output")
- .path_arg(git_tree_temp_tar);
- auto git_archive_output = System::cmd_execute_and_capture_output(git_archive);
- if (git_archive_output.exit_code != 0)
- {
- return {Strings::format("git archive failed with message:\n%s", git_archive_output.output),
- expected_right_tag};
- }
-
- auto untar =
- System::Command{get_tool_exe(Tools::CMAKE)}.string_arg("-E").string_arg("tar").string_arg("xf").path_arg(
- git_tree_temp_tar);
-
- auto untar_output = System::cmd_execute_and_capture_output(untar, System::InWorkingDirectory{git_tree_temp});
- if (untar_output.exit_code != 0)
- {
- return {Strings::format("cmake's untar failed with message:\n%s", untar_output.output), expected_right_tag};
- }
-
- std::error_code ec;
- fs.rename(git_tree_temp, git_tree_final, ec);
-
- if (fs.exists(git_tree_final))
- {
- return git_tree_final;
- }
- if (ec)
- {
- return {
- Strings::format("rename to %s failed with message:\n%s", fs::u8string(git_tree_final), ec.message()),
- expected_right_tag};
- }
- else
- {
- return {"Unknown error", expected_right_tag};
- }
- }
-
- Optional<const Json::Object&> VcpkgPaths::get_manifest() const
- {
- if (auto p = m_pimpl->m_manifest_doc.get())
- {
- return p->first;
- }
- else
- {
- return nullopt;
- }
- }
- Optional<const fs::path&> VcpkgPaths::get_manifest_path() const
- {
- if (m_pimpl->m_manifest_doc)
- {
- return m_pimpl->m_manifest_path;
- }
- else
- {
- return nullopt;
- }
- }
-
- const Configuration& VcpkgPaths::get_configuration() const { return m_pimpl->m_config; }
-
- const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const
- {
- if (!prebuildinfo.using_vcvars())
- {
- static Toolset external_toolset = []() -> Toolset {
- Toolset ret;
- ret.dumpbin.clear();
- ret.supported_architectures = {
- ToolsetArchOption{"", System::get_host_processor(), System::get_host_processor()}};
- ret.vcvarsall.clear();
- ret.vcvarsall_options = {};
- ret.version = "external";
- ret.visual_studio_root_path.clear();
- return ret;
- }();
- return external_toolset;
- }
-
-#if !defined(_WIN32)
- Checks::exit_maybe_upgrade(VCPKG_LINE_INFO, "Cannot build windows triplets from non-windows.");
-#else
- View<Toolset> vs_toolsets = get_all_toolsets();
-
- std::vector<const Toolset*> candidates = Util::fmap(vs_toolsets, [](auto&& x) { return &x; });
- const auto tsv = prebuildinfo.platform_toolset.get();
- auto vsp = prebuildinfo.visual_studio_path.get();
- if (!vsp && !m_pimpl->default_vs_path.empty())
- {
- vsp = &m_pimpl->default_vs_path;
- }
-
- if (tsv && vsp)
- {
- Util::erase_remove_if(
- candidates, [&](const Toolset* t) { return *tsv != t->version || *vsp != t->visual_studio_root_path; });
- Checks::check_exit(VCPKG_LINE_INFO,
- !candidates.empty(),
- "Could not find Visual Studio instance at %s with %s toolset.",
- fs::u8string(*vsp),
- *tsv);
-
- Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1);
- return *candidates.back();
- }
-
- if (tsv)
- {
- Util::erase_remove_if(candidates, [&](const Toolset* t) { return *tsv != t->version; });
- Checks::check_exit(
- VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instance with %s toolset.", *tsv);
- }
-
- if (vsp)
- {
- const fs::path vs_root_path = *vsp;
- Util::erase_remove_if(candidates,
- [&](const Toolset* t) { return vs_root_path != t->visual_studio_root_path; });
- Checks::check_exit(VCPKG_LINE_INFO,
- !candidates.empty(),
- "Could not find Visual Studio instance at %s.",
- vs_root_path.generic_string());
- }
-
- Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found");
- return *candidates.front();
-
-#endif
- }
-
- View<Toolset> VcpkgPaths::get_all_toolsets() const
- {
-#if defined(_WIN32)
- return m_pimpl->toolsets.get_lazy(
- [this]() { return VisualStudio::find_toolset_instances_preferred_first(*this); });
-#else
- return {};
-#endif
- }
-
- const System::Environment& VcpkgPaths::get_action_env(const Build::AbiInfo& abi_info) const
- {
- return m_pimpl->m_env_cache.get_action_env(*this, abi_info);
- }
-
- const std::string& VcpkgPaths::get_triplet_info(const Build::AbiInfo& abi_info) const
- {
- return m_pimpl->m_env_cache.get_triplet_info(*this, abi_info);
- }
-
- const Build::CompilerInfo& VcpkgPaths::get_compiler_info(const Build::AbiInfo& abi_info) const
- {
- return m_pimpl->m_env_cache.get_compiler_info(*this, abi_info);
- }
-
- Files::Filesystem& VcpkgPaths::get_filesystem() const { return *m_pimpl->fs_ptr; }
-
- const FeatureFlagSettings& VcpkgPaths::get_feature_flags() const { return m_pimpl->m_ff_settings; }
-
- void VcpkgPaths::track_feature_flag_metrics() const
- {
- struct
- {
- StringView flag;
- bool enabled;
- } flags[] = {{VcpkgCmdArguments::MANIFEST_MODE_FEATURE, manifest_mode_enabled()}};
-
- for (const auto& flag : flags)
- {
- Metrics::g_metrics.lock()->track_feature(flag.flag.to_string(), flag.enabled);
- }
- }
-
- VcpkgPaths::~VcpkgPaths()
- {
- std::error_code ec;
- if (m_pimpl->file_lock_handle.is_valid())
- {
- m_pimpl->fs_ptr->unlock_file_lock(m_pimpl->file_lock_handle, ec);
- if (ec)
- {
- Debug::print("Failed to unlock filesystem lock: ", ec.message(), '\n');
- }
- }
- }
-}
diff --git a/toolsrc/src/vcpkg/versiondeserializers.cpp b/toolsrc/src/vcpkg/versiondeserializers.cpp
deleted file mode 100644
index 2892aa567..000000000
--- a/toolsrc/src/vcpkg/versiondeserializers.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/versiondeserializers.h>
-
-using namespace vcpkg;
-using namespace vcpkg::Versions;
-
-namespace
-{
- constexpr StringLiteral BASELINE = "baseline";
- constexpr StringLiteral VERSION_RELAXED = "version";
- constexpr StringLiteral VERSION_SEMVER = "version-semver";
- constexpr StringLiteral VERSION_STRING = "version-string";
- constexpr StringLiteral VERSION_DATE = "version-date";
- constexpr StringLiteral PORT_VERSION = "port-version";
-
- struct VersionDeserializer final : Json::IDeserializer<std::string>
- {
- VersionDeserializer(StringLiteral type) : m_type(type) { }
- StringView type_name() const override { return m_type; }
-
- Optional<std::string> visit_string(Json::Reader& r, StringView sv) override
- {
- StringView pv(std::find(sv.begin(), sv.end(), '#'), sv.end());
- if (pv.size() == 1)
- {
- r.add_generic_error(type_name(), "invalid character '#' in version text");
- }
- else if (pv.size() > 1)
- {
- r.add_generic_error(type_name(),
- "invalid character '#' in version text. Did you mean \"port-version\": ",
- pv.substr(1),
- "?");
- }
- return sv.to_string();
- }
- StringLiteral m_type;
- };
-
- struct GenericVersionTDeserializer : Json::IDeserializer<VersionT>
- {
- GenericVersionTDeserializer(StringLiteral version_field) : m_version_field(version_field) { }
- StringView type_name() const override { return " a version object"; }
-
- Optional<VersionT> visit_object(Json::Reader& r, const Json::Object& obj) override
- {
- std::string version;
- int port_version = 0;
-
- static VersionDeserializer version_deserializer{"version"};
-
- r.required_object_field(type_name(), obj, m_version_field, version, version_deserializer);
- r.optional_object_field(obj, PORT_VERSION, port_version, Json::NaturalNumberDeserializer::instance);
-
- return VersionT{std::move(version), port_version};
- }
- StringLiteral m_version_field;
- };
-}
-
-namespace vcpkg
-{
- std::unique_ptr<Json::IDeserializer<std::string>> make_version_deserializer(StringLiteral type_name)
- {
- return std::make_unique<VersionDeserializer>(type_name);
- }
-
- SchemedVersion visit_required_schemed_deserializer(StringView parent_type, Json::Reader& r, const Json::Object& obj)
- {
- auto maybe_schemed_version = visit_optional_schemed_deserializer(parent_type, r, obj);
- if (auto p = maybe_schemed_version.get())
- {
- return std::move(*p);
- }
- else
- {
- r.add_generic_error(parent_type, "expected a versioning field (example: ", VERSION_STRING, ")");
- return {};
- }
- }
- Optional<SchemedVersion> visit_optional_schemed_deserializer(StringView parent_type,
- Json::Reader& r,
- const Json::Object& obj)
- {
- Versions::Scheme version_scheme = Versions::Scheme::String;
- std::string version;
- int port_version = 0;
-
- static VersionDeserializer version_exact_deserializer{"an exact version string"};
- static VersionDeserializer version_relaxed_deserializer{"a relaxed version string"};
- static VersionDeserializer version_semver_deserializer{"a semantic version string"};
- static VersionDeserializer version_date_deserializer{"a date version string"};
-
- bool has_exact = r.optional_object_field(obj, VERSION_STRING, version, version_exact_deserializer);
- bool has_relax = r.optional_object_field(obj, VERSION_RELAXED, version, version_relaxed_deserializer);
- bool has_semver = r.optional_object_field(obj, VERSION_SEMVER, version, version_semver_deserializer);
- bool has_date = r.optional_object_field(obj, VERSION_DATE, version, version_date_deserializer);
- int num_versions = (int)has_exact + (int)has_relax + (int)has_semver + (int)has_date;
- bool has_port_version =
- r.optional_object_field(obj, PORT_VERSION, port_version, Json::NaturalNumberDeserializer::instance);
-
- if (num_versions == 0)
- {
- if (!has_port_version)
- {
- return nullopt;
- }
- else
- {
- r.add_generic_error(parent_type, "unexpected \"port_version\" without a versioning field");
- }
- }
- else if (num_versions > 1)
- {
- r.add_generic_error(parent_type, "expected only one versioning field");
- }
- else
- {
- if (has_exact)
- {
- version_scheme = Versions::Scheme::String;
- }
- else if (has_relax)
- {
- version_scheme = Versions::Scheme::Relaxed;
- auto v = Versions::RelaxedVersion::from_string(version);
- if (!v.has_value())
- {
- r.add_generic_error(parent_type, "'version' text was not a relaxed version:\n", v.error());
- }
- }
- else if (has_semver)
- {
- version_scheme = Versions::Scheme::Semver;
- auto v = Versions::SemanticVersion::from_string(version);
- if (!v.has_value())
- {
- r.add_generic_error(parent_type, "'version-semver' text was not a semantic version:\n", v.error());
- }
- }
- else if (has_date)
- {
- version_scheme = Versions::Scheme::Date;
- auto v = Versions::DateVersion::from_string(version);
- if (!v.has_value())
- {
- r.add_generic_error(parent_type, "'version-date' text was not a date version:\n", v.error());
- }
- }
- else
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- return SchemedVersion(version_scheme, VersionT{version, port_version});
- }
-
- View<StringView> schemed_deserializer_fields()
- {
- static const StringView t[] = {VERSION_RELAXED, VERSION_SEMVER, VERSION_STRING, VERSION_DATE, PORT_VERSION};
- return t;
- }
-
- void serialize_schemed_version(Json::Object& out_obj,
- Versions::Scheme scheme,
- const std::string& version,
- int port_version,
- bool always_emit_port_version)
- {
- auto version_field = [](Versions::Scheme version_scheme) {
- switch (version_scheme)
- {
- case Versions::Scheme::String: return VERSION_STRING;
- case Versions::Scheme::Semver: return VERSION_SEMVER;
- case Versions::Scheme::Relaxed: return VERSION_RELAXED;
- case Versions::Scheme::Date: return VERSION_DATE;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- };
-
- out_obj.insert(version_field(scheme), Json::Value::string(version));
-
- if (port_version != 0 || always_emit_port_version)
- {
- out_obj.insert(PORT_VERSION, Json::Value::integer(port_version));
- }
- }
-
- Json::IDeserializer<VersionT>& get_versiont_deserializer_instance()
- {
- static GenericVersionTDeserializer deserializer(VERSION_STRING);
- return deserializer;
- }
-
- Json::IDeserializer<VersionT>& get_versiontag_deserializer_instance()
- {
- static GenericVersionTDeserializer deserializer(BASELINE);
- return deserializer;
- }
-}
diff --git a/toolsrc/src/vcpkg/versions.cpp b/toolsrc/src/vcpkg/versions.cpp
deleted file mode 100644
index 239c0e728..000000000
--- a/toolsrc/src/vcpkg/versions.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/versions.h>
-
-#include <regex>
-
-namespace vcpkg::Versions
-{
- namespace
- {
- Optional<uint64_t> as_numeric(StringView str)
- {
- uint64_t res = 0;
- size_t digits = 0;
- for (auto&& ch : str)
- {
- uint64_t digit_value = static_cast<unsigned char>(ch) - static_cast<unsigned char>('0');
- if (digit_value > 9) return nullopt;
- if (res > std::numeric_limits<uint64_t>::max() / 10 - digit_value) return nullopt;
- ++digits;
- res = res * 10 + digit_value;
- }
- return res;
- }
- }
-
- VersionSpec::VersionSpec(const std::string& port_name, const VersionT& version)
- : port_name(port_name), version(version)
- {
- }
-
- VersionSpec::VersionSpec(const std::string& port_name, const std::string& version_string, int port_version)
- : port_name(port_name), version(version_string, port_version)
- {
- }
-
- bool operator==(const VersionSpec& lhs, const VersionSpec& rhs)
- {
- return std::tie(lhs.port_name, lhs.version) == std::tie(rhs.port_name, rhs.version);
- }
-
- bool operator!=(const VersionSpec& lhs, const VersionSpec& rhs) { return !(lhs == rhs); }
-
- std::size_t VersionSpecHasher::operator()(const VersionSpec& key) const
- {
- using std::hash;
- using std::size_t;
- using std::string;
-
- return hash<string>()(key.port_name) ^ (hash<string>()(key.version.to_string()) >> 1);
- }
-
- ExpectedS<RelaxedVersion> RelaxedVersion::from_string(const std::string& str)
- {
- std::regex relaxed_scheme_match("^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*");
-
- if (!std::regex_match(str, relaxed_scheme_match))
- {
- return Strings::format(
- "Error: String `%s` must only contain dot-separated numeric values without leading zeroes.", str);
- }
-
- return RelaxedVersion{str, Util::fmap(Strings::split(str, '.'), [](auto&& strval) -> uint64_t {
- return as_numeric(strval).value_or_exit(VCPKG_LINE_INFO);
- })};
- }
-
- ExpectedS<SemanticVersion> SemanticVersion::from_string(const std::string& str)
- {
- // Suggested regex by semver.org
- std::regex semver_scheme_match("^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)"
- "(?:-((?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]"
- "*[a-zA-Z-][0-9a-zA-Z-]*))*))?"
- "(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
-
- if (!std::regex_match(str, semver_scheme_match))
- {
- return Strings::format(
- "Error: String `%s` is not a valid Semantic Version string, consult https://semver.org", str);
- }
-
- SemanticVersion ret;
- ret.original_string = str;
- ret.version_string = str;
-
- auto build_found = ret.version_string.find('+');
- if (build_found != std::string::npos)
- {
- ret.version_string.resize(build_found);
- }
-
- auto prerelease_found = ret.version_string.find('-');
- if (prerelease_found != std::string::npos)
- {
- ret.prerelease_string = ret.version_string.substr(prerelease_found + 1);
- ret.identifiers = Strings::split(ret.prerelease_string, '.');
- ret.version_string.resize(prerelease_found);
- }
-
- std::regex version_match("(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*)){2}");
- if (!std::regex_match(ret.version_string, version_match))
- {
- return Strings::format("Error: String `%s` does not follow the required MAJOR.MINOR.PATCH format.",
- ret.version_string);
- }
-
- auto parts = Strings::split(ret.version_string, '.');
- ret.version = Util::fmap(
- parts, [](auto&& strval) -> uint64_t { return as_numeric(strval).value_or_exit(VCPKG_LINE_INFO); });
-
- return ret;
- }
-
- ExpectedS<DateVersion> DateVersion::from_string(const std::string& str)
- {
- std::regex date_scheme_match("([0-9]{4}-[0-9]{2}-[0-9]{2})(\\.(0|[1-9][0-9]*))*");
- if (!std::regex_match(str, date_scheme_match))
- {
- return Strings::format("Error: String `%s` is not a valid date version."
- "Date section must follow the format YYYY-MM-DD and disambiguators must be "
- "dot-separated positive integer values without leading zeroes.",
- str);
- }
-
- DateVersion ret;
- ret.original_string = str;
- ret.version_string = str;
-
- auto identifiers_found = ret.version_string.find('.');
- if (identifiers_found != std::string::npos)
- {
- ret.identifiers_string = ret.version_string.substr(identifiers_found + 1);
- ret.identifiers = Util::fmap(Strings::split(ret.identifiers_string, '.'), [](auto&& strval) -> uint64_t {
- return as_numeric(strval).value_or_exit(VCPKG_LINE_INFO);
- });
- ret.version_string.resize(identifiers_found);
- }
-
- return ret;
- }
-
- VerComp compare(const std::string& a, const std::string& b, Scheme scheme)
- {
- if (scheme == Scheme::String)
- {
- return (a == b) ? VerComp::eq : VerComp::unk;
- }
- if (scheme == Scheme::Semver)
- {
- return compare(SemanticVersion::from_string(a).value_or_exit(VCPKG_LINE_INFO),
- SemanticVersion::from_string(b).value_or_exit(VCPKG_LINE_INFO));
- }
- if (scheme == Scheme::Relaxed)
- {
- return compare(RelaxedVersion::from_string(a).value_or_exit(VCPKG_LINE_INFO),
- RelaxedVersion::from_string(b).value_or_exit(VCPKG_LINE_INFO));
- }
- if (scheme == Scheme::Date)
- {
- return compare(DateVersion::from_string(a).value_or_exit(VCPKG_LINE_INFO),
- DateVersion::from_string(b).value_or_exit(VCPKG_LINE_INFO));
- }
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- VerComp compare(const RelaxedVersion& a, const RelaxedVersion& b)
- {
- if (a.original_string == b.original_string) return VerComp::eq;
-
- if (a.version < b.version) return VerComp::lt;
- if (a.version > b.version) return VerComp::gt;
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- VerComp compare(const SemanticVersion& a, const SemanticVersion& b)
- {
- if (a.version_string == b.version_string)
- {
- if (a.prerelease_string == b.prerelease_string) return VerComp::eq;
- if (a.prerelease_string.empty()) return VerComp::gt;
- if (b.prerelease_string.empty()) return VerComp::lt;
- }
-
- // Compare version elements left-to-right.
- if (a.version < b.version) return VerComp::lt;
- if (a.version > b.version) return VerComp::gt;
-
- // Compare identifiers left-to-right.
- auto count = std::min(a.identifiers.size(), b.identifiers.size());
- for (size_t i = 0; i < count; ++i)
- {
- auto&& iden_a = a.identifiers[i];
- auto&& iden_b = b.identifiers[i];
-
- auto a_numeric = as_numeric(iden_a);
- auto b_numeric = as_numeric(iden_b);
-
- // Numeric identifiers always have lower precedence than non-numeric identifiers.
- if (a_numeric.has_value() && !b_numeric.has_value()) return VerComp::lt;
- if (!a_numeric.has_value() && b_numeric.has_value()) return VerComp::gt;
-
- // Identifiers consisting of only digits are compared numerically.
- if (a_numeric.has_value() && b_numeric.has_value())
- {
- auto a_value = a_numeric.value_or_exit(VCPKG_LINE_INFO);
- auto b_value = b_numeric.value_or_exit(VCPKG_LINE_INFO);
-
- if (a_value < b_value) return VerComp::lt;
- if (a_value > b_value) return VerComp::gt;
- continue;
- }
-
- // Identifiers with letters or hyphens are compared lexically in ASCII sort order.
- auto strcmp_result = std::strcmp(iden_a.c_str(), iden_b.c_str());
- if (strcmp_result < 0) return VerComp::lt;
- if (strcmp_result > 0) return VerComp::gt;
- }
-
- // A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding
- // identifiers are equal.
- if (a.identifiers.size() < b.identifiers.size()) return VerComp::lt;
- if (a.identifiers.size() > b.identifiers.size()) return VerComp::gt;
-
- // This should be unreachable since direct string comparisons of version_string and prerelease_string should
- // handle this case. If we ever land here, then there's a bug in the the parsing on
- // SemanticVersion::from_string().
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- VerComp compare(const Versions::DateVersion& a, const Versions::DateVersion& b)
- {
- if (a.version_string == b.version_string)
- {
- if (a.identifiers_string == b.identifiers_string) return VerComp::eq;
- if (a.identifiers_string.empty() && !b.identifiers_string.empty()) return VerComp::lt;
- if (!a.identifiers_string.empty() && b.identifiers_string.empty()) return VerComp::gt;
- }
-
- // The date parts in our scheme is lexicographically sortable.
- if (a.version_string < b.version_string) return VerComp::lt;
- if (a.version_string > b.version_string) return VerComp::gt;
- if (a.identifiers < b.identifiers) return VerComp::lt;
- if (a.identifiers > b.identifiers) return VerComp::gt;
-
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-}
diff --git a/toolsrc/src/vcpkg/versiont.cpp b/toolsrc/src/vcpkg/versiont.cpp
deleted file mode 100644
index 09dabb450..000000000
--- a/toolsrc/src/vcpkg/versiont.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <vcpkg/base/strings.h>
-
-#include <vcpkg/versiont.h>
-
-namespace vcpkg
-{
- VersionT::VersionT() noexcept : m_text("0.0.0"), m_port_version(0) { }
- VersionT::VersionT(std::string&& value, int port_version) : m_text(std::move(value)), m_port_version(port_version)
- {
- }
- VersionT::VersionT(const std::string& value, int port_version) : m_text(value), m_port_version(port_version) { }
-
- std::string VersionT::to_string() const { return Strings::concat(*this); }
- void VersionT::to_string(std::string& out) const
- {
- out.append(m_text);
- if (m_port_version) Strings::append(out, '#', m_port_version);
- }
-
- bool operator==(const VersionT& left, const VersionT& right)
- {
- return left.m_port_version == right.m_port_version && left.m_text == right.m_text;
- }
- bool operator!=(const VersionT& left, const VersionT& right) { return !(left == right); }
-
- bool VersionTMapLess::operator()(const VersionT& left, const VersionT& right) const
- {
- auto cmp = left.m_text.compare(right.m_text);
- if (cmp < 0)
- {
- return true;
- }
- else if (cmp > 0)
- {
- return false;
- }
-
- return left.m_port_version < right.m_port_version;
- }
-
- VersionDiff::VersionDiff() noexcept : left(), right() { }
- VersionDiff::VersionDiff(const VersionT& left, const VersionT& right) : left(left), right(right) { }
-
- std::string VersionDiff::to_string() const
- {
- return Strings::format("%s -> %s", left.to_string(), right.to_string());
- }
-}
diff --git a/toolsrc/src/vcpkg/visualstudio.cpp b/toolsrc/src/vcpkg/visualstudio.cpp
deleted file mode 100644
index b1b289191..000000000
--- a/toolsrc/src/vcpkg/visualstudio.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-#if defined(_WIN32)
-
-#include <vcpkg/base/sortedvector.h>
-#include <vcpkg/base/strings.h>
-#include <vcpkg/base/stringview.h>
-#include <vcpkg/base/system.print.h>
-#include <vcpkg/base/system.process.h>
-#include <vcpkg/base/util.h>
-
-#include <vcpkg/visualstudio.h>
-
-namespace vcpkg::VisualStudio
-{
- static constexpr CStringView V_120 = "v120";
- static constexpr CStringView V_140 = "v140";
- static constexpr CStringView V_141 = "v141";
- static constexpr CStringView V_142 = "v142";
-
- struct VisualStudioInstance
- {
- enum class ReleaseType
- {
- STABLE,
- PRERELEASE,
- LEGACY
- };
-
- static std::string release_type_to_string(const ReleaseType& release_type)
- {
- switch (release_type)
- {
- case ReleaseType::STABLE: return "STABLE";
- case ReleaseType::PRERELEASE: return "PRERELEASE";
- case ReleaseType::LEGACY: return "LEGACY";
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
-
- static bool preferred_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right)
- {
- const auto get_preference_weight = [](const ReleaseType& type) -> int {
- switch (type)
- {
- case ReleaseType::STABLE: return 3;
- case ReleaseType::PRERELEASE: return 2;
- case ReleaseType::LEGACY: return 1;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- };
-
- if (left.release_type != right.release_type)
- {
- return get_preference_weight(left.release_type) > get_preference_weight(right.release_type);
- }
-
- return left.version > right.version;
- }
-
- VisualStudioInstance(fs::path&& root_path, std::string&& version, const ReleaseType& release_type)
- : root_path(std::move(root_path)), version(std::move(version)), release_type(release_type)
- {
- }
-
- fs::path root_path;
- std::string version;
- ReleaseType release_type;
-
- std::string to_string() const
- {
- return Strings::format(
- "%s, %s, %s", fs::u8string(root_path), version, release_type_to_string(release_type));
- }
-
- std::string major_version() const { return version.substr(0, 2); }
- };
-
- static std::vector<VisualStudioInstance> get_visual_studio_instances_internal(const VcpkgPaths& paths)
- {
- const auto& fs = paths.get_filesystem();
- std::vector<VisualStudioInstance> instances;
-
- const auto& program_files_32_bit = System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO);
-
- // Instances from vswhere
- const fs::path vswhere_exe = program_files_32_bit / "Microsoft Visual Studio" / "Installer" / "vswhere.exe";
- if (fs.exists(vswhere_exe))
- {
- const auto code_and_output = System::cmd_execute_and_capture_output(System::Command(vswhere_exe)
- .string_arg("-all")
- .string_arg("-prerelease")
- .string_arg("-legacy")
- .string_arg("-products")
- .string_arg("*")
- .string_arg("-format")
- .string_arg("xml"));
- Checks::check_exit(VCPKG_LINE_INFO,
- code_and_output.exit_code == 0,
- "Running vswhere.exe failed with message:\n%s",
- code_and_output.output);
-
- const auto instance_entries =
- Strings::find_all_enclosed(code_and_output.output, "<instance>", "</instance>");
- for (const StringView& instance : instance_entries)
- {
- auto maybe_is_prerelease =
- Strings::find_at_most_one_enclosed(instance, "<isPrerelease>", "</isPrerelease>");
-
- VisualStudioInstance::ReleaseType release_type = VisualStudioInstance::ReleaseType::LEGACY;
- if (const auto p = maybe_is_prerelease.get())
- {
- const auto s = p->to_string();
- if (s == "0")
- release_type = VisualStudioInstance::ReleaseType::STABLE;
- else if (s == "1")
- release_type = VisualStudioInstance::ReleaseType::PRERELEASE;
- else
- Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- instances.emplace_back(
- Strings::find_exactly_one_enclosed(instance, "<installationPath>", "</installationPath>")
- .to_string(),
- Strings::find_exactly_one_enclosed(instance, "<installationVersion>", "</installationVersion>")
- .to_string(),
- release_type);
- }
- }
-
- // VS2019 instance from environment variable
- auto maybe_vs160_comntools = System::get_environment_variable("vs160comntools");
- if (const auto path_as_string = maybe_vs160_comntools.get())
- {
- // We want lexically_normal(), but it is not available
- // Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash.
- auto common7_tools = fs::u8path(*path_as_string);
- if (common7_tools.filename().empty())
- instances.emplace_back(common7_tools.parent_path().parent_path().parent_path(),
- "16.0",
- VisualStudioInstance::ReleaseType::LEGACY);
- else
- instances.emplace_back(
- common7_tools.parent_path().parent_path(), "16.0", VisualStudioInstance::ReleaseType::LEGACY);
- }
-
- const auto append_if_has_cl_vs140 = [&](fs::path&& path_root) {
- const auto cl_exe = path_root / "VC" / "bin" / "cl.exe";
- const auto vcvarsall_bat = path_root / "VC" / "vcvarsall.bat";
-
- if (fs.exists(cl_exe) && fs.exists(vcvarsall_bat))
- instances.emplace_back(std::move(path_root), "14.0", VisualStudioInstance::ReleaseType::LEGACY);
- };
-
- // VS2015 instance from environment variable
- auto maybe_vs140_comntools = System::get_environment_variable("vs140comntools");
- if (const auto path_as_string = maybe_vs140_comntools.get())
- {
- // We want lexically_normal(), but it is not available
- // Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash.
- auto common7_tools = fs::u8path(*path_as_string);
- if (common7_tools.filename().empty())
- append_if_has_cl_vs140(common7_tools.parent_path().parent_path().parent_path());
- else
- append_if_has_cl_vs140(common7_tools.parent_path().parent_path());
- }
-
- // VS2015 instance from Program Files
- append_if_has_cl_vs140(program_files_32_bit / "Microsoft Visual Studio 14.0");
-
- return instances;
- }
-
- std::vector<std::string> get_visual_studio_instances(const VcpkgPaths& paths)
- {
- std::vector<VisualStudioInstance> sorted{get_visual_studio_instances_internal(paths)};
- std::sort(sorted.begin(), sorted.end(), VisualStudioInstance::preferred_first_comparator);
- return Util::fmap(sorted, [](const VisualStudioInstance& instance) { return instance.to_string(); });
- }
-
- std::vector<Toolset> find_toolset_instances_preferred_first(const VcpkgPaths& paths)
- {
- using CPU = System::CPUArchitecture;
-
- const auto& fs = paths.get_filesystem();
-
- // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations.
- std::vector<fs::path> paths_examined;
-
- std::vector<Toolset> found_toolsets;
- std::vector<Toolset> excluded_toolsets;
-
- const SortedVector<VisualStudioInstance> sorted{get_visual_studio_instances_internal(paths),
- VisualStudioInstance::preferred_first_comparator};
-
- const bool v140_is_available = Util::find_if(sorted, [&](const VisualStudioInstance& vs_instance) {
- return vs_instance.major_version() == "14";
- }) != sorted.end();
-
- for (const VisualStudioInstance& vs_instance : sorted)
- {
- const std::string major_version = vs_instance.major_version();
- if (major_version >= "15")
- {
- const fs::path vc_dir = vs_instance.root_path / "VC";
-
- // Skip any instances that do not have vcvarsall.
- const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build";
- const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat";
- paths_examined.push_back(vcvarsall_bat);
- if (!fs.exists(vcvarsall_bat)) continue;
-
- // Get all supported architectures
- std::vector<ToolsetArchOption> supported_architectures;
- if (fs.exists(vcvarsall_dir / "vcvars32.bat"))
- supported_architectures.push_back({"x86", CPU::X86, CPU::X86});
- if (fs.exists(vcvarsall_dir / "vcvars64.bat"))
- supported_architectures.push_back({"amd64", CPU::X64, CPU::X64});
- if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat"))
- supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64});
- if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat"))
- supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM});
- if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat"))
- supported_architectures.push_back({"x86_arm64", CPU::X86, CPU::ARM64});
- if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat"))
- supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86});
- if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat"))
- supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM});
- if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat"))
- supported_architectures.push_back({"amd64_arm64", CPU::X64, CPU::ARM64});
-
- // Locate the "best" MSVC toolchain version
- const fs::path msvc_path = vc_dir / "Tools" / "MSVC";
- std::vector<fs::path> msvc_subdirectories = fs.get_files_non_recursive(msvc_path);
- Util::erase_remove_if(msvc_subdirectories,
- [&fs](const fs::path& path) { return !fs.is_directory(path); });
-
- // Sort them so that latest comes first
- std::sort(
- msvc_subdirectories.begin(),
- msvc_subdirectories.end(),
- [](const fs::path& left, const fs::path& right) { return left.filename() > right.filename(); });
-
- for (const fs::path& subdir : msvc_subdirectories)
- {
- auto toolset_version_full = fs::u8string(subdir.filename());
- auto toolset_version_prefix = toolset_version_full.substr(0, 4);
- CStringView toolset_version;
- std::string vcvars_option;
- if (toolset_version_prefix.size() != 4)
- {
- // unknown toolset
- continue;
- }
- else if (toolset_version_prefix[3] == '1')
- {
- toolset_version = V_141;
- vcvars_option = "-vcvars_ver=14.1";
- }
- else if (toolset_version_prefix[3] == '2')
- {
- toolset_version = V_142;
- vcvars_option = "-vcvars_ver=14.2";
- }
- else
- {
- // unknown toolset minor version
- continue;
- }
- const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe";
- paths_examined.push_back(dumpbin_path);
- if (fs.exists(dumpbin_path))
- {
- Toolset toolset{vs_instance.root_path,
- dumpbin_path,
- vcvarsall_bat,
- {vcvars_option},
- toolset_version,
- supported_architectures};
-
- const auto english_language_pack = dumpbin_path.parent_path() / "1033";
-
- if (!fs.exists(english_language_pack))
- {
- excluded_toolsets.push_back(std::move(toolset));
- continue;
- }
-
- found_toolsets.push_back(std::move(toolset));
-
- if (v140_is_available)
- {
- found_toolsets.push_back({vs_instance.root_path,
- dumpbin_path,
- vcvarsall_bat,
- {"-vcvars_ver=14.0"},
- V_140,
- supported_architectures});
- }
-
- continue;
- }
- }
-
- continue;
- }
-
- if (major_version == "14" || major_version == "12")
- {
- const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat";
-
- paths_examined.push_back(vcvarsall_bat);
- if (fs.exists(vcvarsall_bat))
- {
- const fs::path vs_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe";
- paths_examined.push_back(vs_dumpbin_exe);
-
- const fs::path vs_bin_dir = vcvarsall_bat.parent_path() / "bin";
- std::vector<ToolsetArchOption> supported_architectures;
- if (fs.exists(vs_bin_dir / "vcvars32.bat"))
- supported_architectures.push_back({"x86", CPU::X86, CPU::X86});
- if (fs.exists(vs_bin_dir / "amd64\\vcvars64.bat"))
- supported_architectures.push_back({"x64", CPU::X64, CPU::X64});
- if (fs.exists(vs_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat"))
- supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64});
- if (fs.exists(vs_bin_dir / "x86_arm\\vcvarsx86_arm.bat"))
- supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM});
- if (fs.exists(vs_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat"))
- supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86});
- if (fs.exists(vs_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat"))
- supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM});
-
- if (fs.exists(vs_dumpbin_exe))
- {
- const Toolset toolset = {vs_instance.root_path,
- vs_dumpbin_exe,
- vcvarsall_bat,
- {},
- major_version == "14" ? V_140 : V_120,
- supported_architectures};
-
- const auto english_language_pack = vs_dumpbin_exe.parent_path() / "1033";
-
- if (!fs.exists(english_language_pack))
- {
- excluded_toolsets.push_back(toolset);
- break;
- }
-
- found_toolsets.push_back(toolset);
- }
- }
- }
- }
-
- if (!excluded_toolsets.empty())
- {
- System::print2(
- System::Color::warning,
- "Warning: The following VS instances are excluded because the English language pack is unavailable.\n");
- for (const Toolset& toolset : excluded_toolsets)
- {
- System::print2(" ", fs::u8string(toolset.visual_studio_root_path), '\n');
- }
- System::print2(System::Color::warning, "Please install the English language pack.\n");
- }
-
- if (found_toolsets.empty())
- {
- System::print2(System::Color::error, "Could not locate a complete toolset.\n");
- System::print2("The following paths were examined:\n");
- for (const fs::path& path : paths_examined)
- {
- System::print2(" ", fs::u8string(path), '\n');
- }
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
-
- return found_toolsets;
- }
-}
-
-#endif