aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/include
diff options
context:
space:
mode:
authorAlexander Karatarakis <alkarata@microsoft.com>2016-09-18 20:50:08 -0700
committerAlexander Karatarakis <alkarata@microsoft.com>2016-09-18 20:54:03 -0700
commitccca198c1b1730b0241911cb56dc8e3504958b2a (patch)
treea2dd9b8b087a09afdcecc5cbb3377bed15127eb2 /toolsrc/include
downloadvcpkg-ccca198c1b1730b0241911cb56dc8e3504958b2a.tar.gz
vcpkg-ccca198c1b1730b0241911cb56dc8e3504958b2a.zip
Initial commit
Diffstat (limited to 'toolsrc/include')
-rw-r--r--toolsrc/include/BinaryParagraph.h30
-rw-r--r--toolsrc/include/SourceParagraph.h20
-rw-r--r--toolsrc/include/StatusParagraph.h41
-rw-r--r--toolsrc/include/StatusParagraphs.h49
-rw-r--r--toolsrc/include/expected.h81
-rw-r--r--toolsrc/include/metrics.h19
-rw-r--r--toolsrc/include/opt_bool.h11
-rw-r--r--toolsrc/include/package_spec.h50
-rw-r--r--toolsrc/include/package_spec_parse_result.h34
-rw-r--r--toolsrc/include/post_build_lint.h8
-rw-r--r--toolsrc/include/triplet.h55
-rw-r--r--toolsrc/include/vcpkg.h37
-rw-r--r--toolsrc/include/vcpkg_Checks.h49
-rw-r--r--toolsrc/include/vcpkg_Commands.h67
-rw-r--r--toolsrc/include/vcpkg_Environment.h17
-rw-r--r--toolsrc/include/vcpkg_Files.h11
-rw-r--r--toolsrc/include/vcpkg_Graphs.h119
-rw-r--r--toolsrc/include/vcpkg_Strings.h58
-rw-r--r--toolsrc/include/vcpkg_System.h77
-rw-r--r--toolsrc/include/vcpkg_cmd_arguments.h36
-rw-r--r--toolsrc/include/vcpkg_paths.h29
-rw-r--r--toolsrc/include/vcpkglib_helpers.h12
22 files changed, 910 insertions, 0 deletions
diff --git a/toolsrc/include/BinaryParagraph.h b/toolsrc/include/BinaryParagraph.h
new file mode 100644
index 000000000..88d6e84b1
--- /dev/null
+++ b/toolsrc/include/BinaryParagraph.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <unordered_map>
+#include "SourceParagraph.h"
+#include "triplet.h"
+
+namespace vcpkg
+{
+ struct BinaryParagraph
+ {
+ BinaryParagraph();
+ explicit BinaryParagraph(const std::unordered_map<std::string, std::string>& fields);
+ BinaryParagraph(const SourceParagraph& spgh, const triplet& target_triplet);
+
+ std::string displayname() const;
+
+ std::string fullstem() const;
+
+ std::string dir() const;
+
+ std::string name;
+ std::string version;
+ std::string description;
+ std::string maintainer;
+ triplet target_triplet;
+ std::vector<std::string> depends;
+ };
+
+ std::ostream& operator<<(std::ostream& os, const BinaryParagraph& pgh);
+}
diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h
new file mode 100644
index 000000000..72dca8324
--- /dev/null
+++ b/toolsrc/include/SourceParagraph.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <vector>
+#include <unordered_map>
+
+namespace vcpkg
+{
+ struct SourceParagraph
+ {
+ SourceParagraph();
+
+ explicit SourceParagraph(const std::unordered_map<std::string, std::string>& fields);
+
+ std::string name;
+ std::string version;
+ std::string description;
+ std::string maintainer;
+ std::vector<std::string> depends;
+ };
+}
diff --git a/toolsrc/include/StatusParagraph.h b/toolsrc/include/StatusParagraph.h
new file mode 100644
index 000000000..1386bbdf4
--- /dev/null
+++ b/toolsrc/include/StatusParagraph.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <unordered_map>
+#include "BinaryParagraph.h"
+
+namespace vcpkg
+{
+ enum class install_state_t
+ {
+ error,
+ not_installed,
+ half_installed,
+ installed,
+ };
+
+ enum class want_t
+ {
+ error,
+ unknown,
+ install,
+ hold,
+ deinstall,
+ purge
+ };
+
+ struct StatusParagraph
+ {
+ StatusParagraph();
+ explicit StatusParagraph(const std::unordered_map<std::string, std::string>& fields);
+
+ BinaryParagraph package;
+ want_t want;
+ install_state_t state;
+ };
+
+ std::ostream& operator<<(std::ostream& os, const StatusParagraph& pgh);
+
+ std::string to_string(install_state_t f);
+
+ std::string to_string(want_t f);
+}
diff --git a/toolsrc/include/StatusParagraphs.h b/toolsrc/include/StatusParagraphs.h
new file mode 100644
index 000000000..9446d432c
--- /dev/null
+++ b/toolsrc/include/StatusParagraphs.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "StatusParagraph.h"
+#include <memory>
+
+namespace vcpkg
+{
+ struct StatusParagraphs
+ {
+ StatusParagraphs();
+ explicit StatusParagraphs(std::vector<std::unique_ptr<StatusParagraph>>&& ps);
+
+ using container = std::vector<std::unique_ptr<StatusParagraph>>;
+ using iterator = container::reverse_iterator;
+ using const_iterator = container::const_reverse_iterator;
+
+ const_iterator find(const std::string& name, const triplet& target_triplet) const;
+ iterator find(const std::string& name, const triplet& target_triplet);
+ iterator find_installed(const std::string& name, const triplet& target_triplet);
+
+ iterator insert(std::unique_ptr<StatusParagraph>);
+
+ friend std::ostream& operator<<(std::ostream&, const StatusParagraphs&);
+
+ auto end()
+ {
+ return paragraphs.rend();
+ }
+
+ auto end() const
+ {
+ return paragraphs.rend();
+ }
+
+ auto begin()
+ {
+ return paragraphs.rbegin();
+ }
+
+ auto begin() const
+ {
+ return paragraphs.rbegin();
+ }
+
+ private:
+ std::vector<std::unique_ptr<StatusParagraph>> paragraphs;
+ };
+
+ std::ostream& operator<<(std::ostream&, const StatusParagraphs&);
+}
diff --git a/toolsrc/include/expected.h b/toolsrc/include/expected.h
new file mode 100644
index 000000000..affabcc02
--- /dev/null
+++ b/toolsrc/include/expected.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include "vcpkg_Checks.h"
+
+namespace vcpkg
+{
+ template <class T>
+ class expected
+ {
+ public:
+ // Constructors are intentionally implicit
+ expected(const std::error_code& ec) : m_error_code(ec), m_t()
+ {
+ }
+
+ expected(std::errc ec) : expected(std::make_error_code(ec))
+ {
+ }
+
+ expected(const T& t) : m_error_code(), m_t(t)
+ {
+ }
+
+ expected(T&& t) : m_error_code(), m_t(std::move(t))
+ {
+ }
+
+ expected() : expected(std::error_code(), T())
+ {
+ }
+
+ expected(const expected&) = default;
+ expected(expected&&) = default;
+ expected& operator=(const expected&) = default;
+ expected& operator=(expected&&) = default;
+
+ std::error_code error_code() const
+ {
+ return this->m_error_code;
+ }
+
+ T&& get_or_throw() &&
+ {
+ throw_if_error();
+ return std::move(this->m_t);
+ }
+
+ const T& get_or_throw() const &
+ {
+ throw_if_error();
+ return this->m_t;
+ }
+
+ const T* get() const
+ {
+ if (m_error_code)
+ {
+ return nullptr;
+ }
+ return &this->m_t;
+ }
+
+ T* get()
+ {
+ if (m_error_code)
+ {
+ return nullptr;
+ }
+ return &this->m_t;
+ }
+
+ private:
+ void throw_if_error() const
+ {
+ Checks::check_throw(!this->m_error_code, this->m_error_code.message().c_str());
+ }
+
+ std::error_code m_error_code;
+ T m_t;
+ };
+}
diff --git a/toolsrc/include/metrics.h b/toolsrc/include/metrics.h
new file mode 100644
index 000000000..52662cd97
--- /dev/null
+++ b/toolsrc/include/metrics.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <string>
+
+namespace vcpkg
+{
+ void SetSendMetrics(bool should_send_metrics);
+ void SetPrintMetrics(bool should_print_metrics);
+ void SetUserInformation(const std::string& user_id, const std::string& first_use_time);
+ void InitUserInformation(std::string& user_id, std::string& first_use_time);
+
+ void TrackMetric(const std::string& name, double value);
+ void TrackProperty(const std::string& name, const std::string& value);
+ void TrackProperty(const std::string& name, const std::wstring& value);
+ bool GetCompiledMetricsEnabled();
+
+ void Upload(const std::string& payload);
+ void Flush();
+}
diff --git a/toolsrc/include/opt_bool.h b/toolsrc/include/opt_bool.h
new file mode 100644
index 000000000..3856366c8
--- /dev/null
+++ b/toolsrc/include/opt_bool.h
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace vcpkg
+{
+ enum class opt_bool
+ {
+ unspecified,
+ enabled,
+ disabled
+ };
+}
diff --git a/toolsrc/include/package_spec.h b/toolsrc/include/package_spec.h
new file mode 100644
index 000000000..b8ed1e088
--- /dev/null
+++ b/toolsrc/include/package_spec.h
@@ -0,0 +1,50 @@
+#pragma once
+#include <string>
+#include "package_spec_parse_result.h"
+#include "triplet.h"
+#include "expected.h"
+
+namespace vcpkg
+{
+ struct package_spec
+ {
+ std::string name;
+ triplet target_triplet;
+
+ std::string dir() const;
+ };
+
+ expected<package_spec> parse(const std::string& spec, const triplet& default_target_triplet);
+
+ std::string to_string(const package_spec& spec);
+
+ std::string to_printf_arg(const package_spec& spec);
+
+ bool operator==(const package_spec& left, const package_spec& right);
+
+ std::ostream& operator<<(std::ostream& os, const package_spec& spec);
+} //namespace vcpkg
+
+namespace std
+{
+ template <>
+ struct hash<vcpkg::package_spec>
+ {
+ size_t operator()(const vcpkg::package_spec& value) const
+ {
+ size_t hash = 17;
+ hash = hash * 31 + std::hash<std::string>()(value.name);
+ hash = hash * 31 + std::hash<vcpkg::triplet>()(value.target_triplet);
+ return hash;
+ }
+ };
+
+ template <>
+ struct equal_to<vcpkg::package_spec>
+ {
+ bool operator()(const vcpkg::package_spec& left, const vcpkg::package_spec& right) const
+ {
+ return left == right;
+ }
+ };
+} // namespace std
diff --git a/toolsrc/include/package_spec_parse_result.h b/toolsrc/include/package_spec_parse_result.h
new file mode 100644
index 000000000..e59622951
--- /dev/null
+++ b/toolsrc/include/package_spec_parse_result.h
@@ -0,0 +1,34 @@
+#pragma once
+#include <system_error>
+
+namespace vcpkg
+{
+ enum class package_spec_parse_result
+ {
+ success = 0,
+ too_many_colons
+ };
+
+ struct package_spec_parse_result_category_impl final : std::error_category
+ {
+ virtual const char* name() const noexcept override;
+
+ virtual std::string message(int ev) const noexcept override;
+ };
+
+ const std::error_category& package_spec_parse_result_category();
+
+ std::error_code make_error_code(package_spec_parse_result e);
+
+ package_spec_parse_result to_package_spec_parse_result(int i);
+
+ package_spec_parse_result to_package_spec_parse_result(std::error_code ec);
+}
+
+// Enable implicit conversion to std::error_code
+namespace std
+{
+ template <>
+ struct is_error_code_enum<vcpkg::package_spec_parse_result> : ::std::true_type
+ {};
+}
diff --git a/toolsrc/include/post_build_lint.h b/toolsrc/include/post_build_lint.h
new file mode 100644
index 000000000..bc916a7af
--- /dev/null
+++ b/toolsrc/include/post_build_lint.h
@@ -0,0 +1,8 @@
+#pragma once
+#include "package_spec.h"
+#include "vcpkg_paths.h"
+
+namespace vcpkg
+{
+ void perform_all_checks(const package_spec& spec, const vcpkg_paths& paths);
+}
diff --git a/toolsrc/include/triplet.h b/toolsrc/include/triplet.h
new file mode 100644
index 000000000..f9d1e9483
--- /dev/null
+++ b/toolsrc/include/triplet.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <string>
+
+namespace vcpkg
+{
+ struct triplet
+ {
+ static const triplet X86_WINDOWS;
+ static const triplet X64_WINDOWS;
+ static const triplet X86_UWP;
+ static const triplet X64_UWP;
+ static const triplet ARM_UWP;
+
+ std::string value;
+
+ std::string architecture() const;
+
+ std::string system() const;
+ };
+
+ bool operator==(const triplet& left, const triplet& right);
+
+ bool operator!=(const triplet& left, const triplet& right);
+
+ std::string to_string(const triplet& spec);
+
+ std::string to_printf_arg(const triplet& spec);
+
+ std::ostream& operator<<(std::ostream& os, const triplet& spec);
+}
+
+namespace std
+{
+ template <>
+ struct hash<vcpkg::triplet>
+ {
+ size_t operator()(const vcpkg::triplet& t) const
+ {
+ std::hash<std::string> hasher;
+ size_t hash = 17;
+ hash = hash * 31 + hasher(t.value);
+ return hash;
+ }
+ };
+
+ template <>
+ struct equal_to<vcpkg::triplet>
+ {
+ bool operator()(const vcpkg::triplet& left, const vcpkg::triplet& right) const
+ {
+ return left == right;
+ }
+ };
+} // namespace std
diff --git a/toolsrc/include/vcpkg.h b/toolsrc/include/vcpkg.h
new file mode 100644
index 000000000..264d61fa9
--- /dev/null
+++ b/toolsrc/include/vcpkg.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <filesystem>
+#include <vector>
+#include <unordered_map>
+#include "package_spec.h"
+#include "BinaryParagraph.h"
+#include "StatusParagraphs.h"
+#include "vcpkg_paths.h"
+
+namespace vcpkg
+{
+ namespace fs = std::tr2::sys;
+
+ extern bool g_do_dry_run;
+
+ std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path);
+ std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str);
+ std::string shorten_description(const std::string& desc);
+
+ fs::path find_available_package(const vcpkg_paths& paths, const package_spec& spec);
+ fs::path find_available_port_file(const vcpkg_paths& paths, const package_spec& spec);
+ fs::path control_file_for_package(const fs::path& package_path);
+
+ StatusParagraphs database_load_check(const vcpkg_paths& paths);
+
+ std::vector<std::string> get_unmet_package_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db);
+
+ void install_package(const vcpkg_paths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs& status_db);
+ void deinstall_package(const vcpkg_paths& paths, const package_spec& spec, StatusParagraphs& status_db);
+
+ void search_file(const vcpkg_paths& paths, const std::string& file_substr, const StatusParagraphs& status_db);
+
+ void binary_import(const vcpkg_paths& paths, const fs::path& include_directory, const fs::path& project_directory, const BinaryParagraph& control_file_data);
+
+ const std::string& version();
+} // namespace vcpkg
diff --git a/toolsrc/include/vcpkg_Checks.h b/toolsrc/include/vcpkg_Checks.h
new file mode 100644
index 000000000..05bd0e729
--- /dev/null
+++ b/toolsrc/include/vcpkg_Checks.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "vcpkg_Strings.h"
+
+namespace vcpkg {namespace Checks
+{
+ __declspec(noreturn) void unreachable();
+
+ // Part of the reason these exist is to not include extra headers in this one to avoid circular #includes.
+ _declspec(noreturn) void exit_with_message(const char* errorMessage);
+
+ template <class...Args>
+ _declspec(noreturn) void exit_with_message(const char* errorMessageTemplate, const Args&... errorMessageArgs)
+ {
+ exit_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...).c_str());
+ }
+
+ _declspec(noreturn) void throw_with_message(const char* errorMessage);
+
+ template <class...Args>
+ _declspec(noreturn) void throw_with_message(const char* errorMessageTemplate, const Args&... errorMessageArgs)
+ {
+ throw_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...));
+ }
+
+ void check_throw(bool expression, const char* errorMessage);
+
+ template <class...Args>
+ void check_throw(bool expression, const char* errorMessageTemplate, const Args&... errorMessageArgs)
+ {
+ if (!expression)
+ {
+ // Only create the string if the expression is false
+ throw_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...).c_str());
+ }
+ }
+
+ void check_exit(bool expression, const char* errorMessage);
+
+ template <class...Args>
+ void check_exit(bool expression, const char* errorMessageTemplate, const Args&... errorMessageArgs)
+ {
+ if (!expression)
+ {
+ // Only create the string if the expression is false
+ exit_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...).c_str());
+ }
+ }
+}}
diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h
new file mode 100644
index 000000000..c706c131c
--- /dev/null
+++ b/toolsrc/include/vcpkg_Commands.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "vcpkg_cmd_arguments.h"
+#include "vcpkg_paths.h"
+
+namespace vcpkg
+{
+ extern const char*const INTEGRATE_COMMAND_HELPSTRING;
+
+ void print_usage();
+ void print_example(const char* command_and_arguments);
+ void update_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+
+ void build_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ void build_external_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ void install_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ void remove_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+
+ void edit_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ void create_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+
+ void search_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ void list_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ void import_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ void owns_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ void internal_test_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+
+ void cache_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+
+ void integrate_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+
+ void help_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ void help_topic_valid_triplet(const vcpkg_paths& paths);
+
+ void version_command(const vcpkg_cmd_arguments& args);
+ void contact_command(const vcpkg_cmd_arguments& args);
+
+ using command_type_a = void(*)(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ using command_type_b = void(*)(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ using command_type_c = void(*)(const vcpkg_cmd_arguments& args);
+
+ template <class T>
+ struct package_name_and_function
+ {
+ std::string name;
+ T function;
+ };
+
+ const std::vector<package_name_and_function<command_type_a>>& get_available_commands_type_a();
+ const std::vector<package_name_and_function<command_type_b>>& get_available_commands_type_b();
+ const std::vector<package_name_and_function<command_type_c>>& get_available_commands_type_c();
+
+ template <typename T>
+ T find_command(const std::string& command_name, const std::vector<package_name_and_function<T>> available_commands)
+ {
+ for (const package_name_and_function<T>& cmd : available_commands)
+ {
+ if (cmd.name == command_name)
+ {
+ return cmd.function;
+ }
+ }
+
+ // not found
+ return nullptr;
+ }
+}
diff --git a/toolsrc/include/vcpkg_Environment.h b/toolsrc/include/vcpkg_Environment.h
new file mode 100644
index 000000000..877ac7deb
--- /dev/null
+++ b/toolsrc/include/vcpkg_Environment.h
@@ -0,0 +1,17 @@
+#pragma once
+#include "vcpkg_paths.h"
+
+namespace vcpkg {namespace Environment
+{
+ void ensure_nuget_on_path(const vcpkg_paths& paths);
+
+ void ensure_git_on_path(const vcpkg_paths& paths);
+
+ void ensure_cmake_on_path(const vcpkg_paths& paths);
+
+ inline void ensure_utilities_on_path(const vcpkg_paths& paths)
+ {
+ ensure_cmake_on_path(paths);
+ ensure_git_on_path(paths);
+ }
+}}
diff --git a/toolsrc/include/vcpkg_Files.h b/toolsrc/include/vcpkg_Files.h
new file mode 100644
index 000000000..d23742f74
--- /dev/null
+++ b/toolsrc/include/vcpkg_Files.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "expected.h"
+#include <filesystem>
+
+namespace vcpkg {namespace Files
+{
+ void check_is_directory(const std::tr2::sys::path& dirpath);
+
+ expected<std::string> get_contents(const std::tr2::sys::path& file_path) noexcept;
+}}
diff --git a/toolsrc/include/vcpkg_Graphs.h b/toolsrc/include/vcpkg_Graphs.h
new file mode 100644
index 000000000..81b189f0e
--- /dev/null
+++ b/toolsrc/include/vcpkg_Graphs.h
@@ -0,0 +1,119 @@
+#pragma once
+
+#include <unordered_map>
+
+namespace vcpkg { namespace Graphs
+{
+ enum class ExplorationStatus
+ {
+ // We have not visited this vertex
+ NOT_EXPLORED,
+
+ // We have visited this vertex but haven't visited all vertices in its subtree
+ PARTIALLY_EXPLORED,
+
+ // We have visited this vertex and all vertices in its subtree
+ FULLY_EXPLORED
+ };
+
+ template <class V>
+ class Graph
+ {
+ static void find_topological_sort_internal(V vertex,
+ ExplorationStatus& status,
+ const std::unordered_map<V, std::vector<V>>& adjacency_list,
+ std::unordered_map<V, ExplorationStatus>& exploration_status,
+ std::vector<V>& sorted)
+ {
+ status = ExplorationStatus::PARTIALLY_EXPLORED;
+
+ for (V neighbour : adjacency_list.at(vertex))
+ {
+ ExplorationStatus& neighbour_status = exploration_status[neighbour];
+ if (neighbour_status == ExplorationStatus::NOT_EXPLORED)
+ {
+ find_topological_sort_internal(neighbour, neighbour_status, adjacency_list, exploration_status, sorted);
+ }
+ else if (neighbour_status == ExplorationStatus::PARTIALLY_EXPLORED)
+ {
+ throw std::runtime_error("cycle in graph");
+ }
+ }
+
+ status = ExplorationStatus::FULLY_EXPLORED;
+ sorted.push_back(vertex);
+ }
+
+ public:
+
+ void add_vertex(V v)
+ {
+ this->vertices[v];
+ }
+
+ // TODO: Change with iterators
+ void add_vertices(const std::vector<V>& vs)
+ {
+ for (const V& v : vs)
+ {
+ this->vertices[v];
+ }
+ }
+
+ void add_edge(V u, V v)
+ {
+ this->vertices[v];
+ this->vertices[u].push_back(v);
+ }
+
+ std::vector<V> find_topological_sort() const
+ {
+ std::unordered_map<V, int> indegrees = count_indegrees();
+
+ std::vector<V> sorted;
+ sorted.reserve(indegrees.size());
+
+ std::unordered_map<V, ExplorationStatus> exploration_status;
+ exploration_status.reserve(indegrees.size());
+
+ for (auto& pair : indegrees)
+ {
+ if (pair.second == 0) // Starting from vertices with indegree == 0. Not required.
+ {
+ V vertex = pair.first;
+ ExplorationStatus& status = exploration_status[vertex];
+ if (status == ExplorationStatus::NOT_EXPLORED)
+ {
+ find_topological_sort_internal(vertex, status, this->vertices, exploration_status, sorted);
+ }
+ }
+ }
+
+ return sorted;
+ }
+
+ std::unordered_map<V, int> count_indegrees() const
+ {
+ std::unordered_map<V, int> indegrees;
+
+ for (auto& pair : this->vertices)
+ {
+ indegrees[pair.first];
+ for (V neighbour : pair.second)
+ {
+ ++indegrees[neighbour];
+ }
+ }
+
+ return indegrees;
+ }
+
+ const std::unordered_map<V, std::vector<V>>& adjacency_list() const
+ {
+ return this->vertices;
+ }
+
+ private:
+ std::unordered_map<V, std::vector<V>> vertices;
+ };
+}}
diff --git a/toolsrc/include/vcpkg_Strings.h b/toolsrc/include/vcpkg_Strings.h
new file mode 100644
index 000000000..f4b989292
--- /dev/null
+++ b/toolsrc/include/vcpkg_Strings.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <string>
+
+namespace vcpkg {namespace Strings {namespace details
+{
+ inline const char* to_printf_arg(const std::string& s)
+ {
+ return s.c_str();
+ }
+
+ inline const char* to_printf_arg(const char* s)
+ {
+ return s;
+ }
+
+ inline int to_printf_arg(const int s)
+ {
+ return s;
+ }
+
+ std::string format_internal(const char* fmtstr, ...);
+
+ inline const wchar_t* to_wprintf_arg(const std::wstring& s)
+ {
+ return s.c_str();
+ }
+
+ inline const wchar_t* to_wprintf_arg(const wchar_t* s)
+ {
+ return s;
+ }
+
+ std::wstring format_internal(const wchar_t* fmtstr, ...);
+}}}
+
+namespace vcpkg {namespace Strings
+{
+ template <class...Args>
+ std::string format(const char* fmtstr, const Args&...args)
+ {
+ using vcpkg::Strings::details::to_printf_arg;
+ return details::format_internal(fmtstr, to_printf_arg(to_printf_arg(args))...);
+ }
+
+ template <class...Args>
+ std::wstring format(const wchar_t* fmtstr, const Args&...args)
+ {
+ using vcpkg::Strings::details::to_wprintf_arg;
+ return details::format_internal(fmtstr, to_wprintf_arg(to_wprintf_arg(args))...);
+ }
+
+ std::wstring utf8_to_utf16(const std::string& s);
+
+ std::string utf16_to_utf8(const std::wstring& w);
+
+ std::string::const_iterator case_insensitive_find(const std::string& s, const std::string& pattern);
+}}
diff --git a/toolsrc/include/vcpkg_System.h b/toolsrc/include/vcpkg_System.h
new file mode 100644
index 000000000..f47fc9aab
--- /dev/null
+++ b/toolsrc/include/vcpkg_System.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include "vcpkg_Strings.h"
+
+#include <filesystem>
+
+namespace vcpkg {namespace System
+{
+ std::tr2::sys::path get_exe_path_of_current_process();
+
+ struct exit_code_and_output
+ {
+ int exit_code;
+ std::string output;
+ };
+
+ int cmd_execute(const wchar_t* cmd_line);
+
+ inline int cmd_execute(const std::wstring& cmd_line)
+ {
+ return cmd_execute(cmd_line.c_str());
+ }
+
+ exit_code_and_output cmd_execute_and_capture_output(const wchar_t* cmd_line);
+
+ inline exit_code_and_output cmd_execute_and_capture_output(const std::wstring& cmd_line)
+ {
+ return cmd_execute_and_capture_output(cmd_line.c_str());
+ }
+
+ enum class color
+ {
+ success = 10,
+ error = 12,
+ warning = 14,
+ };
+
+ void print(const char* message);
+ void println(const char* message);
+ void print(color c, const char* message);
+ void println(color c, const char* message);
+
+ template <class...Args>
+ void print(const char* messageTemplate, const Args&... messageArgs)
+ {
+ return print(Strings::format(messageTemplate, messageArgs...).c_str());
+ }
+
+ template <class...Args>
+ void print(color c, const char* messageTemplate, const Args&... messageArgs)
+ {
+ return print(c, Strings::format(messageTemplate, messageArgs...).c_str());
+ }
+
+ template <class...Args>
+ void println(const char* messageTemplate, const Args&... messageArgs)
+ {
+ return println(Strings::format(messageTemplate, messageArgs...).c_str());
+ }
+
+ template <class...Args>
+ void println(color c, const char* messageTemplate, const Args&... messageArgs)
+ {
+ return println(c, Strings::format(messageTemplate, messageArgs...).c_str());
+ }
+
+ struct Stopwatch
+ {
+ int64_t start_time, end_time, freq;
+
+ void start();
+ void stop();
+ double microseconds() const;
+ };
+
+ std::wstring wdupenv_str(const wchar_t* varname) noexcept;
+}}
diff --git a/toolsrc/include/vcpkg_cmd_arguments.h b/toolsrc/include/vcpkg_cmd_arguments.h
new file mode 100644
index 000000000..0df3d1222
--- /dev/null
+++ b/toolsrc/include/vcpkg_cmd_arguments.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_set>
+#include "opt_bool.h"
+#include "package_spec.h"
+#include "vcpkg_paths.h"
+#include "StatusParagraphs.h"
+
+namespace vcpkg
+{
+ struct vcpkg_cmd_arguments
+ {
+ static vcpkg_cmd_arguments create_from_command_line(const int argc, const wchar_t* const* const argv);
+
+ static vcpkg_cmd_arguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end);
+
+ std::unique_ptr<std::string> vcpkg_root_dir;
+ std::unique_ptr<std::string> target_triplet;
+ opt_bool debug = opt_bool::unspecified;
+ opt_bool sendmetrics = opt_bool::unspecified;
+ opt_bool printmetrics = opt_bool::unspecified;
+
+ std::string command;
+ std::vector<std::string> command_arguments;
+ std::unordered_set<std::string> check_and_get_optional_command_arguments(const std::vector<std::string>& valid_options) const;
+
+ void check_max_args(size_t arg_count, const char* example_text = nullptr) const;
+ std::vector<package_spec> parse_all_arguments_as_package_specs(const triplet& default_target_triplet, const char* example_text = nullptr) const;
+ std::vector<package_spec> extract_package_specs_with_unmet_dependencies(const vcpkg_paths& paths, const triplet& default_target_triplet, const StatusParagraphs& status_db) const;
+
+ private:
+ std::unordered_set<std::string> optional_command_arguments;
+ };
+}
diff --git a/toolsrc/include/vcpkg_paths.h b/toolsrc/include/vcpkg_paths.h
new file mode 100644
index 000000000..58ab45bc5
--- /dev/null
+++ b/toolsrc/include/vcpkg_paths.h
@@ -0,0 +1,29 @@
+#pragma once
+#include <filesystem>
+#include "expected.h"
+
+namespace vcpkg
+{
+ struct vcpkg_paths
+ {
+ static expected<vcpkg_paths> create(const std::tr2::sys::path& vcpkg_root_dir);
+
+ std::tr2::sys::path root;
+ std::tr2::sys::path packages;
+ std::tr2::sys::path buildtrees;
+ std::tr2::sys::path downloads;
+ std::tr2::sys::path ports;
+ std::tr2::sys::path installed;
+ std::tr2::sys::path triplets;
+
+ std::tr2::sys::path buildsystems;
+ std::tr2::sys::path buildsystems_msbuild_targets;
+
+ std::tr2::sys::path vcpkg_dir;
+ std::tr2::sys::path vcpkg_dir_status_file;
+ std::tr2::sys::path vcpkg_dir_info;
+ std::tr2::sys::path vcpkg_dir_updates;
+
+ std::tr2::sys::path ports_cmake;
+ };
+}
diff --git a/toolsrc/include/vcpkglib_helpers.h b/toolsrc/include/vcpkglib_helpers.h
new file mode 100644
index 000000000..e15b59b0b
--- /dev/null
+++ b/toolsrc/include/vcpkglib_helpers.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <unordered_map>
+
+namespace vcpkg {namespace details
+{
+ void optional_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname);
+
+ void required_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname);
+
+ void parse_depends(const std::string& depends_string, std::vector<std::string>& out);
+}}