aboutsummaryrefslogtreecommitdiff
path: root/toolsrc
diff options
context:
space:
mode:
authorCurtis J Bezault <curtbezault@gmail.com>2019-08-09 11:59:32 -0400
committerGitHub <noreply@github.com>2019-08-09 11:59:32 -0400
commitc4f1a91ef245ed3e44ea11f13040a77453126165 (patch)
tree3e6c99d970fe8a5fcd1551bbcbf9fde4f0b0a3a4 /toolsrc
parent9da7c5c99ee42e382895dbd0dafdd29beaa61075 (diff)
parent743e168ef5c7705e44d1d5cab5b9cca22328345e (diff)
downloadvcpkg-c4f1a91ef245ed3e44ea11f13040a77453126165.tar.gz
vcpkg-c4f1a91ef245ed3e44ea11f13040a77453126165.zip
Merge branch 'master' into external_file_abi
Diffstat (limited to 'toolsrc')
-rw-r--r--toolsrc/CMakeLists.txt83
-rw-r--r--toolsrc/include/pch.h12
-rw-r--r--toolsrc/include/vcpkg-test/util.h78
-rw-r--r--toolsrc/include/vcpkg/base/files.h108
-rw-r--r--toolsrc/include/vcpkg/base/strings.h4
-rw-r--r--toolsrc/include/vcpkg/base/util.h6
-rw-r--r--toolsrc/include/vcpkg/base/work_queue.h218
-rw-r--r--toolsrc/include/vcpkg/binaryparagraph.h3
-rw-r--r--toolsrc/include/vcpkg/build.h4
-rw-r--r--toolsrc/include/vcpkg/dependencies.h11
-rw-r--r--toolsrc/include/vcpkg/logicexpression.h10
-rw-r--r--toolsrc/include/vcpkg/paragraphs.h1
-rw-r--r--toolsrc/include/vcpkg/pragmas.h11
-rw-r--r--toolsrc/include/vcpkg/sourceparagraph.h6
-rw-r--r--toolsrc/include/vcpkg/statusparagraph.h2
-rw-r--r--toolsrc/include/vcpkg/vcpkgpaths.h2
-rw-r--r--toolsrc/src/vcpkg-test/files.cpp192
-rw-r--r--toolsrc/src/vcpkg-test/util.cpp39
-rw-r--r--toolsrc/src/vcpkg.cpp14
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp334
-rw-r--r--toolsrc/src/vcpkg/binaryparagraph.cpp2
-rw-r--r--toolsrc/src/vcpkg/build.cpp149
-rw-r--r--toolsrc/src/vcpkg/commands.cache.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp18
-rw-r--r--toolsrc/src/vcpkg/commands.dependinfo.cpp17
-rw-r--r--toolsrc/src/vcpkg/commands.import.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.search.cpp8
-rw-r--r--toolsrc/src/vcpkg/dependencies.cpp80
-rw-r--r--toolsrc/src/vcpkg/install.cpp6
-rw-r--r--toolsrc/src/vcpkg/logicexpression.cpp268
-rw-r--r--toolsrc/src/vcpkg/paragraphs.cpp41
-rw-r--r--toolsrc/src/vcpkg/parse.cpp3
-rw-r--r--toolsrc/src/vcpkg/remove.cpp4
-rw-r--r--toolsrc/src/vcpkg/sourceparagraph.cpp28
-rw-r--r--toolsrc/src/vcpkg/statusparagraph.cpp2
-rw-r--r--toolsrc/src/vcpkg/userconfig.cpp2
-rw-r--r--toolsrc/src/vcpkg/vcpkgcmdarguments.cpp35
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp39
-rw-r--r--toolsrc/vcpkg.sln2
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj1
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj.filters3
-rw-r--r--toolsrc/vcpkgtest/vcpkgtest.vcxproj30
-rw-r--r--toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters28
43 files changed, 1177 insertions, 731 deletions
diff --git a/toolsrc/CMakeLists.txt b/toolsrc/CMakeLists.txt
index 5bfae1511..7a41874a6 100644
--- a/toolsrc/CMakeLists.txt
+++ b/toolsrc/CMakeLists.txt
@@ -2,11 +2,17 @@ cmake_minimum_required(VERSION 3.3)
project(vcpkg C CXX)
-enable_testing()
-
+OPTION(BUILD_TESTING "Option for enabling testing" ON)
+OPTION(VCPKG_BUILD_BENCHMARKING "Option for enabling benchmarking" OFF)
OPTION(DEFINE_DISABLE_METRICS "Option for disabling metrics" OFF)
OPTION(VCPKG_ALLOW_APPLE_CLANG "Option for allowing apple clang" OFF)
+if (DEFINE_DISABLE_METRICS)
+ set(DISABLE_METRICS_VALUE "1")
+else()
+ set(DISABLE_METRICS_VALUE "0")
+endif()
+
if(CMAKE_COMPILER_IS_GNUXX OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(GCC 1)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
@@ -27,46 +33,12 @@ else()
message(FATAL_ERROR "Unknown compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()
-if(GCC OR CLANG)
- add_compile_options(-std=c++1z)
- if(WERROR)
- add_compile_options(-Wall -Wno-unknown-pragmas -Werror)
- endif()
-endif()
-
-file(GLOB_RECURSE VCPKGLIB_SOURCES src/vcpkg/*.cpp)
-file(GLOB_RECURSE VCPKGTEST_SOURCES src/vcpkg-test/*.cpp)
-
-if (DEFINE_DISABLE_METRICS)
- set(DISABLE_METRICS_VALUE "1")
-else()
- set(DISABLE_METRICS_VALUE "0")
-endif()
-
-add_library(vcpkglib OBJECT ${VCPKGLIB_SOURCES})
-add_executable(vcpkg src/vcpkg.cpp $<TARGET_OBJECTS:vcpkglib>)
-add_executable(vcpkg-test
- EXCLUDE_FROM_ALL
- ${VCPKGTEST_SOURCES}
- $<TARGET_OBJECTS:vcpkglib>)
-
-foreach(TARGET_NAME vcpkglib vcpkg vcpkg-test)
- target_compile_definitions(${TARGET_NAME} PRIVATE -DDISABLE_METRICS=${DISABLE_METRICS_VALUE})
- target_include_directories(${TARGET_NAME} PRIVATE include)
-endforeach()
-
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
-target_link_libraries(vcpkg PRIVATE Threads::Threads)
-target_link_libraries(vcpkg-test PRIVATE Threads::Threads)
-foreach(TEST_NAME
- arguments chrono dependencies files
- paragraph plan specifier statusparagraphs
- strings supports update
-)
- add_test(${TEST_NAME} vcpkg-test [${TEST_NAME}])
-endforeach()
+add_definitions(-DDISABLE_METRICS=${DISABLE_METRICS_VALUE})
+include_directories(include)
+link_libraries(Threads::Threads)
if(CLANG)
include(CheckCXXSourceCompiles)
@@ -80,11 +52,36 @@ if(CLANG)
endif()
if(GCC OR (CLANG AND USES_LIBSTDCXX))
- target_link_libraries(vcpkg PRIVATE stdc++fs)
- target_link_libraries(vcpkg-test PRIVATE stdc++fs)
+ link_libraries(stdc++fs)
elseif(CLANG)
- target_link_libraries(vcpkg PRIVATE c++fs)
- target_link_libraries(vcpkg-test PRIVATE c++fs)
+ link_libraries(c++fs)
+endif()
+
+if(GCC OR CLANG)
+ add_compile_options(-std=c++1z)
+ if(WERROR)
+ add_compile_options(-Wall -Wno-unknown-pragmas -Werror)
+ endif()
+endif()
+
+file(GLOB_RECURSE VCPKGLIB_SOURCES src/vcpkg/*.cpp)
+
+add_library(vcpkglib OBJECT ${VCPKGLIB_SOURCES})
+add_executable(vcpkg src/vcpkg.cpp $<TARGET_OBJECTS:vcpkglib>)
+
+if (BUILD_TESTING)
+ file(GLOB_RECURSE VCPKGTEST_SOURCES src/vcpkg-test/*.cpp)
+
+ enable_testing()
+ add_executable(vcpkg-test
+ ${VCPKGTEST_SOURCES}
+ $<TARGET_OBJECTS:vcpkglib>)
+
+ add_test(NAME default COMMAND vcpkg-test [${TEST_NAME}])
+
+ if (VCPKG_BUILD_BENCHMARKING)
+ target_compile_options(vcpkg-test PRIVATE -DCATCH_CONFIG_ENABLE_BENCHMARKING)
+ endif()
endif()
if(MSVC)
diff --git a/toolsrc/include/pch.h b/toolsrc/include/pch.h
index 15ec25e76..ce2a7c9c5 100644
--- a/toolsrc/include/pch.h
+++ b/toolsrc/include/pch.h
@@ -1,14 +1,6 @@
#pragma once
-#if defined(_MSC_VER) && _MSC_VER < 1911
-// [[nodiscard]] is not recognized before VS 2017 version 15.3
-#pragma warning(disable : 5030)
-#endif
-
-#if defined(__GNUC__) && __GNUC__ < 7
-// [[nodiscard]] is not recognized before GCC version 7
-#pragma GCC diagnostic ignored "-Wattributes"
-#endif
+#include <vcpkg/pragmas.h>
#if defined(_WIN32)
#define NOMINMAX
@@ -38,8 +30,8 @@
#include <cstddef>
#include <cstdint>
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
-#include <experimental/filesystem>
#include <cstring>
+#include <experimental/filesystem>
#include <fstream>
#include <functional>
#include <iomanip>
diff --git a/toolsrc/include/vcpkg-test/util.h b/toolsrc/include/vcpkg-test/util.h
index fa650abc8..8a458a3e5 100644
--- a/toolsrc/include/vcpkg-test/util.h
+++ b/toolsrc/include/vcpkg-test/util.h
@@ -1,42 +1,68 @@
+#include <vcpkg-test/catch.h>
+#include <vcpkg/pragmas.h>
+
#include <vcpkg/base/files.h>
#include <vcpkg/statusparagraph.h>
#include <memory>
-namespace vcpkg::Test {
+#define CHECK_EC(ec) \
+ do \
+ { \
+ if (ec) \
+ { \
+ FAIL(ec.message()); \
+ } \
+ } while (0)
-std::unique_ptr<vcpkg::StatusParagraph> make_status_pgh(const char* name,
- const char* depends = "",
- const char* default_features = "",
- const char* triplet = "x86-windows");
+namespace vcpkg::Test
+{
+ std::unique_ptr<vcpkg::StatusParagraph> make_status_pgh(const char* name,
+ const char* depends = "",
+ const char* default_features = "",
+ const char* triplet = "x86-windows");
-std::unique_ptr<vcpkg::StatusParagraph> make_status_feature_pgh(const char* name,
- const char* feature,
- const char* depends = "",
- const char* triplet = "x86-windows");
+ std::unique_ptr<vcpkg::StatusParagraph> make_status_feature_pgh(const char* name,
+ const char* feature,
+ const char* depends = "",
+ const char* triplet = "x86-windows");
-vcpkg::PackageSpec unsafe_pspec(std::string name, vcpkg::Triplet t = vcpkg::Triplet::X86_WINDOWS);
+ vcpkg::PackageSpec unsafe_pspec(std::string name, vcpkg::Triplet t = vcpkg::Triplet::X86_WINDOWS);
-template<class T, class S>
-T&& unwrap(vcpkg::ExpectedT<T, S>&& p)
-{
- REQUIRE(p.has_value());
- return std::move(*p.get());
-}
+ template<class T, class S>
+ T&& unwrap(vcpkg::ExpectedT<T, S>&& p)
+ {
+ REQUIRE(p.has_value());
+ return std::move(*p.get());
+ }
-template<class T>
-T&& unwrap(vcpkg::Optional<T>&& opt)
-{
- REQUIRE(opt.has_value());
- return std::move(*opt.get());
-}
+ template<class T>
+ T&& unwrap(vcpkg::Optional<T>&& opt)
+ {
+ REQUIRE(opt.has_value());
+ return std::move(*opt.get());
+ }
+
+ struct AllowSymlinks
+ {
+ enum Tag : bool
+ {
+ No = false,
+ Yes = true,
+ } tag;
+
+ constexpr AllowSymlinks(Tag tag) noexcept : tag(tag) {}
+
+ constexpr explicit AllowSymlinks(bool b) noexcept : tag(b ? Yes : No) {}
-extern const bool SYMLINKS_ALLOWED;
+ constexpr operator bool() const noexcept { return tag == Yes; }
+ };
-extern const fs::path TEMPORARY_DIRECTORY;
+ AllowSymlinks can_create_symlinks() noexcept;
-void create_symlink(const fs::path& file, const fs::path& target, std::error_code& ec);
+ const fs::path& base_temporary_directory() noexcept;
-void create_directory_symlink(const fs::path& file, const fs::path& target, std::error_code& ec);
+ void create_symlink(const fs::path& file, const fs::path& target, std::error_code& ec);
+ void create_directory_symlink(const fs::path& file, const fs::path& target, std::error_code& ec);
}
diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h
index a5e04db25..19e4f78fd 100644
--- a/toolsrc/include/vcpkg/base/files.h
+++ b/toolsrc/include/vcpkg/base/files.h
@@ -10,47 +10,125 @@ namespace fs
namespace stdfs = std::experimental::filesystem;
using stdfs::copy_options;
- using stdfs::file_status;
- using stdfs::file_type;
using stdfs::path;
using stdfs::perms;
using stdfs::u8path;
+#if defined(_WIN32)
+ enum class file_type
+ {
+ none = 0,
+ not_found = -1,
+ regular = 1,
+ directory = 2,
+ symlink = 3,
+ block = 4,
+ character = 5,
+ fifo = 6,
+ socket = 7,
+ unknown = 8,
+ // also stands for a junction
+ directory_symlink = 42
+ };
+
+ struct file_status
+ {
+ explicit file_status(file_type type = file_type::none, perms permissions = perms::unknown) noexcept
+ : m_type(type), m_permissions(permissions)
+ {
+ }
+
+ file_type type() const noexcept { return m_type; }
+ void type(file_type type) noexcept { m_type = type; }
+
+ perms permissions() const noexcept { return m_permissions; }
+ void permissions(perms perm) noexcept { m_permissions = perm; }
+
+ private:
+ file_type m_type;
+ perms m_permissions;
+ };
+
+#else
+
+ using stdfs::file_status;
+ using stdfs::file_type;
+
+#endif
+
/*
std::experimental::filesystem's file_status and file_type are broken in
the presence of symlinks -- a symlink is treated as the object it points
to for `symlink_status` and `symlink_type`
*/
- using stdfs::status;
-
// we want to poison ADL with these niebloids
namespace detail
{
+ struct status_t
+ {
+ file_status operator()(const path& p, std::error_code& ec) const noexcept;
+ file_status operator()(vcpkg::LineInfo li, const path& p) const noexcept;
+ file_status operator()(const path& p) const;
+ };
struct symlink_status_t
{
file_status operator()(const path& p, std::error_code& ec) const noexcept;
- file_status operator()(const path& p, vcpkg::LineInfo li) const noexcept;
+ file_status operator()(vcpkg::LineInfo li, const path& p) const noexcept;
};
struct is_symlink_t
{
- inline bool operator()(file_status s) const { return stdfs::is_symlink(s); }
+ bool operator()(file_status s) const
+ {
+#if defined(_WIN32)
+ return s.type() == file_type::directory_symlink || s.type() == file_type::symlink;
+#else
+ return stdfs::is_symlink(s);
+#endif
+ }
};
struct is_regular_file_t
{
- inline bool operator()(file_status s) const { return stdfs::is_regular_file(s); }
+ inline bool operator()(file_status s) const
+ {
+#if defined(_WIN32)
+ return s.type() == file_type::regular;
+#else
+ return stdfs::is_regular_file(s);
+#endif
+ }
};
struct is_directory_t
{
- inline bool operator()(file_status s) const { return stdfs::is_directory(s); }
+ inline bool operator()(file_status s) const
+ {
+#if defined(_WIN32)
+ return s.type() == file_type::directory;
+#else
+ return stdfs::is_directory(s);
+#endif
+ }
+ };
+ struct exists_t
+ {
+ inline bool operator()(file_status s) const
+ {
+#if defined(_WIN32)
+ return s.type() != file_type::not_found && s.type() != file_type::none;
+#else
+ return stdfs::exists(s);
+#endif
+ }
};
}
+ constexpr detail::status_t status{};
constexpr detail::symlink_status_t symlink_status{};
constexpr detail::is_symlink_t is_symlink{};
constexpr detail::is_regular_file_t is_regular_file{};
constexpr detail::is_directory_t is_directory{};
+ constexpr detail::exists_t exists{};
}
/*
@@ -59,12 +137,14 @@ namespace fs
Therefore, put `symlink_status` in the global namespace, so that they get
our symlink_status.
- We also want to poison the ADL on is_regular_file and is_directory, because
+ We also want to poison the ADL on the other functions, because
we don't want people calling these functions on paths
*/
+using fs::exists;
using fs::is_directory;
using fs::is_regular_file;
using fs::is_symlink;
+using fs::status;
using fs::symlink_status;
namespace vcpkg::Files
@@ -92,9 +172,13 @@ namespace vcpkg::Files
bool remove(const fs::path& path, LineInfo linfo);
virtual bool remove(const fs::path& path, std::error_code& ec) = 0;
- virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) = 0;
- std::uintmax_t remove_all(const fs::path& path, LineInfo li);
- virtual bool exists(const fs::path& path) const = 0;
+ virtual void remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) = 0;
+ void remove_all(const fs::path& path, LineInfo li);
+ bool exists(const fs::path& path, std::error_code& ec) const;
+ bool exists(LineInfo li, const fs::path& path) const;
+ // this should probably not exist, but would require a pass through of
+ // existing code to fix
+ bool exists(const fs::path& path) const;
virtual bool is_directory(const fs::path& path) const = 0;
virtual bool is_regular_file(const fs::path& path) const = 0;
virtual bool is_empty(const fs::path& path) const = 0;
diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h
index d7de9b0b2..dde4e9693 100644
--- a/toolsrc/include/vcpkg/base/strings.h
+++ b/toolsrc/include/vcpkg/base/strings.h
@@ -185,8 +185,6 @@ namespace vcpkg::Strings
bool contains(StringView haystack, StringView needle);
- // base 32 encoding, since base64 encoding requires lowercase letters,
- // which are not distinct from uppercase letters on macOS or Windows filesystems.
- // follows RFC 4648
+ // base 32 encoding, following IETC RFC 4648
std::string b32_encode(std::uint64_t x) noexcept;
}
diff --git a/toolsrc/include/vcpkg/base/util.h b/toolsrc/include/vcpkg/base/util.h
index e629ef0b2..90c947aa9 100644
--- a/toolsrc/include/vcpkg/base/util.h
+++ b/toolsrc/include/vcpkg/base/util.h
@@ -3,19 +3,19 @@
#include <algorithm>
#include <map>
#include <mutex>
+#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
-#include <type_traits>
namespace vcpkg::Util
{
- template <class T>
+ template<class T>
constexpr std::add_const_t<T>& as_const(T& t) noexcept
{
return t;
}
- template <class T>
+ template<class T>
void as_const(const T&&) = delete;
template<class Container>
diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h
index 70142e110..a60613a3c 100644
--- a/toolsrc/include/vcpkg/base/work_queue.h
+++ b/toolsrc/include/vcpkg/base/work_queue.h
@@ -1,108 +1,46 @@
#pragma once
+#include <vcpkg/base/checks.h>
+
#include <condition_variable>
#include <memory>
-#include <queue>
+#include <vector>
namespace vcpkg
{
- template<class Action, class ThreadLocalData>
- struct WorkQueue;
-
- namespace detail
- {
- // for SFINAE purposes, keep out of the class
- template<class Action, class ThreadLocalData>
- auto call_moved_action(Action& action,
- const WorkQueue<Action, ThreadLocalData>& work_queue,
- ThreadLocalData& tld) -> decltype(static_cast<void>(std::move(action)(tld, work_queue)))
- {
- std::move(action)(tld, work_queue);
- }
-
- template<class Action, class ThreadLocalData>
- auto call_moved_action(Action& action, const WorkQueue<Action, ThreadLocalData>&, ThreadLocalData& tld)
- -> decltype(static_cast<void>(std::move(action)(tld)))
- {
- std::move(action)(tld);
- }
- }
-
- template<class Action, class ThreadLocalData>
+ template<class Action>
struct WorkQueue
{
- template<class F>
- WorkQueue(std::uint16_t num_threads, LineInfo li, const F& tld_init) noexcept
- {
- m_line_info = li;
-
- set_unjoined_workers(num_threads);
- m_threads.reserve(num_threads);
- for (std::size_t i = 0; i < num_threads; ++i)
- {
- m_threads.push_back(std::thread(Worker{this, tld_init()}));
- }
- }
-
- WorkQueue(WorkQueue const&) = delete;
- WorkQueue(WorkQueue&&) = delete;
+ WorkQueue(LineInfo li) : m_line_info(li) {}
+ WorkQueue(const WorkQueue&) = delete;
~WorkQueue()
{
- auto lck = std::unique_lock<std::mutex>(m_mutex);
- if (!is_joined(m_state))
- {
- Checks::exit_with_message(m_line_info, "Failed to call join() on a WorkQueue that was destroyed");
- }
- }
-
- // should only be called once; anything else is an error
- void run(LineInfo li)
- {
- // this should _not_ be locked before `run()` is called; however, we
- // want to terminate if someone screws up, rather than cause UB
- auto lck = std::unique_lock<std::mutex>(m_mutex);
-
- if (m_state != State::BeforeRun)
+ auto lck = std::unique_lock<std::mutex>(m_mutex, std::try_to_lock);
+ /*
+ if we don't own the lock, there isn't much we can do
+ it is likely a spurious failure
+ */
+ if (lck && m_running_workers != 0)
{
- Checks::exit_with_message(li, "Attempted to run() twice");
+ Checks::exit_with_message(
+ m_line_info, "Internal error -- outstanding workers (%u) at destruct point", m_running_workers);
}
-
- m_state = State::Running;
}
- // runs all remaining tasks, and blocks on their finishing
- // if this is called in an existing task, _will block forever_
- // DO NOT DO THAT
- // thread-unsafe
- void join(LineInfo li)
+ template<class F>
+ void run_and_join(unsigned num_threads, const F& tld_init) noexcept
{
- {
- auto lck = std::unique_lock<std::mutex>(m_mutex);
- if (is_joined(m_state))
- {
- Checks::exit_with_message(li, "Attempted to call join() more than once");
- }
- else if (m_state == State::Terminated)
- {
- m_state = State::TerminatedJoined;
- }
- else
- {
- m_state = State::Joined;
- }
- }
+ if (m_actions.empty()) return;
- while (unjoined_workers())
+ std::vector<std::thread> threads;
+ threads.reserve(num_threads);
+ for (unsigned i = 0; i < num_threads; ++i)
{
- if (!running_workers())
- {
- m_cv.notify_one();
- }
+ threads.emplace_back(Worker<decltype(tld_init())>{this, tld_init()});
}
- // wait for all threads to join
- for (auto& thrd : m_threads)
+ for (auto& thrd : threads)
{
thrd.join();
}
@@ -111,18 +49,12 @@ namespace vcpkg
// useful in the case of errors
// doesn't stop any existing running tasks
// returns immediately, so that one can call this in a task
- void terminate() const
+ void cancel() const
{
{
- auto lck = std::unique_lock<std::mutex>(m_mutex);
- if (is_joined(m_state))
- {
- m_state = State::TerminatedJoined;
- }
- else
- {
- m_state = State::Terminated;
- }
+ auto lck = std::lock_guard<std::mutex>(m_mutex);
+ m_cancelled = true;
+ m_actions.clear();
}
m_cv.notify_all();
}
@@ -130,15 +62,16 @@ namespace vcpkg
void enqueue_action(Action a) const
{
{
- auto lck = std::unique_lock<std::mutex>(m_mutex);
- m_actions.push_back(std::move(a));
+ auto lck = std::lock_guard<std::mutex>(m_mutex);
+ if (m_cancelled) return;
- if (m_state == State::BeforeRun) return;
+ m_actions.push_back(std::move(a));
}
m_cv.notify_one();
}
private:
+ template<class ThreadLocalData>
struct Worker
{
const WorkQueue* work_queue;
@@ -146,85 +79,62 @@ namespace vcpkg
void operator()()
{
- // unlocked when waiting, or when in the action
- // locked otherwise
auto lck = std::unique_lock<std::mutex>(work_queue->m_mutex);
-
- work_queue->m_cv.wait(lck, [&] { return work_queue->m_state != State::BeforeRun; });
-
- work_queue->increment_running_workers();
for (;;)
{
- const auto state = work_queue->m_state;
-
- if (is_terminated(state))
+ const auto& w = *work_queue;
+ work_queue->m_cv.wait(lck, [&w] {
+ if (w.m_cancelled)
+ return true;
+ else if (!w.m_actions.empty())
+ return true;
+ else if (w.m_running_workers == 0)
+ return true;
+ else
+ return false;
+ });
+
+ if (work_queue->m_cancelled || work_queue->m_actions.empty())
{
+ /*
+ if we've been cancelled, or if the work queue is empty
+ and there are no other workers, we want to return
+ immediately; we don't check for the latter condition
+ since if we're at this point, then either the queue
+ is not empty, or there are no other workers, or both.
+ We can't have an empty queue, and other workers, or
+ we would still be in the wait.
+ */
break;
}
- if (work_queue->m_actions.empty())
- {
- if (state == State::Running || work_queue->running_workers() > 1)
- {
- work_queue->decrement_running_workers();
- work_queue->m_cv.wait(lck);
- work_queue->increment_running_workers();
- continue;
- }
-
- // the queue is joining, and we are the only worker running
- // no more work!
- break;
- }
+ ++work_queue->m_running_workers;
- Action action = std::move(work_queue->m_actions.back());
+ auto action = std::move(work_queue->m_actions.back());
work_queue->m_actions.pop_back();
lck.unlock();
work_queue->m_cv.notify_one();
- detail::call_moved_action(action, *work_queue, tld);
+ std::move(action)(tld, *work_queue);
lck.lock();
- }
- work_queue->decrement_running_workers();
- work_queue->decrement_unjoined_workers();
+ const auto after = --work_queue->m_running_workers;
+ if (work_queue->m_actions.empty() && after == 0)
+ {
+ work_queue->m_cv.notify_all();
+ return;
+ }
+ }
}
};
- enum class State : std::int16_t
- {
- // can only exist upon construction
- BeforeRun = -1,
-
- Running,
- Joined,
- Terminated,
- TerminatedJoined,
- };
-
- static bool is_terminated(State st) { return st == State::Terminated || st == State::TerminatedJoined; }
-
- static bool is_joined(State st) { return st == State::Joined || st == State::TerminatedJoined; }
-
mutable std::mutex m_mutex{};
// these are all under m_mutex
- mutable State m_state = State::BeforeRun;
+ mutable bool m_cancelled = false;
mutable std::vector<Action> m_actions{};
mutable std::condition_variable m_cv{};
+ mutable unsigned long m_running_workers = 0;
- mutable std::atomic<std::uint32_t> m_workers;
- // = unjoined_workers << 16 | running_workers
-
- void set_unjoined_workers(std::uint16_t threads) { m_workers = std::uint32_t(threads) << 16; }
- void decrement_unjoined_workers() const { m_workers -= 1 << 16; }
-
- std::uint16_t unjoined_workers() const { return std::uint16_t(m_workers >> 16); }
-
- void increment_running_workers() const { ++m_workers; }
- void decrement_running_workers() const { --m_workers; }
- std::uint16_t running_workers() const { return std::uint16_t(m_workers); }
-
- std::vector<std::thread> m_threads{};
LineInfo m_line_info;
};
}
diff --git a/toolsrc/include/vcpkg/binaryparagraph.h b/toolsrc/include/vcpkg/binaryparagraph.h
index d75e4abb1..a68fcfb36 100644
--- a/toolsrc/include/vcpkg/binaryparagraph.h
+++ b/toolsrc/include/vcpkg/binaryparagraph.h
@@ -1,6 +1,7 @@
#pragma once
#include <vcpkg/packagespec.h>
+#include <vcpkg/parse.h>
#include <vcpkg/sourceparagraph.h>
#include <map>
@@ -20,7 +21,7 @@ namespace vcpkg
struct BinaryParagraph
{
BinaryParagraph();
- explicit BinaryParagraph(std::unordered_map<std::string, std::string> fields);
+ explicit BinaryParagraph(Parse::RawParagraph fields);
BinaryParagraph(const SourceParagraph& spgh, const Triplet& triplet, const std::string& abi_tag);
BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet);
diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h
index 2d5e18a43..c393d989b 100644
--- a/toolsrc/include/vcpkg/build.h
+++ b/toolsrc/include/vcpkg/build.h
@@ -126,8 +126,8 @@ namespace vcpkg::Build
/// Runs the triplet file in a "capture" mode to create a PreBuildInfo
/// </summary>
static PreBuildInfo from_triplet_file(const VcpkgPaths& paths,
- const Triplet& triplet,
- Optional<const SourceControlFileLocation&> port = nullopt);
+ const Triplet& triplet,
+ Optional<const SourceControlFileLocation&> port = nullopt);
std::string triplet_abi_tag;
std::string target_architecture;
diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h
index 964158026..e9018b1b8 100644
--- a/toolsrc/include/vcpkg/dependencies.h
+++ b/toolsrc/include/vcpkg/dependencies.h
@@ -145,7 +145,7 @@ namespace vcpkg::Dependencies
struct PathsPortFileProvider : Util::ResourceBase, PortFileProvider
{
- explicit PathsPortFileProvider(const vcpkg::VcpkgPaths& paths,
+ explicit PathsPortFileProvider(const vcpkg::VcpkgPaths& paths,
const std::vector<std::string>* ports_dirs_paths);
Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override;
std::vector<const SourceControlFileLocation*> load_all_control_files() const override;
@@ -186,9 +186,10 @@ namespace vcpkg::Dependencies
std::vector<ExportPlanAction> create_export_plan(const std::vector<PackageSpec>& specs,
const StatusParagraphs& status_db);
- std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFileLocation>& map,
- const std::vector<FeatureSpec>& specs,
- const StatusParagraphs& status_db);
+ std::vector<AnyAction> create_feature_install_plan(
+ const std::unordered_map<std::string, SourceControlFileLocation>& map,
+ const std::vector<FeatureSpec>& specs,
+ const StatusParagraphs& status_db);
/// <summary>Figure out which actions are required to install features specifications in `specs`.</summary>
/// <param name="provider">Contains the ports of the current environment.</param>
@@ -199,7 +200,7 @@ namespace vcpkg::Dependencies
const StatusParagraphs& status_db,
const CreateInstallPlanOptions& options = {});
- void print_plan(const std::vector<AnyAction>& action_plan,
+ void print_plan(const std::vector<AnyAction>& action_plan,
const bool is_recursive = true,
const fs::path& default_ports_dir = "");
}
diff --git a/toolsrc/include/vcpkg/logicexpression.h b/toolsrc/include/vcpkg/logicexpression.h
new file mode 100644
index 000000000..8795971b9
--- /dev/null
+++ b/toolsrc/include/vcpkg/logicexpression.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <string>
+
+namespace vcpkg
+{
+ // Evaluate simple vcpkg logic expressions. An identifier in the expression is considered 'true'
+ // if it is a substring of the evaluation_context (typically the name of the triplet)
+ bool evaluate_expression(const std::string& expression, const std::string& evaluation_context);
+} \ No newline at end of file
diff --git a/toolsrc/include/vcpkg/paragraphs.h b/toolsrc/include/vcpkg/paragraphs.h
index 56f09387a..7e2410aef 100644
--- a/toolsrc/include/vcpkg/paragraphs.h
+++ b/toolsrc/include/vcpkg/paragraphs.h
@@ -12,7 +12,6 @@ namespace vcpkg::Paragraphs
Expected<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path);
Expected<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path);
- Expected<RawParagraph> parse_single_paragraph(const std::string& str);
Expected<std::vector<RawParagraph>> parse_paragraphs(const std::string& str);
Parse::ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& control_path);
diff --git a/toolsrc/include/vcpkg/pragmas.h b/toolsrc/include/vcpkg/pragmas.h
new file mode 100644
index 000000000..fa1039bce
--- /dev/null
+++ b/toolsrc/include/vcpkg/pragmas.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#if defined(_MSC_VER) && _MSC_VER < 1911
+// [[nodiscard]] is not recognized before VS 2017 version 15.3
+#pragma warning(disable : 5030)
+#endif
+
+#if defined(__GNUC__) && __GNUC__ < 7
+// [[nodiscard]] is not recognized before GCC version 7
+#pragma GCC diagnostic ignored "-Wattributes"
+#endif
diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h
index 9fbd83475..95347770a 100644
--- a/toolsrc/include/vcpkg/sourceparagraph.h
+++ b/toolsrc/include/vcpkg/sourceparagraph.h
@@ -23,8 +23,7 @@ namespace vcpkg
std::vector<std::string> filter_dependencies(const std::vector<Dependency>& deps, const Triplet& t);
std::vector<FeatureSpec> filter_dependencies_to_specs(const std::vector<Dependency>& deps, const Triplet& t);
- std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps,
- const Triplet& t);
+ std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps, const Triplet& t);
// zlib[uwp] becomes Dependency{"zlib", "uwp"}
std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends);
@@ -71,7 +70,8 @@ namespace vcpkg
};
/// <summary>
- /// Full metadata of a package: core and other features. As well as the location the SourceControlFile was loaded from.
+ /// Full metadata of a package: core and other features. As well as the location the SourceControlFile was loaded
+ /// from.
/// </summary>
struct SourceControlFileLocation
{
diff --git a/toolsrc/include/vcpkg/statusparagraph.h b/toolsrc/include/vcpkg/statusparagraph.h
index e79c946cc..6e832fe2f 100644
--- a/toolsrc/include/vcpkg/statusparagraph.h
+++ b/toolsrc/include/vcpkg/statusparagraph.h
@@ -30,7 +30,7 @@ namespace vcpkg
struct StatusParagraph
{
StatusParagraph() noexcept;
- explicit StatusParagraph(std::unordered_map<std::string, std::string>&& fields);
+ explicit StatusParagraph(Parse::RawParagraph&& fields);
bool is_installed() const { return want == Want::INSTALL && state == InstallState::INSTALLED; }
diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h
index ce442858b..8107b8201 100644
--- a/toolsrc/include/vcpkg/vcpkgpaths.h
+++ b/toolsrc/include/vcpkg/vcpkgpaths.h
@@ -55,7 +55,7 @@ namespace vcpkg
fs::path package_dir(const PackageSpec& spec) const;
fs::path build_info_file_path(const PackageSpec& spec) const;
fs::path listfile_path(const BinaryParagraph& pgh) const;
-
+
bool is_valid_triplet(const Triplet& t) const;
const std::vector<std::string>& get_available_triplets() const;
const fs::path get_triplet_file_path(const Triplet& triplet) const;
diff --git a/toolsrc/src/vcpkg-test/files.cpp b/toolsrc/src/vcpkg-test/files.cpp
index 9e14cec0c..a2faf455c 100644
--- a/toolsrc/src/vcpkg-test/files.cpp
+++ b/toolsrc/src/vcpkg-test/files.cpp
@@ -9,29 +9,63 @@
#include <vector>
-using vcpkg::Test::SYMLINKS_ALLOWED;
-using vcpkg::Test::TEMPORARY_DIRECTORY;
+using vcpkg::Test::AllowSymlinks;
+using vcpkg::Test::base_temporary_directory;
+using vcpkg::Test::can_create_symlinks;
+
+#define CHECK_EC_ON_FILE(file, ec) \
+ do \
+ { \
+ if (ec) \
+ { \
+ FAIL(file << ": " << ec.message()); \
+ } \
+ } while (0)
namespace
{
- using uid = std::uniform_int_distribution<std::uint64_t>;
+ using uid_t = std::uniform_int_distribution<std::uint64_t>;
+ using urbg_t = std::mt19937_64;
- std::mt19937_64 get_urbg(std::uint64_t index)
+ urbg_t get_urbg(std::uint64_t index)
{
// smallest prime > 2**63 - 1
- return std::mt19937_64{index + 9223372036854775837ULL};
+ return urbg_t{index + 9223372036854775837ULL};
}
- std::string get_random_filename(std::mt19937_64& urbg) { return vcpkg::Strings::b32_encode(uid{}(urbg)); }
+ std::string get_random_filename(urbg_t& urbg) { return vcpkg::Strings::b32_encode(uid_t{}(urbg)); }
- void create_directory_tree(std::mt19937_64& urbg,
+ struct MaxDepth
+ {
+ std::uint64_t i;
+ explicit MaxDepth(std::uint64_t i) : i(i) {}
+ operator uint64_t() const { return i; }
+ };
+
+ struct Width
+ {
+ std::uint64_t i;
+ explicit Width(std::uint64_t i) : i(i) {}
+ operator uint64_t() const { return i; }
+ };
+
+ struct CurrentDepth
+ {
+ std::uint64_t i;
+ explicit CurrentDepth(std::uint64_t i) : i(i) {}
+ operator uint64_t() const { return i; }
+ CurrentDepth incremented() const { return CurrentDepth{i + 1}; }
+ };
+
+ void create_directory_tree(urbg_t& urbg,
vcpkg::Files::Filesystem& fs,
- std::uint64_t depth,
- const fs::path& base)
+ const fs::path& base,
+ MaxDepth max_depth,
+ AllowSymlinks allow_symlinks = AllowSymlinks::Yes,
+ Width width = Width{5},
+ CurrentDepth current_depth = CurrentDepth{0})
{
std::random_device rd;
- constexpr std::uint64_t max_depth = 5;
- constexpr std::uint64_t width = 5;
// we want ~70% of our "files" to be directories, and then a third
// each of the remaining ~30% to be regular files, directory symlinks,
@@ -42,18 +76,24 @@ namespace
constexpr std::uint64_t regular_symlink_tag = 8;
constexpr std::uint64_t directory_symlink_tag = 9;
+ allow_symlinks = AllowSymlinks{allow_symlinks && can_create_symlinks()};
+
// if we're at the max depth, we only want to build non-directories
std::uint64_t file_type;
- if (depth < max_depth)
+ if (current_depth >= max_depth)
+ {
+ file_type = uid_t{regular_file_tag, directory_symlink_tag}(urbg);
+ }
+ else if (current_depth < 2)
{
- file_type = uid{directory_min_tag, regular_symlink_tag}(urbg);
+ file_type = directory_min_tag;
}
else
{
- file_type = uid{regular_file_tag, regular_symlink_tag}(urbg);
+ file_type = uid_t{directory_min_tag, regular_symlink_tag}(urbg);
}
- if (!SYMLINKS_ALLOWED && file_type > regular_file_tag)
+ if (!allow_symlinks && file_type > regular_file_tag)
{
file_type = regular_file_tag;
}
@@ -62,14 +102,20 @@ namespace
if (file_type <= directory_max_tag)
{
fs.create_directory(base, ec);
- if (ec) {
- INFO("File that failed: " << base);
- REQUIRE_FALSE(ec);
+ if (ec)
+ {
+ CHECK_EC_ON_FILE(base, ec);
}
for (int i = 0; i < width; ++i)
{
- create_directory_tree(urbg, fs, depth + 1, base / get_random_filename(urbg));
+ create_directory_tree(urbg,
+ fs,
+ base / get_random_filename(urbg),
+ max_depth,
+ allow_symlinks,
+ width,
+ current_depth.incremented());
}
}
else if (file_type == regular_file_tag)
@@ -80,19 +126,34 @@ namespace
else if (file_type == regular_symlink_tag)
{
// regular symlink
- fs.write_contents(base, "", ec);
- REQUIRE_FALSE(ec);
auto base_link = base;
- base_link.replace_filename(base.filename().u8string() + "-link");
- vcpkg::Test::create_symlink(base, base_link, ec);
+ base_link.replace_filename(base.filename().u8string() + "-orig");
+ fs.write_contents(base_link, "", ec);
+ CHECK_EC_ON_FILE(base_link, ec);
+ vcpkg::Test::create_symlink(base_link, base, ec);
}
else // type == directory_symlink_tag
{
// directory symlink
- vcpkg::Test::create_directory_symlink(base / "..", base, ec);
+ auto parent = base;
+ parent.remove_filename();
+ vcpkg::Test::create_directory_symlink(parent, base, ec);
}
- REQUIRE_FALSE(ec);
+ CHECK_EC_ON_FILE(base, ec);
+ REQUIRE(fs::exists(fs.symlink_status(base, ec)));
+ CHECK_EC_ON_FILE(base, ec);
+ }
+
+ vcpkg::Files::Filesystem& setup(urbg_t& urbg)
+ {
+ auto& fs = vcpkg::Files::get_real_filesystem();
+
+ std::error_code ec;
+ fs.create_directory(base_temporary_directory(), ec);
+ CHECK_EC_ON_FILE(base_temporary_directory(), ec);
+
+ return fs;
}
}
@@ -100,22 +161,83 @@ TEST_CASE ("remove all", "[files]")
{
auto urbg = get_urbg(0);
- fs::path temp_dir = TEMPORARY_DIRECTORY / get_random_filename(urbg);
+ auto& fs = setup(urbg);
- auto& fs = vcpkg::Files::get_real_filesystem();
+ fs::path temp_dir = base_temporary_directory() / get_random_filename(urbg);
+ INFO("temp dir is: " << temp_dir);
+
+ create_directory_tree(urbg, fs, temp_dir, MaxDepth{5});
std::error_code ec;
- fs.create_directory(TEMPORARY_DIRECTORY, ec);
+ fs::path fp;
+ fs.remove_all(temp_dir, ec, fp);
+ CHECK_EC_ON_FILE(fp, ec);
+
+ REQUIRE_FALSE(fs.exists(temp_dir, ec));
+ CHECK_EC_ON_FILE(temp_dir, ec);
+}
- REQUIRE_FALSE(ec);
+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
+TEST_CASE ("remove all -- benchmarks", "[files][!benchmark]")
+{
+ auto urbg = get_urbg(1);
+ auto& fs = setup(urbg);
- INFO("temp dir is: " << temp_dir);
+ struct
+ {
+ urbg_t& urbg;
+ vcpkg::Files::Filesystem& fs;
- create_directory_tree(urbg, fs, 0, temp_dir);
+ void operator()(Catch::Benchmark::Chronometer& meter, MaxDepth max_depth, AllowSymlinks allow_symlinks) const
+ {
+ std::vector<fs::path> temp_dirs;
+ temp_dirs.resize(meter.runs());
- fs::path fp;
- fs.remove_all(temp_dir, ec, fp);
- REQUIRE_FALSE(ec);
+ std::generate(begin(temp_dirs), end(temp_dirs), [&] {
+ fs::path temp_dir = base_temporary_directory() / get_random_filename(urbg);
+ create_directory_tree(urbg, fs, temp_dir, max_depth, allow_symlinks);
+ return temp_dir;
+ });
+
+ meter.measure([&](int run) {
+ std::error_code ec;
+ fs::path fp;
+ const auto& temp_dir = temp_dirs[run];
+
+ fs.remove_all(temp_dir, ec, fp);
+ CHECK_EC_ON_FILE(fp, ec);
+ });
+
+ for (const auto& dir : temp_dirs)
+ {
+ std::error_code ec;
+ REQUIRE_FALSE(fs.exists(dir, ec));
+ CHECK_EC_ON_FILE(dir, ec);
+ }
+ }
+ } do_benchmark = {urbg, fs};
+
+ BENCHMARK_ADVANCED("small directory, no symlinks")(Catch::Benchmark::Chronometer meter)
+ {
+ do_benchmark(meter, MaxDepth{2}, AllowSymlinks::No);
+ };
+
+ BENCHMARK_ADVANCED("large directory, no symlinks")(Catch::Benchmark::Chronometer meter)
+ {
+ do_benchmark(meter, MaxDepth{5}, AllowSymlinks::No);
+ };
- REQUIRE_FALSE(fs.exists(temp_dir));
+ if (can_create_symlinks())
+ {
+ BENCHMARK_ADVANCED("small directory, symlinks")(Catch::Benchmark::Chronometer meter)
+ {
+ do_benchmark(meter, MaxDepth{2}, AllowSymlinks::Yes);
+ };
+
+ BENCHMARK_ADVANCED("large directory, symlinks")(Catch::Benchmark::Chronometer meter)
+ {
+ do_benchmark(meter, MaxDepth{5}, AllowSymlinks::Yes);
+ };
+ }
}
+#endif
diff --git a/toolsrc/src/vcpkg-test/util.cpp b/toolsrc/src/vcpkg-test/util.cpp
index a80ab36a0..384954b4e 100644
--- a/toolsrc/src/vcpkg-test/util.cpp
+++ b/toolsrc/src/vcpkg-test/util.cpp
@@ -74,14 +74,15 @@ namespace vcpkg::Test
return m_ret.value_or_exit(VCPKG_LINE_INFO);
}
- static bool system_allows_symlinks()
+ static AllowSymlinks internal_can_create_symlinks() noexcept
{
-#if defined(_WIN32)
- if (!__cpp_lib_filesystem)
- {
- return false;
- }
-
+#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_NONE
+ return AllowSymlinks::No;
+#elif FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_UNIX
+ return AllowSymlinks::Yes;
+#elif !defined(_WIN32) // FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD
+ return AllowSymlinks::Yes;
+#else
HKEY key;
bool allow_symlinks = true;
@@ -96,13 +97,14 @@ namespace vcpkg::Test
if (status == ERROR_SUCCESS) RegCloseKey(key);
- return allow_symlinks;
-#else
- return true;
+ return allow_symlinks ? AllowSymlinks::Yes : AllowSymlinks::No;
#endif
}
+ const static AllowSymlinks CAN_CREATE_SYMLINKS = internal_can_create_symlinks();
+
+ AllowSymlinks can_create_symlinks() noexcept { return CAN_CREATE_SYMLINKS; }
- static fs::path internal_temporary_directory()
+ static fs::path internal_base_temporary_directory()
{
#if defined(_WIN32)
wchar_t* tmp = static_cast<wchar_t*>(std::calloc(32'767, 2));
@@ -122,18 +124,19 @@ namespace vcpkg::Test
#endif
}
- const bool SYMLINKS_ALLOWED = system_allows_symlinks();
- const fs::path TEMPORARY_DIRECTORY = internal_temporary_directory();
+ const static fs::path BASE_TEMPORARY_DIRECTORY = internal_base_temporary_directory();
-#if FILESYSTEM_SYMLINK == FILSYSTEM_SYMLINK_NONE
- constexpr inline char no_filesystem_message[] =
+ const fs::path& base_temporary_directory() noexcept { return BASE_TEMPORARY_DIRECTORY; }
+
+#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_NONE
+ constexpr char no_filesystem_message[] =
"<filesystem> doesn't exist; on windows, we don't attempt to use the win32 calls to create symlinks";
#endif
void create_symlink(const fs::path& target, const fs::path& file, std::error_code& ec)
{
#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD
- if (SYMLINKS_ALLOWED)
+ if (can_create_symlinks())
{
std::filesystem::path targetp = target.native();
std::filesystem::path filep = file.native();
@@ -157,12 +160,12 @@ namespace vcpkg::Test
void create_directory_symlink(const fs::path& target, const fs::path& file, std::error_code& ec)
{
#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD
- if (SYMLINKS_ALLOWED)
+ if (can_create_symlinks())
{
std::filesystem::path targetp = target.native();
std::filesystem::path filep = file.native();
- std::filesystem::create_symlink(targetp, filep);
+ std::filesystem::create_directory_symlink(targetp, filep);
}
else
{
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index 46ec8c013..3fdbd0d3e 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -125,12 +125,8 @@ static void inner(const VcpkgCmdArguments& args)
auto default_vs_path = System::get_environment_variable("VCPKG_VISUAL_STUDIO_PATH").value_or("");
-
-
- const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir,
- vcpkg_scripts_root_dir,
- default_vs_path,
- args.overlay_triplets.get());
+ const Expected<VcpkgPaths> expected_paths =
+ VcpkgPaths::create(vcpkg_root_dir, vcpkg_scripts_root_dir, default_vs_path, args.overlay_triplets.get());
Checks::check_exit(VCPKG_LINE_INFO,
!expected_paths.error(),
"Error: Invalid vcpkg root directory %s: %s",
@@ -143,7 +139,11 @@ static void inner(const VcpkgCmdArguments& args)
#else
const int exit_code = chdir(paths.root.c_str());
#endif
- Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working directory to the vcpkg root directory failed. Did you incorrectly define the VCPKG_ROOT environment variable, or did you mistakenly create a file named .vcpkg-root somewhere?");
+ Checks::check_exit(
+ VCPKG_LINE_INFO,
+ exit_code == 0,
+ "Changing the working directory to the vcpkg root directory failed. Did you incorrectly define the VCPKG_ROOT "
+ "environment variable, or did you mistakenly create a file named .vcpkg-root somewhere?");
if (args.command == "install" || args.command == "remove" || args.command == "export" || args.command == "update")
{
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index 6c6945e44..4a0a52f06 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -23,29 +23,35 @@
namespace fs::detail
{
- file_status symlink_status_t::operator()(const path& p, std::error_code& ec) const noexcept
+ static file_status status_implementation(bool follow_symlinks, const path& p, std::error_code& ec)
{
#if defined(_WIN32)
- static_cast<void>(ec);
-
- /*
- do not find the permissions of the file -- it's unnecessary for the
- things that vcpkg does.
- if one were to add support for this in the future, one should look
- into GetFileSecurityW
- */
- perms permissions = perms::unknown;
-
WIN32_FILE_ATTRIBUTE_DATA file_attributes;
file_type ft = file_type::unknown;
+ perms permissions = perms::unknown;
if (!GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &file_attributes))
{
- ft = file_type::not_found;
+ const auto err = GetLastError();
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+ {
+ ft = file_type::not_found;
+ }
+ else
+ {
+ ec.assign(err, std::system_category());
+ }
}
- else if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ else if (!follow_symlinks && file_attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
- // check for reparse point -- if yes, then symlink
- ft = file_type::symlink;
+ // this also gives junctions file_type::directory_symlink
+ if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ ft = file_type::directory_symlink;
+ }
+ else
+ {
+ ft = file_type::symlink;
+ }
}
else if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
@@ -57,17 +63,60 @@ namespace fs::detail
ft = file_type::regular;
}
+ if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ {
+ constexpr auto all_write = perms::group_write | perms::owner_write | perms::others_write;
+ permissions = perms::all & ~all_write;
+ }
+ else if (ft != file_type::none && ft != file_type::none)
+ {
+ permissions = perms::all;
+ }
+
return file_status(ft, permissions);
#else
- return stdfs::symlink_status(p, ec);
+ auto result = symlink ? stdfs::symlink_status(p, ec) : stdfs::status(p, ec);
+ // libstdc++ doesn't correctly not-set ec on nonexistent paths
+ if (ec.value() == ENOENT)
+ {
+ ec.clear();
+ result = file_status(file_type::not_found, perms::unknown);
+ }
+ return result;
+#endif
+ }
+
+ file_status status_t::operator()(const path& p, std::error_code& ec) const noexcept
+ {
+ return status_implementation(false, p, ec);
+ }
+ file_status status_t::operator()(vcpkg::LineInfo li, const path& p) const noexcept
+ {
+ std::error_code ec;
+ auto result = (*this)(p, ec);
+ if (ec) vcpkg::Checks::exit_with_message(li, "error getting status of path %s: %s", p.string(), ec.message());
+
+ return result;
+ }
+ file_status status_t::operator()(const path& p) const
+ {
+#if defined(_WIN32)
+ return (*this)(VCPKG_LINE_INFO, p);
+#else
+ return fs::stdfs::status(p);
#endif
}
- file_status symlink_status_t::operator()(const path& p, vcpkg::LineInfo li) const noexcept
+ file_status symlink_status_t::operator()(const path& p, std::error_code& ec) const noexcept
+ {
+ return status_implementation(true, p, ec);
+ }
+
+ file_status symlink_status_t::operator()(vcpkg::LineInfo li, const path& p) const noexcept
{
std::error_code ec;
- auto result = symlink_status(p, ec);
+ auto result = (*this)(p, ec);
if (ec) vcpkg::Checks::exit_with_message(li, "error getting status of path %s: %s", p.string(), ec.message());
return result;
@@ -78,6 +127,48 @@ namespace vcpkg::Files
{
static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])");
+ namespace
+ {
+ // does _not_ follow symlinks
+ void set_writeable(const fs::path& path, std::error_code& ec) noexcept
+ {
+#if defined(_WIN32)
+ auto const file_name = path.c_str();
+ WIN32_FILE_ATTRIBUTE_DATA attributes;
+ if (!GetFileAttributesExW(file_name, GetFileExInfoStandard, &attributes))
+ {
+ ec.assign(GetLastError(), std::system_category());
+ return;
+ }
+
+ auto dw_attributes = attributes.dwFileAttributes;
+ dw_attributes &= ~FILE_ATTRIBUTE_READONLY;
+ if (!SetFileAttributesW(file_name, dw_attributes))
+ {
+ ec.assign(GetLastError(), std::system_category());
+ }
+#else
+ struct stat s;
+ if (lstat(path.c_str(), &s))
+ {
+ ec.assign(errno, std::system_category());
+ return;
+ }
+
+ auto mode = s.st_mode;
+ // if the file is a symlink, perms don't matter
+ if (!(mode & S_IFLNK))
+ {
+ mode |= S_IWUSR;
+ if (chmod(path.c_str(), mode))
+ {
+ ec.assign(errno, std::system_category());
+ }
+ }
+#endif
+ }
+ }
+
std::string Filesystem::read_contents(const fs::path& path, LineInfo linfo) const
{
auto maybe_contents = this->read_contents(path);
@@ -110,6 +201,25 @@ namespace vcpkg::Files
return r;
}
+ bool Filesystem::exists(const fs::path& path, std::error_code& ec) const
+ {
+ return fs::exists(this->symlink_status(path, ec));
+ }
+
+ bool Filesystem::exists(LineInfo li, const fs::path& path) const
+ {
+ std::error_code ec;
+ auto result = this->exists(path, ec);
+ if (ec) Checks::exit_with_message(li, "error checking existence of file %s: %s", path.u8string(), ec.message());
+ return result;
+ }
+ bool Filesystem::exists(const fs::path& path) const
+ {
+ std::error_code ec;
+ // drop this on the floor, for compatibility with existing code
+ return exists(path, ec);
+ }
+
void Filesystem::write_lines(const fs::path& path, const std::vector<std::string>& lines, LineInfo linfo)
{
std::error_code ec;
@@ -117,12 +227,12 @@ namespace vcpkg::Files
if (ec) Checks::exit_with_message(linfo, "error writing lines: %s: %s", path.u8string(), ec.message());
}
- std::uintmax_t Filesystem::remove_all(const fs::path& path, LineInfo li)
+ void Filesystem::remove_all(const fs::path& path, LineInfo li)
{
std::error_code ec;
fs::path failure_point;
- const auto result = this->remove_all(path, ec, failure_point);
+ this->remove_all(path, ec, failure_point);
if (ec)
{
@@ -132,8 +242,6 @@ namespace vcpkg::Files
failure_point.string(),
ec.message());
}
-
- return result;
}
struct RealFilesystem final : Filesystem
@@ -174,6 +282,9 @@ namespace vcpkg::Files
std::string line;
while (std::getline(file_stream, line))
{
+ // Remove the trailing \r to accomodate Windows line endings.
+ if ((!line.empty()) && (line.back() == '\r')) line.pop_back();
+
output.push_back(line);
}
file_stream.close();
@@ -184,7 +295,7 @@ namespace vcpkg::Files
const std::string& filename) const override
{
fs::path current_dir = starting_dir;
- if (exists(current_dir / filename))
+ if (exists(VCPKG_LINE_INFO, current_dir / filename))
{
return current_dir;
}
@@ -209,7 +320,7 @@ namespace vcpkg::Files
current_dir = std::move(parent);
const fs::path candidate = current_dir / filename;
- if (exists(candidate))
+ if (exists(VCPKG_LINE_INFO, candidate))
{
return current_dir;
}
@@ -327,146 +438,113 @@ namespace vcpkg::Files
#endif
}
virtual bool remove(const fs::path& path, std::error_code& ec) override { return fs::stdfs::remove(path, ec); }
- virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) override
+ virtual void remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) override
{
/*
- does not use the std::filesystem call since it is buggy, and can
- have spurious errors before VS 2017 update 6, and on later versions
- (as well as on macOS and Linux), this is just as fast and will have
- fewer spurious errors due to locks.
+ does not use the std::experimental::filesystem call since this is
+ quite a bit faster, and also supports symlinks
*/
- /*
- `remove` doesn't actually remove anything -- it simply moves the
- files into a parent directory (which ends up being at `path`),
- and then inserts `actually_remove{current_path}` into the work
- queue.
- */
struct remove
{
- struct tld
+ struct ErrorInfo : Util::ResourceBase
{
- const fs::path& tmp_directory;
- std::uint64_t index;
-
- std::atomic<std::uintmax_t>& files_deleted;
-
- std::mutex& ec_mutex;
- std::error_code& ec;
- fs::path& failure_point;
+ std::error_code ec;
+ fs::path failure_point;
};
-
- struct actually_remove;
- using queue = WorkQueue<actually_remove, tld>;
-
/*
if `current_path` is a directory, first `remove`s all
- elements of the directory, then calls remove.
+ elements of the directory, then removes current_path.
- else, just calls remove.
+ else if `current_path` exists, removes current_path
+
+ else does nothing
*/
- struct actually_remove
+ static void do_remove(const fs::path& current_path, ErrorInfo& err)
{
- fs::path current_path;
+ std::error_code ec;
+ const auto path_status = fs::symlink_status(current_path, ec);
+ if (check_ec(ec, current_path, err)) return;
+ if (!fs::exists(path_status)) return;
- void operator()(tld& info, const queue& queue) const
- {
- std::error_code ec;
- const auto path_type = fs::symlink_status(current_path, ec).type();
+ const auto path_type = path_status.type();
- if (check_ec(ec, info, queue, current_path)) return;
+ if ((path_status.permissions() & fs::perms::owner_write) != fs::perms::owner_write)
+ {
+ set_writeable(current_path, ec);
+ if (check_ec(ec, current_path, err)) return;
+ }
- if (path_type == fs::file_type::directory)
+ if (path_type == fs::file_type::directory)
+ {
+ for (const auto& entry : fs::stdfs::directory_iterator(current_path))
{
- for (const auto& entry : fs::stdfs::directory_iterator(current_path))
- {
- remove{}(entry, info, queue);
- }
+ do_remove(entry, err);
+ if (err.ec) return;
}
-
- if (fs::stdfs::remove(current_path, ec))
+#if defined(_WIN32)
+ if (!RemoveDirectoryW(current_path.c_str()))
{
- info.files_deleted.fetch_add(1, std::memory_order_relaxed);
+ ec.assign(GetLastError(), std::system_category());
}
- else
+#else
+ if (rmdir(current_path.c_str()))
{
- check_ec(ec, info, queue, current_path);
+ ec.assign(errno, std::system_category());
}
+#endif
}
- };
-
- static bool check_ec(const std::error_code& ec,
- tld& info,
- const queue& queue,
- const fs::path& failure_point)
- {
- if (ec)
+#if defined(_WIN32)
+ else if (path_type == fs::file_type::directory_symlink)
{
- queue.terminate();
-
- auto lck = std::unique_lock<std::mutex>(info.ec_mutex);
- if (!info.ec)
+ if (!RemoveDirectoryW(current_path.c_str()))
{
- info.ec = ec;
- info.failure_point = failure_point;
+ ec.assign(GetLastError(), std::system_category());
}
-
- return true;
}
else
{
- return false;
+ if (!DeleteFileW(current_path.c_str()))
+ {
+ ec.assign(GetLastError(), std::system_category());
+ }
}
+#else
+ else
+ {
+ if (unlink(current_path.c_str()))
+ {
+ ec.assign(errno, std::system_category());
+ }
+ }
+#endif
+
+ check_ec(ec, current_path, err);
}
- void operator()(const fs::path& current_path, tld& info, const queue& queue) const
+ static bool check_ec(const std::error_code& ec, const fs::path& current_path, ErrorInfo& err)
{
- std::error_code ec;
-
- const auto tmp_name = Strings::b32_encode(info.index++);
- const auto tmp_path = info.tmp_directory / tmp_name;
-
- fs::stdfs::rename(current_path, tmp_path, ec);
- if (check_ec(ec, info, queue, current_path)) return;
+ if (ec)
+ {
+ err.ec = ec;
+ err.failure_point = current_path;
- queue.enqueue_action(actually_remove{std::move(tmp_path)});
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
};
- const auto path_type = fs::symlink_status(path, ec).type();
-
- std::atomic<std::uintmax_t> files_deleted{0};
-
- if (path_type == fs::file_type::directory)
- {
- std::uint64_t index = 0;
- std::mutex ec_mutex;
-
- auto const tld_gen = [&] {
- index += static_cast<std::uint64_t>(1) << 32;
- return remove::tld{path, index, files_deleted, ec_mutex, ec, failure_point};
- };
-
- remove::queue queue{4, VCPKG_LINE_INFO, tld_gen};
-
- // note: we don't actually start the queue running until the
- // `join()`. This allows us to rename all the top-level files in
- // peace, so that we don't get collisions.
- auto main_tld = tld_gen();
- for (const auto& entry : fs::stdfs::directory_iterator(path))
- {
- remove{}(entry, main_tld, queue);
- }
-
- queue.join(VCPKG_LINE_INFO);
- }
-
/*
we need to do backoff on the removal of the top level directory,
- since we need to place all moved files into that top level
- directory, and so we can only delete the directory after all the
+ so we can only delete the directory after all the
lower levels have been deleted.
*/
+
+ remove::ErrorInfo err;
for (int backoff = 0; backoff < 5; ++backoff)
{
if (backoff)
@@ -476,16 +554,16 @@ namespace vcpkg::Files
std::this_thread::sleep_for(backoff_time);
}
- if (fs::stdfs::remove(path, ec))
+ remove::do_remove(path, err);
+ if (!err.ec)
{
- files_deleted.fetch_add(1, std::memory_order_relaxed);
break;
}
}
- return files_deleted;
+ ec = std::move(err.ec);
+ failure_point = std::move(err.failure_point);
}
- virtual bool exists(const fs::path& path) const override { return fs::stdfs::exists(path); }
virtual bool is_directory(const fs::path& path) const override { return fs::stdfs::is_directory(path); }
virtual bool is_regular_file(const fs::path& path) const override { return fs::stdfs::is_regular_file(path); }
virtual bool is_empty(const fs::path& path) const override { return fs::stdfs::is_empty(path); }
@@ -563,7 +641,7 @@ namespace vcpkg::Files
for (auto&& ext : EXTS)
{
auto p = fs::u8path(base + ext.c_str());
- if (Util::find(ret, p) == ret.end() && this->exists(p))
+ if (Util::find(ret, p) == ret.end() && this->exists(VCPKG_LINE_INFO, p))
{
ret.push_back(p);
Debug::print("Found path: ", p.u8string(), '\n');
diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp
index 9be2310c6..ef194f9f3 100644
--- a/toolsrc/src/vcpkg/binaryparagraph.cpp
+++ b/toolsrc/src/vcpkg/binaryparagraph.cpp
@@ -56,7 +56,7 @@ namespace vcpkg
BinaryParagraph::BinaryParagraph() = default;
- BinaryParagraph::BinaryParagraph(std::unordered_map<std::string, std::string> fields)
+ BinaryParagraph::BinaryParagraph(Parse::RawParagraph fields)
{
using namespace vcpkg::Parse;
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index 69a313c1a..6f14f46f8 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -64,8 +64,7 @@ namespace vcpkg::Build::Command
std::set<std::string> features_as_set(full_spec.features.begin(), full_spec.features.end());
features_as_set.emplace("core");
- const Build::BuildPackageConfig build_config{
- scfl, spec.triplet(), build_package_options, features_as_set};
+ const Build::BuildPackageConfig build_config{scfl, spec.triplet(), build_package_options, features_as_set};
const auto build_timer = Chrono::ElapsedTimer::create_started();
const auto result = Build::build_package(paths, build_config, status_db);
@@ -304,19 +303,17 @@ namespace vcpkg::Build
const std::set<std::string>& feature_list,
const Triplet& triplet)
{
- return Util::fmap_flatten(
- feature_list,
- [&](std::string const& feature) -> std::vector<Features> {
- if (feature == "core")
- {
- return filter_dependencies_to_features(scf.core_paragraph->depends, triplet);
- }
+ return Util::fmap_flatten(feature_list, [&](std::string const& feature) -> std::vector<Features> {
+ if (feature == "core")
+ {
+ return filter_dependencies_to_features(scf.core_paragraph->depends, triplet);
+ }
- auto maybe_feature = scf.find_feature(feature);
- Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value());
+ auto maybe_feature = scf.find_feature(feature);
+ Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value());
- return filter_dependencies_to_features(maybe_feature.get()->depends, triplet);
- });
+ return filter_dependencies_to_features(maybe_feature.get()->depends, triplet);
+ });
}
static std::vector<std::string> get_dependency_names(const SourceControlFile& scf,
@@ -324,10 +321,7 @@ namespace vcpkg::Build
const Triplet& triplet)
{
return Util::fmap(get_dependencies(scf, feature_list, triplet),
- [&](const Features& feat) {
- return feat.name;
- }
- );
+ [&](const Features& feat) { return feat.name; });
}
static std::vector<FeatureSpec> compute_required_feature_specs(const BuildPackageConfig& config,
@@ -335,8 +329,7 @@ namespace vcpkg::Build
{
const Triplet& triplet = config.triplet;
- const std::vector<std::string> dep_strings =
- get_dependency_names(config.scf, config.feature_list, triplet);
+ const std::vector<std::string> dep_strings = get_dependency_names(config.scf, config.feature_list, triplet);
auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet);
Util::sort_unique_erase(dep_fspecs);
@@ -439,8 +432,7 @@ namespace vcpkg::Build
{
const Toolset& toolset = paths.get_toolset(pre_build_info);
const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE);
- std::vector<System::CMakeVariable> variables =
- get_cmake_vars(paths, config, triplet, toolset);
+ std::vector<System::CMakeVariable> variables = get_cmake_vars(paths, config, triplet, toolset);
const std::string cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, paths.ports_cmake, variables);
@@ -571,13 +563,10 @@ namespace vcpkg::Build
const auto timer = Chrono::ElapsedTimer::create_started();
- std::string command =
- make_build_cmd(paths, pre_build_info, config, triplet);
- std::unordered_map<std::string, std::string> env =
- make_env_passthrough(pre_build_info);
+ std::string command = make_build_cmd(paths, pre_build_info, config, triplet);
+ std::unordered_map<std::string, std::string> env = make_env_passthrough(pre_build_info);
- const int return_code =
- System::cmd_execute_clean(command, env);
+ const int return_code = System::cmd_execute_clean(command, env);
const auto buildtimeus = timer.microseconds();
const auto spec_string = spec.to_string();
@@ -864,8 +853,7 @@ namespace vcpkg::Build
AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi});
}
- const auto pre_build_info =
- PreBuildInfo::from_triplet_file(paths, triplet, config.scfl);
+ const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet, config.scfl);
auto maybe_abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis);
@@ -1021,7 +1009,7 @@ namespace vcpkg::Build
Commands::Version::version());
}
- static BuildInfo inner_create_buildinfo(std::unordered_map<std::string, std::string> pgh)
+ static BuildInfo inner_create_buildinfo(Parse::RawParagraph pgh)
{
Parse::ParagraphParser parser(std::move(pgh));
@@ -1078,8 +1066,7 @@ namespace vcpkg::Build
BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath)
{
- const Expected<std::unordered_map<std::string, std::string>> pghs =
- Paragraphs::get_single_paragraph(fs, filepath);
+ const Expected<Parse::RawParagraph> pghs = Paragraphs::get_single_paragraph(fs, filepath);
Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package");
return inner_create_buildinfo(*pghs.get());
}
@@ -1098,14 +1085,11 @@ namespace vcpkg::Build
if (port)
{
- args.emplace_back(
- "CMAKE_ENV_OVERRIDES_FILE",
- port.value_or_exit(VCPKG_LINE_INFO).source_location / "environment-overrides.cmake");
+ args.emplace_back("CMAKE_ENV_OVERRIDES_FILE",
+ port.value_or_exit(VCPKG_LINE_INFO).source_location / "environment-overrides.cmake");
}
- const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
- ports_cmake_script_path,
- args);
+ const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, ports_cmake_script_path, args);
const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake);
Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, ec_data.output);
@@ -1137,51 +1121,49 @@ namespace vcpkg::Build
{
switch (maybe_option->second)
{
- case VcpkgTripletVar::TARGET_ARCHITECTURE :
- pre_build_info.target_architecture = variable_value;
- break;
- case VcpkgTripletVar::CMAKE_SYSTEM_NAME :
- pre_build_info.cmake_system_name = variable_value;
- break;
- case VcpkgTripletVar::CMAKE_SYSTEM_VERSION :
- pre_build_info.cmake_system_version = variable_value;
- break;
- case VcpkgTripletVar::PLATFORM_TOOLSET :
- pre_build_info.platform_toolset =
- variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::VISUAL_STUDIO_PATH :
- pre_build_info.visual_studio_path =
- variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
- break;
- case VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE :
- pre_build_info.external_toolchain_file =
- variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::BUILD_TYPE :
- if (variable_value.empty())
- pre_build_info.build_type = nullopt;
- else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
- pre_build_info.build_type = ConfigurationType::DEBUG;
- else if (Strings::case_insensitive_ascii_equals(variable_value, "release"))
- pre_build_info.build_type = ConfigurationType::RELEASE;
- else
- Checks::exit_with_message(
+ case VcpkgTripletVar::TARGET_ARCHITECTURE:
+ pre_build_info.target_architecture = variable_value;
+ break;
+ case VcpkgTripletVar::CMAKE_SYSTEM_NAME: pre_build_info.cmake_system_name = variable_value; break;
+ case VcpkgTripletVar::CMAKE_SYSTEM_VERSION:
+ pre_build_info.cmake_system_version = variable_value;
+ break;
+ case VcpkgTripletVar::PLATFORM_TOOLSET:
+ pre_build_info.platform_toolset =
+ variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ break;
+ case VcpkgTripletVar::VISUAL_STUDIO_PATH:
+ pre_build_info.visual_studio_path =
+ variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
+ break;
+ case VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE:
+ pre_build_info.external_toolchain_file =
+ variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ break;
+ case VcpkgTripletVar::BUILD_TYPE:
+ if (variable_value.empty())
+ pre_build_info.build_type = nullopt;
+ else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
+ pre_build_info.build_type = ConfigurationType::DEBUG;
+ else if (Strings::case_insensitive_ascii_equals(variable_value, "release"))
+ pre_build_info.build_type = ConfigurationType::RELEASE;
+ else
+ Checks::exit_with_message(
VCPKG_LINE_INFO, "Unknown setting for VCPKG_BUILD_TYPE: %s", variable_value);
- break;
- case VcpkgTripletVar::ENV_PASSTHROUGH :
- pre_build_info.passthrough_env_vars = Strings::split(variable_value, ";");
- break;
- case VcpkgTripletVar::EXTERNAL_FILES :
- pre_build_info.external_files =
- get_external_file_hashes(
- paths,
- Util::fmap(Strings::split(variable_value, ";"),
- [](const std::string& path)
- {
- return fs::path{path};
- }));
- break;
+ break;
+ case VcpkgTripletVar::ENV_PASSTHROUGH :
+ pre_build_info.passthrough_env_vars = Strings::split(variable_value, ";");
+ break;
+ case VcpkgTripletVar::EXTERNAL_FILES :
+ pre_build_info.external_files =
+ get_external_file_hashes(
+ paths,
+ Util::fmap(Strings::split(variable_value, ";"),
+ [](const std::string& path)
+ {
+ return fs::path{path};
+ }));
+ break;
}
}
else
@@ -1190,8 +1172,7 @@ namespace vcpkg::Build
}
}
- pre_build_info.triplet_abi_tag =
- get_triplet_abi(paths, pre_build_info, triplet);
+ pre_build_info.triplet_abi_tag = get_triplet_abi(paths, pre_build_info, triplet);
return pre_build_info;
}
diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp
index c321de3b5..4c49db004 100644
--- a/toolsrc/src/vcpkg/commands.cache.cpp
+++ b/toolsrc/src/vcpkg/commands.cache.cpp
@@ -14,7 +14,7 @@ namespace vcpkg::Commands::Cache
std::vector<BinaryParagraph> output;
for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages))
{
- const Expected<std::unordered_map<std::string, std::string>> pghs =
+ const Expected<Parse::RawParagraph> pghs =
Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL");
if (const auto p = pghs.get())
{
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp
index b4290baab..f0f162f5c 100644
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ b/toolsrc/src/vcpkg/commands.ci.cpp
@@ -236,12 +236,7 @@ namespace vcpkg::Commands::CI
{
auto triplet = p->spec.triplet();
- const Build::BuildPackageConfig build_config{
- *scfl,
- triplet,
- build_options,
- p->feature_list
- };
+ const Build::BuildPackageConfig build_config{*scfl, triplet, build_options, p->feature_list};
auto dependency_abis =
Util::fmap(p->computed_dependencies, [&](const PackageSpec& spec) -> Build::AbiEntry {
@@ -253,14 +248,7 @@ namespace vcpkg::Commands::CI
return {spec.name(), it->second};
});
const auto& pre_build_info = pre_build_info_cache.get_lazy(
- triplet,
- [&]() {
- return Build::PreBuildInfo::from_triplet_file(
- paths,
- triplet,
- *scfl);
- }
- );
+ triplet, [&]() { return Build::PreBuildInfo::from_triplet_file(paths, triplet, *scfl); });
auto maybe_tag_and_file =
Build::compute_abi_tag(paths, build_config, pre_build_info, dependency_abis);
@@ -362,7 +350,7 @@ namespace vcpkg::Commands::CI
}
StatusParagraphs status_db = database_load_check(paths);
-
+
Dependencies::PathsPortFileProvider provider(paths, args.overlay_ports.get());
const Build::BuildPackageOptions install_plan_options = {
diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp
index 8394e0166..7c04a5a2f 100644
--- a/toolsrc/src/vcpkg/commands.dependinfo.cpp
+++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp
@@ -5,12 +5,12 @@
#include <vcpkg/base/util.h>
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
#include <vcpkg/packagespec.h>
+#include <vcpkg/paragraphs.h>
-#include <vector>
#include <memory>
#include <vcpkg/dependencies.h>
+#include <vector>
using vcpkg::Dependencies::PathsPortFileProvider;
@@ -171,14 +171,14 @@ namespace vcpkg::Commands::DependInfo
{
if (requested_feature_name == "*")
{
- for (auto &&feature_paragraph : (*source_control_file)->feature_paragraphs)
+ for (auto&& feature_paragraph : (*source_control_file)->feature_paragraphs)
{
collected_features.insert(std::addressof(Util::as_const(*feature_paragraph)));
}
continue;
}
auto maybe_feature = (*source_control_file)->find_feature(requested_feature_name);
- if (auto &&feature_paragraph = maybe_feature.get())
+ if (auto&& feature_paragraph = maybe_feature.get())
{
collected_features.insert(std::addressof(Util::as_const(*feature_paragraph)));
}
@@ -197,7 +197,8 @@ namespace vcpkg::Commands::DependInfo
{
for (const auto& dependency : feature_paragraph->depends)
{
- build_dependencies_list(packages_to_keep, dependency.depend.name, source_control_files, switches);
+ build_dependencies_list(
+ packages_to_keep, dependency.depend.name, source_control_files, switches);
}
}
}
@@ -214,9 +215,9 @@ namespace vcpkg::Commands::DependInfo
// TODO: Optimize implementation, current implementation needs to load all ports from disk which is too slow.
PathsPortFileProvider provider(paths, args.overlay_ports.get());
- auto source_control_files = Util::fmap(provider.load_all_control_files(), [](auto&& scfl) -> const SourceControlFile * {
- return scfl->source_control_file.get();
- });
+ auto source_control_files =
+ Util::fmap(provider.load_all_control_files(),
+ [](auto&& scfl) -> const SourceControlFile* { return scfl->source_control_file.get(); });
if (args.command_arguments.size() >= 1)
{
diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp
index 40f5a434c..c18d788c5 100644
--- a/toolsrc/src/vcpkg/commands.import.cpp
+++ b/toolsrc/src/vcpkg/commands.import.cpp
@@ -108,7 +108,7 @@ namespace vcpkg::Commands::Import
const fs::path include_directory(args.command_arguments[1]);
const fs::path project_directory(args.command_arguments[2]);
- const Expected<std::unordered_map<std::string, std::string>> pghs =
+ const Expected<Parse::RawParagraph> pghs =
Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path);
Checks::check_exit(VCPKG_LINE_INFO,
pghs.get() != nullptr,
diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp
index 3d8387ee1..943233502 100644
--- a/toolsrc/src/vcpkg/commands.search.cpp
+++ b/toolsrc/src/vcpkg/commands.search.cpp
@@ -2,12 +2,12 @@
#include <vcpkg/base/system.print.h>
#include <vcpkg/commands.h>
+#include <vcpkg/dependencies.h>
#include <vcpkg/globalstate.h>
#include <vcpkg/help.h>
#include <vcpkg/paragraphs.h>
#include <vcpkg/sourceparagraph.h>
#include <vcpkg/vcpkglib.h>
-#include <vcpkg/dependencies.h>
using vcpkg::Dependencies::PathsPortFileProvider;
@@ -67,9 +67,9 @@ namespace vcpkg::Commands::Search
const bool full_description = Util::Sets::contains(options.switches, OPTION_FULLDESC);
PathsPortFileProvider provider(paths, args.overlay_ports.get());
- auto source_paragraphs = Util::fmap(provider.load_all_control_files(), [](auto&& port) -> const SourceControlFile * {
- return port->source_control_file.get();
- });
+ auto source_paragraphs =
+ Util::fmap(provider.load_all_control_files(),
+ [](auto&& port) -> const SourceControlFile* { return port->source_control_file.get(); });
if (args.command_arguments.empty())
{
diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp
index 50c310dbb..c175cc86f 100644
--- a/toolsrc/src/vcpkg/dependencies.cpp
+++ b/toolsrc/src/vcpkg/dependencies.cpp
@@ -108,9 +108,8 @@ namespace vcpkg::Dependencies
static ClusterSource cluster_from_scf(const SourceControlFileLocation& scfl, Triplet t)
{
ClusterSource ret;
- ret.build_edges.emplace("core",
- filter_dependencies_to_specs(scfl.source_control_file->core_paragraph->depends,
- t));
+ ret.build_edges.emplace("core",
+ filter_dependencies_to_specs(scfl.source_control_file->core_paragraph->depends, t));
for (const auto& feature : scfl.source_control_file->feature_paragraphs)
ret.build_edges.emplace(feature->name, filter_dependencies_to_specs(feature->depends, t));
@@ -123,22 +122,23 @@ namespace vcpkg::Dependencies
const PortFileProvider& m_provider;
};
- std::string to_output_string(RequestType request_type,
- const CStringView s,
- const Build::BuildPackageOptions& options,
+ std::string to_output_string(RequestType request_type,
+ const CStringView s,
+ const Build::BuildPackageOptions& options,
const fs::path& install_port_path,
const fs::path& default_port_path)
{
- if (!default_port_path.empty()
- && !Strings::case_insensitive_ascii_starts_with(install_port_path.u8string(),
- default_port_path.u8string()))
+ if (!default_port_path.empty() &&
+ !Strings::case_insensitive_ascii_starts_with(install_port_path.u8string(), default_port_path.u8string()))
{
const char* const from_head = options.use_head_version == Build::UseHeadVersion::YES ? " (from HEAD)" : "";
switch (request_type)
{
- case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s -- %s", s, from_head, install_port_path.u8string());
- case RequestType::USER_REQUESTED: return Strings::format(" %s%s -- %s", s, from_head, install_port_path.u8string());
- default: Checks::unreachable(VCPKG_LINE_INFO);
+ case RequestType::AUTO_SELECTED:
+ return Strings::format(" * %s%s -- %s", s, from_head, install_port_path.u8string());
+ case RequestType::USER_REQUESTED:
+ return Strings::format(" %s%s -- %s", s, from_head, install_port_path.u8string());
+ default: Checks::unreachable(VCPKG_LINE_INFO);
}
}
return to_output_string(request_type, s, options);
@@ -152,7 +152,7 @@ namespace vcpkg::Dependencies
switch (request_type)
{
- case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s", s, from_head);
+ case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s", s, from_head);
case RequestType::USER_REQUESTED: return Strings::format(" %s%s", s, from_head);
default: Checks::unreachable(VCPKG_LINE_INFO);
}
@@ -162,7 +162,7 @@ namespace vcpkg::Dependencies
{
switch (request_type)
{
- case RequestType::AUTO_SELECTED: return Strings::format(" * %s", s);
+ case RequestType::AUTO_SELECTED: return Strings::format(" * %s", s);
case RequestType::USER_REQUESTED: return Strings::format(" %s", s);
default: Checks::unreachable(VCPKG_LINE_INFO);
}
@@ -293,7 +293,8 @@ namespace vcpkg::Dependencies
MapPortFileProvider::MapPortFileProvider(const std::unordered_map<std::string, SourceControlFileLocation>& map)
: ports(map)
- {}
+ {
+ }
Optional<const SourceControlFileLocation&> MapPortFileProvider::get_control_file(const std::string& spec) const
{
@@ -304,11 +305,11 @@ namespace vcpkg::Dependencies
std::vector<const SourceControlFileLocation*> MapPortFileProvider::load_all_control_files() const
{
- return Util::fmap(ports, [](auto&& kvpair) -> const SourceControlFileLocation * { return &kvpair.second; });
+ return Util::fmap(ports, [](auto&& kvpair) -> const SourceControlFileLocation* { return &kvpair.second; });
}
PathsPortFileProvider::PathsPortFileProvider(const vcpkg::VcpkgPaths& paths,
- const std::vector<std::string>* ports_dirs_paths)
+ const std::vector<std::string>* ports_dirs_paths)
: filesystem(paths.get_filesystem())
{
if (ports_dirs_paths)
@@ -325,7 +326,7 @@ namespace vcpkg::Dependencies
overlay.string());
Checks::check_exit(VCPKG_LINE_INFO,
- fs::stdfs::is_directory(overlay),
+ fs::is_directory(status(overlay)),
"Error: Path \"%s\" must be a directory",
overlay.string());
@@ -354,7 +355,7 @@ namespace vcpkg::Dependencies
{
if (scf->get()->core_paragraph->name == spec)
{
- SourceControlFileLocation scfl{ std::move(*scf), ports_dir };
+ SourceControlFileLocation scfl{std::move(*scf), ports_dir};
auto it = cache.emplace(spec, std::move(scfl));
return it.first->second;
}
@@ -362,9 +363,8 @@ namespace vcpkg::Dependencies
else
{
vcpkg::print_error_message(maybe_scf.error());
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: Failed to load port from %s",
- spec, ports_dir.u8string());
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Error: Failed to load port from %s", spec, ports_dir.u8string());
}
}
@@ -373,7 +373,7 @@ namespace vcpkg::Dependencies
{
if (scf->get()->core_paragraph->name == spec)
{
- SourceControlFileLocation scfl{ std::move(*scf), ports_dir / spec };
+ SourceControlFileLocation scfl{std::move(*scf), ports_dir / spec};
auto it = cache.emplace(spec, std::move(scfl));
return it.first->second;
}
@@ -399,7 +399,7 @@ namespace vcpkg::Dependencies
auto port_name = scf->get()->core_paragraph->name;
if (cache.find(port_name) == cache.end())
{
- SourceControlFileLocation scfl{ std::move(*scf), ports_dir };
+ SourceControlFileLocation scfl{std::move(*scf), ports_dir};
auto it = cache.emplace(port_name, std::move(scfl));
ret.emplace_back(&it.first->second);
}
@@ -407,9 +407,8 @@ namespace vcpkg::Dependencies
else
{
vcpkg::print_error_message(maybe_scf.error());
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: Failed to load port from %s",
- ports_dir.u8string());
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Error: Failed to load port from %s", ports_dir.u8string());
}
continue;
}
@@ -421,7 +420,7 @@ namespace vcpkg::Dependencies
auto port_name = scf->core_paragraph->name;
if (cache.find(port_name) == cache.end())
{
- SourceControlFileLocation scfl{ std::move(scf), ports_dir / port_name };
+ SourceControlFileLocation scfl{std::move(scf), ports_dir / port_name};
auto it = cache.emplace(port_name, std::move(scfl));
ret.emplace_back(&it.first->second);
}
@@ -772,9 +771,10 @@ namespace vcpkg::Dependencies
/// <param name="map">Map of all source control files in the current environment.</param>
/// <param name="specs">Feature specifications to resolve dependencies for.</param>
/// <param name="status_db">Status of installed packages in the current environment.</param>
- std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFileLocation>& map,
- const std::vector<FeatureSpec>& specs,
- const StatusParagraphs& status_db)
+ std::vector<AnyAction> create_feature_install_plan(
+ const std::unordered_map<std::string, SourceControlFileLocation>& map,
+ const std::vector<FeatureSpec>& specs,
+ const StatusParagraphs& status_db)
{
MapPortFileProvider provider(map);
return create_feature_install_plan(provider, specs, status_db);
@@ -836,9 +836,8 @@ namespace vcpkg::Dependencies
{
// If it will be transiently uninstalled, we need to issue a full installation command
auto* pscfl = p_cluster->source.value_or_exit(VCPKG_LINE_INFO).scfl;
- Checks::check_exit(VCPKG_LINE_INFO,
- pscfl != nullptr,
- "Error: Expected a SourceControlFileLocation to exist");
+ Checks::check_exit(
+ VCPKG_LINE_INFO, pscfl != nullptr, "Error: Expected a SourceControlFileLocation to exist");
auto&& scfl = *pscfl;
auto dep_specs = Util::fmap(m_graph_plan->install_graph.adjacency_list(p_cluster),
@@ -918,7 +917,9 @@ namespace vcpkg::Dependencies
PackageGraph::~PackageGraph() = default;
- void print_plan(const std::vector<AnyAction>& action_plan, const bool is_recursive, const fs::path& default_ports_dir)
+ void print_plan(const std::vector<AnyAction>& action_plan,
+ const bool is_recursive,
+ const fs::path& default_ports_dir)
{
std::vector<const RemovePlanAction*> remove_plans;
std::vector<const InstallPlanAction*> rebuilt_plans;
@@ -975,13 +976,10 @@ namespace vcpkg::Dependencies
static auto actions_to_output_string = [&](const std::vector<const InstallPlanAction*>& v) {
return Strings::join("\n", v, [&](const InstallPlanAction* p) {
- if (auto * pscfl = p->source_control_file_location.get())
+ if (auto* pscfl = p->source_control_file_location.get())
{
- return to_output_string(p->request_type,
- p->displayname(),
- p->build_options,
- pscfl->source_location,
- default_ports_dir);
+ return to_output_string(
+ p->request_type, p->displayname(), p->build_options, pscfl->source_location, default_ports_dir);
}
return to_output_string(p->request_type, p->displayname(), p->build_options);
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index 32af57b39..165f13126 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -331,10 +331,8 @@ namespace vcpkg::Install
auto result = [&]() -> Build::ExtendedBuildResult {
const auto& scfl = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO);
- const Build::BuildPackageConfig build_config{scfl,
- action.spec.triplet(),
- action.build_options,
- action.feature_list};
+ const Build::BuildPackageConfig build_config{
+ scfl, action.spec.triplet(), action.build_options, action.feature_list};
return Build::build_package(paths, build_config, status_db);
}();
diff --git a/toolsrc/src/vcpkg/logicexpression.cpp b/toolsrc/src/vcpkg/logicexpression.cpp
new file mode 100644
index 000000000..0cf08ee03
--- /dev/null
+++ b/toolsrc/src/vcpkg/logicexpression.cpp
@@ -0,0 +1,268 @@
+
+#include "pch.h"
+
+#include <vcpkg/base/checks.h>
+#include <vcpkg/base/system.print.h>
+#include <vcpkg/logicexpression.h>
+
+#include <string>
+#include <vector>
+
+namespace vcpkg
+{
+ struct ParseError
+ {
+ ParseError(int column, std::string line, std::string message) : column(column), line(line), message(message) {}
+
+ const int column;
+ const std::string line;
+ const std::string message;
+
+ void print_error() const
+ {
+ System::print2(System::Color::error,
+ "Error: ",
+ message,
+ "\n"
+ " on expression: \"",
+ line,
+ "\"\n",
+ " ",
+ std::string(column, ' '),
+ "^\n");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ };
+
+ // logic expression supports the following :
+ // primary-expression:
+ // ( logic-expression )
+ // identifier
+ // identifier:
+ // alpha-numeric string of characters
+ // logic-expression: <- this is the entry point
+ // not-expression
+ // not-expression | logic-expression
+ // not-expression & logic-expression
+ // not-expression:
+ // ! primary-expression
+ // primary-expression
+ //
+ // | and & have equal precidence and cannot be used together at the same nesting level
+ // for example a|b&c is not allowd but (a|b)&c and a|(b&c) are allowed.
+ class ExpressionParser
+ {
+ public:
+ ExpressionParser(const std::string& str, const std::string& evaluation_context)
+ : raw_text(str), evaluation_context(evaluation_context)
+ {
+ go_to_begin();
+
+ final_result = logic_expression();
+
+ if (current_iter != raw_text.end())
+ {
+ add_error("Invalid logic expression");
+ }
+
+ if (err)
+ {
+ err->print_error();
+ final_result = false;
+ }
+ }
+
+ bool get_result() const { return final_result; }
+
+ bool has_error() const { return err == nullptr; }
+
+ private:
+ bool final_result;
+
+ std::string::const_iterator current_iter;
+ const std::string& raw_text;
+ char current_char;
+
+ const std::string& evaluation_context;
+
+ std::unique_ptr<ParseError> err;
+
+ void add_error(std::string message, int column = -1)
+ {
+ // avoid castcading errors by only saving the first
+ if (!err)
+ {
+ if (column < 0)
+ {
+ column = current_column();
+ }
+ err = std::make_unique<ParseError>(column, raw_text, message);
+ }
+
+ // Avoid error loops by skipping to the end
+ skip_to_end();
+ }
+
+ int current_column() const { return static_cast<int>(current_iter - raw_text.begin()); }
+
+ void go_to_begin()
+ {
+ current_iter = raw_text.begin();
+ current_char = (current_iter != raw_text.end() ? *current_iter : current_char);
+
+ if (current_char == ' ' || current_char == '\t')
+ {
+ next_skip_whitespace();
+ }
+ }
+ void skip_to_end()
+ {
+ current_iter = raw_text.end();
+ current_char = '\0';
+ }
+ char current() const { return current_char; }
+ char next()
+ {
+ if (current_char != '\0')
+ {
+ current_iter++;
+ current_char = (current_iter != raw_text.end() ? *current_iter : '\0');
+ }
+ return current();
+ }
+ void skip_whitespace()
+ {
+ while (current_char == ' ' || current_char == '\t')
+ {
+ current_char = next();
+ }
+ }
+ char next_skip_whitespace()
+ {
+ next();
+ skip_whitespace();
+ return current_char;
+ }
+
+ static bool is_alphanum(char ch)
+ {
+ return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '-');
+ }
+
+ bool evaluate_identifier(const std::string name) const
+ {
+ return evaluation_context.find(name) != std::string::npos;
+ }
+
+ // identifier:
+ // alpha-numeric string of characters
+ bool identifier_expression()
+ {
+ auto curr = current();
+ std::string name;
+
+ for (curr = current(); is_alphanum(curr); curr = next())
+ {
+ name += curr;
+ }
+
+ if (name.empty())
+ {
+ add_error("Invalid logic expression, unexpected character");
+ return false;
+ }
+
+ bool result = evaluate_identifier(name);
+ skip_whitespace();
+ return result;
+ }
+
+ // not-expression:
+ // ! primary-expression
+ // primary-expression
+ bool not_expression()
+ {
+ if (current() == '!')
+ {
+ next_skip_whitespace();
+ return !primary_expression();
+ }
+
+ return primary_expression();
+ }
+
+ template<char oper, char other, bool operation(bool, bool)>
+ bool logic_expression_helper(bool seed)
+ {
+ do
+ {
+ // Support chains of the operator to avoid breaking backwards compatability
+ while (next() == oper)
+ {
+ };
+ seed = operation(not_expression(), seed);
+
+ } while (current() == oper);
+
+ if (current() == other)
+ {
+ add_error("Mixing & and | is not allowed, Use () to specify order of operations.");
+ }
+
+ skip_whitespace();
+ return seed;
+ }
+ static bool and_helper(bool left, bool right) { return left && right; }
+ static bool or_helper(bool left, bool right) { return left || right; }
+
+ // logic-expression: <- entry point
+ // not-expression
+ // not-expression | logic-expression
+ // not-expression & logic-expression
+ bool logic_expression()
+ {
+ auto result = not_expression();
+
+ switch (current())
+ {
+ case '|':
+ {
+ return logic_expression_helper<'|', '&', or_helper>(result);
+ }
+ case '&':
+ {
+ return logic_expression_helper<'&', '|', and_helper>(result);
+ }
+ default: return result;
+ }
+ }
+
+ // primary-expression:
+ // ( logic-expression )
+ // identifier
+ bool primary_expression()
+ {
+ if (current() == '(')
+ {
+ next_skip_whitespace();
+ bool result = logic_expression();
+ if (current() != ')')
+ {
+ add_error("Error: missing closing )");
+ return result;
+ }
+ next_skip_whitespace();
+ return result;
+ }
+
+ return identifier_expression();
+ }
+ };
+
+ bool evaluate_expression(const std::string& expression, const std::string& evaluation_context)
+ {
+ ExpressionParser parser(expression, evaluation_context);
+
+ return parser.get_result();
+ }
+}
diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp
index 21ef2c4d9..1232b940a 100644
--- a/toolsrc/src/vcpkg/paragraphs.cpp
+++ b/toolsrc/src/vcpkg/paragraphs.cpp
@@ -116,7 +116,7 @@ namespace vcpkg::Paragraphs
skip_spaces(ch);
}
- void get_paragraph(char& ch, std::unordered_map<std::string, std::string>& fields)
+ void get_paragraph(char& ch, RawParagraph& fields)
{
fields.clear();
std::string fieldname;
@@ -141,9 +141,9 @@ namespace vcpkg::Paragraphs
}
public:
- std::vector<std::unordered_map<std::string, std::string>> get_paragraphs()
+ std::vector<RawParagraph> get_paragraphs()
{
- std::vector<std::unordered_map<std::string, std::string>> paragraphs;
+ std::vector<RawParagraph> paragraphs;
char ch;
peek(ch);
@@ -164,51 +164,48 @@ namespace vcpkg::Paragraphs
}
};
- Expected<std::unordered_map<std::string, std::string>> get_single_paragraph(const Files::Filesystem& fs,
- const fs::path& control_path)
+ Expected<RawParagraph> parse_single_paragraph(const std::string& str)
{
- const Expected<std::string> contents = fs.read_contents(control_path);
- if (auto spgh = contents.get())
+ const std::vector<RawParagraph> p = Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
+
+ if (p.size() == 1)
{
- return parse_single_paragraph(*spgh);
+ return p.at(0);
}
- return contents.error();
+ return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH);
}
- Expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const Files::Filesystem& fs,
- const fs::path& control_path)
+ Expected<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path)
{
const Expected<std::string> contents = fs.read_contents(control_path);
if (auto spgh = contents.get())
{
- return parse_paragraphs(*spgh);
+ return parse_single_paragraph(*spgh);
}
return contents.error();
}
- Expected<std::unordered_map<std::string, std::string>> parse_single_paragraph(const std::string& str)
+ Expected<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path)
{
- const std::vector<std::unordered_map<std::string, std::string>> p =
- Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
-
- if (p.size() == 1)
+ const Expected<std::string> contents = fs.read_contents(control_path);
+ if (auto spgh = contents.get())
{
- return p.at(0);
+ return parse_paragraphs(*spgh);
}
- return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH);
+ return contents.error();
}
- Expected<std::vector<std::unordered_map<std::string, std::string>>> parse_paragraphs(const std::string& str)
+ Expected<std::vector<RawParagraph>> parse_paragraphs(const std::string& str)
{
return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
}
ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& path)
{
- Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs = get_paragraphs(fs, path / "CONTROL");
+ Expected<std::vector<RawParagraph>> pghs = get_paragraphs(fs, path / "CONTROL");
if (auto vector_pghs = pghs.get())
{
return SourceControlFile::parse_control_file(std::move(*vector_pghs));
@@ -221,7 +218,7 @@ namespace vcpkg::Paragraphs
Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec)
{
- Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs =
+ Expected<std::vector<RawParagraph>> pghs =
get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL");
if (auto p = pghs.get())
diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp
index d50296cf8..9c9968249 100644
--- a/toolsrc/src/vcpkg/parse.cpp
+++ b/toolsrc/src/vcpkg/parse.cpp
@@ -6,8 +6,7 @@
namespace vcpkg::Parse
{
- static Optional<std::string> remove_field(std::unordered_map<std::string, std::string>* fields,
- const std::string& fieldname)
+ static Optional<std::string> remove_field(RawParagraph* fields, const std::string& fieldname)
{
auto it = fields->find(fieldname);
if (it == fields->end())
diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp
index 84ec6c981..65e00668a 100644
--- a/toolsrc/src/vcpkg/remove.cpp
+++ b/toolsrc/src/vcpkg/remove.cpp
@@ -73,7 +73,7 @@ namespace vcpkg::Remove
if (ec)
{
#if defined(_WIN32)
- fs::stdfs::permissions(target, fs::stdfs::perms::owner_all | fs::stdfs::perms::group_all, ec);
+ fs::stdfs::permissions(target, fs::perms::owner_all | fs::perms::group_all, ec);
fs.remove(target, ec);
if (ec)
{
@@ -86,7 +86,7 @@ namespace vcpkg::Remove
#endif
}
}
- else if (!fs::stdfs::exists(status))
+ else if (!fs::exists(status))
{
System::printf(System::Color::warning, "Warning: %s: file not found\n", target.u8string());
}
diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp
index 5542ef923..ebb9cd4f4 100644
--- a/toolsrc/src/vcpkg/sourceparagraph.cpp
+++ b/toolsrc/src/vcpkg/sourceparagraph.cpp
@@ -1,5 +1,6 @@
#include "pch.h"
+#include <vcpkg/logicexpression.h>
#include <vcpkg/packagespec.h>
#include <vcpkg/sourceparagraph.h>
#include <vcpkg/triplet.h>
@@ -144,7 +145,7 @@ namespace vcpkg
}
ParseExpected<SourceControlFile> SourceControlFile::parse_control_file(
- std::vector<std::unordered_map<std::string, std::string>>&& control_paragraphs)
+ std::vector<Parse::RawParagraph>&& control_paragraphs)
{
if (control_paragraphs.size() == 0)
{
@@ -224,15 +225,8 @@ namespace vcpkg
std::vector<std::string> ret;
for (auto&& dep : deps)
{
- auto qualifiers = Strings::split(dep.qualifier, "&");
- if (std::all_of(qualifiers.begin(), qualifiers.end(), [&](const std::string& qualifier) {
- if (qualifier.empty()) return true;
- if (qualifier[0] == '!')
- {
- return t.canonical_name().find(qualifier.substr(1)) == std::string::npos;
- }
- return t.canonical_name().find(qualifier) != std::string::npos;
- }))
+ const auto& qualifier = dep.qualifier;
+ if (qualifier.empty() || evaluate_expression(qualifier, t.canonical_name()))
{
ret.emplace_back(dep.name());
}
@@ -240,21 +234,13 @@ namespace vcpkg
return ret;
}
- std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps,
- const Triplet& t)
+ std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps, const Triplet& t)
{
std::vector<Features> ret;
for (auto&& dep : deps)
{
- auto qualifiers = Strings::split(dep.qualifier, "&");
- if (std::all_of(qualifiers.begin(), qualifiers.end(), [&](const std::string& qualifier) {
- if (qualifier.empty()) return true;
- if (qualifier[0] == '!')
- {
- return t.canonical_name().find(qualifier.substr(1)) == std::string::npos;
- }
- return t.canonical_name().find(qualifier) != std::string::npos;
- }))
+ const auto& qualifier = dep.qualifier;
+ if (qualifier.empty() || evaluate_expression(qualifier, t.canonical_name()))
{
ret.emplace_back(dep.depend);
}
diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp
index 86946a31a..f7e00f21c 100644
--- a/toolsrc/src/vcpkg/statusparagraph.cpp
+++ b/toolsrc/src/vcpkg/statusparagraph.cpp
@@ -24,7 +24,7 @@ namespace vcpkg
.push_back('\n');
}
- StatusParagraph::StatusParagraph(std::unordered_map<std::string, std::string>&& fields)
+ StatusParagraph::StatusParagraph(Parse::RawParagraph&& fields)
: want(Want::ERROR_STATE), state(InstallState::ERROR_STATE)
{
auto status_it = fields.find(BinaryParagraphRequiredField::STATUS);
diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp
index a7c4e2765..a3c019be7 100644
--- a/toolsrc/src/vcpkg/userconfig.cpp
+++ b/toolsrc/src/vcpkg/userconfig.cpp
@@ -51,7 +51,7 @@ namespace vcpkg
{
const auto& pghs = *p_pghs;
- std::unordered_map<std::string, std::string> keys;
+ Parse::RawParagraph keys;
if (pghs.size() > 0) keys = pghs[0];
for (size_t x = 1; x < pghs.size(); ++x)
diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
index 7a28fb571..e48340df7 100644
--- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
+++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
@@ -148,9 +148,8 @@ namespace vcpkg
}
if (Strings::starts_with(arg, "--scripts-root="))
{
- parse_cojoined_value(arg.substr(sizeof("--scripts-root=") - 1),
- "--scripts-root",
- args.scripts_root_dir);
+ parse_cojoined_value(
+ arg.substr(sizeof("--scripts-root=") - 1), "--scripts-root", args.scripts_root_dir);
continue;
}
if (arg == "--triplet")
@@ -161,16 +160,14 @@ namespace vcpkg
}
if (Strings::starts_with(arg, "--overlay-ports="))
{
- parse_cojoined_multivalue(arg.substr(sizeof("--overlay-ports=") - 1),
- "--overlay-ports",
- args.overlay_ports);
+ parse_cojoined_multivalue(
+ arg.substr(sizeof("--overlay-ports=") - 1), "--overlay-ports", args.overlay_ports);
continue;
}
if (Strings::starts_with(arg, "--overlay-triplets="))
{
- parse_cojoined_multivalue(arg.substr(sizeof("--overlay-triplets=") - 1),
- "--overlay-triplets",
- args.overlay_triplets);
+ parse_cojoined_multivalue(
+ arg.substr(sizeof("--overlay-triplets=") - 1), "--overlay-triplets", args.overlay_triplets);
continue;
}
if (arg == "--debug")
@@ -224,11 +221,11 @@ namespace vcpkg
{
const auto& key = arg.substr(0, eq_pos);
const auto& value = arg.substr(eq_pos + 1);
-
+
auto it = args.optional_command_arguments.find(key);
if (args.optional_command_arguments.end() == it)
{
- args.optional_command_arguments.emplace(key, std::vector<std::string> { value });
+ args.optional_command_arguments.emplace(key, std::vector<std::string>{value});
}
else
{
@@ -370,8 +367,9 @@ namespace vcpkg
{
if (v.empty())
{
- System::printf(
- System::Color::error, "Error: The option '%s' must be passed an argument.\n", option.name);
+ System::printf(System::Color::error,
+ "Error: The option '%s' must be passed an argument.\n",
+ option.name);
failed = true;
}
else
@@ -389,7 +387,7 @@ namespace vcpkg
System::printf(System::Color::error, "Unknown option(s) for command '%s':\n", this->command);
for (auto&& option : options_copy)
{
- System::print2(" ", option.first, "\n");
+ System::print2(" '", option.first, "'\n");
}
System::print2("\n");
failed = true;
@@ -425,12 +423,9 @@ namespace vcpkg
System::printf(" %-40s %s\n", (option.name + "=..."), option.short_help_text);
}
System::printf(" %-40s %s\n", "--triplet <t>", "Set the default triplet for unqualified packages");
- System::printf(" %-40s %s\n",
- "--overlay-ports=<path>",
- "Specify directories to be used when searching for ports");
- System::printf(" %-40s %s\n",
- "--overlay-triplets=<path>",
- "Specify directories containing triplets files");
+ System::printf(
+ " %-40s %s\n", "--overlay-ports=<path>", "Specify directories to be used when searching for ports");
+ System::printf(" %-40s %s\n", "--overlay-triplets=<path>", "Specify directories containing triplets files");
System::printf(" %-40s %s\n",
"--vcpkg-root <path>",
"Specify the vcpkg directory to use instead of current directory or tool directory");
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index d16acf2e8..c5b5749ff 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -42,7 +42,7 @@ namespace vcpkg
if (auto odp = overriddenDownloadsPath.get())
{
auto asPath = fs::u8path(*odp);
- if (!fs::stdfs::is_directory(asPath))
+ if (!fs::is_directory(status(asPath)))
{
Metrics::g_metrics.lock()->track_property("error", "Invalid VCPKG_DOWNLOADS override directory.");
Checks::exit_with_message(
@@ -71,12 +71,12 @@ namespace vcpkg
{
if (scripts_dir->empty() || !fs::stdfs::is_directory(*scripts_dir))
{
- Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory.");
- 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.",
- scripts_dir->u8string());
+ Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory.");
+ 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.",
+ scripts_dir->u8string());
}
paths.scripts = *scripts_dir;
@@ -147,26 +147,25 @@ namespace vcpkg
}
Util::sort_unique_erase(output);
return output;
- });
+ });
}
const fs::path VcpkgPaths::get_triplet_file_path(const Triplet& triplet) const
{
- return m_triplets_cache.get_lazy(triplet, [&]()-> auto {
- for (auto&& triplet_dir : triplets_dirs)
- {
- auto&& path = triplet_dir / (triplet.canonical_name() + ".cmake");
- if (this->get_filesystem().exists(path))
+ return m_triplets_cache.get_lazy(
+ triplet, [&]() -> auto {
+ for (auto&& triplet_dir : triplets_dirs)
{
- return path;
+ auto&& path = triplet_dir / (triplet.canonical_name() + ".cmake");
+ if (this->get_filesystem().exists(path))
+ {
+ return path;
+ }
}
- }
- Checks::exit_with_message(VCPKG_LINE_INFO,
- "Error: Triplet file %s.cmake not found",
- triplet.canonical_name());
- });
-
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Error: Triplet file %s.cmake not found", triplet.canonical_name());
+ });
}
const fs::path& VcpkgPaths::get_tool_exe(const std::string& tool) const
diff --git a/toolsrc/vcpkg.sln b/toolsrc/vcpkg.sln
index 8d0c849c6..b9f6ade65 100644
--- a/toolsrc/vcpkg.sln
+++ b/toolsrc/vcpkg.sln
@@ -1,4 +1,4 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj b/toolsrc/vcpkglib/vcpkglib.vcxproj
index d28bae8ec..568d316c6 100644
--- a/toolsrc/vcpkglib/vcpkglib.vcxproj
+++ b/toolsrc/vcpkglib/vcpkglib.vcxproj
@@ -249,6 +249,7 @@
<ClCompile Include="..\src\vcpkg\help.cpp" />
<ClCompile Include="..\src\vcpkg\input.cpp" />
<ClCompile Include="..\src\vcpkg\install.cpp" />
+ <ClCompile Include="..\src\vcpkg\logicexpression.cpp" />
<ClCompile Include="..\src\vcpkg\metrics.cpp" />
<ClCompile Include="..\src\vcpkg\packagespec.cpp" />
<ClCompile Include="..\src\vcpkg\packagespecparseresult.cpp" />
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
index aec56b039..1074a5116 100644
--- a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
+++ b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
@@ -108,6 +108,9 @@
<ClCompile Include="..\src\vcpkg\install.cpp">
<Filter>Source Files\vcpkg</Filter>
</ClCompile>
+ <ClCompile Include="..\src\vcpkg\logicexpression.cpp">
+ <Filter>Source Files\vcpkg</Filter>
+ </ClCompile>
<ClCompile Include="..\src\vcpkg\metrics.cpp">
<Filter>Source Files\vcpkg</Filter>
</ClCompile>
diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj b/toolsrc/vcpkgtest/vcpkgtest.vcxproj
index 530dfbc5d..d656de747 100644
--- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj
+++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj
@@ -19,19 +19,19 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\vcpkg-tests\arguments.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\catch.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\chrono.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\dependencies.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\files.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\paragraph.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\plan.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\specifier.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\statusparagraphs.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\strings.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\supports.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\update.cpp" />
- <ClCompile Include="..\src\vcpkg-tests\util.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\arguments.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\catch.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\chrono.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\dependencies.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\files.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\paragraph.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\plan.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\specifier.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\statusparagraphs.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\strings.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\supports.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\update.cpp" />
+ <ClCompile Include="..\src\vcpkg-test\util.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\vcpkglib\vcpkglib.vcxproj">
@@ -39,8 +39,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="..\include\vcpkg-tests\catch.h" />
- <ClInclude Include="..\include\vcpkg-tests\util.h" />
+ <ClInclude Include="..\include\vcpkg-test\catch.h" />
+ <ClInclude Include="..\include\vcpkg-test\util.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F27B8DB0-1279-4AF8-A2E3-1D49C4F0220D}</ProjectGuid>
diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters b/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters
index d9808ca89..74a746af1 100644
--- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters
+++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters
@@ -15,43 +15,43 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\vcpkg-tests\arguments.cpp">
+ <ClCompile Include="..\src\vcpkg-test\arguments.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\catch.cpp">
+ <ClCompile Include="..\src\vcpkg-test\catch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\chrono.cpp">
+ <ClCompile Include="..\src\vcpkg-test\chrono.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\dependencies.cpp">
+ <ClCompile Include="..\src\vcpkg-test\dependencies.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\paragraph.cpp">
+ <ClCompile Include="..\src\vcpkg-test\paragraph.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\plan.cpp">
+ <ClCompile Include="..\src\vcpkg-test\plan.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\specifier.cpp">
+ <ClCompile Include="..\src\vcpkg-test\specifier.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\statusparagraphs.cpp">
+ <ClCompile Include="..\src\vcpkg-test\statusparagraphs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\supports.cpp">
+ <ClCompile Include="..\src\vcpkg-test\supports.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\update.cpp">
+ <ClCompile Include="..\src\vcpkg-test\update.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\vcpkg-tests\util.cpp">
+ <ClCompile Include="..\src\vcpkg-test\util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\tests.files.cpp">
+ <ClCompile Include="..\src\vcpkg-test\files.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\tests.strings.cpp">
+ <ClCompile Include="..\src\vcpkg-test\strings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -63,4 +63,4 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>