From 051a6fd5b3d83fedc83592236413c9b8c0015c6d Mon Sep 17 00:00:00 2001 From: Phil Christensen Date: Wed, 21 Aug 2019 13:48:47 -0700 Subject: [boost] split Build-Depends on multipls lines --- toolsrc/src/vcpkg/parse.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index 0509339c5..8f90aef15 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -44,6 +44,11 @@ namespace vcpkg::Parse return nullptr; } + static bool is_whitespace(char c) + { + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; + } + std::vector parse_comma_list(const std::string& str) { if (str.empty()) @@ -66,7 +71,7 @@ namespace vcpkg::Parse // skip comma and space ++pos; - while (str[pos] == ' ') + while (is_whitespace(str[pos])) { ++pos; } -- cgit v1.2.3 From cc35672763a340b4d6d836a2b9e4ec0e3d703e50 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Tue, 20 Aug 2019 18:43:51 -0700 Subject: =?UTF-8?q?(#7798)=20[vcpkg]=20Fix=20the=20build=20on=20FreeBSD=20?= =?UTF-8?q?=F0=9F=98=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a `#else` line to `toolsrc/src/vcpkg/base/files.cpp`. On Linux and macOS, there are specific ways to copy from file descriptor to file descriptor, but on FreeBSD there isn't (as far as I could tell). This change does a copy using the POSIX standard `read` and `write` calls. (This change was to `RealFilesystem::rename_or_copy`). We expect to have people on FreeBSD install CMake themselves, and use `./bootstrap.sh -useSystemBinaries`, in order to build vcpkg. Since CMake 3.15.2 exists in the FreeBSD 12 (latest stable) package manager, it's trivial to install it. --- toolsrc/src/vcpkg/base/files.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index bbf37fd25..5ebe8d834 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -8,9 +8,8 @@ #include #include -#if defined(__linux__) || defined(__APPLE__) +#if !defined(_WIN32) #include -#include #include #include #include @@ -396,7 +395,7 @@ namespace vcpkg::Files { this->rename(oldpath, newpath, ec); Util::unused(temp_suffix); -#if defined(__linux__) || defined(__APPLE__) +#if !defined(_WIN32) if (ec) { auto dst = newpath; @@ -419,6 +418,33 @@ namespace vcpkg::Files 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 + ssize_t written_bytes = 0; + { + constexpr std::size_t buffer_length = 4096; + auto buffer = std::make_unique(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 if (written_bytes == -1) { -- cgit v1.2.3 From 13c95f16bfab4e516d088e15a1e77733b3f8745f Mon Sep 17 00:00:00 2001 From: Phil Christensen Date: Fri, 23 Aug 2019 10:20:18 -0700 Subject: clean up list parsing logic and add clear warnings --- toolsrc/src/vcpkg/parse.cpp | 88 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 20 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index 8f90aef15..91b2b2786 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace vcpkg::Parse { @@ -58,26 +59,73 @@ namespace vcpkg::Parse std::vector out; - size_t cur = 0; - do - { - auto pos = str.find(',', cur); - if (pos == std::string::npos) - { - out.push_back(str.substr(cur)); - break; - } - out.push_back(str.substr(cur, pos - cur)); - - // skip comma and space - ++pos; - while (is_whitespace(str[pos])) - { - ++pos; - } - - cur = pos; - } while (cur != std::string::npos); + auto iter = str.cbegin(); + + do { + // Trim leading whitespace of each element + while (iter != str.cend() && is_whitespace(*iter)) + { + ++iter; + } + + // Allow commas inside of []. + bool bracket_nesting = false; + + auto element_begin = iter; + auto element_end = iter; + while (iter != str.cend() && (*iter != ',' || bracket_nesting)) + { + char value = *iter; + + // do not support nested [] + if (value == '[') + { + bracket_nesting = true; + } + else if (value == ']') + { + bracket_nesting = false; + } + + ++iter; + + // Trim ending whitespace + if (!is_whitespace(value)) + { + // Update element_end after iter is incremented so it will be one past. + element_end = iter; + } + } + + if (element_begin == element_end) + { + System::print2( System::Color::warning, + "Warning: empty element in list\n" + "> '", str, "'\n" + "> ", std::string(static_cast(element_begin - str.cbegin()), ' '), "^\n" + ); + } + else + { + out.push_back({ element_begin, element_end }); + } + + if (iter != str.cend()) + { + //Not at the end, must be at a comma that needs to be stepped over + ++iter; + + if (iter == str.end()) + { + System::print2(System::Color::warning, + "Warning: empty element in list\n" + "> '", str, "'\n" + "> ", std::string(str.length(), ' '), "^\n" + ); + } + } + + } while (iter != str.cend()); return out; } -- cgit v1.2.3 From 373aeff92288b6e0bb49db2db98432229a2c9988 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 24 Aug 2019 13:01:57 -0700 Subject: [vcpkg] Move do_build_package_and_clean_buildtrees() above generating cpkg_abi_info.txt so it will be included in the package. (#7864) --- toolsrc/src/vcpkg/build.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index aeb01b27d..a2e90f33b 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -872,14 +872,14 @@ namespace vcpkg::Build System::printf("Could not locate cached archive: %s\n", archive_path.u8string()); } + ExtendedBuildResult result = do_build_package_and_clean_buildtrees( + paths, pre_build_info, spec, pre_build_info.public_abi_override.value_or(abi_tag_and_file->tag), config); + fs.create_directories(abi_package_dir, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Coud not create directory %s", abi_package_dir.u8string()); fs.copy_file(abi_tag_and_file->tag_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string()); - ExtendedBuildResult result = do_build_package_and_clean_buildtrees( - paths, pre_build_info, spec, pre_build_info.public_abi_override.value_or(abi_tag_and_file->tag), config); - if (config.build_package_options.binary_caching == BinaryCaching::YES && result.code == BuildResult::SUCCEEDED) { const auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); -- cgit v1.2.3 From 782723959399a1a0725ac4921b1b7a7c9d10baf7 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 8 Aug 2019 16:14:59 -0700 Subject: =?UTF-8?q?(#7757)=20[vcpkg]=20Switch=20to=20internal=20hash=20alg?= =?UTF-8?q?orithms=20=F0=9F=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On non-Windows platforms, there is no standard way to get the hash of an item -- before this PR, what we did was check for the existence of a few common utility names (shasum, sha1, sha256, sha512), and then call that utility on a file we created containing the contents we wish to hash. This PR adds internal hashers for sha1, sha256, and sha512, and standardizes the interface to allow anyone to implement hashers in the future. These hashers are not extremely optimized, so it's likely that in the future we could get more optimized, but for now we just call out to BCryptHasher on Windows, since it's standard and easy to use (and about 2x faster for sha1 and sha256, and 1.5x faster for sha512). However, they are reasonably fast for being unoptimized. I attempted a few minor optimizations, which actually made the code slower! So as of right now, it's implemented as just a basic conversion of the code on Wikipedia to C++. I have tested these on the standard NIST test vectors (and those test vectors are located in vcpkg-test/hash.cpp). --- toolsrc/src/vcpkg-test/hash.cpp | 276 +++++++++++ toolsrc/src/vcpkg/base/downloads.cpp | 2 +- toolsrc/src/vcpkg/base/hash.cpp | 830 +++++++++++++++++++++++++++------- toolsrc/src/vcpkg/base/stringview.cpp | 6 +- toolsrc/src/vcpkg/build.cpp | 29 +- toolsrc/src/vcpkg/commands.cpp | 11 +- toolsrc/src/vcpkg/metrics.cpp | 2 +- 7 files changed, 984 insertions(+), 172 deletions(-) create mode 100644 toolsrc/src/vcpkg-test/hash.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg-test/hash.cpp b/toolsrc/src/vcpkg-test/hash.cpp new file mode 100644 index 000000000..9f3ccc25e --- /dev/null +++ b/toolsrc/src/vcpkg-test/hash.cpp @@ -0,0 +1,276 @@ +#include + +#include + +#include +#include +#include +#include + +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(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 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(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/base/downloads.cpp b/toolsrc/src/vcpkg/base/downloads.cpp index 4bb2178e5..df6b1be09 100644 --- a/toolsrc/src/vcpkg/base/downloads.cpp +++ b/toolsrc/src/vcpkg/base/downloads.cpp @@ -127,7 +127,7 @@ namespace vcpkg::Downloads const fs::path& path, const std::string& sha512) { - std::string actual_hash = vcpkg::Hash::get_file_hash(fs, path, "SHA512"); + std::string actual_hash = vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO, fs, path, Hash::Algorithm::Sha512); // // This is the NEW hash for 7zip diff --git a/toolsrc/src/vcpkg/base/hash.cpp b/toolsrc/src/vcpkg/base/hash.cpp index 62a01ed17..11df3e329 100644 --- a/toolsrc/src/vcpkg/base/hash.cpp +++ b/toolsrc/src/vcpkg/base/hash.cpp @@ -14,238 +14,758 @@ #ifndef NT_SUCCESS #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #endif + #endif namespace vcpkg::Hash { - static void verify_has_only_allowed_chars(const std::string& s) + using uchar = unsigned char; + + Optional 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 { - static const std::regex ALLOWED_CHARS{"^[a-zA-Z0-9-]*$"}; - Checks::check_exit(VCPKG_LINE_INFO, - std::regex_match(s, ALLOWED_CHARS), - "Only alphanumeric chars and dashes are currently allowed. String was:\n" - " % s", - s); + 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); + } } -#if defined(_WIN32) + namespace { - std::string to_hex(const unsigned char* string, const size_t bytes) + struct UInt128 { - static constexpr char HEX_MAP[] = "0123456789abcdef"; + std::uint64_t top; + std::uint64_t bottom; - std::string output; - output.resize(2 * bytes); + UInt128() = default; + UInt128(std::uint64_t value) : top(0), bottom(value) {} - size_t current_char = 0; - for (size_t i = 0; i < bytes; i++) + 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); + } + + return *this; + } + + 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); + } + + return *this; + } + + UInt128& operator+=(std::size_t lhs) noexcept + { + // bottom + lhs > uint64::max + if (bottom > std::numeric_limits::max() - lhs) + { + top += 1; + } + bottom += lhs; + return *this; + } + }; + + } + template + void top_bits(T) = delete; + + static constexpr uchar top_bits(uchar x) noexcept { return x; } + static constexpr uchar top_bits(std::uint32_t x) noexcept { return (x >> 24) & 0xFF; } + static constexpr uchar top_bits(std::uint64_t x) noexcept { return (x >> 56) & 0xFF; } + static constexpr uchar top_bits(UInt128 x) noexcept { return top_bits(x.top); } + + // treats UIntTy as big endian for the purpose of this mapping + template + 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 <<= 8; + } + + for (const auto byte : buff) { // high - output[current_char] = HEX_MAP[(string[i] & 0xF0) >> 4]; - ++current_char; + output[output_index] = HEX_MAP[(byte & 0xF0) >> 4]; + ++output_index; // low - output[current_char] = HEX_MAP[(string[i] & 0x0F)]; - ++current_char; + output[output_index] = HEX_MAP[byte & 0x0F]; + ++output_index; } - - return output; } - class BCryptHasher + return output; + } + + namespace + { +#if defined(_WIN32) + BCRYPT_ALG_HANDLE get_alg_handle(LPCWSTR algorithm_identifier) noexcept { - struct BCryptAlgorithmHandle : Util::ResourceBase + BCRYPT_ALG_HANDLE result; + auto error = BCryptOpenAlgorithmProvider(&result, algorithm_identifier, nullptr, 0); + if (!NT_SUCCESS(error)) { - BCRYPT_ALG_HANDLE handle = nullptr; + Checks::exit_with_message(VCPKG_LINE_INFO, "Failure to open algorithm: %ls", algorithm_identifier); + } + + return result; + } - ~BCryptAlgorithmHandle() + 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) { - if (handle) BCryptCloseAlgorithmProvider(handle, 0); + 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::exit_with_message(VCPKG_LINE_INFO, "Unknown algorithm"); } - }; - struct BCryptHashHandle : Util::ResourceBase + clear(); + } + + virtual void add_bytes(const void* start_, const void* end_) noexcept override { - BCRYPT_HASH_HANDLE handle = nullptr; + // BCryptHashData takes its input as non-const, but does not modify it + uchar* start = const_cast(static_cast(start_)); + const uchar* end = static_cast(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::max(); + Checks::check_exit(VCPKG_LINE_INFO, end - start <= max); +#endif - ~BCryptHashHandle() - { - if (handle) BCryptDestroyHash(handle); - } - }; + const auto length = static_cast(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"); + } - static void initialize_hash_handle(BCryptHashHandle& hash_handle, - const BCryptAlgorithmHandle& algorithm_handle) + virtual void clear() noexcept override { - const NTSTATUS error_code = - BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); + 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"); } - static void hash_data(BCryptHashHandle& hash_handle, const unsigned char* buffer, const size_t& data_size) + virtual std::string get_hash() noexcept override { - const NTSTATUS error_code = BCryptHashData( - hash_handle.handle, const_cast(buffer), static_cast(data_size), 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + const auto hash_size = get_hash_buffer_size(); + const auto buffer = std::make_unique(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); } - static std::string finalize_hash_handle(const BCryptHashHandle& hash_handle, const ULONG length_in_bytes) + ~BCryptHasher() { BCryptDestroyHash(hash_handle); } + + private: + unsigned long get_hash_buffer_size() const { - std::unique_ptr hash_buffer = std::make_unique(length_in_bytes); - const NTSTATUS error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); - return to_hex(hash_buffer.get(), length_in_bytes); - } - - public: - explicit BCryptHasher(std::string hash_type) - { - NTSTATUS error_code = BCryptOpenAlgorithmProvider( - &this->algorithm_handle.handle, - Strings::to_utf16(Strings::ascii_to_uppercase(std::move(hash_type))).c_str(), - nullptr, - 0); - Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); - - DWORD hash_buffer_bytes; - DWORD cb_data; - error_code = BCryptGetProperty(this->algorithm_handle.handle, - BCRYPT_HASH_LENGTH, - reinterpret_cast(&hash_buffer_bytes), - sizeof(DWORD), - &cb_data, - 0); + unsigned long hash_buffer_bytes; + unsigned long cb_data; + const NTSTATUS error_code = BCryptGetProperty(alg_handle, + BCRYPT_HASH_LENGTH, + reinterpret_cast(&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"); - this->length_in_bytes = hash_buffer_bytes; + + return hash_buffer_bytes; } - std::string hash_file(const fs::path& path) const - { - BCryptHashHandle hash_handle; - initialize_hash_handle(hash_handle, this->algorithm_handle); + 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 + 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 + struct ShaHasher final : Hasher + { + ShaHasher() = default; - FILE* file = nullptr; - const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); - Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string()); - if (file != nullptr) + virtual void add_bytes(const void* start, const void* end) noexcept override + { + for (;;) { - unsigned char buffer[4096]; - while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + start = add_to_unprocessed(start, end); + if (!start) { - hash_data(hash_handle, buffer, actual_size); + break; // done } - fclose(file); + + m_impl.process_full_chunk(m_chunk); + m_current_chunk_size = 0; } + } + + virtual void clear() noexcept override + { + m_impl.clear(); - return finalize_hash_handle(hash_handle, length_in_bytes); + // m_chunk is theoretically uninitialized, so no need to reset it + m_current_chunk_size = 0; + m_message_length = 0; } - std::string hash_string(const std::string& s) const + virtual std::string get_hash() noexcept override { - BCryptHashHandle hash_handle; - initialize_hash_handle(hash_handle, this->algorithm_handle); - hash_data(hash_handle, reinterpret_cast(s.c_str()), s.size()); - return finalize_hash_handle(hash_handle, length_in_bytes); + process_last_chunk(); + return to_hex(m_impl.begin(), m_impl.end()); } private: - BCryptAlgorithmHandle algorithm_handle; - ULONG length_in_bytes; - }; - } + // 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(start_); + const uchar* end = static_cast(end_); - std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type) - { - Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string()); - return BCryptHasher{hash_type}.hash_file(path); - } + const auto remaining = chunk_size - m_current_chunk_size; - std::string get_string_hash(const std::string& s, const std::string& hash_type) - { - verify_has_only_allowed_chars(s); - return BCryptHasher{hash_type}.hash_string(s); - } + 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; + } + } -#else - static std::string get_digest_size(const std::string& hash_type) - { - if (!Strings::case_insensitive_ascii_starts_with(hash_type, "SHA")) + // 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(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(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 m_chunk{}; + std::size_t m_current_chunk_size = 0; + message_length_type m_message_length = 0; + }; + template + inline void sha_fill_initial_words(const uchar* chunk, WordTy* words) { - Checks::exit_with_message( - VCPKG_LINE_INFO, "shasum only supports SHA hashes, but %s was provided", hash_type); + // 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(8 * (sizeof(WordTy) - 1 - byte)); + words[word] |= shl(chunk[word * sizeof(WordTy) + byte], bits_to_shift); + } + } } - return hash_type.substr(3, hash_type.length() - 3); - } + 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; - static std::string parse_shasum_output(const std::string& shasum_output) - { - std::vector split = Strings::split(shasum_output, " "); - // Checking if >= 3 because filenames with spaces will show up as multiple tokens. - // The hash is the first token so we don't need to parse the filename anyway. - Checks::check_exit(VCPKG_LINE_INFO, - split.size() >= 3, - "Expected output of the form [hash filename\n] (3+ tokens), but got\n" - "[%s] (%s tokens)", - shasum_output, - std::to_string(split.size())); - - return split[0]; - } + Sha1Algorithm() noexcept { clear(); } - std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type) - { - const std::string digest_size = get_digest_size(hash_type); - Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string()); + void process_full_chunk(const std::array& 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; + } - // Try hash-specific tools, like sha512sum + 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 { - const auto ec_data = System::cmd_execute_and_capture_output( - Strings::format(R"(sha%ssum "%s")", digest_size, path.u8string())); - if (ec_data.exit_code == 0) + 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& chunk) noexcept { - return parse_shasum_output(ec_data.output); + 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]; + } } - } - // Try shasum + 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 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 { - const auto ec_data = System::cmd_execute_and_capture_output( - Strings::format(R"(shasum -a %s "%s")", digest_size, path.u8string())); - if (ec_data.exit_code == 0) + 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& 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 { - return parse_shasum_output(ec_data.output); + 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; } - } - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not hash file %s with %s", path.u8string(), hash_type); + constexpr static std::array 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 Sha256Algorithm::round_constants; + constexpr std::array Sha512Algorithm::round_constants; +#endif } - std::string get_string_hash(const std::string& s, const std::string& hash_type) + std::unique_ptr get_hasher_for(Algorithm algo) noexcept { - const std::string digest_size = get_digest_size(hash_type); - verify_has_only_allowed_chars(s); +#if defined(_WIN32) + return std::make_unique(algo); +#else + switch (algo) + { + case Algorithm::Sha1: return std::make_unique>(); + case Algorithm::Sha256: return std::make_unique>(); + case Algorithm::Sha512: return std::make_unique>(); + default: vcpkg::Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown hashing algorithm: %s", algo); + } +#endif + } - // Try hash-specific tools, like sha512sum + template + static std::string do_hash(Algorithm algo, const F& f) noexcept + { +#if defined(_WIN32) + auto hasher = BCryptHasher(algo); + return f(hasher); +#else + switch (algo) { - const auto ec_data = - System::cmd_execute_and_capture_output(Strings::format(R"(echo -n "%s" | sha%ssum)", s, digest_size)); - if (ec_data.exit_code == 0) + case Algorithm::Sha1: + { + auto hasher = ShaHasher(); + return f(hasher); + } + case Algorithm::Sha256: + { + auto hasher = ShaHasher(); + return f(hasher); + } + case Algorithm::Sha512: { - return parse_shasum_output(ec_data.output); + auto hasher = ShaHasher(); + 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(); + }); + } - // Try shasum + 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) { - const auto ec_data = System::cmd_execute_and_capture_output( - Strings::format(R"(echo -n "%s" | shasum -a %s)", s, digest_size)); - if (ec_data.exit_code == 0) - { - return parse_shasum_output(ec_data.output); - } + ec.assign(ENOENT, std::system_category()); + return {}; } - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not hash input string with %s", hash_type); + return do_hash(algo, [&file, &ec](Hasher& hasher) { + constexpr std::size_t buffer_size = 4096; + auto buffer = std::make_unique(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(); + } + } + }); } -#endif } diff --git a/toolsrc/src/vcpkg/base/stringview.cpp b/toolsrc/src/vcpkg/base/stringview.cpp index d0b2cd43a..839d72ce8 100644 --- a/toolsrc/src/vcpkg/base/stringview.cpp +++ b/toolsrc/src/vcpkg/base/stringview.cpp @@ -76,8 +76,10 @@ namespace vcpkg 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); } - bool StringView::operator==(StringView other) const + bool operator==(StringView lhs, StringView rhs) noexcept { - return other.size() == size() && memcmp(data(), other.data(), size()) == 0; + return lhs.size() == lhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; } + + bool operator!=(StringView lhs, StringView rhs) noexcept { return !(lhs == rhs); } } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index a2e90f33b..9245ddfbc 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -486,32 +486,33 @@ namespace vcpkg::Build } else { - hash = Hash::get_file_hash(fs, triplet_file_path, "SHA1"); + const auto algo = Hash::Algorithm::Sha1; + hash = Hash::get_file_hash(VCPKG_LINE_INFO, fs, triplet_file_path, algo); if (auto p = pre_build_info.external_toolchain_file.get()) { hash += "-"; - hash += Hash::get_file_hash(fs, *p, "SHA1"); + hash += Hash::get_file_hash(VCPKG_LINE_INFO, fs, *p, algo); } else if (pre_build_info.cmake_system_name == "Linux") { hash += "-"; - hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "linux.cmake", "SHA1"); + hash += Hash::get_file_hash(VCPKG_LINE_INFO, fs, paths.scripts / "toolchains" / "linux.cmake", algo); } else if (pre_build_info.cmake_system_name == "Darwin") { hash += "-"; - hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "osx.cmake", "SHA1"); + hash += Hash::get_file_hash(VCPKG_LINE_INFO, fs, paths.scripts / "toolchains" / "osx.cmake", algo); } else if (pre_build_info.cmake_system_name == "FreeBSD") { hash += "-"; - hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "freebsd.cmake", "SHA1"); + hash += Hash::get_file_hash(VCPKG_LINE_INFO, fs, paths.scripts / "toolchains" / "freebsd.cmake", algo); } else if (pre_build_info.cmake_system_name == "Android") { hash += "-"; - hash += Hash::get_file_hash(fs, paths.scripts / "toolchains" / "android.cmake", "SHA1"); + hash += Hash::get_file_hash(VCPKG_LINE_INFO, fs, paths.scripts / "toolchains" / "android.cmake", algo); } s_hash_cache.emplace(triplet_file_path, hash); @@ -651,8 +652,9 @@ namespace vcpkg::Build { if (fs::is_regular_file(fs.status(VCPKG_LINE_INFO, port_file))) { - port_files.emplace_back(port_file.path().filename().u8string(), - vcpkg::Hash::get_file_hash(fs, port_file, "SHA1")); + port_files.emplace_back( + port_file.path().filename().u8string(), + vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO, fs, port_file, Hash::Algorithm::Sha1)); if (port_files.size() > max_port_file_count) { @@ -679,7 +681,10 @@ namespace vcpkg::Build abi_tag_entries.emplace_back( "vcpkg_fixup_cmake_targets", - vcpkg::Hash::get_file_hash(fs, paths.scripts / "cmake" / "vcpkg_fixup_cmake_targets.cmake", "SHA1")); + vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO, + fs, + paths.scripts / "cmake" / "vcpkg_fixup_cmake_targets.cmake", + Hash::Algorithm::Sha1)); abi_tag_entries.emplace_back("triplet", pre_build_info.triplet_abi_tag); abi_tag_entries.emplace_back("features", Strings::join(";", config.feature_list)); @@ -688,7 +693,8 @@ namespace vcpkg::Build { abi_tag_entries.emplace_back( "public_abi_override", - Hash::get_string_hash(pre_build_info.public_abi_override.value_or_exit(VCPKG_LINE_INFO), "SHA1")); + Hash::get_string_hash(pre_build_info.public_abi_override.value_or_exit(VCPKG_LINE_INFO), + Hash::Algorithm::Sha1)); } if (config.build_package_options.use_head_version == UseHeadVersion::YES) @@ -717,7 +723,8 @@ namespace vcpkg::Build const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); fs.write_contents(abi_file_path, full_abi_info, VCPKG_LINE_INFO); - return AbiTagAndFile{Hash::get_file_hash(fs, abi_file_path, "SHA1"), abi_file_path}; + return AbiTagAndFile{Hash::get_file_hash(VCPKG_LINE_INFO, fs, abi_file_path, Hash::Algorithm::Sha1), + abi_file_path}; } System::print2( diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 3ac568979..962dbd48b 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -99,8 +99,15 @@ namespace vcpkg::Commands::Hash Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); const fs::path file_to_hash = args.command_arguments[0]; - const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512"; - const std::string hash = vcpkg::Hash::get_file_hash(paths.get_filesystem(), file_to_hash, algorithm); + + 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); } diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 11f613830..b8c55919e 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -266,7 +266,7 @@ namespace vcpkg::Metrics const auto match = *next; if (match[0] != "00-00-00-00-00-00") { - return vcpkg::Hash::get_string_hash(match[0], "SHA256"); + return vcpkg::Hash::get_string_hash(match[0].str(), Hash::Algorithm::Sha256); } ++next; } -- cgit v1.2.3 From 6d8e66ff4fe40ef0937e33e809287476e2c04ee5 Mon Sep 17 00:00:00 2001 From: Phil Christensen Date: Mon, 26 Aug 2019 16:21:57 -0700 Subject: Run clang-format and add more error messages --- toolsrc/src/vcpkg/parse.cpp | 154 +++++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 72 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index 91b2b2786..a3f4186fc 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -2,8 +2,8 @@ #include -#include #include +#include namespace vcpkg::Parse { @@ -45,10 +45,7 @@ namespace vcpkg::Parse return nullptr; } - static bool is_whitespace(char c) - { - return c == ' ' || c == '\t' || c == '\n' || c == '\r'; - } + static bool is_whitespace(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } std::vector parse_comma_list(const std::string& str) { @@ -59,73 +56,86 @@ namespace vcpkg::Parse std::vector out; - auto iter = str.cbegin(); - - do { - // Trim leading whitespace of each element - while (iter != str.cend() && is_whitespace(*iter)) - { - ++iter; - } - - // Allow commas inside of []. - bool bracket_nesting = false; - - auto element_begin = iter; - auto element_end = iter; - while (iter != str.cend() && (*iter != ',' || bracket_nesting)) - { - char value = *iter; - - // do not support nested [] - if (value == '[') - { - bracket_nesting = true; - } - else if (value == ']') - { - bracket_nesting = false; - } - - ++iter; - - // Trim ending whitespace - if (!is_whitespace(value)) - { - // Update element_end after iter is incremented so it will be one past. - element_end = iter; - } - } - - if (element_begin == element_end) - { - System::print2( System::Color::warning, - "Warning: empty element in list\n" - "> '", str, "'\n" - "> ", std::string(static_cast(element_begin - str.cbegin()), ' '), "^\n" - ); - } - else - { - out.push_back({ element_begin, element_end }); - } - - if (iter != str.cend()) - { - //Not at the end, must be at a comma that needs to be stepped over - ++iter; - - if (iter == str.end()) - { - System::print2(System::Color::warning, - "Warning: empty element in list\n" - "> '", str, "'\n" - "> ", std::string(str.length(), ' '), "^\n" - ); - } - } - - } while (iter != str.cend()); + auto iter = str.cbegin(); + + do + { + // Trim leading whitespace of each element + while (iter != str.cend() && is_whitespace(*iter)) + { + ++iter; + } + + // Allow commas inside of []. + bool bracket_nesting = false; + + auto element_begin = iter; + auto element_end = iter; + while (iter != str.cend() && (*iter != ',' || bracket_nesting)) + { + char value = *iter; + + // do not support nested [] + if (value == '[') + { + Checks::check_exit(VCPKG_LINE_INFO, + !bracket_nesting, + "Lists do not support nested brackets, Did you forget a ']'?\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast(iter - str.cbegin()), ' ')); + bracket_nesting = true; + } + else if (value == ']') + { + Checks::check_exit(VCPKG_LINE_INFO, + bracket_nesting, + "Found unmatched ']'. Did you forget a '['?\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast(iter - str.cbegin()), ' ')); + bracket_nesting = false; + } + + ++iter; + + // Trim ending whitespace + if (!is_whitespace(value)) + { + // Update element_end after iter is incremented so it will be one past. + element_end = iter; + } + } + + Checks::check_exit(VCPKG_LINE_INFO, + element_begin != element_end, + "Empty element in list\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast(element_begin - str.cbegin()), ' ')); + + out.push_back({element_begin, element_end}); + + if (iter != str.cend()) + { + Checks::check_exit(VCPKG_LINE_INFO, *iter == ',', "Internal parsing error - expected comma"); + + // Not at the end, must be at a comma that needs to be stepped over + ++iter; + + Checks::check_exit(VCPKG_LINE_INFO, + iter != str.end(), + "Empty element in list\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(str.length(), ' ')); + } + + } while (iter != str.cend()); return out; } -- cgit v1.2.3 From 8bae937e1725a85cb7829ad3113debbeef43674a Mon Sep 17 00:00:00 2001 From: Phil Christensen Date: Mon, 26 Aug 2019 16:39:38 -0700 Subject: avoid assembling error strings unless there is an error --- toolsrc/src/vcpkg/parse.cpp | 65 +++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 29 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index a3f4186fc..6015d9927 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -78,24 +78,28 @@ namespace vcpkg::Parse // do not support nested [] if (value == '[') { - Checks::check_exit(VCPKG_LINE_INFO, - !bracket_nesting, - "Lists do not support nested brackets, Did you forget a ']'?\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(static_cast(iter - str.cbegin()), ' ')); + if (bracket_nesting) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Lists do not support nested brackets, Did you forget a ']'?\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast(iter - str.cbegin()), ' ')); + } bracket_nesting = true; } else if (value == ']') { - Checks::check_exit(VCPKG_LINE_INFO, - bracket_nesting, - "Found unmatched ']'. Did you forget a '['?\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(static_cast(iter - str.cbegin()), ' ')); + if (!bracket_nesting) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Found unmatched ']'. Did you forget a '['?\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast(iter - str.cbegin()), ' ')); + } bracket_nesting = false; } @@ -109,14 +113,15 @@ namespace vcpkg::Parse } } - Checks::check_exit(VCPKG_LINE_INFO, - element_begin != element_end, - "Empty element in list\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(static_cast(element_begin - str.cbegin()), ' ')); - + if (element_begin == element_end) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Empty element in list\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast(element_begin - str.cbegin()), ' ')); + } out.push_back({element_begin, element_end}); if (iter != str.cend()) @@ -126,13 +131,15 @@ namespace vcpkg::Parse // Not at the end, must be at a comma that needs to be stepped over ++iter; - Checks::check_exit(VCPKG_LINE_INFO, - iter != str.end(), - "Empty element in list\n" - "> '%s'\n" - "> %s^\n", - str, - std::string(str.length(), ' ')); + if (iter == str.end()) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Empty element in list\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(str.length(), ' ')); + } } } while (iter != str.cend()); -- cgit v1.2.3 From 32a53e1f3755960b09fc228dce23885aa7efcb8f Mon Sep 17 00:00:00 2001 From: nicole mazzuca Date: Tue, 27 Aug 2019 14:03:49 -0700 Subject: =?UTF-8?q?[vcpkg]=20fix=20bug=20in=20StringView::operator=3D=3D?= =?UTF-8?q?=20=F0=9F=98=B1=20(#7930)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this change, `lhs == rhs` missed the check for `lhs.size() == rhs.size()`, and then did a `memcmp` on the buffers up to `lhs.size()`. This means that, if `lhs.size() < rhs.size()`, it would allow two unequal strings to compare equal if, up to `lhs.size()` they are the same; and if `lhs.size() > rhs.size()`, then it would read out of bounds. --- toolsrc/src/vcpkg-test/stringview.cpp | 17 +++++++++++++++++ toolsrc/src/vcpkg/base/stringview.cpp | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 toolsrc/src/vcpkg-test/stringview.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg-test/stringview.cpp b/toolsrc/src/vcpkg-test/stringview.cpp new file mode 100644 index 000000000..4df8e6be5 --- /dev/null +++ b/toolsrc/src/vcpkg-test/stringview.cpp @@ -0,0 +1,17 @@ +#include + +#include + +template +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/base/stringview.cpp b/toolsrc/src/vcpkg/base/stringview.cpp index 839d72ce8..6b159db48 100644 --- a/toolsrc/src/vcpkg/base/stringview.cpp +++ b/toolsrc/src/vcpkg/base/stringview.cpp @@ -78,7 +78,7 @@ namespace vcpkg bool operator==(StringView lhs, StringView rhs) noexcept { - return lhs.size() == lhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; + return lhs.size() == rhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; } bool operator!=(StringView lhs, StringView rhs) noexcept { return !(lhs == rhs); } -- cgit v1.2.3 From 65d4bc146bf7c1c21989b680497b1f6f9a09c967 Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Wed, 28 Aug 2019 11:47:17 -0700 Subject: [vcpkg install] Enable Download Mode (#7797) * [portfile functions] Override execute_process() to accept ALLOW_IN_DOWNLOAD_MODE option * [vcpkg install] Set VCPKG_DOWNLOAD_MODE when using --only-downloads option * [vcpkg_find_acquire_program] Allow in Download Mode * Don't stop when build fails for a package * Download sources for all packages in dependency graph * Improve output messages * Enable acquiring MSYS packages in download mode * Documentation * Update documentation * execute_process() always fails on Download Mode * Regenerate docs and fix formatting * Run clang-format * Use _execute_process on vcpkg_from_ helpers --- toolsrc/src/vcpkg/build.cpp | 39 +++++++++++++++++++++++++++------- toolsrc/src/vcpkg/commands.ci.cpp | 2 ++ toolsrc/src/vcpkg/commands.upgrade.cpp | 1 + toolsrc/src/vcpkg/export.cpp | 1 + toolsrc/src/vcpkg/install.cpp | 18 +++++++++++++--- 5 files changed, 50 insertions(+), 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 9245ddfbc..e5c00b929 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -53,6 +53,7 @@ namespace vcpkg::Build::Command const Build::BuildPackageOptions build_package_options{ Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, @@ -407,6 +408,11 @@ namespace vcpkg::Build {"VCPKG_CONCURRENCY", std::to_string(get_concurrency())}, }; + if (Util::Enum::to_bool(config.build_package_options.only_downloads)) + { + variables.push_back({"VCPKG_DOWNLOAD_MODE", "true"}); + } + if (!System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value()) { variables.push_back({"GIT", git_exe_path}); @@ -528,6 +534,7 @@ namespace vcpkg::Build const BuildPackageConfig& config) { auto& fs = paths.get_filesystem(); + #if defined(_WIN32) const fs::path& powershell_exe_path = paths.get_tool_exe("powershell-core"); if (!fs.exists(powershell_exe_path.parent_path() / "powershell.exe")) @@ -559,6 +566,14 @@ namespace vcpkg::Build #else const int return_code = System::cmd_execute_clean(command, env); #endif + // With the exception of empty packages, builds in "Download Mode" always result in failure. + if (config.build_package_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 = spec.to_string(); @@ -793,20 +808,23 @@ namespace vcpkg::Build const std::string& name = config.scf.core_paragraph->name; std::vector required_fspecs = compute_required_feature_specs(config, status_db); - std::vector required_fspecs_copy = required_fspecs; // extract out the actual package ids auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); Util::sort_unique_erase(dep_pspecs); // Find all features that aren't installed. This mutates required_fspecs. - Util::erase_remove_if(required_fspecs, [&](FeatureSpec const& fspec) { - return status_db.is_installed(fspec) || fspec.name() == name; - }); - - if (!required_fspecs.empty()) + // Skip this validation when running in Download Mode. + if (config.build_package_options.only_downloads != Build::OnlyDownloads::YES) { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + Util::erase_remove_if(required_fspecs, [&](FeatureSpec const& fspec) { + return status_db.is_installed(fspec) || fspec.name() == name; + }); + + if (!required_fspecs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + } } const PackageSpec spec = @@ -817,7 +835,10 @@ namespace vcpkg::Build // dep_pspecs was not destroyed for (auto&& pspec : dep_pspecs) { - if (pspec == spec) continue; + if (pspec == spec || Util::Enum::to_bool(config.build_package_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( @@ -949,6 +970,7 @@ namespace vcpkg::Build 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 DOWNLOADED_STRING = "DOWNLOADED"; switch (build_result) { @@ -959,6 +981,7 @@ namespace vcpkg::Build 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::DOWNLOADED: return DOWNLOADED_STRING; default: Checks::unreachable(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index f0f162f5c..6e0a71adf 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -212,6 +212,7 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions build_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::YES, Build::CleanPackages::YES, Build::CleanDownloads::NO, @@ -356,6 +357,7 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::YES, Build::CleanPackages::YES, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index 1e64b2eb6..b1dbf6194 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -154,6 +154,7 @@ namespace vcpkg::Commands::Upgrade const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 5ceb47adf..349d9aefd 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -73,6 +73,7 @@ namespace vcpkg::Export static constexpr Build::BuildPackageOptions BUILD_OPTIONS = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 1812f1624..009965887 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -342,6 +342,13 @@ namespace vcpkg::Install return Build::build_package(paths, build_config, 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"); @@ -467,16 +474,18 @@ namespace vcpkg::Install 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_DOWNLOADS = "--only-downloads"; static constexpr StringLiteral OPTION_RECURSE = "--recurse"; static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; 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 std::array INSTALL_SWITCHES = {{ + static constexpr std::array 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_RECURSE, "Allow removal of packages as part of installation"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, {OPTION_USE_ARIA2, "Use aria2 to perform download tasks"}, @@ -631,10 +640,12 @@ namespace vcpkg::Install 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 is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE)); 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)); + const KeepGoing keep_going = + to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING) || only_downloads); auto& fs = paths.get_filesystem(); @@ -647,11 +658,12 @@ namespace vcpkg::Install const Build::BuildPackageOptions install_plan_options = { Util::Enum::to_enum(use_head_version), Util::Enum::to_enum(!no_downloads), + Util::Enum::to_enum(only_downloads), clean_after_build ? Build::CleanBuildtrees::YES : Build::CleanBuildtrees::NO, clean_after_build ? Build::CleanPackages::YES : Build::CleanPackages::NO, clean_after_build ? Build::CleanDownloads::YES : Build::CleanDownloads::NO, download_tool, - GlobalState::g_binary_caching ? Build::BinaryCaching::YES : Build::BinaryCaching::NO, + (GlobalState::g_binary_caching && !only_downloads) ? Build::BinaryCaching::YES : Build::BinaryCaching::NO, Build::FailOnTombstone::NO, }; -- cgit v1.2.3 From 4b404e8cfbdde4277733adaacc399fa4e1b57320 Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Wed, 28 Aug 2019 11:59:30 -0700 Subject: Revert "[vcpkg install] Enable Download Mode (#7797)" (#7949) This reverts commit 65d4bc146bf7c1c21989b680497b1f6f9a09c967. --- toolsrc/src/vcpkg/build.cpp | 39 +++++++--------------------------- toolsrc/src/vcpkg/commands.ci.cpp | 2 -- toolsrc/src/vcpkg/commands.upgrade.cpp | 1 - toolsrc/src/vcpkg/export.cpp | 1 - toolsrc/src/vcpkg/install.cpp | 18 +++------------- 5 files changed, 11 insertions(+), 50 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index e5c00b929..9245ddfbc 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -53,7 +53,6 @@ namespace vcpkg::Build::Command const Build::BuildPackageOptions build_package_options{ Build::UseHeadVersion::NO, Build::AllowDownloads::YES, - Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, @@ -408,11 +407,6 @@ namespace vcpkg::Build {"VCPKG_CONCURRENCY", std::to_string(get_concurrency())}, }; - if (Util::Enum::to_bool(config.build_package_options.only_downloads)) - { - variables.push_back({"VCPKG_DOWNLOAD_MODE", "true"}); - } - if (!System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value()) { variables.push_back({"GIT", git_exe_path}); @@ -534,7 +528,6 @@ namespace vcpkg::Build const BuildPackageConfig& config) { auto& fs = paths.get_filesystem(); - #if defined(_WIN32) const fs::path& powershell_exe_path = paths.get_tool_exe("powershell-core"); if (!fs.exists(powershell_exe_path.parent_path() / "powershell.exe")) @@ -566,14 +559,6 @@ namespace vcpkg::Build #else const int return_code = System::cmd_execute_clean(command, env); #endif - // With the exception of empty packages, builds in "Download Mode" always result in failure. - if (config.build_package_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 = spec.to_string(); @@ -808,23 +793,20 @@ namespace vcpkg::Build const std::string& name = config.scf.core_paragraph->name; std::vector required_fspecs = compute_required_feature_specs(config, status_db); + std::vector required_fspecs_copy = required_fspecs; // extract out the actual package ids auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); Util::sort_unique_erase(dep_pspecs); // Find all features that aren't installed. This mutates required_fspecs. - // Skip this validation when running in Download Mode. - if (config.build_package_options.only_downloads != Build::OnlyDownloads::YES) - { - Util::erase_remove_if(required_fspecs, [&](FeatureSpec const& fspec) { - return status_db.is_installed(fspec) || fspec.name() == name; - }); + Util::erase_remove_if(required_fspecs, [&](FeatureSpec const& fspec) { + return status_db.is_installed(fspec) || fspec.name() == name; + }); - if (!required_fspecs.empty()) - { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; - } + if (!required_fspecs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; } const PackageSpec spec = @@ -835,10 +817,7 @@ namespace vcpkg::Build // dep_pspecs was not destroyed for (auto&& pspec : dep_pspecs) { - if (pspec == spec || Util::Enum::to_bool(config.build_package_options.only_downloads)) - { - continue; - } + if (pspec == spec) 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( @@ -970,7 +949,6 @@ namespace vcpkg::Build 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 DOWNLOADED_STRING = "DOWNLOADED"; switch (build_result) { @@ -981,7 +959,6 @@ namespace vcpkg::Build 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::DOWNLOADED: return DOWNLOADED_STRING; default: Checks::unreachable(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index 6e0a71adf..f0f162f5c 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -212,7 +212,6 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions build_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, - Build::OnlyDownloads::NO, Build::CleanBuildtrees::YES, Build::CleanPackages::YES, Build::CleanDownloads::NO, @@ -357,7 +356,6 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, - Build::OnlyDownloads::NO, Build::CleanBuildtrees::YES, Build::CleanPackages::YES, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index b1dbf6194..1e64b2eb6 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -154,7 +154,6 @@ namespace vcpkg::Commands::Upgrade const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, - Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 349d9aefd..5ceb47adf 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -73,7 +73,6 @@ namespace vcpkg::Export static constexpr Build::BuildPackageOptions BUILD_OPTIONS = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, - Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 009965887..1812f1624 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -342,13 +342,6 @@ namespace vcpkg::Install return Build::build_package(paths, build_config, 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"); @@ -474,18 +467,16 @@ namespace vcpkg::Install 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_DOWNLOADS = "--only-downloads"; static constexpr StringLiteral OPTION_RECURSE = "--recurse"; static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; 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 std::array INSTALL_SWITCHES = {{ + static constexpr std::array 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_RECURSE, "Allow removal of packages as part of installation"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, {OPTION_USE_ARIA2, "Use aria2 to perform download tasks"}, @@ -640,12 +631,10 @@ namespace vcpkg::Install 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 is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE)); 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 KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING)); auto& fs = paths.get_filesystem(); @@ -658,12 +647,11 @@ namespace vcpkg::Install const Build::BuildPackageOptions install_plan_options = { Util::Enum::to_enum(use_head_version), Util::Enum::to_enum(!no_downloads), - Util::Enum::to_enum(only_downloads), clean_after_build ? Build::CleanBuildtrees::YES : Build::CleanBuildtrees::NO, clean_after_build ? Build::CleanPackages::YES : Build::CleanPackages::NO, clean_after_build ? Build::CleanDownloads::YES : Build::CleanDownloads::NO, download_tool, - (GlobalState::g_binary_caching && !only_downloads) ? Build::BinaryCaching::YES : Build::BinaryCaching::NO, + GlobalState::g_binary_caching ? Build::BinaryCaching::YES : Build::BinaryCaching::NO, Build::FailOnTombstone::NO, }; -- cgit v1.2.3 From f5c732b40d43f062278f247036b773477823813b Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Wed, 28 Aug 2019 13:49:29 -0700 Subject: Download Mode (#7950) * [portfile functions] Override execute_process() to accept ALLOW_IN_DOWNLOAD_MODE option * [vcpkg install] Set VCPKG_DOWNLOAD_MODE when using --only-downloads option * [vcpkg_find_acquire_program] Allow in Download Mode * Don't stop when build fails for a package * Download sources for all packages in dependency graph * Improve output messages * Enable acquiring MSYS packages in download mode * Documentation * Update documentation * execute_process() always fails on Download Mode * Regenerate docs and fix formatting * Run clang-format * Use _execute_process on vcpkg_from_ helpers * Fix calls to _execute_process() when not in Download Mode --- toolsrc/src/vcpkg/build.cpp | 39 +++++++++++++++++++++++++++------- toolsrc/src/vcpkg/commands.ci.cpp | 2 ++ toolsrc/src/vcpkg/commands.upgrade.cpp | 1 + toolsrc/src/vcpkg/export.cpp | 1 + toolsrc/src/vcpkg/install.cpp | 18 +++++++++++++--- 5 files changed, 50 insertions(+), 11 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 9245ddfbc..e5c00b929 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -53,6 +53,7 @@ namespace vcpkg::Build::Command const Build::BuildPackageOptions build_package_options{ Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, @@ -407,6 +408,11 @@ namespace vcpkg::Build {"VCPKG_CONCURRENCY", std::to_string(get_concurrency())}, }; + if (Util::Enum::to_bool(config.build_package_options.only_downloads)) + { + variables.push_back({"VCPKG_DOWNLOAD_MODE", "true"}); + } + if (!System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value()) { variables.push_back({"GIT", git_exe_path}); @@ -528,6 +534,7 @@ namespace vcpkg::Build const BuildPackageConfig& config) { auto& fs = paths.get_filesystem(); + #if defined(_WIN32) const fs::path& powershell_exe_path = paths.get_tool_exe("powershell-core"); if (!fs.exists(powershell_exe_path.parent_path() / "powershell.exe")) @@ -559,6 +566,14 @@ namespace vcpkg::Build #else const int return_code = System::cmd_execute_clean(command, env); #endif + // With the exception of empty packages, builds in "Download Mode" always result in failure. + if (config.build_package_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 = spec.to_string(); @@ -793,20 +808,23 @@ namespace vcpkg::Build const std::string& name = config.scf.core_paragraph->name; std::vector required_fspecs = compute_required_feature_specs(config, status_db); - std::vector required_fspecs_copy = required_fspecs; // extract out the actual package ids auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); Util::sort_unique_erase(dep_pspecs); // Find all features that aren't installed. This mutates required_fspecs. - Util::erase_remove_if(required_fspecs, [&](FeatureSpec const& fspec) { - return status_db.is_installed(fspec) || fspec.name() == name; - }); - - if (!required_fspecs.empty()) + // Skip this validation when running in Download Mode. + if (config.build_package_options.only_downloads != Build::OnlyDownloads::YES) { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + Util::erase_remove_if(required_fspecs, [&](FeatureSpec const& fspec) { + return status_db.is_installed(fspec) || fspec.name() == name; + }); + + if (!required_fspecs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + } } const PackageSpec spec = @@ -817,7 +835,10 @@ namespace vcpkg::Build // dep_pspecs was not destroyed for (auto&& pspec : dep_pspecs) { - if (pspec == spec) continue; + if (pspec == spec || Util::Enum::to_bool(config.build_package_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( @@ -949,6 +970,7 @@ namespace vcpkg::Build 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 DOWNLOADED_STRING = "DOWNLOADED"; switch (build_result) { @@ -959,6 +981,7 @@ namespace vcpkg::Build 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::DOWNLOADED: return DOWNLOADED_STRING; default: Checks::unreachable(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index f0f162f5c..6e0a71adf 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -212,6 +212,7 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions build_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::YES, Build::CleanPackages::YES, Build::CleanDownloads::NO, @@ -356,6 +357,7 @@ namespace vcpkg::Commands::CI const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::YES, Build::CleanPackages::YES, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp index 1e64b2eb6..b1dbf6194 100644 --- a/toolsrc/src/vcpkg/commands.upgrade.cpp +++ b/toolsrc/src/vcpkg/commands.upgrade.cpp @@ -154,6 +154,7 @@ namespace vcpkg::Commands::Upgrade const Build::BuildPackageOptions install_plan_options = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index 5ceb47adf..349d9aefd 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -73,6 +73,7 @@ namespace vcpkg::Export static constexpr Build::BuildPackageOptions BUILD_OPTIONS = { Build::UseHeadVersion::NO, Build::AllowDownloads::YES, + Build::OnlyDownloads::NO, Build::CleanBuildtrees::NO, Build::CleanPackages::NO, Build::CleanDownloads::NO, diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 1812f1624..009965887 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -342,6 +342,13 @@ namespace vcpkg::Install return Build::build_package(paths, build_config, 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"); @@ -467,16 +474,18 @@ namespace vcpkg::Install 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_DOWNLOADS = "--only-downloads"; static constexpr StringLiteral OPTION_RECURSE = "--recurse"; static constexpr StringLiteral OPTION_KEEP_GOING = "--keep-going"; 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 std::array INSTALL_SWITCHES = {{ + static constexpr std::array 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_RECURSE, "Allow removal of packages as part of installation"}, {OPTION_KEEP_GOING, "Continue installing packages on failure"}, {OPTION_USE_ARIA2, "Use aria2 to perform download tasks"}, @@ -631,10 +640,12 @@ namespace vcpkg::Install 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 is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE)); 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)); + const KeepGoing keep_going = + to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING) || only_downloads); auto& fs = paths.get_filesystem(); @@ -647,11 +658,12 @@ namespace vcpkg::Install const Build::BuildPackageOptions install_plan_options = { Util::Enum::to_enum(use_head_version), Util::Enum::to_enum(!no_downloads), + Util::Enum::to_enum(only_downloads), clean_after_build ? Build::CleanBuildtrees::YES : Build::CleanBuildtrees::NO, clean_after_build ? Build::CleanPackages::YES : Build::CleanPackages::NO, clean_after_build ? Build::CleanDownloads::YES : Build::CleanDownloads::NO, download_tool, - GlobalState::g_binary_caching ? Build::BinaryCaching::YES : Build::BinaryCaching::NO, + (GlobalState::g_binary_caching && !only_downloads) ? Build::BinaryCaching::YES : Build::BinaryCaching::NO, Build::FailOnTombstone::NO, }; -- cgit v1.2.3 From 84ba23ad3300a86e00841c5e26cbf753f6e89f3f Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Fri, 6 Sep 2019 11:35:56 -0700 Subject: =?UTF-8?q?[x-history]=20Prints=20CONTROL=20version=20history=20of?= =?UTF-8?q?=20a=20port=20=F0=9F=91=BB=20(#7377)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [port-history] Print port CONTROL version history * Add commands.porthistory.cpp to VS project * Get most recent commit for each version * Apply clang-format * Fix output format * Rename command to x-history --- toolsrc/src/vcpkg/commands.cpp | 1 + toolsrc/src/vcpkg/commands.porthistory.cpp | 91 ++++++++++++++++++++++++++++++ toolsrc/src/vcpkg/help.cpp | 1 + 3 files changed, 93 insertions(+) create mode 100644 toolsrc/src/vcpkg/commands.porthistory.cpp (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp index 962dbd48b..1f424a559 100644 --- a/toolsrc/src/vcpkg/commands.cpp +++ b/toolsrc/src/vcpkg/commands.cpp @@ -47,6 +47,7 @@ namespace vcpkg::Commands {"autocomplete", &Autocomplete::perform_and_exit}, {"hash", &Hash::perform_and_exit}, {"fetch", &Fetch::perform_and_exit}, + {"x-history", &PortHistory::perform_and_exit}, {"x-vsinstances", &X_VSInstances::perform_and_exit}, }; return t; diff --git a/toolsrc/src/vcpkg/commands.porthistory.cpp b/toolsrc/src/vcpkg/commands.porthistory.cpp new file mode 100644 index 000000000..44fccbb7f --- /dev/null +++ b/toolsrc/src/vcpkg/commands.porthistory.cpp @@ -0,0 +1,91 @@ +#include "pch.h" + +#include +#include + +#include +#include +#include + +namespace vcpkg::Commands::PortHistory +{ + struct PortControlVersion + { + std::string commit_id; + std::string version; + std::string date; + }; + + static System::ExitCodeAndOutput run_git_command(const VcpkgPaths& paths, const std::string& cmd) + { + const fs::path& git_exe = paths.get_tool_exe(Tools::GIT); + const fs::path dot_git_dir = paths.root / ".git"; + + const std::string full_cmd = + Strings::format(R"("%s" --git-dir="%s" %s)", git_exe.u8string(), dot_git_dir.u8string(), cmd); + + auto output = System::cmd_execute_and_capture_output(full_cmd); + Checks::check_exit(VCPKG_LINE_INFO, output.exit_code == 0, "Failed to run command: %s", full_cmd); + return output; + } + + static std::string get_version_from_commit(const VcpkgPaths& paths, + const std::string& commit_id, + const std::string& port_name) + { + const std::string cmd = Strings::format(R"(show %s:ports/%s/CONTROL)", commit_id, port_name); + auto output = run_git_command(paths, cmd); + + const auto version = Strings::find_at_most_one_enclosed(output.output, "Version: ", "\n"); + Checks::check_exit(VCPKG_LINE_INFO, version.has_value(), "CONTROL file does not have a 'Version' field"); + return version.get()->to_string(); + } + + static std::vector read_versions_from_log(const VcpkgPaths& paths, const std::string& port_name) + { + const std::string cmd = + Strings::format(R"(log --format="%%H %%cd" --date=short --left-only -- ports/%s/.)", port_name); + auto output = run_git_command(paths, cmd); + + 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 ret; + std::string last_version; + for (auto&& commit_date_pair : commits) + { + const std::string version = get_version_from_commit(paths, commit_date_pair.first, port_name); + if (last_version != version) + { + ret.emplace_back(PortControlVersion{commit_date_pair.first, version, commit_date_pair.second}); + last_version = version; + } + } + return ret; + } + + const CommandStructure COMMAND_STRUCTURE = { + Help::create_example_string("history "), + 1, + 1, + {}, + nullptr, + }; + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) + { + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); + + std::string port_name = args.command_arguments.at(0); + std::vector versions = read_versions_from_log(paths, port_name); + System::print2(" version date vcpkg commit\n"); + for (auto&& version : versions) + { + System::printf("%20.20s %s %s\n", version.version, version.date, version.commit_id); + } + Checks::exit_success(VCPKG_LINE_INFO); + } +} diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 9b2751739..1b8e8886e 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -91,6 +91,7 @@ namespace vcpkg::Help " vcpkg list List installed packages\n" " vcpkg update Display list of packages for updating\n" " vcpkg upgrade Rebuild all outdated packages\n" + " vcpkg history Shows the history of CONTROL versions of a package\n" " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" " vcpkg help topics Display the list of help topics\n" " vcpkg help Display help for a specific topic\n" -- cgit v1.2.3 From 90c3f80fffc376664e2a607c58e7f13ab06eb41e Mon Sep 17 00:00:00 2001 From: JackBoosY <47264268+JackBoosY@users.noreply.github.com> Date: Mon, 9 Sep 2019 23:53:24 +0800 Subject: fix x-history help desc. (#8101) --- toolsrc/src/vcpkg/help.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 1b8e8886e..48c836e63 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -91,7 +91,7 @@ namespace vcpkg::Help " vcpkg list List installed packages\n" " vcpkg update Display list of packages for updating\n" " vcpkg upgrade Rebuild all outdated packages\n" - " vcpkg history Shows the history of CONTROL versions of a package\n" + " vcpkg x-history Shows the history of CONTROL versions of a package\n" " vcpkg hash [alg] Hash a file by specific algorithm, default SHA512\n" " vcpkg help topics Display the list of help topics\n" " vcpkg help Display help for a specific topic\n" -- cgit v1.2.3 From cb0fc1a5f98f98aa8b86a32c9bce3074e775042e Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Wed, 11 Sep 2019 11:10:31 -0700 Subject: [vcpkg] Fix depend-info command arguments (#8135) --- toolsrc/src/vcpkg/commands.dependinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp index faf207980..79cbba590 100644 --- a/toolsrc/src/vcpkg/commands.dependinfo.cpp +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -228,8 +228,8 @@ namespace vcpkg::Commands::DependInfo const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("depend-info sqlite3"), - 0, - SIZE_MAX, + 1, + 1, {DEPEND_SWITCHES, DEPEND_SETTINGS}, nullptr, }; -- cgit v1.2.3 From 191c864927ea9e9e8788408adda4eff35d3edaf1 Mon Sep 17 00:00:00 2001 From: martin-s Date: Fri, 13 Sep 2019 06:52:52 +0000 Subject: Fix bug in `.vcpkg-root` detection that breaks `--overlay-triplets` (#7954) * - Added scripts variable to ports file. - Added check if triplet file is not available (NPE). * - Fixed line endings. * Provide location of .vcpkg-root to ports.cmake * vcpkg sets VCPKG_ROOT_PATH in ports.cmake * [vcpkg] Fail if VCPKG_ROOT_PATH is not passed from vcpkg.exe * [vcpkg] Fix vcpkg rooth path * [vcpkg] Make --x-scripts-root an experimental command --- toolsrc/src/vcpkg-test/arguments.cpp | 4 ++-- toolsrc/src/vcpkg/build.cpp | 1 + toolsrc/src/vcpkg/help.cpp | 2 +- toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 8 ++++---- toolsrc/src/vcpkg/vcpkgpaths.cpp | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg-test/arguments.cpp b/toolsrc/src/vcpkg-test/arguments.cpp index 326b07579..c63a31396 100644 --- a/toolsrc/src/vcpkg-test/arguments.cpp +++ b/toolsrc/src/vcpkg-test/arguments.cpp @@ -13,7 +13,7 @@ TEST_CASE ("VcpkgCmdArguments from lowercase argument sequence", "[arguments]") { std::vector t = {"--vcpkg-root", "C:\\vcpkg", - "--scripts-root=C:\\scripts", + "--x-scripts-root=C:\\scripts", "--debug", "--sendmetrics", "--printmetrics", @@ -45,7 +45,7 @@ TEST_CASE ("VcpkgCmdArguments from uppercase argument sequence", "[arguments]") { std::vector t = {"--VCPKG-ROOT", "C:\\vcpkg", - "--SCRIPTS-ROOT=C:\\scripts", + "--X-SCRIPTS-ROOT=C:\\scripts", "--DEBUG", "--SENDMETRICS", "--PRINTMETRICS", diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index e5c00b929..618e4126b 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -396,6 +396,7 @@ namespace vcpkg::Build {"CMD", "BUILD"}, {"PORT", config.scf.core_paragraph->name}, {"CURRENT_PORT_DIR", config.port_dir}, + {"VCPKG_ROOT_PATH", paths.root}, {"TARGET_TRIPLET", triplet.canonical_name()}, {"TARGET_TRIPLET_FILE", paths.get_triplet_file_path(triplet).u8string()}, {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 48c836e63..0c53536fb 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -125,7 +125,7 @@ namespace vcpkg::Help " (default: " ENVVAR(VCPKG_ROOT) // ")\n" "\n" - " --scripts-root= Specify the scripts root directory\n" + " --x-scripts-root= (Experimental) Specify the scripts root directory\n" "\n" " @response_file Specify a " "response file to provide additional parameters\n" diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index e48340df7..5f99b85e5 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -146,10 +146,10 @@ namespace vcpkg parse_value(arg_begin, arg_end, "--vcpkg-root", args.vcpkg_root_dir); continue; } - if (Strings::starts_with(arg, "--scripts-root=")) + if (Strings::starts_with(arg, "--x-scripts-root=")) { parse_cojoined_value( - arg.substr(sizeof("--scripts-root=") - 1), "--scripts-root", args.scripts_root_dir); + arg.substr(sizeof("--x-scripts-root=") - 1), "--x-scripts-root", args.scripts_root_dir); continue; } if (arg == "--triplet") @@ -430,7 +430,7 @@ namespace vcpkg "--vcpkg-root ", "Specify the vcpkg directory to use instead of current directory or tool directory"); System::printf(" %-40s %s\n", - "--scripts-root=", - "Specify the scripts directory to use instead of default vcpkg scripts directory"); + "--x-scripts-root=", + "(Experimental) Specify the scripts directory to use instead of default vcpkg scripts directory"); } } diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 4f01ed03b..078121fcc 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -76,7 +76,7 @@ namespace vcpkg Checks::exit_with_message( VCPKG_LINE_INFO, "Invalid scripts override directory: %s; " - "create that directory or unset --scripts-root to use the default scripts location.", + "create that directory or unset --x-scripts-root to use the default scripts location.", scripts_dir->u8string()); } -- cgit v1.2.3 From b4a0c8d57453cd77c5958800c345e6fd9938f0a4 Mon Sep 17 00:00:00 2001 From: Phoebe <925731795@qq.com> Date: Wed, 18 Sep 2019 00:35:50 +0800 Subject: [vcpkg] Continue on malformed paths in PATH (#8129) Previously vcpkg would exit on malformed paths. We now will continue and ignore the malformed path. --- toolsrc/src/vcpkg/base/files.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 5ebe8d834..3d7df1a68 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -185,6 +185,7 @@ namespace vcpkg::Files if (ec) Checks::exit_with_message(li, "error checking existence of file %s: %s", path.u8string(), ec.message()); return result; } + bool Filesystem::exists(const fs::path& path) const { std::error_code ec; @@ -667,13 +668,14 @@ namespace vcpkg::Files auto paths = Strings::split(System::get_environment_variable("PATH").value_or_exit(VCPKG_LINE_INFO), ";"); std::vector ret; + std::error_code ec; for (auto&& path : paths) { auto base = path + "/" + name; for (auto&& ext : EXTS) { auto p = fs::u8path(base + ext.c_str()); - if (Util::find(ret, p) == ret.end() && this->exists(VCPKG_LINE_INFO, p)) + if (Util::find(ret, p) == ret.end() && this->exists(p, ec)) { ret.push_back(p); Debug::print("Found path: ", p.u8string(), '\n'); -- cgit v1.2.3 From 54173e7fe250fc75604569708109bd6398b87694 Mon Sep 17 00:00:00 2001 From: Alexander Neumann <30894796+Neumann-A@users.noreply.github.com> Date: Tue, 17 Sep 2019 18:55:47 +0200 Subject: Fix #8193 (#8200) --- toolsrc/src/vcpkg/commands.create.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toolsrc/src') diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp index 31bf97f30..e04599dfe 100644 --- a/toolsrc/src/vcpkg/commands.create.cpp +++ b/toolsrc/src/vcpkg/commands.create.cpp @@ -24,7 +24,7 @@ namespace vcpkg::Commands::Create const fs::path& cmake_exe = paths.get_tool_exe(Tools::CMAKE); - std::vector cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}}; + std::vector cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}, {"VCPKG_ROOT_PATH", paths.root}}; if (args.command_arguments.size() >= 3) { -- cgit v1.2.3